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