unit at a time
[platform/upstream/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 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
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
238 ARMul_OSExit (ARMul_State * state)
239 {
240   free ((char *) state->OSptr);
241 }
242
243
244 /* Return the last Operating System Error.  */
245
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
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
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
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
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
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
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
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
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
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
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
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 */