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