OSDN Git Service

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