diff options
Diffstat (limited to 'libc/arm')
| -rw-r--r-- | libc/arm/libcfunc.c | 45 | ||||
| -rw-r--r-- | libc/arm/swi.h | 65 | ||||
| -rw-r--r-- | libc/arm/sys/param.h | 10 | ||||
| -rw-r--r-- | libc/arm/syscalls.c | 504 | 
4 files changed, 624 insertions, 0 deletions
| diff --git a/libc/arm/libcfunc.c b/libc/arm/libcfunc.c new file mode 100644 index 0000000..9825ccc --- /dev/null +++ b/libc/arm/libcfunc.c @@ -0,0 +1,45 @@ +/* Support files for GNU libc.  Files in the C namespace go here. +   Files in the system namespace (ie those that start with an underscore) +   go in syscalls.c. +    +   Note: These functions are in a seperate file so that OS providers can +   overrride the system call stubs (defined in syscalls.c) without having +   to provide libc funcitons as well.  */ +#include "swi.h" + +#ifdef ARM_RDI_MONITOR + +static inline int +do_AngelSWI (int reason, void * arg) +{ +  int value; +  asm volatile ("mov r0, %1; mov r1, %2; swi %a3; mov %0, r0" +       : "=r" (value) /* Outputs */ +       : "r" (reason), "r" (arg), "i" (AngelSWI) /* Inputs */ +       : "r0", "r1", "lr" +		/* Clobbers r0 and r1, and lr if in supervisor mode */); +  return value; +} +#endif /* ARM_RDI_MONITOR */ + + +void +abort (void) +{ +#ifdef ARM_RDI_MONITOR +  do_AngelSWI (AngelSWI_Reason_ReportException, +	      (void *) ADP_Stopped_RunTimeError); +#else + asm ("mov r0,#17\nswi %a0" :: "i" (SWI_Exit)); +#endif +} + +isatty (int fd) +{ +  return 1; +} + +void +alarm (void) +{ +} diff --git a/libc/arm/swi.h b/libc/arm/swi.h new file mode 100644 index 0000000..91fad59 --- /dev/null +++ b/libc/arm/swi.h @@ -0,0 +1,65 @@ + +/***************************************************************************\ +*                               SWI numbers                                 * +\***************************************************************************/ + +/* SWI numbers for RDP (Demon) monitor */ +#define SWI_WriteC                 0x0 +#define SWI_Write0                 0x2 +#define SWI_ReadC                  0x4 +#define SWI_CLI                    0x5 +#define SWI_GetEnv                 0x10 +#define SWI_Exit                   0x11 +#define SWI_EnterOS                0x16 + +#define SWI_GetErrno               0x60 +#define SWI_Clock                  0x61 +#define SWI_Time                   0x63 +#define SWI_Remove                 0x64 +#define SWI_Rename                 0x65 +#define SWI_Open                   0x66 + +#define SWI_Close                  0x68 +#define SWI_Write                  0x69 +#define SWI_Read                   0x6a +#define SWI_Seek                   0x6b +#define SWI_Flen                   0x6c + +#define SWI_IsTTY                  0x6e +#define SWI_TmpNam                 0x6f +#define SWI_InstallHandler         0x70 +#define SWI_GenerateError          0x71 + + +/* Now the SWI numbers and reason codes for RDI (Angel) monitors */ +#define AngelSWI_ARM 			(0x123456) +#ifdef __thumb__ +#define AngelSWI 			(0xAB) +#else +#define AngelSWI 			AngelSWI_ARM +#endif + +/* The reason codes: */ +#define AngelSWI_Reason_Open		(0x01) +#define AngelSWI_Reason_Close		(0x02) +#define AngelSWI_Reason_WriteC		(0x03) +#define AngelSWI_Reason_Write0		(0x04) +#define AngelSWI_Reason_Write		(0x05) +#define AngelSWI_Reason_Read		(0x06) +#define AngelSWI_Reason_ReadC		(0x07) +#define AngelSWI_Reason_IsTTY		(0x09) +#define AngelSWI_Reason_Seek		(0x0A) +#define AngelSWI_Reason_FLen		(0x0C) +#define AngelSWI_Reason_TmpNam		(0x0D) +#define AngelSWI_Reason_Remove		(0x0E) +#define AngelSWI_Reason_Rename		(0x0F) +#define AngelSWI_Reason_Clock		(0x10) +#define AngelSWI_Reason_Time		(0x11) +#define AngelSWI_Reason_System		(0x12) +#define AngelSWI_Reason_Errno		(0x13) +#define AngelSWI_Reason_GetCmdLine 	(0x15) +#define AngelSWI_Reason_HeapInfo 	(0x16) +#define AngelSWI_Reason_EnterSVC 	(0x17) +#define AngelSWI_Reason_ReportException (0x18) +#define ADP_Stopped_ApplicationExit 	((2 << 16) + 38) +#define ADP_Stopped_RunTimeError 	((2 << 16) + 34) diff --git a/libc/arm/sys/param.h b/libc/arm/sys/param.h new file mode 100644 index 0000000..968c8ef --- /dev/null +++ b/libc/arm/sys/param.h @@ -0,0 +1,10 @@ +/* ARM configuration file; HZ is 100 rather than the default 60 */ + +#ifndef _SYS_PARAM_H +# define _SYS_PARAM_H + +# define HZ (100) +# define NOFILE	(60) +# define PATHSIZE (1024) + +#endif diff --git a/libc/arm/syscalls.c b/libc/arm/syscalls.c new file mode 100644 index 0000000..f9dc4d9 --- /dev/null +++ b/libc/arm/syscalls.c @@ -0,0 +1,504 @@ +/* Support files for GNU libc.  Files in the system namespace go here. +   Files in the C namespace (ie those that do not start with an +   underscore) go in .c.  */ + +#include <_ansi.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/fcntl.h> +#include <stdio.h> +#include <time.h> +#include <sys/time.h> +#include <sys/times.h> +#include <errno.h> +#include "swi.h" + +/* Adjust our internal handles to stay away from std* handles */ +#define FILE_HANDLE_OFFSET (0x20) + +static int monitor_stdin; +static int monitor_stdout; +static int monitor_stderr; + +/* Struct used to keep track of the file position, just so we +   can implement fseek(fh,x,SEEK_CUR).  */ +typedef struct +{ +  int handle; +  int pos; +} +poslog; + +#define MAX_OPEN_FILES 20 +static poslog openfiles [MAX_OPEN_FILES]; + +static int +findslot (int fh) +{ +  int i; +  for (i = 0; i < MAX_OPEN_FILES; i ++) +    if (openfiles[i].handle == fh) +      break; +  return i; +} + +#ifdef ARM_RDI_MONITOR + +static inline int +do_AngelSWI (int reason, void * arg) +{ +  int value; +  asm volatile ("mov r0, %1; mov r1, %2; swi %a3; mov %0, r0" +       : "=r" (value) /* Outputs */ +       : "r" (reason), "r" (arg), "i" (AngelSWI) /* Inputs */ +       : "r0", "r1", "lr" +		/* Clobbers r0 and r1, and lr if in supervisor mode */); +  return value; +} +#endif /* ARM_RDI_MONITOR */ + +/* Function to convert std(in|out|err) handles to internal versions */ +static int +remap_handle (int fh) +{ +  if (fh == __sfileno (stdin)) +    return monitor_stdin; +  if (fh == __sfileno (stdout)) +    return monitor_stdout; +  if (fh == __sfileno (stderr)) +    return monitor_stderr; + +  return fh - FILE_HANDLE_OFFSET; +} + +void +initialise_monitor_handles (void) +{ +  int i; +   +#ifdef ARM_RDI_MONITOR +  int block[3]; +   +  block[0] = (int) ":tt"; +  block[2] = 3;     /* length of filename */ +  block[1] = 0;     /* mode "r" */ +  monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, block); + +  block[0] = (int) ":tt"; +  block[2] = 3;     /* length of filename */ +  block[1] = 4;     /* mode "w" */ +  monitor_stdout = monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, block); +#else +  int fh; +  const char * name; + +  name = ":tt"; +  asm ("mov r0,%2; mov r1, #0; swi %a1; mov %0, r0" +       : "=r"(fh) +       : "i" (SWI_Open),"r"(name) +       : "r0","r1"); +  monitor_stdin = fh; + +  name = ":tt"; +  asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0" +       : "=r"(fh) +       : "i" (SWI_Open),"r"(name) +       : "r0","r1"); +  monitor_stdout = monitor_stderr = fh; +#endif + +  for (i = 0; i < MAX_OPEN_FILES; i ++) +    openfiles[i].handle = -1; + +  openfiles[0].handle = monitor_stdin; +  openfiles[0].pos = 0; +  openfiles[1].handle = monitor_stdout; +  openfiles[1].pos = 0; +} + +static int +get_errno () +{ +#ifdef ARM_RDI_MONITOR +  return do_AngelSWI (AngelSWI_Reason_Errno, NULL); +#else +  asm ("swi %a0" :: "i" (SWI_GetErrno)); +#endif +} + +static int +error (int result) +{ +  errno = get_errno (); +  return result; +} + +static int +wrap (int result) +{ +  if (result == -1) +    return error (-1); +  return result; +} + +/* Returns # chars not! written */ + +int +_swiread (int file, +	  char * ptr, +	  int len) +{ +  int fh = remap_handle (file); +#ifdef ARM_RDI_MONITOR +  int block[3]; +   +  block[0] = fh; +  block[1] = (int) ptr; +  block[2] = len; +   +  return do_AngelSWI (AngelSWI_Reason_Read, block); +#else +  asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0" +       : /* No outputs */ +       : "i"(SWI_Read), "r"(fh), "r"(ptr), "r"(len) +       : "r0","r1","r2"); +#endif +} + +int +_read (int file, +       char * ptr, +       int len) +{ +  int slot = findslot (remap_handle (file)); +  int x = _swiread (file, ptr, len); + +  if (x < 0) +    return error (-1); + +  if (slot != MAX_OPEN_FILES) +    openfiles [slot].pos += len - x; + +  /* x == len is not an error, at least if we want feof() to work */ +  return len - x; +} + +int +_swilseek (int file, +	int ptr, +	int dir) +{ +  int res; +  int fh = remap_handle (file); +  int slot = findslot (fh); +#ifdef ARM_RDI_MONITOR +  int block[2]; +#endif + +  if (dir == SEEK_CUR) +    { +      if (slot == MAX_OPEN_FILES) +	return -1; +      ptr = openfiles[slot].pos + ptr; +      dir = SEEK_SET; +    } +   +#ifdef ARM_RDI_MONITOR +  if (dir == SEEK_END) +    { +      block[0] = fh; +      ptr += do_AngelSWI (AngelSWI_Reason_FLen, block); +    } +   +  /* This code only does absolute seeks */ +  block[0] = remap_handle (file); +  block[1] = ptr; +  res = do_AngelSWI (AngelSWI_Reason_Seek, block); +#else +  if (dir == SEEK_END) +    { +      asm ("mov r0, %2; swi %a1; mov %0, r0" +	   : "=r" (res) +	   : "i" (SWI_Flen), "r" (fh) +	   : "r0"); +      ptr += res; +    } + +  /* This code only does absolute seeks */ +  asm ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0" +       : "=r" (res) +       : "i" (SWI_Seek), "r" (fh), "r" (ptr) +       : "r0", "r1"); +#endif + +  if (slot != MAX_OPEN_FILES && res == 0) +    openfiles[slot].pos = ptr; + +  /* This is expected to return the position in the file */ +  return res == 0 ? ptr : -1; +} + +int +_lseek (int file, +	int ptr, +	int dir) +{ +  return wrap (_swilseek (file, ptr, dir)); +} + +/* Returns #chars not! written */ +int +_swiwrite ( +	   int    file, +	   char * ptr, +	   int    len) +{ +  int fh = remap_handle (file); +#ifdef ARM_RDI_MONITOR +  int block[3]; +   +  block[0] = fh; +  block[1] = (int) ptr; +  block[2] = len; +   +  return do_AngelSWI (AngelSWI_Reason_Write, block); +#else +  asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0" +       : /* No outputs */ +       : "i"(SWI_Write), "r"(fh), "r"(ptr), "r"(len) +       : "r0","r1","r2"); +#endif +} + +int +_write (int    file, +	char * ptr, +	int    len) +{ +  int slot = findslot (remap_handle (file)); +  int x = _swiwrite (file, ptr,len); + +  if (x == -1 || x == len) +    return error (-1); +   +  if (slot != MAX_OPEN_FILES) +    openfiles[slot].pos += len - x; +   +  return len - x; +} + +int +_swiopen (const char * path, +	  int          flags) +{ +  int aflags = 0, fh; +#ifdef ARM_RDI_MONITOR +  int block[3]; +#endif +   +  int i = findslot (-1); +   +  if (i == MAX_OPEN_FILES) +    return -1; + +  /* The flags are Unix-style, so we need to convert them */ +#ifdef O_BINARY +  if (flags & O_BINARY) +    aflags |= 1; +#endif + +  if (flags & O_RDWR) +    aflags |= 2; + +  if (flags & O_CREAT) +    aflags |= 4; + +  if (flags & O_TRUNC) +    aflags |= 4; + +  if (flags & O_APPEND) +    { +      aflags &= ~4;     /* Can't ask for w AND a; means just 'a' */ +      aflags |= 8; +    } +   +#ifdef ARM_RDI_MONITOR +  block[0] = (int) path; +  block[2] = strlen (path); +  block[1] = aflags; +   +  fh = do_AngelSWI (AngelSWI_Reason_Open, block); +   +#else +  asm ("mov r0,%2; mov r1, %3; swi %a1; mov %0, r0" +       : "=r"(fh) +       : "i" (SWI_Open),"r"(path),"r"(aflags) +       : "r0","r1"); +#endif +   +  if (fh >= 0) +    { +      openfiles[i].handle = fh; +      openfiles[i].pos = 0; +    } + +  return fh >= 0 ? fh + FILE_HANDLE_OFFSET : error (fh); +} + +int +_open (const char * path, +       int          flags, +       ...) +{ +  return wrap (_swiopen (path, flags)); +} + +int +_swiclose (int file) +{ +  int myhan = remap_handle (file); +  int slot = findslot (myhan); +   +  if (slot != MAX_OPEN_FILES) +    openfiles[slot].handle = -1; + +#ifdef ARM_RDI_MONITOR +  return do_AngelSWI (AngelSWI_Reason_Close, & myhan); +#else +  asm ("mov r0, %1; swi %a0" :: "i" (SWI_Close),"r"(myhan):"r0"); +#endif +} + +int +_close (int file) +{ +  return wrap (_swiclose (file)); +} + +void +_exit (int n) +{ +  /* FIXME: return code is thrown away */ +   +#ifdef ARM_RDI_MONITOR +  do_AngelSWI (AngelSWI_Reason_ReportException, +	      (void *) ADP_Stopped_ApplicationExit); +#else +  asm ("swi %a0" :: "i" (SWI_Exit)); +#endif +} + +int +_kill (int n, int m) +{ +#ifdef ARM_RDI_MONITOR +  do_AngelSWI (AngelSWI_Reason_ReportException, +	      (void *) ADP_Stopped_ApplicationExit); +#else +  asm ("swi %a0" :: "i" (SWI_Exit)); +#endif +} + +int +_getpid (int n) +{ +  return 1; +} + +register char * stack_ptr asm ("sp"); + +caddr_t +_sbrk (int incr) +{ +  extern char   end asm ("end");	/* Defined by the linker */ +  static char * heap_end; +  char *        prev_heap_end; + +  if (heap_end == NULL) +    heap_end = & end; +   +  prev_heap_end = heap_end; +   +  if (heap_end + incr > stack_ptr) +    { +      _write (1, "_sbrk: Heap and stack collision\n", 32); +      abort (); +    } +   +  heap_end += incr; + +  return (caddr_t) prev_heap_end; +} + +int +_fstat (int           file, +	struct stat * st) +{ +  st->st_mode = S_IFCHR; +  return 0; +} + +int +_unlink (void) +{ +  return -1; +} + +void +_raise (void) +{ +} + +int +_gettimeofday (struct timeval * tp, struct timezone * tzp) +{ + +  if (tp) +    { +    /* Ask the host for the seconds since the Unix epoch */ +#ifdef ARM_RDI_MONITOR +      tp->tv_sec = do_AngelSWI (AngelSWI_Reason_Time,NULL); +#else +      { +        int value; +        asm ("swi %a1; mov %0, r0" : "=r" (value): "i" (SWI_Time) : "r0"); +        tp->tv_sec = value; +      } +#endif +      tp->tv_usec = 0; +    } + +  /* Return fixed data for the timezone */ +  if (tzp) +    { +      tzp->tz_minuteswest = 0; +      tzp->tz_dsttime = 0; +    } + +  return 0; +} + +/* Return a clock that ticks at 100Hz. */ +clock_t  +_times(struct tms * tp) +{ +  clock_t timeval; + +#ifdef ARM_RDI_MONITOR +  timeval = do_AngelSWI (AngelSWI_Reason_Clock,NULL); +#else +  asm ("swi %a1; mov %0, r0" : "=r" (timeval): "i" (SWI_Clock) : "r0"); +#endif + +  if (tp) +    { +      tp->tms_utime  = timeval;	/* user time */ +      tp->tms_stime  = 0;	/* system time */ +      tp->tms_cutime = 0;	/* user time, children */ +      tp->tms_cstime = 0;	/* system time, children */ +    } +   +  return timeval; +}; + + | 
