1 /* Support files for GNU libc. Files in the system namespace go here.
2 Files in the C namespace (ie those that do not start with an
3 underscore) go in .c. */
12 #include <sys/times.h>
19 #include "r_typedefs.h"
28 /* Forward prototypes. */
29 int _system _PARAMS ((const char *));
30 int _rename _PARAMS ((const char *, const char *));
31 int _isatty _PARAMS ((int));
32 clock_t _times _PARAMS ((struct tms *));
33 int _gettimeofday _PARAMS ((struct timeval *, void *));
34 void _raise _PARAMS ((void));
35 int _unlink _PARAMS ((const char *));
36 int _link _PARAMS ((void));
37 int _stat _PARAMS ((const char *, struct stat *));
38 int _fstat _PARAMS ((int, struct stat *));
39 caddr_t _sbrk _PARAMS ((int));
40 int _getpid _PARAMS ((int));
41 int _kill _PARAMS ((int, int));
42 void _exit _PARAMS ((int));
43 int _close _PARAMS ((int));
44 int _swiclose _PARAMS ((int));
45 int _open _PARAMS ((const char *, int, ...));
46 int _swiopen _PARAMS ((const char *, int));
47 int _write _PARAMS ((int, const char *, unsigned int));
49 int _swiwrite _PARAMS ((int, char *, int));
50 int _lseek _PARAMS ((int, int, int));
51 int _swilseek _PARAMS ((int, int, int));
52 int _read _PARAMS ((int, char *, unsigned int));
54 int _swiread _PARAMS ((int, char *, int));
55 void initialise_monitor_handles _PARAMS ((void));
57 static int wrap _PARAMS ((int));
58 static int error _PARAMS ((int));
59 static int get_errno _PARAMS ((void));
60 static int remap_handle _PARAMS ((int));
62 #ifdef ARM_RDI_MONITOR
63 static int do_AngelSWI _PARAMS ((int, void *));
66 static int findslot _PARAMS ((int));
68 /* Register name faking - works in collusion with the linker. */
69 register char * stack_ptr __asm ("sp");
72 /* following is copied from libc/stdio/local.h to check std streams */
73 extern void _EXFUN(__sinit,(struct _reent *));
74 #define CHECK_INIT(ptr) \
77 if ((ptr) && !(ptr)->__sdidinit) \
82 /* Adjust our internal handles to stay away from std* handles. */
83 #define FILE_HANDLE_OFFSET (0x20)
85 static int monitor_stdin;
86 static int monitor_stdout;
87 static int monitor_stderr;
89 /* Struct used to keep track of the file position, just so we
90 can implement fseek(fh,x,SEEK_CUR). */
98 #define MAX_OPEN_FILES (20)
99 static poslog openfiles [MAX_OPEN_FILES];
105 for (i = 0; i < MAX_OPEN_FILES; i ++)
106 if (openfiles[i].handle == fh)
113 #ifdef ARM_RDI_MONITOR
116 do_AngelSWI (int reason, void * arg)
119 asm volatile ("mov r0, %1; mov r1, %2; " AngelSWIInsn " %a3; mov %0, r0"
120 : "=r" (value) /* Outputs */
121 : "r" (reason), "r" (arg), "i" (AngelSWI) /* Inputs */
122 : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"
123 /* Clobbers r0 and r1, and lr if in supervisor mode */);
124 /* Accordingly to page 13-77 of ARM DUI 0040D other registers
125 can also be clobbered. Some memory positions may also be
126 changed by a system call, so they should not be kept in
127 registers. Note: we are assuming the manual is right and
128 Angel is respecting the APCS. */
131 #endif /* ARM_RDI_MONITOR */
133 /* Function to convert std(in|out|err) handles to internal versions. */
135 remap_handle (int fh)
139 if (STDIN_FILENO == fh)
141 return (monitor_stdin);
143 if (STDOUT_FILENO == fh)
145 return (monitor_stdout);
147 if (STDERR_FILENO == fh)
149 return (monitor_stderr);
152 return (fh - FILE_HANDLE_OFFSET);
156 initialise_monitor_handles (void)
160 #ifdef ARM_RDI_MONITOR
161 int volatile block[3];
163 block[0] = (int) ":tt";
164 block[2] = 3; /* length of filename */
165 block[1] = 0; /* mode "r" */
166 monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
168 block[0] = (int) ":tt";
169 block[2] = 3; /* length of filename */
170 block[1] = 4; /* mode "w" */
171 monitor_stdout = monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
177 __asm ("mov r0,%2; mov r1, #0; swi %a1; mov %0, r0"
179 : "i" (SWI_Open),"r"(pname)
184 __asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0"
186 : "i" (SWI_Open),"r"(pname)
188 monitor_stdout = (monitor_stderr = fh);
191 for (i = 0; i < MAX_OPEN_FILES; i ++)
193 openfiles[i].handle = (-1);
196 openfiles[0].handle = monitor_stdin;
197 openfiles[0].pos = 0;
198 openfiles[1].handle = monitor_stdout;
199 openfiles[1].pos = 0;
205 #ifdef ARM_RDI_MONITOR
206 return do_AngelSWI (AngelSWI_Reason_Errno, NULL);
208 __asm ("swi %a0" :: "i" (SWI_GetErrno));
216 errno = get_errno ();
230 /* Returns # chars not! written. */
236 int fh = remap_handle (file);
237 #ifdef ARM_RDI_MONITOR
241 block[1] = (int) ptr;
244 return do_AngelSWI (AngelSWI_Reason_Read, block);
246 __asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0"
248 : "i"(SWI_Read), "r"(fh), "r"(ptr), "r"(len)
254 /******************************************************************************
255 * Function Name: _read
256 * Description : GNU interface to low-level I/O read
257 * Arguments : int file_no
258 * : const char *buffer
260 * Return Value : none
261 ******************************************************************************/
262 int _read(int file_no , char *buffer , unsigned int n)
264 return (sio_read(file_no , buffer , n));
273 int fh = remap_handle (file);
274 int slot = findslot (fh);
275 #ifdef ARM_RDI_MONITOR
281 if (MAX_OPEN_FILES == slot)
285 ptr = (openfiles[slot].pos + ptr);
289 #ifdef ARM_RDI_MONITOR
293 ptr += do_AngelSWI (AngelSWI_Reason_FLen, block);
296 /* This code only does absolute seeks. */
297 block[0] = remap_handle (file);
299 res = do_AngelSWI (AngelSWI_Reason_Seek, block);
303 __asm ("mov r0, %2; swi %a1; mov %0, r0"
305 : "i" (SWI_Flen), "r" (fh)
310 /* This code only does absolute seeks. */
311 __asm ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0"
313 : "i" (SWI_Seek), "r" (fh), "r" (ptr)
317 if ((MAX_OPEN_FILES != slot) && (0 == res))
319 openfiles[slot].pos = ptr;
322 /* This is expected to return the position in the file. */
323 return ((0 == res) ? ptr : (-1));
331 return (wrap (_swilseek (file, ptr, dir)));
334 /* Returns #chars not! written. */
341 int fh = remap_handle (file);
342 #ifdef ARM_RDI_MONITOR
346 block[1] = (int) ptr;
349 return do_AngelSWI (AngelSWI_Reason_Write, block);
351 __asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0"
353 : "i"(SWI_Write), "r"(fh), "r"(ptr), "r"(len)
359 /******************************************************************************
360 * Function Name: _write
361 * Description : GNU interface to low-level I/O write
362 * Arguments : int file_no
363 * : const char *buffer
365 * Return Value : none
366 ******************************************************************************/
367 int _write(int file_no , const char *buffer , unsigned int n)
369 return (sio_write(file_no , buffer , n));
373 _swiopen (const char * path,
377 #ifdef ARM_RDI_MONITOR
381 int i = findslot (-1);
383 if (MAX_OPEN_FILES == i)
388 /* The flags are Unix-style, so we need to convert them. */
390 if (flags & O_BINARY)
411 if (flags & O_APPEND)
413 aflags &= (~4); /* Can't ask for w AND a; means just 'a'. */
417 #ifdef ARM_RDI_MONITOR
418 block[0] = (int) path;
419 block[2] = strlen (path);
422 fh = do_AngelSWI (AngelSWI_Reason_Open, block);
425 __asm ("mov r0,%2; mov r1, %3; swi %a1; mov %0, r0"
427 : "i" (SWI_Open),"r"(path),"r"(aflags)
433 openfiles[i].handle = fh;
434 openfiles[i].pos = 0;
437 return ((fh >= 0) ? (fh + FILE_HANDLE_OFFSET) : error (fh));
441 _open (const char * path,
445 return (wrap (_swiopen (path, flags)));
451 int myhan = remap_handle (file);
452 int slot = findslot (myhan);
454 if (MAX_OPEN_FILES != slot)
456 openfiles[slot].handle = (-1);
459 #ifdef ARM_RDI_MONITOR
460 return do_AngelSWI (AngelSWI_Reason_Close, & myhan);
462 __asm ("mov r0, %1; swi %a0" :: "i" (SWI_Close),"r"(myhan):"r0");
470 return (wrap (_swiclose (file)));
474 _kill (int pid, int sig)
476 (void)pid; (void)sig;
477 #ifdef ARM_RDI_MONITOR
478 /* Note: The pid argument is thrown away. */
481 return do_AngelSWI (AngelSWI_Reason_ReportException,
482 (void *) ADP_Stopped_RunTimeError);
484 return do_AngelSWI (AngelSWI_Reason_ReportException,
485 (void *) ADP_Stopped_ApplicationExit);
488 __asm ("swi %a0" :: "i" (SWI_Exit));
496 /* There is only one SWI for both _exit and _kill. For _exit, call
497 the SWI with the second argument set to -1, an invalid value for
498 signum, so that the SWI handler can distinguish the two calls.
499 Note: The RDI implementation of _kill throws away both its
504 /* exit occurred */
\r
518 extern char end __asm ("end"); /* Defined by the linker. */
519 static char * pheap_end;
520 char * prev_heap_end;
522 if (NULL == pheap_end)
527 prev_heap_end = pheap_end;
529 if ((pheap_end + incr) > stack_ptr)
531 /* Some of the libstdc++-v3 tests rely upon detecting
532 out of memory errors, so do not abort here. */
534 extern void abort (void);
536 _write (1, "_sbrk: Heap and stack collision\n", 32);
541 return ((caddr_t) (-1));
547 return ((caddr_t) prev_heap_end);
551 _fstat (int file, struct stat * st)
554 memset (st, 0, sizeof (* st));
555 st->st_mode = S_IFCHR;
556 st->st_blksize = 1024;
560 int _stat (const char *fname, struct stat *st)
564 /* The best we can do is try to open the file read-only. If it exists,
565 then we can guess a few things about it. */
566 if ((file = _open (fname, O_RDONLY)) < 0)
571 memset (st, 0, sizeof (* st));
572 st->st_mode = (S_IFREG | S_IREAD);
573 st->st_blksize = 1024;
574 _swiclose (file); /* Not interested in the error. */
585 _unlink (const char *path)
587 #ifdef ARM_RDI_MONITOR
590 block[1] = strlen(path);
591 return wrap (do_AngelSWI (AngelSWI_Reason_Remove, block)) ? -1 : 0;
604 _gettimeofday (struct timeval * tp, void * tzvp)
606 struct timezone * ptzp = tzvp;
609 /* Ask the host for the seconds since the Unix epoch. */
610 #ifdef ARM_RDI_MONITOR
611 tp->tv_sec = do_AngelSWI (AngelSWI_Reason_Time,NULL);
615 __asm ("swi %a1; mov %0, r0" : "=r" (value): "i" (SWI_Time) : "r0");
622 /* Return fixed data for the time-zone. */
625 ptzp->tz_minuteswest = 0;
626 ptzp->tz_dsttime = 0;
632 /* Return a clock that ticks at 100Hz. */
634 _times (struct tms * tp)
638 #ifdef ARM_RDI_MONITOR
639 timeval = do_AngelSWI (AngelSWI_Reason_Clock,NULL);
641 __asm ("swi %a1; mov %0, r0" : "=r" (timeval): "i" (SWI_Clock) : "r0");
646 tp->tms_utime = timeval; /* user time */
647 tp->tms_stime = 0; /* system time */
648 tp->tms_cutime = 0; /* user time, children */
649 tp->tms_cstime = 0; /* system time, children */
659 #ifdef ARM_RDI_MONITOR
660 int fh = remap_handle (fd);
661 return wrap (do_AngelSWI (AngelSWI_Reason_IsTTY, &fh));
663 return ((fd <= 2) ? 1 : 0); /* one of stdin, stdout, stderr */
668 _system (const char *s)
670 #ifdef ARM_RDI_MONITOR
674 /* Hmmm. The ARM debug interface specification doesn't say whether
675 SYS_SYSTEM does the right thing with a null argument, or assign any
676 meaning to its return value. Try to do something reasonable.... */
678 return 1; /* maybe there is a shell available? we can hope. :-P */
680 block[1] = strlen (s);
681 e = wrap (do_AngelSWI (AngelSWI_Reason_System, block));
682 if ((e >= 0) && (e < 256))
684 /* We have to convert e, an exit status to the encoded status of
685 the command. To avoid hard coding the exit status, we simply
686 loop until we find the right position. */
689 for (exit_code = e; e && WEXITSTATUS (e) != exit_code; e <<= 1)
704 _rename (const char * oldpath, const char * newpath)
706 #ifdef ARM_RDI_MONITOR
709 block[1] = strlen(oldpath);
711 block[3] = strlen(newpath);
712 return wrap (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0;