xref: /netbsd-src/external/gpl3/gdb/dist/sim/arm/armos.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /*  armos.c -- ARMulator OS interface:  ARM6 Instruction Emulator.
2     Copyright (C) 1994 Advanced RISC Machines Ltd.
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
17 
18 /* This file contains a model of Demon, ARM Ltd's Debug Monitor,
19    including all the SWI's required to support the C library. The code in
20    it is not really for the faint-hearted (especially the abort handling
21    code), but it is a complete example. Defining NOOS will disable all the
22    fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI
23    0x11 to halt the emulator.  */
24 
25 #include "config.h"
26 #include "ansidecl.h"
27 
28 #include <time.h>
29 #include <errno.h>
30 #include <limits.h>
31 #include <string.h>
32 #include "targ-vals.h"
33 
34 #ifndef TARGET_O_BINARY
35 #define TARGET_O_BINARY 0
36 #endif
37 
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>		/* For SEEK_SET etc.  */
40 #endif
41 
42 #ifdef __riscos
43 extern int _fisatty (FILE *);
44 #define isatty_(f) _fisatty(f)
45 #else
46 #ifdef __ZTC__
47 #include <io.h>
48 #define isatty_(f) isatty((f)->_file)
49 #else
50 #ifdef macintosh
51 #include <ioctl.h>
52 #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
53 #else
54 #define isatty_(f) isatty (fileno (f))
55 #endif
56 #endif
57 #endif
58 
59 #include "armdefs.h"
60 #include "armos.h"
61 #include "armemu.h"
62 
63 #ifndef NOOS
64 #ifndef VALIDATE
65 /* #ifndef ASIM */
66 #include "armfpe.h"
67 /* #endif */
68 #endif
69 #endif
70 
71 /* For RDIError_BreakpointReached.  */
72 #include "dbg_rdi.h"
73 
74 #include "gdb/callback.h"
75 extern host_callback *sim_callback;
76 
77 extern unsigned ARMul_OSInit       (ARMul_State *);
78 extern void     ARMul_OSExit       (ARMul_State *);
79 extern unsigned ARMul_OSHandleSWI  (ARMul_State *, ARMword);
80 extern unsigned ARMul_OSException  (ARMul_State *, ARMword, ARMword);
81 extern ARMword  ARMul_OSLastErrorP (ARMul_State *);
82 extern ARMword  ARMul_Debug        (ARMul_State *, ARMword, ARMword);
83 
84 #define BUFFERSIZE 4096
85 #ifndef FOPEN_MAX
86 #define FOPEN_MAX 64
87 #endif
88 #define UNIQUETEMPS 256
89 #ifndef PATH_MAX
90 #define PATH_MAX 1024
91 #endif
92 
93 /* OS private Information.  */
94 
95 struct OSblock
96 {
97   ARMword Time0;
98   ARMword ErrorP;
99   ARMword ErrorNo;
100   FILE *FileTable[FOPEN_MAX];
101   char FileFlags[FOPEN_MAX];
102   char *tempnames[UNIQUETEMPS];
103 };
104 
105 #define NOOP 0
106 #define BINARY 1
107 #define READOP 2
108 #define WRITEOP 4
109 
110 #ifdef macintosh
111 #define FIXCRLF(t,c) ((t & BINARY) ? \
112                       c : \
113                       ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \
114                      )
115 #else
116 #define FIXCRLF(t,c) c
117 #endif
118 
119 /* Bit mask of enabled SWI implementations.  */
120 unsigned int swi_mask = -1;
121 
122 
123 static ARMword softvectorcode[] =
124 {
125   /* Installed instructions:
126        swi    tidyexception + event;
127        mov    lr, pc;
128        ldmia  fp, {fp, pc};
129        swi    generateexception  + event.  */
130   0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /* Reset */
131   0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /* Undef */
132   0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /* SWI */
133   0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /* Prefetch abort */
134   0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /* Data abort */
135   0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /* Address exception */
136   0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /* IRQ */
137   0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /* FIQ */
138   0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /* Error */
139   0xe1a0f00e			/* Default handler */
140 };
141 
142 /* Time for the Operating System to initialise itself.  */
143 
144 unsigned
145 ARMul_OSInit (ARMul_State * state)
146 {
147 #ifndef NOOS
148 #ifndef VALIDATE
149   ARMword instr, i, j;
150   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
151 
152   if (state->OSptr == NULL)
153     {
154       state->OSptr = (unsigned char *) malloc (sizeof (struct OSblock));
155       if (state->OSptr == NULL)
156 	{
157 	  perror ("OS Memory");
158 	  exit (15);
159 	}
160     }
161 
162   OSptr = (struct OSblock *) state->OSptr;
163   OSptr->ErrorP = 0;
164   state->Reg[13] = ADDRSUPERSTACK;			/* Set up a stack for the current mode...  */
165   ARMul_SetReg (state, SVC32MODE,   13, ADDRSUPERSTACK);/* ...and for supervisor mode...  */
166   ARMul_SetReg (state, ABORT32MODE, 13, ADDRSUPERSTACK);/* ...and for abort 32 mode...  */
167   ARMul_SetReg (state, UNDEF32MODE, 13, ADDRSUPERSTACK);/* ...and for undef 32 mode...  */
168   ARMul_SetReg (state, SYSTEMMODE,  13, ADDRSUPERSTACK);/* ...and for system mode.  */
169   instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8);		/* Load pc from soft vector */
170 
171   for (i = ARMul_ResetV; i <= ARMFIQV; i += 4)
172     /* Write hardware vectors.  */
173     ARMul_WriteWord (state, i, instr);
174 
175   SWI_vector_installed = 0;
176 
177   for (i = ARMul_ResetV; i <= ARMFIQV + 4; i += 4)
178     {
179       ARMul_WriteWord (state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
180       ARMul_WriteWord (state, ADDRSOFHANDLERS + 2 * i + 4L,
181 		       SOFTVECTORCODE + sizeof (softvectorcode) - 4L);
182     }
183 
184   for (i = 0; i < sizeof (softvectorcode); i += 4)
185     ARMul_WriteWord (state, SOFTVECTORCODE + i, softvectorcode[i / 4]);
186 
187   for (i = 0; i < FOPEN_MAX; i++)
188     OSptr->FileTable[i] = NULL;
189 
190   for (i = 0; i < UNIQUETEMPS; i++)
191     OSptr->tempnames[i] = NULL;
192 
193   ARMul_ConsolePrint (state, ", Demon 1.01");
194 
195 /* #ifndef ASIM */
196 
197   /* Install FPE.  */
198   for (i = 0; i < fpesize; i += 4)
199     /* Copy the code.  */
200     ARMul_WriteWord (state, FPESTART + i, fpecode[i >> 2]);
201 
202   /* Scan backwards from the end of the code.  */
203   for (i = FPESTART + fpesize;; i -= 4)
204     {
205       /* When we reach the marker value, break out of
206 	 the loop, leaving i pointing at the maker.  */
207       if ((j = ARMul_ReadWord (state, i)) == 0xffffffff)
208 	break;
209 
210       /* If necessary, reverse the error strings.  */
211       if (state->bigendSig && j < 0x80000000)
212 	{
213 	  /* It's part of the string so swap it.  */
214 	  j = ((j >> 0x18) & 0x000000ff) |
215 	    ((j >> 0x08) & 0x0000ff00) |
216 	    ((j << 0x08) & 0x00ff0000) | ((j << 0x18) & 0xff000000);
217 	  ARMul_WriteWord (state, i, j);
218 	}
219     }
220 
221   /* Copy old illegal instr vector.  */
222   ARMul_WriteWord (state, FPEOLDVECT, ARMul_ReadWord (state, ARMUndefinedInstrV));
223   /* Install new vector.  */
224   ARMul_WriteWord (state, ARMUndefinedInstrV, FPENEWVECT (ARMul_ReadWord (state, i - 4)));
225   ARMul_ConsolePrint (state, ", FPE");
226 
227 /* #endif  ASIM */
228 #endif /* VALIDATE */
229 #endif /* NOOS */
230 
231   /* Intel do not want DEMON SWI support.  */
232    if (state->is_XScale)
233     swi_mask = SWI_MASK_ANGEL;
234 
235    return TRUE;
236 }
237 
238 void
239 ARMul_OSExit (ARMul_State * state)
240 {
241   free ((char *) state->OSptr);
242 }
243 
244 
245 /* Return the last Operating System Error.  */
246 
247 ARMword ARMul_OSLastErrorP (ARMul_State * state)
248 {
249   return ((struct OSblock *) state->OSptr)->ErrorP;
250 }
251 
252 static int translate_open_mode[] =
253 {
254   TARGET_O_RDONLY,		/* "r"   */
255   TARGET_O_RDONLY + TARGET_O_BINARY,	/* "rb"  */
256   TARGET_O_RDWR,		/* "r+"  */
257   TARGET_O_RDWR + TARGET_O_BINARY,		/* "r+b" */
258   TARGET_O_WRONLY + TARGET_O_CREAT + TARGET_O_TRUNC,	/* "w"   */
259   TARGET_O_WRONLY + TARGET_O_BINARY + TARGET_O_CREAT + TARGET_O_TRUNC,	/* "wb"  */
260   TARGET_O_RDWR + TARGET_O_CREAT + TARGET_O_TRUNC,	/* "w+"  */
261   TARGET_O_RDWR + TARGET_O_BINARY + TARGET_O_CREAT + TARGET_O_TRUNC,	/* "w+b" */
262   TARGET_O_WRONLY + TARGET_O_APPEND + TARGET_O_CREAT,	/* "a"   */
263   TARGET_O_WRONLY + TARGET_O_BINARY + TARGET_O_APPEND + TARGET_O_CREAT,	/* "ab"  */
264   TARGET_O_RDWR + TARGET_O_APPEND + TARGET_O_CREAT,	/* "a+"  */
265   TARGET_O_RDWR + TARGET_O_BINARY + TARGET_O_APPEND + TARGET_O_CREAT	/* "a+b" */
266 };
267 
268 static void
269 SWIWrite0 (ARMul_State * state, ARMword addr)
270 {
271   ARMword temp;
272   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
273 
274   while ((temp = ARMul_SafeReadByte (state, addr++)) != 0)
275     {
276       char buffer = temp;
277       /* Note - we cannot just cast 'temp' to a (char *) here,
278 	 since on a big-endian host the byte value will end
279 	 up in the wrong place and a nul character will be printed.  */
280       (void) sim_callback->write_stdout (sim_callback, & buffer, 1);
281     }
282 
283   OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
284 }
285 
286 static void
287 WriteCommandLineTo (ARMul_State * state, ARMword addr)
288 {
289   ARMword temp;
290   char *cptr = state->CommandLine;
291 
292   if (cptr == NULL)
293     cptr = "\0";
294   do
295     {
296       temp = (ARMword) * cptr++;
297       ARMul_SafeWriteByte (state, addr++, temp);
298     }
299   while (temp != 0);
300 }
301 
302 static int
303 ReadFileName (ARMul_State * state, char *buf, ARMword src, size_t n)
304 {
305   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
306   char *p = buf;
307 
308   while (n--)
309     if ((*p++ = ARMul_SafeReadByte (state, src++)) == '\0')
310       return 0;
311   OSptr->ErrorNo = cb_host_to_target_errno (sim_callback, ENAMETOOLONG);
312   state->Reg[0] = -1;
313   return -1;
314 }
315 
316 static void
317 SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
318 {
319   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
320   char buf[PATH_MAX];
321   int flags;
322 
323   if (ReadFileName (state, buf, name, sizeof buf) == -1)
324     return;
325 
326   /* Now we need to decode the Demon open mode.  */
327   flags = translate_open_mode[SWIflags];
328 
329   /* Filename ":tt" is special: it denotes stdin/out.  */
330   if (strcmp (buf, ":tt") == 0)
331     {
332       if (flags == TARGET_O_RDONLY) /* opening tty "r" */
333 	state->Reg[0] = 0;	/* stdin */
334       else
335 	state->Reg[0] = 1;	/* stdout */
336     }
337   else
338     {
339       state->Reg[0] = sim_callback->open (sim_callback, buf, flags);
340       OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
341     }
342 }
343 
344 static void
345 SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
346 {
347   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
348   int res;
349   int i;
350   char *local = malloc (len);
351 
352   if (local == NULL)
353     {
354       sim_callback->printf_filtered
355 	(sim_callback,
356 	 "sim: Unable to read 0x%ulx bytes - out of memory\n",
357 	 len);
358       return;
359     }
360 
361   res = sim_callback->read (sim_callback, f, local, len);
362   if (res > 0)
363     for (i = 0; i < res; i++)
364       ARMul_SafeWriteByte (state, ptr + i, local[i]);
365 
366   free (local);
367   state->Reg[0] = res == -1 ? -1 : len - res;
368   OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
369 }
370 
371 static void
372 SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
373 {
374   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
375   int res;
376   ARMword i;
377   char *local = malloc (len);
378 
379   if (local == NULL)
380     {
381       sim_callback->printf_filtered
382 	(sim_callback,
383 	 "sim: Unable to write 0x%lx bytes - out of memory\n",
384 	 (long) len);
385       return;
386     }
387 
388   for (i = 0; i < len; i++)
389     local[i] = ARMul_SafeReadByte (state, ptr + i);
390 
391   res = sim_callback->write (sim_callback, f, local, len);
392   state->Reg[0] = res == -1 ? -1 : len - res;
393   free (local);
394 
395   OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
396 }
397 
398 static void
399 SWIflen (ARMul_State * state, ARMword fh)
400 {
401   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
402   ARMword addr;
403 
404   if (fh > FOPEN_MAX)
405     {
406       OSptr->ErrorNo = EBADF;
407       state->Reg[0] = -1L;
408       return;
409     }
410 
411   addr = sim_callback->lseek (sim_callback, fh, 0, SEEK_CUR);
412 
413   state->Reg[0] = sim_callback->lseek (sim_callback, fh, 0L, SEEK_END);
414   (void) sim_callback->lseek (sim_callback, fh, addr, SEEK_SET);
415 
416   OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
417 }
418 
419 static void
420 SWIremove (ARMul_State * state, ARMword path)
421 {
422   char buf[PATH_MAX];
423 
424   if (ReadFileName (state, buf, path, sizeof buf) != -1)
425     {
426       struct OSblock *OSptr = (struct OSblock *) state->OSptr;
427       state->Reg[0] = sim_callback->unlink (sim_callback, buf);
428       OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
429     }
430 }
431 
432 static void
433 SWIrename (ARMul_State * state, ARMword old, ARMword new)
434 {
435   char oldbuf[PATH_MAX], newbuf[PATH_MAX];
436 
437   if (ReadFileName (state, oldbuf, old, sizeof oldbuf) != -1
438       && ReadFileName (state, newbuf, new, sizeof newbuf) != -1)
439     {
440       struct OSblock *OSptr = (struct OSblock *) state->OSptr;
441       state->Reg[0] = sim_callback->rename (sim_callback, oldbuf, newbuf);
442       OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
443     }
444 }
445 
446 /* The emulator calls this routine when a SWI instruction is encuntered.
447    The parameter passed is the SWI number (lower 24 bits of the instruction).  */
448 
449 unsigned
450 ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
451 {
452   struct OSblock * OSptr = (struct OSblock *) state->OSptr;
453   int              unhandled = FALSE;
454 
455   switch (number)
456     {
457     case SWI_Read:
458       if (swi_mask & SWI_MASK_DEMON)
459 	SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
460       else
461 	unhandled = TRUE;
462       break;
463 
464     case SWI_Write:
465       if (swi_mask & SWI_MASK_DEMON)
466 	SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
467       else
468 	unhandled = TRUE;
469       break;
470 
471     case SWI_Open:
472       if (swi_mask & SWI_MASK_DEMON)
473 	SWIopen (state, state->Reg[0], state->Reg[1]);
474       else
475 	unhandled = TRUE;
476       break;
477 
478     case SWI_Clock:
479       if (swi_mask & SWI_MASK_DEMON)
480 	{
481 	  /* Return number of centi-seconds.  */
482 	  state->Reg[0] =
483 #ifdef CLOCKS_PER_SEC
484 	    (CLOCKS_PER_SEC >= 100)
485 	    ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
486 	    : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
487 #else
488 	  /* Presume unix... clock() returns microseconds.  */
489 	  (ARMword) (clock () / 10000);
490 #endif
491 	  OSptr->ErrorNo = errno;
492 	}
493       else
494 	unhandled = TRUE;
495       break;
496 
497     case SWI_Time:
498       if (swi_mask & SWI_MASK_DEMON)
499 	{
500 	  state->Reg[0] = (ARMword) sim_callback->time (sim_callback, NULL);
501 	  OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
502 	}
503       else
504 	unhandled = TRUE;
505       break;
506 
507     case SWI_Close:
508       if (swi_mask & SWI_MASK_DEMON)
509 	{
510 	  state->Reg[0] = sim_callback->close (sim_callback, state->Reg[0]);
511 	  OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
512 	}
513       else
514 	unhandled = TRUE;
515       break;
516 
517     case SWI_Flen:
518       if (swi_mask & SWI_MASK_DEMON)
519 	SWIflen (state, state->Reg[0]);
520       else
521 	unhandled = TRUE;
522       break;
523 
524     case SWI_Exit:
525       if (swi_mask & SWI_MASK_DEMON)
526 	state->Emulate = FALSE;
527       else
528 	unhandled = TRUE;
529       break;
530 
531     case SWI_Seek:
532       if (swi_mask & SWI_MASK_DEMON)
533 	{
534 	  /* We must return non-zero for failure.  */
535 	  state->Reg[0] = -1 >= sim_callback->lseek (sim_callback, state->Reg[0], state->Reg[1], SEEK_SET);
536 	  OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
537 	}
538       else
539 	unhandled = TRUE;
540       break;
541 
542     case SWI_WriteC:
543       if (swi_mask & SWI_MASK_DEMON)
544 	{
545 	  char tmp = state->Reg[0];
546 	  (void) sim_callback->write_stdout (sim_callback, &tmp, 1);
547 	  OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
548 	}
549       else
550 	unhandled = TRUE;
551       break;
552 
553     case SWI_Write0:
554       if (swi_mask & SWI_MASK_DEMON)
555 	SWIWrite0 (state, state->Reg[0]);
556       else
557 	unhandled = TRUE;
558       break;
559 
560     case SWI_GetErrno:
561       if (swi_mask & SWI_MASK_DEMON)
562 	state->Reg[0] = OSptr->ErrorNo;
563       else
564 	unhandled = TRUE;
565       break;
566 
567     case SWI_GetEnv:
568       if (swi_mask & SWI_MASK_DEMON)
569 	{
570 	  state->Reg[0] = ADDRCMDLINE;
571 	  if (state->MemSize)
572 	    state->Reg[1] = state->MemSize;
573 	  else
574 	    state->Reg[1] = ADDRUSERSTACK;
575 
576 	  WriteCommandLineTo (state, state->Reg[0]);
577 	}
578       else
579 	unhandled = TRUE;
580       break;
581 
582     case SWI_Breakpoint:
583       state->EndCondition = RDIError_BreakpointReached;
584       state->Emulate = FALSE;
585       break;
586 
587     case SWI_Remove:
588       if (swi_mask & SWI_MASK_DEMON)
589 	SWIremove (state, state->Reg[0]);
590       else
591 	unhandled = TRUE;
592       break;
593 
594     case SWI_Rename:
595       if (swi_mask & SWI_MASK_DEMON)
596 	SWIrename (state, state->Reg[0], state->Reg[1]);
597       else
598 	unhandled = TRUE;
599       break;
600 
601     case SWI_IsTTY:
602       if (swi_mask & SWI_MASK_DEMON)
603 	{
604 	  state->Reg[0] = sim_callback->isatty (sim_callback, state->Reg[0]);
605 	  OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
606 	}
607       else
608 	unhandled = TRUE;
609       break;
610 
611       /* Handle Angel SWIs as well as Demon ones.  */
612     case AngelSWI_ARM:
613     case AngelSWI_Thumb:
614       if (swi_mask & SWI_MASK_ANGEL)
615 	{
616 	  ARMword addr;
617 	  ARMword temp;
618 
619 	  /* R1 is almost always a parameter block.  */
620 	  addr = state->Reg[1];
621 	  /* R0 is a reason code.  */
622 	  switch (state->Reg[0])
623 	    {
624 	    case -1:
625 	      /* This can happen when a SWI is interrupted (eg receiving a
626 		 ctrl-C whilst processing SWIRead()).  The SWI will complete
627 		 returning -1 in r0 to the caller.  If GDB is then used to
628 		 resume the system call the reason code will now be -1.  */
629 	      return TRUE;
630 
631 	      /* Unimplemented reason codes.  */
632 	    case AngelSWI_Reason_ReadC:
633 	    case AngelSWI_Reason_TmpNam:
634 	    case AngelSWI_Reason_System:
635 	    case AngelSWI_Reason_EnterSVC:
636 	    default:
637 	      state->Emulate = FALSE;
638 	      return FALSE;
639 
640 	    case AngelSWI_Reason_Clock:
641 	      /* Return number of centi-seconds.  */
642 	      state->Reg[0] =
643 #ifdef CLOCKS_PER_SEC
644 		(CLOCKS_PER_SEC >= 100)
645 		? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
646 		: (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
647 #else
648 	      /* Presume unix... clock() returns microseconds.  */
649 	      (ARMword) (clock () / 10000);
650 #endif
651 	      OSptr->ErrorNo = errno;
652 	      break;
653 
654 	    case AngelSWI_Reason_Time:
655 	      state->Reg[0] = (ARMword) sim_callback->time (sim_callback, NULL);
656 	      OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
657 	      break;
658 
659 	    case AngelSWI_Reason_WriteC:
660 	      {
661 		char tmp = ARMul_SafeReadByte (state, addr);
662 		(void) sim_callback->write_stdout (sim_callback, &tmp, 1);
663 		OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
664 		break;
665 	      }
666 
667 	    case AngelSWI_Reason_Write0:
668 	      SWIWrite0 (state, addr);
669 	      break;
670 
671 	    case AngelSWI_Reason_Close:
672 	      state->Reg[0] = sim_callback->close (sim_callback, ARMul_ReadWord (state, addr));
673 	      OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
674 	      break;
675 
676 	    case AngelSWI_Reason_Seek:
677 	      state->Reg[0] = -1 >= sim_callback->lseek (sim_callback, ARMul_ReadWord (state, addr),
678 							 ARMul_ReadWord (state, addr + 4),
679 							 SEEK_SET);
680 	      OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
681 	      break;
682 
683 	    case AngelSWI_Reason_FLen:
684 	      SWIflen (state, ARMul_ReadWord (state, addr));
685 	      break;
686 
687 	    case AngelSWI_Reason_GetCmdLine:
688 	      WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
689 	      break;
690 
691 	    case AngelSWI_Reason_HeapInfo:
692 	      /* R1 is a pointer to a pointer.  */
693 	      addr = ARMul_ReadWord (state, addr);
694 
695 	      /* Pick up the right memory limit.  */
696 	      if (state->MemSize)
697 		temp = state->MemSize;
698 	      else
699 		temp = ADDRUSERSTACK;
700 
701 	      ARMul_WriteWord (state, addr, 0);		/* Heap base.  */
702 	      ARMul_WriteWord (state, addr + 4, temp);	/* Heap limit.  */
703 	      ARMul_WriteWord (state, addr + 8, temp);	/* Stack base.  */
704 	      ARMul_WriteWord (state, addr + 12, temp);	/* Stack limit.  */
705 	      break;
706 
707 	    case AngelSWI_Reason_ReportException:
708 	      if (state->Reg[1] == ADP_Stopped_ApplicationExit)
709 		state->Reg[0] = 0;
710 	      else
711 		state->Reg[0] = -1;
712 	      state->Emulate = FALSE;
713 	      break;
714 
715 	    case ADP_Stopped_ApplicationExit:
716 	      state->Reg[0] = 0;
717 	      state->Emulate = FALSE;
718 	      break;
719 
720 	    case ADP_Stopped_RunTimeError:
721 	      state->Reg[0] = -1;
722 	      state->Emulate = FALSE;
723 	      break;
724 
725 	    case AngelSWI_Reason_Errno:
726 	      state->Reg[0] = OSptr->ErrorNo;
727 	      break;
728 
729 	    case AngelSWI_Reason_Open:
730 	      SWIopen (state,
731 		       ARMul_ReadWord (state, addr),
732 		       ARMul_ReadWord (state, addr + 4));
733 	      break;
734 
735 	    case AngelSWI_Reason_Read:
736 	      SWIread (state,
737 		       ARMul_ReadWord (state, addr),
738 		       ARMul_ReadWord (state, addr + 4),
739 		       ARMul_ReadWord (state, addr + 8));
740 	      break;
741 
742 	    case AngelSWI_Reason_Write:
743 	      SWIwrite (state,
744 			ARMul_ReadWord (state, addr),
745 			ARMul_ReadWord (state, addr + 4),
746 			ARMul_ReadWord (state, addr + 8));
747 	      break;
748 
749 	    case AngelSWI_Reason_IsTTY:
750 	      state->Reg[0] = sim_callback->isatty (sim_callback,
751 						    ARMul_ReadWord (state, addr));
752 	      OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
753 	      break;
754 
755 	    case AngelSWI_Reason_Remove:
756 	      SWIremove (state,
757 			 ARMul_ReadWord (state, addr));
758 
759 	    case AngelSWI_Reason_Rename:
760 	      SWIrename (state,
761 			 ARMul_ReadWord (state, addr),
762 			 ARMul_ReadWord (state, addr + 4));
763 	    }
764 	}
765       else
766 	unhandled = TRUE;
767       break;
768 
769       /* The following SWIs are generated by the softvectorcode[]
770 	 installed by default by the simulator.  */
771     case 0x91: /* Undefined Instruction.  */
772       {
773 	ARMword addr = state->RegBank[UNDEFBANK][14] - 4;
774 
775 	sim_callback->printf_filtered
776 	  (sim_callback, "sim: exception: Unhandled Instruction '0x%08x' at 0x%08x.  Stopping.\n",
777 	   ARMul_ReadWord (state, addr), addr);
778 	state->EndCondition = RDIError_SoftwareInterrupt;
779 	state->Emulate = FALSE;
780 	return FALSE;
781       }
782 
783     case 0x90: /* Reset.  */
784     case 0x92: /* SWI.  */
785       /* These two can be safely ignored.  */
786       break;
787 
788     case 0x93: /* Prefetch Abort.  */
789     case 0x94: /* Data Abort.  */
790     case 0x95: /* Address Exception.  */
791     case 0x96: /* IRQ.  */
792     case 0x97: /* FIQ.  */
793     case 0x98: /* Error.  */
794       unhandled = TRUE;
795       break;
796 
797     case -1:
798       /* This can happen when a SWI is interrupted (eg receiving a
799 	 ctrl-C whilst processing SWIRead()).  The SWI will complete
800 	 returning -1 in r0 to the caller.  If GDB is then used to
801 	 resume the system call the reason code will now be -1.  */
802       return TRUE;
803 
804     case 0x180001: /* RedBoot's Syscall SWI in ARM mode.  */
805       if (swi_mask & SWI_MASK_REDBOOT)
806 	{
807 	  switch (state->Reg[0])
808 	    {
809 	      /* These numbers are defined in libgloss/syscall.h
810 		 but the simulator should not be dependend upon
811 		 libgloss being installed.  */
812 	    case 1:  /* Exit.  */
813 	      state->Emulate = FALSE;
814 	      /* Copy exit code into r0.  */
815 	      state->Reg[0] = state->Reg[1];
816 	      break;
817 
818 	    case 2:  /* Open.  */
819 	      SWIopen (state, state->Reg[1], state->Reg[2]);
820 	      break;
821 
822 	    case 3:  /* Close.  */
823 	      state->Reg[0] = sim_callback->close (sim_callback, state->Reg[1]);
824 	      OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
825 	      break;
826 
827 	    case 4:  /* Read.  */
828 	      SWIread (state, state->Reg[1], state->Reg[2], state->Reg[3]);
829 	      break;
830 
831 	    case 5:  /* Write.  */
832 	      SWIwrite (state, state->Reg[1], state->Reg[2], state->Reg[3]);
833 	      break;
834 
835 	    case 6:  /* Lseek.  */
836 	      state->Reg[0] = sim_callback->lseek (sim_callback,
837 						   state->Reg[1],
838 						   state->Reg[2],
839 						   state->Reg[3]);
840 	      OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
841 	      break;
842 
843 	    case 17: /* Utime.  */
844 	      state->Reg[0] = (ARMword) sim_callback->time (sim_callback,
845 							    (long *) state->Reg[1]);
846 	      OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
847 	      break;
848 
849 	    case 7:  /* Unlink.  */
850 	    case 8:  /* Getpid.  */
851 	    case 9:  /* Kill.  */
852 	    case 10: /* Fstat.  */
853 	    case 11: /* Sbrk.  */
854 	    case 12: /* Argvlen.  */
855 	    case 13: /* Argv.  */
856 	    case 14: /* ChDir.  */
857 	    case 15: /* Stat.  */
858 	    case 16: /* Chmod.  */
859 	    case 18: /* Time.  */
860 	      sim_callback->printf_filtered
861 		(sim_callback,
862 		 "sim: unhandled RedBoot syscall `%d' encountered - "
863 		 "returning ENOSYS\n",
864 		 state->Reg[0]);
865 	      state->Reg[0] = -1;
866 	      OSptr->ErrorNo = cb_host_to_target_errno
867 		(sim_callback, ENOSYS);
868 	      break;
869 	    case 1001: /* Meminfo. */
870 	      {
871 		ARMword totmem = state->Reg[1],
872 			topmem = state->Reg[2];
873 		ARMword stack = state->MemSize > 0
874 		  ? state->MemSize : ADDRUSERSTACK;
875 		if (totmem != 0)
876 		  ARMul_WriteWord (state, totmem, stack);
877 		if (topmem != 0)
878 		  ARMul_WriteWord (state, topmem, stack);
879 		state->Reg[0] = 0;
880 		break;
881 	      }
882 
883 	    default:
884 	      sim_callback->printf_filtered
885 		(sim_callback,
886 		 "sim: unknown RedBoot syscall '%d' encountered - ignoring\n",
887 		 state->Reg[0]);
888 	      return FALSE;
889 	    }
890 	  break;
891 	}
892 
893     default:
894       unhandled = TRUE;
895     }
896 
897   if (unhandled)
898     {
899       if (SWI_vector_installed)
900 	{
901 	  ARMword cpsr;
902 	  ARMword i_size;
903 
904 	  cpsr = ARMul_GetCPSR (state);
905 	  i_size = INSN_SIZE;
906 
907 	  ARMul_SetSPSR (state, SVC32MODE, cpsr);
908 
909 	  cpsr &= ~0xbf;
910 	  cpsr |= SVC32MODE | 0x80;
911 	  ARMul_SetCPSR (state, cpsr);
912 
913 	  state->RegBank[SVCBANK][14] = state->Reg[14] = state->Reg[15] - i_size;
914 	  state->NextInstr            = RESUME;
915 	  state->Reg[15]              = state->pc = ARMSWIV;
916 	  FLUSHPIPE;
917 	}
918       else
919 	{
920 	  sim_callback->printf_filtered
921 	    (sim_callback,
922 	     "sim: unknown SWI encountered - %x - ignoring\n",
923 	     number);
924 	  return FALSE;
925 	}
926     }
927 
928   return TRUE;
929 }
930 
931 #ifndef NOOS
932 #ifndef ASIM
933 
934 /* The emulator calls this routine when an Exception occurs.  The second
935    parameter is the address of the relevant exception vector.  Returning
936    FALSE from this routine causes the trap to be taken, TRUE causes it to
937    be ignored (so set state->Emulate to FALSE!).  */
938 
939 unsigned
940 ARMul_OSException (ARMul_State * state  ATTRIBUTE_UNUSED,
941 		   ARMword       vector ATTRIBUTE_UNUSED,
942 		   ARMword       pc     ATTRIBUTE_UNUSED)
943 {
944   return FALSE;
945 }
946 
947 #endif
948 #endif /* NOOS */
949