Only perform access checks if 'check' is set.
[external/binutils.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 "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               /* Unimplemented reason codes.  */
557             case AngelSWI_Reason_ReadC:
558             case AngelSWI_Reason_IsTTY:
559             case AngelSWI_Reason_TmpNam:
560             case AngelSWI_Reason_Remove:
561             case AngelSWI_Reason_Rename:
562             case AngelSWI_Reason_System:
563             case AngelSWI_Reason_EnterSVC:
564             default:
565               state->Emulate = FALSE;
566               return FALSE;
567
568             case AngelSWI_Reason_Clock:
569               /* Return number of centi-seconds.  */
570               state->Reg[0] =
571 #ifdef CLOCKS_PER_SEC
572                 (CLOCKS_PER_SEC >= 100)
573                 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
574                 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
575 #else
576               /* Presume unix... clock() returns microseconds.  */
577               (ARMword) (clock () / 10000);
578 #endif
579               OSptr->ErrorNo = errno;
580               break;
581
582             case AngelSWI_Reason_Time:
583               state->Reg[0] = (ARMword) sim_callback->time (sim_callback, NULL);
584               OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
585               break;
586
587             case AngelSWI_Reason_WriteC:
588               {
589                 char tmp = ARMul_SafeReadByte (state, addr);
590                 (void) sim_callback->write_stdout (sim_callback, &tmp, 1);
591                 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
592                 break;
593               }
594
595             case AngelSWI_Reason_Write0:
596               SWIWrite0 (state, addr);
597               break;
598
599             case AngelSWI_Reason_Close:
600               state->Reg[0] = sim_callback->close (sim_callback, ARMul_ReadWord (state, addr));
601               OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
602               break;
603
604             case AngelSWI_Reason_Seek:
605               state->Reg[0] = -1 >= sim_callback->lseek (sim_callback, ARMul_ReadWord (state, addr),
606                                                          ARMul_ReadWord (state, addr + 4),
607                                                          SEEK_SET);
608               OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
609               break;
610
611             case AngelSWI_Reason_FLen:
612               SWIflen (state, ARMul_ReadWord (state, addr));
613               break;
614
615             case AngelSWI_Reason_GetCmdLine:
616               WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
617               break;
618
619             case AngelSWI_Reason_HeapInfo:
620               /* R1 is a pointer to a pointer.  */
621               addr = ARMul_ReadWord (state, addr);
622
623               /* Pick up the right memory limit.  */
624               if (state->MemSize)
625                 temp = state->MemSize;
626               else
627                 temp = ADDRUSERSTACK;
628
629               ARMul_WriteWord (state, addr, 0);         /* Heap base.  */
630               ARMul_WriteWord (state, addr + 4, temp);  /* Heap limit.  */
631               ARMul_WriteWord (state, addr + 8, temp);  /* Stack base.  */
632               ARMul_WriteWord (state, addr + 12, temp); /* Stack limit.  */
633               break;
634
635             case AngelSWI_Reason_ReportException:
636               if (state->Reg[1] == ADP_Stopped_ApplicationExit)
637                 state->Reg[0] = 0;
638               else
639                 state->Reg[0] = -1;
640               state->Emulate = FALSE;
641               break;
642
643             case ADP_Stopped_ApplicationExit:
644               state->Reg[0] = 0;
645               state->Emulate = FALSE;
646               break;
647
648             case ADP_Stopped_RunTimeError:
649               state->Reg[0] = -1;
650               state->Emulate = FALSE;
651               break;
652
653             case AngelSWI_Reason_Errno:
654               state->Reg[0] = OSptr->ErrorNo;
655               break;
656
657             case AngelSWI_Reason_Open:
658               SWIopen (state,
659                        ARMul_ReadWord (state, addr),
660                        ARMul_ReadWord (state, addr + 4));
661               break;
662
663             case AngelSWI_Reason_Read:
664               SWIread (state,
665                        ARMul_ReadWord (state, addr),
666                        ARMul_ReadWord (state, addr + 4),
667                        ARMul_ReadWord (state, addr + 8));
668               break;
669
670             case AngelSWI_Reason_Write:
671               SWIwrite (state,
672                         ARMul_ReadWord (state, addr),
673                         ARMul_ReadWord (state, addr + 4),
674                         ARMul_ReadWord (state, addr + 8));
675               break;
676             }
677         }
678       else
679         unhandled = TRUE;
680       break;
681
682     case 0x90:
683     case 0x91:
684     case 0x92:
685       /* These are used by the FPE code.  */
686       break;
687       
688     case 0x180001: /* RedBoot's Syscall SWI in ARM mode.  */
689       if (swi_mask & SWI_MASK_REDBOOT)
690         {
691           switch (state->Reg[0])
692             {
693               /* These numbers are defined in libgloss/syscall.h
694                  but the simulator should not be dependend upon
695                  libgloss being installed.  */
696             case 1:  /* Exit.  */
697               state->Emulate = FALSE;
698               /* Copy exit code into r0.  */
699               state->Reg[0] = state->Reg[1];
700               break;
701
702             case 2:  /* Open.  */
703               SWIopen (state, state->Reg[1], state->Reg[2]);
704               break;
705
706             case 3:  /* Close.  */
707               state->Reg[0] = sim_callback->close (sim_callback, state->Reg[1]);
708               OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
709               break;
710
711             case 4:  /* Read.  */
712               SWIread (state, state->Reg[1], state->Reg[2], state->Reg[3]);
713               break;
714
715             case 5:  /* Write.  */
716               SWIwrite (state, state->Reg[1], state->Reg[2], state->Reg[3]);
717               break;
718
719             case 6:  /* Lseek.  */
720               state->Reg[0] = sim_callback->lseek (sim_callback,
721                                                    state->Reg[1],
722                                                    state->Reg[2],
723                                                    state->Reg[3]);
724               OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
725               break;
726
727             case 17: /* Utime.  */
728               state->Reg[0] = (ARMword) sim_callback->time (sim_callback,
729                                                             (long *) state->Reg[1]);
730               OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
731               break;
732
733             case 7:  /* Unlink.  */
734             case 8:  /* Getpid.  */
735             case 9:  /* Kill.  */
736             case 10: /* Fstat.  */
737             case 11: /* Sbrk.  */
738             case 12: /* Argvlen.  */
739             case 13: /* Argv.  */
740             case 14: /* ChDir.  */
741             case 15: /* Stat.  */
742             case 16: /* Chmod.  */
743             case 18: /* Time.  */
744               sim_callback->printf_filtered
745                 (sim_callback,
746                  "sim: unhandled RedBoot syscall '%d' encountered - ignoring\n",
747                  state->Reg[0]);
748               return FALSE;
749
750             default:
751               sim_callback->printf_filtered
752                 (sim_callback,
753                  "sim: unknown RedBoot syscall '%d' encountered - ignoring\n",
754                  state->Reg[0]);
755               return FALSE;
756             }
757           break;
758         }
759       
760     default:
761       unhandled = TRUE;
762     }
763       
764   if (unhandled)
765     {
766       if (SWI_vector_installed)
767         {
768           ARMword cpsr;
769           ARMword i_size;
770
771           cpsr = ARMul_GetCPSR (state);
772           i_size = INSN_SIZE;
773
774           ARMul_SetSPSR (state, SVC32MODE, cpsr);
775
776           cpsr &= ~0xbf;
777           cpsr |= SVC32MODE | 0x80;
778           ARMul_SetCPSR (state, cpsr);
779
780           state->RegBank[SVCBANK][14] = state->Reg[14] = state->Reg[15] - i_size;
781           state->NextInstr            = RESUME;
782           state->Reg[15]              = state->pc = ARMSWIV;
783           FLUSHPIPE;
784         }
785       else
786         {
787           sim_callback->printf_filtered
788             (sim_callback,
789              "sim: unknown SWI encountered - %x - ignoring\n",
790              number);
791           return FALSE;
792         }
793     }
794
795   return TRUE;
796 }
797
798 #ifndef NOOS
799 #ifndef ASIM
800
801 /* The emulator calls this routine when an Exception occurs.  The second
802    parameter is the address of the relevant exception vector.  Returning
803    FALSE from this routine causes the trap to be taken, TRUE causes it to
804    be ignored (so set state->Emulate to FALSE!).  */
805
806 unsigned
807 ARMul_OSException (ARMul_State * state  ATTRIBUTE_UNUSED,
808                    ARMword       vector ATTRIBUTE_UNUSED,
809                    ARMword       pc     ATTRIBUTE_UNUSED)
810 {
811   return FALSE;
812 }
813
814 #endif
815 #endif /* NOOS */