460 lines
8.2 KiB
C
Executable File
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 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; 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
|