Mon Jun 1 17:14:19 1998 Anthony Thompson (athompso@cambridge.arm.com)
authorJason Molenda <jmolenda@apple.com>
Tue, 2 Jun 1998 00:18:31 +0000 (00:18 +0000)
committerJason Molenda <jmolenda@apple.com>
Tue, 2 Jun 1998 00:18:31 +0000 (00:18 +0000)
        * armos.c (ARMul_OSHandleSWI::SWI_Open): Handle special case
        of ":tt" to catch stdin in addition to stdout.
        (ARMul_OSHandleSWI::SWI_Seek): Return 0 or 1 to indicate failure
        or success of lseek().

From PR 15839, modified a bit by me to appease my sense of style--but
not too much because I am lazy.

sim/arm/ChangeLog
sim/arm/armos.c [new file with mode: 0644]

index 2524d253dc935c782a6f90a857d1901eb1540314..e73d7f21c96e12c5364acc52b0cb828abab24e07 100644 (file)
@@ -1,3 +1,22 @@
+Mon Jun  1 17:14:19 1998  Anthony Thompson (athompso@cambridge.arm.com)
+
+       * armos.c (ARMul_OSHandleSWI::SWI_Open): Handle special case
+       of ":tt" to catch stdin in addition to stdout.
+       (ARMul_OSHandleSWI::SWI_Seek): Return 0 or 1 to indicate failure
+       or success of lseek().
+
+Wed May 20 17:36:25 1998  Nick Clifton  <nickc@cygnus.com>
+
+       * armos.c (ARMul_OSHandleSWI): Special case code to catch attempts
+       to open stdout.
+
+Wed Apr 29 15:29:55 1998  Jeff Johnston  <jjohnstn@cygnus.com>
+
+       * armos.c (ARMul_OSHandleSWI): Added code for SWI_Clock,
+       SWI_Flen, and SWI_Time.  Also fixed SWI_Seek code to only
+       seek from offset 0 and not to use R2 for whence since it is
+       not passed as part of the SWI call.
+
 Tue Apr 28 18:33:31 1998  Geoffrey Noer  <noer@cygnus.com>
 
        * configure: Regenerated to track ../common/aclocal.m4 changes.
