#ifdef __cplusplus extern "C" { #endif #include "syscalls.h" #include #include #include #include "fileio.h" #define SYS_ftruncate 3000 #define SYS_isatty 3001 #define outbyte putchar #define inbyte getserial /* Set to 1 if we are running on hardware. The config instruction is * always emulated on the simulator. The emulation code pokes this * variable to 1. */ extern int _hardware; /* _cpu_config==0 => Abel * _cpu_config==1 => Zeta * _cpu_config==2 => Phi */ extern int _cpu_config; int _use_syscall; extern char _end; // Defined by the linker script extern char *heap_ptr; extern int __bss_start__; extern int __bss_end__; extern int __ctors_start__; extern int __ctors_end__; extern int __dtors_start__; extern int __dtors_end__; extern int _syscall(int *foo, int ID, ...); extern int main(int argc, char **argv); static char *args[]={"dummy.exe"}; extern void _init(void); void _initIO(void); void _break(); void __attribute__ ((weak)) _premain() { int t; int *ctors; char *ramtop; /* we only use syscalls w/Zeta */ _use_syscall=(_cpu_config==1); // Clear BSS data int *bss=&__bss_start__; while(bss<&__bss_end__) *bss++=0; ramtop=(char *)addresscheck((volatile int *)&_end,0); malloc_add(&_end,ramtop-&_end); // Add the entire RAM to the free memory pool // Run global constructors... ctors=&__ctors_start__; while(ctors<&__ctors_end__) { printf("."); void (*fp)(); fp=(void (*)())(*ctors); fp(); ++ctors; } t=main(1, args); // Run global destructors... ctors=&__dtors_start__; while(ctors<&__dtors_end__) { void (*fp)(); fp=(void (*)())(*ctors); fp(); ++ctors; } _exit(t); } /* NOTE!!!! compiled with -fomit-frame-pointer to make sure that 'status' has the * correct value when breakpointing at _exit */ void __attribute__ ((weak)) _exit (int status) { /* end of the universe, cause memory fault */ __asm("breakpoint"); for (;;); _break; } void __attribute__ ((weak)) _zpu_interrupt(void) { /* not implemented in libgloss */ __asm("breakpoint"); for (;;); } int __attribute__ ((weak)) _DEFUN (write, (fd, buf, nbytes), int fd _AND char *buf _AND int nbytes) { if (_use_syscall) { int t; int result; result=_syscall(&t, SYS_write, fd, buf, nbytes); errno=t; return result; } else { int i; for (i = 0; i < nbytes; i++) { if (*(buf + i) == '\n') { outbyte ('\r'); } outbyte (*(buf + i)); } return (nbytes); } } /* * read -- read bytes from the serial port. Ignore fd, since * we only have stdin. */ int __attribute__ ((weak)) _DEFUN (read, (fd, buf, nbytes), int fd _AND char *buf _AND int nbytes) { if (_use_syscall) { int t; int result; result=_syscall(&t, SYS_read, fd, buf, nbytes); errno=t; return result; } else { int i = 0; for (i = 0; i < nbytes; i++) { char t=inbyte(); if ((t!='\r')&&(t!='\n')) { *(buf + i) = t; outbyte(t); // echo } else { // terminate the line in the way expected by the libraries *(buf + i) = '\n'; i++; outbyte('\r'); outbyte('\n'); break; } } return (i); } } /* * open -- open a file descriptor. We don't have a filesystem, so * we return an error. */ int __attribute__ ((weak)) open(const char *buf, int flags, int mode, ...) { if (_use_syscall) { int t; int result; result=_syscall(&t, SYS_open, buf, strlen(buf)+1, flags, mode); errno=t; return result; } else { errno = EIO; return (-1); } } /* * close -- We don't need to do anything, but pretend we did. */ int __attribute__ ((weak)) _DEFUN (close ,(fd), int fd) { if (_use_syscall) { int t; int result; result=_syscall(&t, SYS_close, fd); errno=t; return result; } else { return (0); } } int __attribute__ ((weak)) ftruncate (int file, off_t length) { /* if (_use_syscall) { int t; int result; result=_syscall(&t, SYS_ftruncate, file, length); errno=t; return result; } else */ { return -1; } } /* * unlink -- since we have no file system, * we just return an error. */ int __attribute__ ((weak)) _DEFUN (unlink, (path), char * path) { if (_use_syscall) { int t; int result; result=_syscall(&t, SYS_unlink, path, strlen(path)+1); errno=t; return result; } else { errno = EIO; return (-1); } } /* * lseek -- Since a serial port is non-seekable, we return an error. */ off_t __attribute__ ((weak)) _DEFUN (lseek, (fd, offset, whence), int fd _AND off_t offset _AND int whence) { if (_use_syscall) { int t; int result; result=_syscall(&t, SYS_lseek, fd, offset, whence); errno=t; return result; } else { errno = ESPIPE; return ((off_t)-1); } } /* we convert from bigendian to smallendian*/ static long conv(char *a, int len) { long t=0; int i; for (i=0; ist_dev=conv(gdb_stat->fst_dev, sizeof(gdb_stat->fst_dev)); buf->st_ino=conv(gdb_stat->fst_ino, sizeof(gdb_stat->fst_ino)); buf->st_mode=conv(gdb_stat->fst_mode, sizeof(gdb_stat->fst_mode)); buf->st_nlink=conv(gdb_stat->fst_nlink, sizeof(gdb_stat->fst_nlink)); buf->st_uid=conv(gdb_stat->fst_uid, sizeof(gdb_stat->fst_uid)); buf->st_gid=conv(gdb_stat->fst_gid, sizeof(gdb_stat->fst_gid)); buf->st_rdev=conv(gdb_stat->fst_rdev, sizeof(gdb_stat->fst_rdev)); buf->st_size=conv(gdb_stat->fst_size, sizeof(gdb_stat->fst_size)); #if 0 conv_64(fio_ulong_t, &gdb_stat->fst_blksize); conv_64(fio_ulong_t, &gdb_stat->fst_blocks); #endif #if 0 conv_time(fst_atime; conv_time(fst_mtime; conv_time(fst_ctime; #endif } int __attribute__ ((weak)) _DEFUN (fstat, (fd, buf), int fd _AND struct stat *buf) { if (_use_syscall) { int t; int result; struct fio_stat gdb_stat; result=_syscall(&t, SYS_fstat, fd, &gdb_stat); convert(&gdb_stat, buf); errno=t; return result; } else { /* * fstat -- Since we have no file system, we just return an error. */ buf->st_mode = S_IFCHR; /* Always pretend to be a tty */ buf->st_blksize = 0; return (0); } } int __attribute__ ((weak)) _DEFUN (stat, (path, buf), const char *path _AND struct stat *buf) { if (_use_syscall) { int t; int result; struct fio_stat gdb_stat; result=_syscall(&t, SYS_stat, path, strlen(path)+1, &gdb_stat); convert(&gdb_stat, buf); errno=t; return result; } else { errno = EIO; return (-1); } } int __attribute__ ((weak)) _DEFUN (isatty, (fd), int fd) { if (_use_syscall) { int t; int result; result=_syscall(&t, SYS_isatty, fd); errno=t; return result; } else { /* * isatty -- returns 1 if connected to a terminal device, * returns 0 if not. Since we're hooked up to a * serial port, we'll say yes _AND return a 1. */ return (1); } } extern unsigned long _stext; extern unsigned long _etext; extern unsigned long _sdata; extern unsigned long _edata; extern unsigned long _sbss; extern unsigned long _ebss; extern unsigned long _estack; #ifndef STACK_MARGIN #define STACK_MARGIN 8192 #endif //char *__brkval = (char *)&_ebss; // //void * _sbrk(int incr) //{ // char *prev, *stack; // // prev = __brkval; // if (incr != 0) { // #if defined __K64F__ // __asm__ volatile("mov %0, sp" : "=r" (stack) ::); // #endif // if (prev + incr >= stack - STACK_MARGIN) { //// errno = ENOMEM; // return (void *)-1; // } // __brkval = prev + incr; // } // return prev; //} extern char __HeapBase; /**< Defined by the linker */ extern char __HeapLimit; /**< Defined by the linker */ void * _sbrk(int incr) { static char *heap_end; char *prev_heap_end; if (heap_end == 0) { heap_end = &__HeapBase; } prev_heap_end = heap_end; if ((heap_end + incr) > (char*) &__HeapLimit) { //errno = ENOMEM; return ((void*)-1); // error - no more memory } heap_end += incr; return prev_heap_end; } #ifdef __cplusplus } #endif