結局、MIPSで試していたのだが、コンパイルは成功した。システムコールの部分を自分で作るかどうかがポイントだ。 あとは、リンカスクリプトを調整してうまくメモリマップに入るように調整する。
上記のリポジトリを落してきて、
make TARGET=linux-mips TOOLCHAIN=gcc-mips TARGET_MIPS=1
でコンパイルできるようになっている。コンパイルにはmipsel-linux-elf-gccが必要だが、util/make/gcc-mips.makを編集することで別のコンパイラも利用できるようにした。
結局、
Using Newlib in ARM bare metal programsbalau82.wordpress.com
を参考にして、以下のような mith/syscalls/syscalls.c を作成している。これはコンパイルが通ればとりあえず良かったため、まずはこのままにして、後で調整する予定。
#include <sys/stat.h> #include <unistd.h> enum { UART_FR_RXFE = 0x10, UART_FR_TXFF = 0x20, UART0_ADDR = 0x10009000, }; #define UART_DR(baseaddr) (*(unsigned int *)(baseaddr)) #define UART_FR(baseaddr) (*(((unsigned int *)(baseaddr))+6)) void _exit (int status) { __asm ("wait"); } int close(int file) { return -1; } int fstat(int file, struct stat *st) { st->st_mode = S_IFCHR; return 0; } int stat(const char *path, struct stat *buf) { buf->st_mode = S_IFCHR; return 0; } int isatty(int file) { return 1; } off_t _EXFUN(lseek, (int __fildes, off_t __offset, int __whence )) { return 0; } int open(const char *name, int flags, int mode) { return -1; } _READ_WRITE_RETURN_TYPE _EXFUN(read, (int __fd, void *__buf, size_t __nbyte )) { unsigned int *buf = (unsigned int *)__buf; int todo; if(__nbyte == 0) return 0; while(UART_FR(UART0_ADDR) & UART_FR_RXFE); *buf++ = UART_DR(UART0_ADDR); for(todo = 1; todo < __nbyte; todo++) { if(UART_FR(UART0_ADDR) & UART_FR_RXFE) { break; } *buf++ = UART_DR(UART0_ADDR); } return todo; } char *heap_end = 0; void * sbrk(intptr_t increment) { extern char heap_low; /* Defined by the linker */ extern char heap_top; /* Defined by the linker */ char *prev_heap_end; if (heap_end == 0) { heap_end = &heap_low; } prev_heap_end = heap_end; if (heap_end + increment > &heap_top) { /* Heap and stack collision */ return (void *)0; } heap_end += increment; return (void *) prev_heap_end; } _READ_WRITE_RETURN_TYPE _EXFUN(write, (int __fd, const void *__buf, size_t __nbyte )) { int todo; unsigned int *buf = (unsigned int *)__buf; for (todo = 0; todo < __nbyte; todo++) { UART_DR(UART0_ADDR) = *buf++; } return __nbyte; }
これでバイナリファイルを作成して、自作MIPSシミュレータで流してみようと思ったのだが、浮動小数点の計算が出てきて失敗した(今の僕のシミュレータは浮動小数点に対応していない...) RTLでの実装もなかなか難しいし、とりあえずはsoft-floatが使えるようにgccをコンパイルし直そうかなあ...