diff --git a/sim/arm/armos.c b/sim/arm/armos.c
new file mode 100644 (file)
index 0000000..4eb672d
--- /dev/null
@@ -0,0 +1,961 @@
+/*  armos.c -- ARMulator OS interface:  ARM6 Instruction Emulator.
+    Copyright (C) 1994 Advanced RISC Machines Ltd.
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This file contains a model of Demon, ARM Ltd's Debug Monitor,
+including all the SWI's required to support the C library. The code in
+it is not really for the faint-hearted (especially the abort handling
+code), but it is a complete example. Defining NOOS will disable all the
+fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI
+0x11 to halt the emulator. */
+
+#include "config.h"
+
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+
+#ifndef O_RDONLY
+#define O_RDONLY 0
+#endif
+#ifndef O_WRONLY
+#define O_WRONLY 1
+#endif
+#ifndef O_RDWR
+#define O_RDWR   2
+#endif
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifdef __STDC__
+#define unlink(s) remove(s)
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>    /* For SEEK_SET etc */
+#endif
+
+#ifdef __riscos
+extern int _fisatty(FILE *);
+#define isatty_(f) _fisatty(f)
+#else
+#ifdef __ZTC__
+#include <io.h>
+#define isatty_(f) isatty((f)->_file)
+#else
+#ifdef macintosh
+#include <ioctl.h>
+#define isatty_(f) (~ioctl((f)->_file,FIOINTERACTIVE,NULL))
+#else
+#define isatty_(f) isatty(fileno(f))
+#endif
+#endif
+#endif
+
+#include "armdefs.h"
+#include "armos.h"
+#ifndef NOOS
+#ifndef VALIDATE
+/* #ifndef ASIM */
+#include "armfpe.h"
+/* #endif */
+#endif
+#endif
+
+/* For RDIError_BreakpointReached.  */
+#include "dbg_rdi.h"
+
+extern unsigned ARMul_OSInit(ARMul_State *state) ;
+extern void ARMul_OSExit(ARMul_State *state) ;
+extern unsigned ARMul_OSHandleSWI(ARMul_State *state,ARMword number) ;
+extern unsigned ARMul_OSException(ARMul_State *state, ARMword vector, ARMword pc) ;
+extern ARMword ARMul_OSLastErrorP(ARMul_State *state) ;
+extern ARMword ARMul_Debug(ARMul_State *state, ARMword pc, ARMword instr) ;
+
+#define BUFFERSIZE 4096
+#ifndef FOPEN_MAX
+#define FOPEN_MAX 64
+#endif
+#define UNIQUETEMPS 256
+
+#ifndef NOOS
+static void UnwindDataAbort(ARMul_State *state, ARMword addr);
+static void getstring(ARMul_State *state, ARMword from, char *to) ;
+#endif
+
+/***************************************************************************\
+*                          OS private Information                           *
+\***************************************************************************/
+
+struct OSblock {
+   ARMword Time0 ;
+   ARMword ErrorP ;
+   ARMword ErrorNo ;
+   FILE *FileTable[FOPEN_MAX] ;
+   char FileFlags[FOPEN_MAX] ;
+   char *tempnames[UNIQUETEMPS] ;
+   } ;
+
+#define NOOP 0
+#define BINARY 1
+#define READOP 2
+#define WRITEOP 4
+
+#ifdef macintosh
+#define FIXCRLF(t,c) ((t & BINARY)?c:((c=='\n'||c=='\r')?(c ^ 7):c))
+#else                   
+#define FIXCRLF(t,c) c 
+#endif
+
+static ARMword softvectorcode[] =
+{   /* basic: swi tidyexception + event; mov pc, lr;
+              ldmia r11,{r11,pc}; swi generateexception + event
+     */
+  0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /*Reset*/
+  0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /*Undef*/
+  0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /*SWI  */
+  0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /*Prefetch abort*/
+  0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /*Data abort*/
+  0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /*Address exception*/
+  0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /*IRQ*/
+  0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /*FIQ*/
+  0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /*Error*/
+  0xe1a0f00e /* default handler */
+};
+
+/***************************************************************************\
+*            Time for the Operating System to initialise itself.            *
+\***************************************************************************/
+
+unsigned ARMul_OSInit(ARMul_State *state)
+{
+#ifndef NOOS
+#ifndef VALIDATE
+ ARMword instr, i , j ;
+ struct OSblock* OSptr = (struct OSblock*)state->OSptr;
+
+ if (state->OSptr == NULL) {
+    state->OSptr = (unsigned char *)malloc(sizeof(struct OSblock));
+    if (state->OSptr == NULL) {
+       perror("OS Memory");
+       exit(15);
+       }
+    }
+ OSptr = (struct OSblock*)state->OSptr;
+ OSptr->ErrorP = 0;
+ state->Reg[13] = ADDRSUPERSTACK;  /* set up a stack for the current mode */
+ ARMul_SetReg(state,SVC32MODE,13,ADDRSUPERSTACK); /* and for supervisor mode */
+ ARMul_SetReg(state,ABORT32MODE,13,ADDRSUPERSTACK); /* and for abort 32 mode */
+ ARMul_SetReg(state,UNDEF32MODE,13,ADDRSUPERSTACK); /* and for undef 32 mode */
+ instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8); /* load pc from soft vector */
+ for (i = ARMul_ResetV ; i <= ARMFIQV ; i += 4)
+    ARMul_WriteWord(state, i, instr);    /* write hardware vectors */
+ for (i = ARMul_ResetV ; i <= ARMFIQV + 4 ; i += 4) {
+    ARMul_WriteWord(state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
+    ARMul_WriteWord(state, ADDRSOFHANDLERS + 2*i + 4L, SOFTVECTORCODE + sizeof(softvectorcode) - 4L);
+    }
+ for (i = 0 ; i < sizeof(softvectorcode) ; i += 4)
+    ARMul_WriteWord(state, SOFTVECTORCODE + i, softvectorcode[i/4]);
+ for (i = 0 ; i < FOPEN_MAX ; i++)
+    OSptr->FileTable[i] = NULL ;
+ for (i = 0 ; i < UNIQUETEMPS ; i++)
+    OSptr->tempnames[i] = NULL ;
+ ARMul_ConsolePrint (state, ", Demon 1.01");
+
+/* #ifndef ASIM */
+
+ /* install fpe */
+ for (i = 0 ; i < fpesize ; i+=4) /* copy the code */
+    ARMul_WriteWord(state,FPESTART + i,fpecode[i >> 2]) ;
+ for (i = FPESTART + fpesize ; ; i-=4) { /* reverse the error strings */
+    if ((j = ARMul_ReadWord(state,i)) == 0xffffffff)
+       break ;
+    if (state->bigendSig && j < 0x80000000) { /* it's part of the string so swap it */
+       j = ((j >> 0x18) & 0x000000ff) |
+           ((j >> 0x08) & 0x0000ff00) |
+           ((j << 0x08) & 0x00ff0000) |
+           ((j << 0x18) & 0xff000000) ;
+       ARMul_WriteWord(state,i,j) ;
+       }
+    }
+ ARMul_WriteWord(state,FPEOLDVECT,ARMul_ReadWord(state,4)) ; /* copy old illegal instr vector */
+ ARMul_WriteWord(state,4,FPENEWVECT(ARMul_ReadWord(state,i-4))) ; /* install new vector */
+ ARMul_ConsolePrint (state, ", FPE") ;
+
+/* #endif /* ASIM */
+#endif /* VALIDATE */
+#endif /* NOOS */
+
+ return(TRUE) ;
+}
+
+void ARMul_OSExit(ARMul_State *state)
+{
+ free((char *)state->OSptr) ;
+}
+
+
+/***************************************************************************\
+*                  Return the last Operating System Error.                  *
+\***************************************************************************/
+
+ARMword ARMul_OSLastErrorP(ARMul_State *state)
+{
+  return ((struct OSblock *)state->OSptr)->ErrorP;
+}
+
+/***************************************************************************\
+* The emulator calls this routine when a SWI instruction is encuntered. The *
+* parameter passed is the SWI number (lower 24 bits of the instruction).    *
+\***************************************************************************/
+
+#if 1
+/* This is the cygnus way of doing it, which makes it simple
+   to do our tests */
+
+
+static int translate_open_mode[] =
+{
+  O_RDONLY,                          /* "r"   */
+  O_RDONLY+O_BINARY,                 /* "rb"  */
+  O_RDWR,                            /* "r+"  */
+  O_RDWR  +O_BINARY,                 /* "r+b" */
+  O_WRONLY         +O_CREAT+O_TRUNC, /* "w"   */
+  O_WRONLY+O_BINARY+O_CREAT+O_TRUNC, /* "wb"  */
+  O_RDWR           +O_CREAT+O_TRUNC, /* "w+"  */
+  O_RDWR  +O_BINARY+O_CREAT+O_TRUNC, /* "w+b" */
+  O_WRONLY         +O_APPEND+O_CREAT,/* "a"   */
+  O_WRONLY+O_BINARY+O_APPEND+O_CREAT,/* "ab"  */
+  O_RDWR           +O_APPEND+O_CREAT,/* "a+"  */
+  O_RDWR  +O_BINARY+O_APPEND+O_CREAT /* "a+b" */
+};
+
+unsigned ARMul_OSHandleSWI(ARMul_State *state,ARMword number)
+{
+  ARMword addr, temp, fildes ;
+  char buffer[BUFFERSIZE], *cptr ;
+  FILE *fptr ;
+  struct OSblock* OSptr = (struct OSblock*)state->OSptr ;
+
+  switch (number)
+    {
+    case SWI_Read:
+      {
+       int f = state->Reg[0];
+       int ptr = state->Reg[1];
+       int len = state->Reg[2];
+       int res;
+       int i;
+       char *local = malloc (len);
+       res = read (f,local, len);
+       if (res > 0)
+         for (i = 0; i < res; i++) 
+           ARMul_WriteByte(state, ptr + i, local[i]) ;
+       free (local);
+       state->Reg[0] = res == -1 ? -1 : len - res;
+       OSptr->ErrorNo = errno;
+       return TRUE;     
+      }
+
+    case SWI_Write:
+      {
+       int f = state->Reg[0];
+       int ptr = state->Reg[1];
+       int len = state->Reg[2];
+       int res;
+       int i;
+       char *local = malloc (len);
+
+       for (i = 0; i < len; i++) 
+         {
+           local[i] = ARMul_ReadByte(state, ptr + i);
+         }
+       res = write (f, local, len);
+       state->Reg[0] = res == -1 ? -1 : len - res;
+       free (local);
+       OSptr->ErrorNo = errno;
+       return TRUE;     
+      }
+
+    case SWI_Open:
+      {
+       char dummy[2000];
+       int i;
+       for (i = 0; 
+            dummy[i] = ARMul_ReadByte(state, state->Reg[0] + i);
+            i++)
+         ;
+
+        /* Now we need to decode the Demon open mode */
+        flags = translate_open_mode[state->Reg[1]];
+  
+        /* Filename ":tt" is special: it denotes stdin/out */
+        if (strcmp (dummy, ":tt") == 0)
+          {
+            if (flags == O_RDONLY) /* opening tty "r" */
+              state->Reg[0] = 0 /* stdin */ ;
+            else 
+              state->Reg[0] = 1 /* stdout */ ;
+          }
+        else
+          {
+            state->Reg[0] = (int) open (dummy, flags);
+            OSptr->ErrorNo = errno;
+          }
+
+       return TRUE;
+      }
+
+    case SWI_Clock :
+       /* return number of centi-seconds... */
+       state->Reg[0] =
+#ifdef CLOCKS_PER_SEC
+          (CLOCKS_PER_SEC >= 100)
+             ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
+             : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
+#else
+     /* presume unix... clock() returns microseconds */
+          (ARMword) (clock() / 10000) ;
+#endif
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_Time :
+       state->Reg[0] = (ARMword)time(NULL) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+   
+    case SWI_Close:
+      state->Reg[0] = close (state->Reg[0]);
+      OSptr->ErrorNo = errno;
+      return TRUE;
+
+    case SWI_Flen :
+       if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX)
+         {
+           OSptr->ErrorNo = EBADF ;
+           state->Reg[0] = -1L ;
+           return(TRUE) ;
+         }
+       fildes = state->Reg[0];
+       addr = lseek(fildes, 0, SEEK_CUR);
+       if (addr < 0)
+         state->Reg[0] = -1L ;
+       else
+         {
+           state->Reg[0] = lseek(fildes, 0L, SEEK_END);
+           (void)lseek(fildes, addr, SEEK_SET);
+         }
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+
+    case SWI_Exit:
+      state->Emulate = FALSE ;
+      return TRUE;
+
+    case SWI_Seek:
+      {
+       /* We must return non-zero for failure */
+       state->Reg[0] = -1 >= lseek (state->Reg[0],
+                                   state->Reg[1],
+                                   SEEK_SET);
+       OSptr->ErrorNo = errno;
+       return TRUE;
+      }
+
+    case SWI_WriteC :
+      (void)fputc((int)state->Reg[0],stderr) ;
+      OSptr->ErrorNo = errno ;
+      return(TRUE) ;
+
+    case SWI_Write0 :
+      addr = state->Reg[0] ;
+      while ((temp = ARMul_ReadByte(state,addr++)) != 0)
+        (void)fputc((char)temp,stderr) ;
+      OSptr->ErrorNo = errno ;
+      return(TRUE) ;
+
+    case SWI_GetErrno :
+      state->Reg[0] = OSptr->ErrorNo ;
+      return(TRUE) ;
+
+    case SWI_Breakpoint :
+      state->EndCondition = RDIError_BreakpointReached ;
+      state->Emulate = FALSE ;
+      return(TRUE) ;
+
+    case SWI_GetEnv :
+       state->Reg[0] = ADDRCMDLINE ;
+       if (state->MemSize)
+          state->Reg[1] = state->MemSize ;
+       else
+          state->Reg[1] = ADDRUSERSTACK ;
+
+       addr = state->Reg[0] ;
+       cptr = state->CommandLine ;
+       if (cptr == NULL)
+          cptr = "\0" ;
+       do {
+          temp = (ARMword)*cptr++ ;
+          ARMul_WriteByte(state,addr++,temp) ;
+          } while (temp != 0) ;
+       return(TRUE) ;
+
+    default :
+      state->Emulate = FALSE ;      
+      return(FALSE) ;
+    }
+}
+#else
+unsigned ARMul_OSHandleSWI(ARMul_State *state,ARMword number)
+{
+#ifdef NOOS
+ return(FALSE) ;
+#else
+#ifdef VALIDATE
+ switch (number) {
+    case 0x11 :
+       state->Emulate = FALSE ;
+       return(TRUE) ;
+    case 0x01 :
+       if (ARM32BITMODE)
+          ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ;
+       else
+          ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ;
+       return(TRUE) ;
+    default :
+       return(FALSE) ;
+    }
+#else
+ ARMword addr, temp ;
+ char buffer[BUFFERSIZE], *cptr ;
+ FILE *fptr ;
+ struct OSblock* OSptr = (struct OSblock*)state->OSptr ;
+
+ switch (number) {
+    case SWI_WriteC :
+       (void)fputc((int)state->Reg[0],stderr) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_Write0 :
+       addr = state->Reg[0] ;
+       while ((temp = ARMul_ReadByte(state,addr++)) != 0)
+          fputc((char)temp,stderr) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_ReadC :
+       state->Reg[0] = (ARMword)fgetc(stdin) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_CLI :
+       addr = state->Reg[0] ;
+       getstring(state,state->Reg[0],buffer) ;
+       state->Reg[0] = (ARMword)system(buffer) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_GetEnv :
+       state->Reg[0] = ADDRCMDLINE ;
+       if (state->MemSize)
+          state->Reg[1] = state->MemSize ;
+       else
+          state->Reg[1] = ADDRUSERSTACK ;
+
+       addr = state->Reg[0] ;
+       cptr = state->CommandLine ;
+       if (cptr == NULL)
+          cptr = "\0" ;
+       do {
+          temp = (ARMword)*cptr++ ;
+          ARMul_WriteByte(state,addr++,temp) ;
+          } while (temp != 0) ;
+       return(TRUE) ;
+
+    case SWI_Exit :
+#ifdef ASIM
+       simkernel1_abort_run() ;
+#else
+       state->Emulate = FALSE ;
+#endif
+       return(TRUE) ;
+
+    case SWI_EnterOS :
+       if (ARM32BITMODE)
+          ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ;
+       else
+          ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ;
+       return(TRUE) ;
+
+    case SWI_GetErrno :
+       state->Reg[0] = OSptr->ErrorNo ;
+       return(TRUE) ;
+
+    case SWI_Clock :
+       /* return muber of centi-seconds... */
+       state->Reg[0] =
+#ifdef CLOCKS_PER_SEC
+          (CLOCKS_PER_SEC >= 100)
+             ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
+             : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
+#else
+     /* presume unix... clock() returns microseconds */
+          (ARMword) (clock() / 10000) ;
+#endif
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_Time :
+       state->Reg[0] = (ARMword)time(NULL) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_Remove :
+       getstring(state,state->Reg[0],buffer) ;
+       state->Reg[0] = unlink(buffer) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_Rename : {
+       char buffer2[BUFFERSIZE] ;
+
+       getstring(state,state->Reg[0],buffer) ;
+       getstring(state,state->Reg[1],buffer2) ;
+       state->Reg[0] = rename(buffer,buffer2) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+       }
+
+    case SWI_Open : {
+#if 0
+      /* It seems to me that these are in the wrong order
+        sac@cygnus.com, so I've redone it to use the
+        flags instead, with the functionality which was already
+        there -- ahh, perhaps the TRUNC bit is in a different
+        place on the original host ?*/
+       static char* fmode[] = {"r","rb","r+","r+b",
+                               "w","wb","w+","w+b",
+                               "a","ab","a+","a+b",
+                               "r","r","r","r"} /* last 4 are illegal */ ;
+#endif
+
+       unsigned type ;
+
+       type = (unsigned)(state->Reg[1] & 3L) ;
+       getstring(state,state->Reg[0],buffer) ;
+       if (strcmp(buffer,":tt")==0 && (type == O_RDONLY )) /* opening tty "r" */
+          fptr = stdin ;
+       else if (strcmp(buffer,":tt")==0 && (type == O_WRONLY)) /* opening tty "w" */
+          fptr = stderr ;
+       else
+        {
+          switch (type) 
+            {
+            case O_RDONLY:
+              fptr = fopen(buffer,"r") ;
+              break;
+            case O_WRONLY:
+              fptr = fopen(buffer,"w") ;
+              break;
+            case O_RDWR:
+              fptr = fopen(buffer,"rw") ;
+              break;
+            }
+        }
+
+       state->Reg[0] = 0 ;
+       if (fptr != NULL) {
+          for (temp = 0 ; temp < FOPEN_MAX ; temp++)
+             if (OSptr->FileTable[temp] == NULL) {
+                OSptr->FileTable[temp] = fptr ;
+                OSptr->FileFlags[temp] = type & 1 ; /* preserve the binary bit */
+                state->Reg[0] = (ARMword)(temp + 1) ;
+                break ;
+                }
+          if (state->Reg[0] == 0)
+             OSptr->ErrorNo = EMFILE ; /* too many open files */
+          else
+             OSptr->ErrorNo = errno ;
+          }
+       else
+         OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+       }
+
+    case SWI_Close :
+       temp = state->Reg[0] ;
+       if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
+          OSptr->ErrorNo = EBADF ;
+          state->Reg[0] = -1L ;
+          return(TRUE) ;
+          }
+       temp-- ;
+       fptr = OSptr->FileTable[temp] ;
+       if (fptr == stdin || fptr == stderr)
+          state->Reg[0] = 0 ;
+       else
+          state->Reg[0] = fclose(fptr) ;
+       OSptr->FileTable[temp] = NULL ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_Write : {
+       unsigned size, upto, type ;
+       char ch ;
+
+       temp = state->Reg[0] ;
+       if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
+          OSptr->ErrorNo = EBADF ;
+          state->Reg[0] = -1L ;
+          return(TRUE) ;
+          }
+       temp-- ;
+       fptr = OSptr->FileTable[temp] ;
+       type = OSptr->FileFlags[temp] ;
+       addr = state->Reg[1] ;
+       size = (unsigned)state->Reg[2] ;
+
+       if (type & READOP)
+          fseek(fptr,0L,SEEK_CUR) ;
+       OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP ; ;
+       while (size > 0) {
+          if (size >= BUFFERSIZE)
+             upto = BUFFERSIZE ;
+          else
+             upto = size ;
+          for (cptr = buffer ; (cptr - buffer) < upto ; cptr++) {
+             ch = (char)ARMul_ReadByte(state,(ARMword)addr++) ;
+             *cptr = FIXCRLF(type,ch) ;
+             }
+          temp = fwrite(buffer,1,upto,fptr) ;
+          if (temp < upto) {
+             state->Reg[0] = (ARMword)(size - temp) ;
+             OSptr->ErrorNo = errno ;
+             return(TRUE) ;
+             }
+          size -= upto ;
+          }
+       state->Reg[0] = 0 ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+       }
+
+    case SWI_Read : {
+       unsigned size, upto, type ;
+       char ch ;
+
+       temp = state->Reg[0] ;
+       if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
+          OSptr->ErrorNo = EBADF ;
+          state->Reg[0] = -1L ;
+          return(TRUE) ;
+          }
+       temp-- ;
+       fptr = OSptr->FileTable[temp] ;
+       addr = state->Reg[1] ;
+       size = (unsigned)state->Reg[2] ;
+       type = OSptr->FileFlags[temp] ;
+
+       if (type & WRITEOP)
+          fseek(fptr,0L,SEEK_CUR) ;
+       OSptr->FileFlags[temp] = (type & BINARY) | READOP ; ;
+       while (size > 0) {
+          if (isatty_(fptr)) {
+             upto = (size >= BUFFERSIZE)?BUFFERSIZE:size + 1 ;
+             if (fgets(buffer, upto, fptr) != 0)
+               temp = strlen(buffer) ;
+             else
+               temp = 0 ;
+             upto-- ; /* 1 char used for terminating null */
+             }
+          else {
+             upto = (size>=BUFFERSIZE)?BUFFERSIZE:size ;
+             temp = fread(buffer,1,upto,fptr) ;
+             }
+          for (cptr = buffer ; (cptr - buffer) < temp ; cptr++) {
+             ch = *cptr ;
+             ARMul_WriteByte(state,(ARMword)addr++,FIXCRLF(type,ch)) ;
+             }
+          if (temp < upto) {
+             state->Reg[0] = (ARMword)(size - temp) ;
+             OSptr->ErrorNo = errno ;
+             return(TRUE) ;
+             }
+          size -= upto ;
+          }
+       state->Reg[0] = 0 ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+       }
+
+    case SWI_Seek :
+       if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
+           || OSptr->FileTable[state->Reg[0] - 1] == 0) {
+          OSptr->ErrorNo = EBADF ;
+          state->Reg[0] = -1L ;
+          return(TRUE) ;
+          }
+       fptr = OSptr->FileTable[state->Reg[0] - 1] ;
+       state->Reg[0] = fseek(fptr,(long)state->Reg[1],SEEK_SET) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_Flen :
+       if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
+           || OSptr->FileTable[state->Reg[0] - 1] == 0) {
+          OSptr->ErrorNo = EBADF ;
+          state->Reg[0] = -1L ;
+          return(TRUE) ;
+          }
+       fptr = OSptr->FileTable[state->Reg[0] - 1] ;
+       addr = (ARMword)ftell(fptr) ;
+       if (fseek(fptr,0L,SEEK_END) < 0)
+          state->Reg[0] = -1 ;
+       else {
+          state->Reg[0] = (ARMword)ftell(fptr) ;
+          (void)fseek(fptr,addr,SEEK_SET) ;
+          }
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_IsTTY :
+       if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
+           || OSptr->FileTable[state->Reg[0] - 1] == 0) {
+          OSptr->ErrorNo = EBADF ;
+          state->Reg[0] = -1L ;
+          return(TRUE) ;
+          }
+       fptr = OSptr->FileTable[state->Reg[0] - 1] ;
+       state->Reg[0] = isatty_(fptr) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+
+    case SWI_TmpNam :{
+       ARMword size ;
+
+       addr = state->Reg[0] ;
+       temp = state->Reg[1] & 0xff ;
+       size = state->Reg[2] ;
+       if (OSptr->tempnames[temp] == NULL) {
+          if ((OSptr->tempnames[temp] = malloc(L_tmpnam)) == NULL) {
+             state->Reg[0] = 0 ;
+             return(TRUE) ;
+             }
+          (void)tmpnam(OSptr->tempnames[temp]) ;
+          }
+       cptr = OSptr->tempnames[temp] ;
+       if (strlen(cptr) > state->Reg[2])
+          state->Reg[0] = 0 ;
+       else
+          do {
+             ARMul_WriteByte(state,addr++,*cptr) ;
+             } while (*cptr++ != 0) ;
+       OSptr->ErrorNo = errno ;
+       return(TRUE) ;
+       }
+
+    case SWI_InstallHandler:
+       {  ARMword handlerp = ADDRSOFHANDLERS + state->Reg[0] * 8;
+          ARMword oldr1 = ARMul_ReadWord(state, handlerp),
+                  oldr2 = ARMul_ReadWord(state, handlerp + 4);
+          ARMul_WriteWord(state, handlerp, state->Reg[1]);
+          ARMul_WriteWord(state, handlerp + 4, state->Reg[2]);
+          state->Reg[1] = oldr1;
+          state->Reg[2] = oldr2;
+          return(TRUE);
+       }
+
+    case SWI_GenerateError:
+       ARMul_Abort(state, ARMSWIV) ;
+       if (state->Emulate)
+          ARMul_SetR15(state, ARMul_ReadWord(state, ADDRSOFTVECTORS + ARMErrorV));
+       return(TRUE);
+
+/* SWI's 0x9x unwind the state of the CPU after an abort of type x */
+
+    case 0x90: /* Branch through zero */
+       {  ARMword oldpsr = ARMul_GetCPSR(state) ;
+          ARMul_SetCPSR(state, (oldpsr & 0xffffffc0) | 0x13) ;
+          ARMul_SetSPSR(state, SVC32MODE, oldpsr) ;
+          state->Reg[14] = 0;
+          goto TidyCommon;
+       }
+
+    case 0x98: /* Error */
+       {  ARMword errorp = state->Reg[0],
+                  regp = state->Reg[1];
+          unsigned i;
+          ARMword errorpsr = ARMul_ReadWord(state, regp + 16*4);
+          for (i = 0; i < 15; i++)
+            ARMul_SetReg(state,errorpsr,i,ARMul_ReadWord(state, regp + i*4L)) ;
+          state->Reg[14] = ARMul_ReadWord(state, regp + 15*4L);
+          state->Reg[10] = errorp;
+          ARMul_SetSPSR(state,state->Mode,errorpsr) ;
+          OSptr->ErrorP = errorp;
+          goto TidyCommon;
+       }
+
+    case 0x94: /* Data abort */
+       {  ARMword addr = state->Reg[14] - 8;
+          ARMword cpsr = ARMul_GetCPSR(state) ;
+          if (ARM26BITMODE)
+             addr = addr & 0x3fffffc ;
+          ARMul_SetCPSR(state,ARMul_GetSPSR(state,cpsr)) ;
+          UnwindDataAbort(state, addr);
+          if (addr >= FPESTART && addr < FPEEND) { /* in the FPE */
+             ARMword sp, spsr ;
+             unsigned i ;
+
+             sp = state->Reg[13] ;
+             state->Reg[13] += 64 ; /* fix the aborting mode sp */
+             state->Reg[14] = ARMul_ReadWord(state,sp + 60) ; /* and its lr */
+             spsr = ARMul_GetSPSR(state,state->Mode) ;
+             state->Mode = ARMul_SwitchMode(state, state->Mode, spsr);
+             for (i = 0 ; i < 15 ; i++) {
+                ARMul_SetReg(state,spsr,i,ARMul_ReadWord(state,sp)) ;
+                sp += 4 ;
+                }
+             ARMul_SetCPSR(state,cpsr) ;
+             state->Reg[14] = ARMul_ReadWord(state,sp) + 4 ; /* botch it */
+             ARMul_SetSPSR(state,state->Mode,spsr) ;
+             }
+          else
+             ARMul_SetCPSR(state,cpsr) ;
+
+          /* and fall through to correct r14 */
+       }
+    case 0x95: /* Address Exception */
+       state->Reg[14] -= 4;
+    case 0x91: /* Undefined instruction */
+    case 0x92: /* SWI */
+    case 0x93: /* Prefetch abort */
+    case 0x96: /* IRQ */
+    case 0x97: /* FIQ */
+       state->Reg[14] -= 4;
+    TidyCommon:
+       if (state->VectorCatch & (1 << (number - 0x90))) {
+          ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
+          ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ;
+          if (number == 0x90)
+             state->EndCondition = 10 ; /* Branch through Zero Error */
+          else
+             state->EndCondition = (unsigned)number - 0x8f;
+          state->Emulate = FALSE ;
+          }
+       else {
+          ARMword sp = state->Reg[13];
+          ARMul_WriteWord(state, sp - 4, state->Reg[14]);
+          ARMul_WriteWord(state, sp - 8, state->Reg[12]);
+          ARMul_WriteWord(state, sp - 12, state->Reg[11]);
+          ARMul_WriteWord(state, sp - 16, state->Reg[10]);
+          state->Reg[13] = sp - 16;
+          state->Reg[11] = ADDRSOFHANDLERS + 8 * (number - 0x90);
+          }
+       return(TRUE);
+
+/* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */
+
+    case 0x80: case 0x81: case 0x82: case 0x83:
+    case 0x84: case 0x85: case 0x86: case 0x87: case 0x88:
+       {  ARMword sp = state->Reg[13];
+          state->Reg[10] = ARMul_ReadWord(state, sp);
+          state->Reg[11] = ARMul_ReadWord(state, sp + 4);
+          state->Reg[12] = ARMul_ReadWord(state, sp + 8);
+          state->Reg[14] = ARMul_ReadWord(state, sp + 12);
+          state->Reg[13] = sp + 16;
+          ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
+          ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ;
+          if (number == 0x80)
+             state->EndCondition = 10 ; /* Branch through Zero Error */
+          else
+             state->EndCondition = (unsigned)number - 0x7f;
+          state->Emulate = FALSE ;
+          return(TRUE);
+       }
+
+    default :
+          state->Emulate = FALSE ;      
+       return(FALSE) ;
+    }
+#endif
+#endif
+ }
+#endif
+
+#ifndef NOOS
+#ifndef ASIM
+
+/***************************************************************************\
+* The emulator calls this routine when an Exception occurs.  The second     *
+* parameter is the address of the relevant exception vector.  Returning     *
+* FALSE from this routine causes the trap to be taken, TRUE causes it to    *
+* be ignored (so set state->Emulate to FALSE!).                             *
+\***************************************************************************/
+
+unsigned ARMul_OSException(ARMul_State *state, ARMword vector, ARMword pc)
+{ /* don't use this here */
+ return(FALSE) ;
+}
+
+#endif
+
+/***************************************************************************\
+*                            Unwind a data abort                            *
+\***************************************************************************/
+
+static void UnwindDataAbort(ARMul_State *state, ARMword addr)
+{
+  ARMword instr = ARMul_ReadWord(state, addr);
+  ARMword rn = BITS(16, 19);
+  ARMword itype = BITS(24, 27);
+  ARMword offset;
+  if (rn == 15) return;
+  if (itype == 8 || itype == 9) {
+    /* LDM or STM */
+    unsigned long regs = BITS(0, 15);
+    offset = 0;
+    if (!BIT(21)) return; /* no wb */
+    for (; regs != 0; offset++)
+      regs ^= (regs & -regs);
+    if (offset == 0) offset = 16;
+  } else if (itype == 12 ||              /* post-indexed CPDT */
+             (itype == 13 && BIT(21))) { /* pre_indexed CPDT with WB */
+    offset = BITS(0, 7);
+  } else
+    return;
+
+  if (BIT(23))
+    state->Reg[rn] -= offset * 4;
+  else
+    state->Reg[rn] += offset * 4;
+}
+
+/***************************************************************************\
+*           Copy a string from the debuggee's memory to the host's          *
+\***************************************************************************/
+
+static void getstring(ARMul_State *state, ARMword from, char *to)
+{do {
+    *to = (char)ARMul_ReadByte(state,from++) ;
+    } while (*to++ != '\0') ;
+ }
+
+#endif /* NOOS */