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