Files
zSoft/common/syscalls.c

460 lines
8.2 KiB
C
Executable File

#ifdef __cplusplus
extern "C" {
#endif
#include "syscalls.h"
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include "fileio.h"
#define SYS_ftruncate 3000
#define SYS_isatty 3001
#define outbyte xputc
#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__)
{
xprintf(".");
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; i<len; i++)
{
t|=(((int)a[i])&0xff)<<((len-1-i)*8);
}
return t;
}
static void convert(struct fio_stat *gdb_stat, struct stat *buf)
{
memset(buf, 0, sizeof(*buf));
buf->st_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