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