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
43extern 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"
75extern host_callback *sim_callback;
76
77extern unsigned ARMul_OSInit       (ARMul_State *);
78extern void     ARMul_OSExit       (ARMul_State *);
79extern unsigned ARMul_OSHandleSWI  (ARMul_State *, ARMword);
80extern unsigned ARMul_OSException  (ARMul_State *, ARMword, ARMword);
81extern ARMword  ARMul_OSLastErrorP (ARMul_State *);
82extern 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
95struct 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.  */
120unsigned int swi_mask = -1;
121
122
123static 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
144unsigned
145ARMul_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
238void
239ARMul_OSExit (ARMul_State * state)
240{
241  free ((char *) state->OSptr);
242}
243
244
245/* Return the last Operating System Error.  */
246
247ARMword ARMul_OSLastErrorP (ARMul_State * state)
248{
249  return ((struct OSblock *) state->OSptr)->ErrorP;
250}
251
252static 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
268static void
269SWIWrite0 (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
286static void
287WriteCommandLineTo (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
302static int
303ReadFileName (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
316static void
317SWIopen (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
344static void
345SWIread (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
371static void
372SWIwrite (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
398static void
399SWIflen (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
419static void
420SWIremove (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
432static void
433SWIrename (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
449unsigned
450ARMul_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
939unsigned
940ARMul_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 */
949