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