import gdb-1999-12-06 snapshot
[external/binutils.git] / sim / arm / armos.c
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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
27 #include <time.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <fcntl.h>
31
32 #ifndef O_RDONLY
33 #define O_RDONLY 0
34 #endif
35 #ifndef O_WRONLY
36 #define O_WRONLY 1
37 #endif
38 #ifndef O_RDWR
39 #define O_RDWR   2
40 #endif
41 #ifndef O_BINARY
42 #define O_BINARY 0
43 #endif
44
45 #ifdef __STDC__
46 #define unlink(s) remove(s)
47 #endif
48
49 #ifdef HAVE_UNISTD_H
50 #include <unistd.h>     /* For SEEK_SET etc */
51 #endif
52
53 #ifdef __riscos
54 extern int _fisatty(FILE *);
55 #define isatty_(f) _fisatty(f)
56 #else
57 #ifdef __ZTC__
58 #include <io.h>
59 #define isatty_(f) isatty((f)->_file)
60 #else
61 #ifdef macintosh
62 #include <ioctl.h>
63 #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
64 #else
65 #define isatty_(f) isatty (fileno (f))
66 #endif
67 #endif
68 #endif
69
70 #include "armdefs.h"
71 #include "armos.h"
72 #ifndef NOOS
73 #ifndef VALIDATE
74 /* #ifndef ASIM */
75 #include "armfpe.h"
76 /* #endif */
77 #endif
78 #endif
79
80 /* For RDIError_BreakpointReached.  */
81 #include "dbg_rdi.h"
82
83 extern unsigned ARMul_OSInit(ARMul_State *state) ;
84 extern void ARMul_OSExit(ARMul_State *state) ;
85 extern unsigned ARMul_OSHandleSWI(ARMul_State *state,ARMword number) ;
86 extern unsigned ARMul_OSException(ARMul_State *state, ARMword vector, ARMword pc) ;
87 extern ARMword ARMul_OSLastErrorP(ARMul_State *state) ;
88 extern ARMword ARMul_Debug(ARMul_State *state, ARMword pc, ARMword instr) ;
89
90 #define BUFFERSIZE 4096
91 #ifndef FOPEN_MAX
92 #define FOPEN_MAX 64
93 #endif
94 #define UNIQUETEMPS 256
95
96 #ifndef NOOS
97 static void UnwindDataAbort(ARMul_State *state, ARMword addr);
98 static void getstring(ARMul_State *state, ARMword from, char *to) ;
99 #endif
100
101 /***************************************************************************\
102 *                          OS private Information                           *
103 \***************************************************************************/
104
105 struct OSblock {
106    ARMword Time0 ;
107    ARMword ErrorP ;
108    ARMword ErrorNo ;
109    FILE *FileTable[FOPEN_MAX] ;
110    char FileFlags[FOPEN_MAX] ;
111    char *tempnames[UNIQUETEMPS] ;
112    } ;
113
114 #define NOOP 0
115 #define BINARY 1
116 #define READOP 2
117 #define WRITEOP 4
118
119 #ifdef macintosh
120 #define FIXCRLF(t,c) ((t & BINARY) ? \
121                       c : \
122                       ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \
123                      )
124 #else                   
125 #define FIXCRLF(t,c) c 
126 #endif
127
128 static ARMword softvectorcode[] =
129 {   /* basic: swi tidyexception + event; mov pc, lr;
130               ldmia r11,{r11,pc}; swi generateexception + event
131      */
132   0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /*Reset*/
133   0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /*Undef*/
134   0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /*SWI  */
135   0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /*Prefetch abort*/
136   0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /*Data abort*/
137   0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /*Address exception*/
138   0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /*IRQ*/
139   0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /*FIQ*/
140   0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /*Error*/
141   0xe1a0f00e /* default handler */
142 };
143
144 /***************************************************************************\
145 *            Time for the Operating System to initialise itself.            *
146 \***************************************************************************/
147
148 unsigned 
149 ARMul_OSInit (ARMul_State *state)
150 {
151 #ifndef NOOS
152 #ifndef VALIDATE
153  ARMword instr, i , j ;
154  struct OSblock* OSptr = (struct OSblock*)state->OSptr;
155
156  if (state->OSptr == NULL) {
157     state->OSptr = (unsigned char *)malloc(sizeof(struct OSblock));
158     if (state->OSptr == NULL) {
159        perror("OS Memory");
160        exit(15);
161        }
162     }
163  OSptr = (struct OSblock*)state->OSptr;
164  OSptr->ErrorP = 0;
165  state->Reg[13] = ADDRSUPERSTACK;  /* set up a stack for the current mode */
166  ARMul_SetReg(state,SVC32MODE,13,ADDRSUPERSTACK); /* and for supervisor mode */
167  ARMul_SetReg(state,ABORT32MODE,13,ADDRSUPERSTACK); /* and for abort 32 mode */
168  ARMul_SetReg(state,UNDEF32MODE,13,ADDRSUPERSTACK); /* and for undef 32 mode */
169  instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8); /* load pc from soft vector */
170  for (i = ARMul_ResetV ; i <= ARMFIQV ; i += 4)
171     ARMul_WriteWord(state, i, instr);    /* write hardware vectors */
172  for (i = ARMul_ResetV ; i <= ARMFIQV + 4 ; i += 4) {
173     ARMul_WriteWord(state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
174     ARMul_WriteWord(state, ADDRSOFHANDLERS + 2*i + 4L, SOFTVECTORCODE + sizeof(softvectorcode) - 4L);
175     }
176  for (i = 0 ; i < sizeof(softvectorcode) ; i += 4)
177     ARMul_WriteWord(state, SOFTVECTORCODE + i, softvectorcode[i/4]);
178  for (i = 0 ; i < FOPEN_MAX ; i++)
179     OSptr->FileTable[i] = NULL ;
180  for (i = 0 ; i < UNIQUETEMPS ; i++)
181     OSptr->tempnames[i] = NULL ;
182  ARMul_ConsolePrint (state, ", Demon 1.01");
183
184 /* #ifndef ASIM */
185
186  /* install fpe */
187  for (i = 0 ; i < fpesize ; i+=4) /* copy the code */
188     ARMul_WriteWord(state,FPESTART + i,fpecode[i >> 2]) ;
189  for (i = FPESTART + fpesize ; ; i-=4) { /* reverse the error strings */
190     if ((j = ARMul_ReadWord(state,i)) == 0xffffffff)
191        break ;
192     if (state->bigendSig && j < 0x80000000) { /* it's part of the string so swap it */
193        j = ((j >> 0x18) & 0x000000ff) |
194            ((j >> 0x08) & 0x0000ff00) |
195            ((j << 0x08) & 0x00ff0000) |
196            ((j << 0x18) & 0xff000000) ;
197        ARMul_WriteWord(state,i,j) ;
198        }
199     }
200  ARMul_WriteWord(state,FPEOLDVECT,ARMul_ReadWord(state,4)) ; /* copy old illegal instr vector */
201  ARMul_WriteWord(state,4,FPENEWVECT(ARMul_ReadWord(state,i-4))) ; /* install new vector */
202  ARMul_ConsolePrint (state, ", FPE") ;
203
204 /* #endif /* ASIM */
205 #endif /* VALIDATE */
206 #endif /* NOOS */
207
208  return(TRUE) ;
209 }
210
211 void 
212 ARMul_OSExit (ARMul_State *state)
213 {
214  free((char *)state->OSptr);
215 }
216
217
218 /***************************************************************************\
219 *                  Return the last Operating System Error.                  *
220 \***************************************************************************/
221
222 ARMword 
223 ARMul_OSLastErrorP (ARMul_State *state)
224 {
225   return ((struct OSblock *)state->OSptr)->ErrorP;
226 }
227
228 #if 1  /* CYGNUS LOCAL */
229 /* This is the cygnus way of doing it, which makes it simple to do our tests */
230
231 static int translate_open_mode[] =
232 {
233   O_RDONLY,                          /* "r"   */
234   O_RDONLY+O_BINARY,                 /* "rb"  */
235   O_RDWR,                            /* "r+"  */
236   O_RDWR  +O_BINARY,                 /* "r+b" */
237   O_WRONLY         +O_CREAT+O_TRUNC, /* "w"   */
238   O_WRONLY+O_BINARY+O_CREAT+O_TRUNC, /* "wb"  */
239   O_RDWR           +O_CREAT+O_TRUNC, /* "w+"  */
240   O_RDWR  +O_BINARY+O_CREAT+O_TRUNC, /* "w+b" */
241   O_WRONLY         +O_APPEND+O_CREAT,/* "a"   */
242   O_WRONLY+O_BINARY+O_APPEND+O_CREAT,/* "ab"  */
243   O_RDWR           +O_APPEND+O_CREAT,/* "a+"  */
244   O_RDWR  +O_BINARY+O_APPEND+O_CREAT /* "a+b" */
245 };
246
247 static void 
248 SWIWrite0 (ARMul_State *state, ARMword addr)
249 {
250   ARMword temp;
251   struct OSblock* OSptr = (struct OSblock*) state->OSptr;
252
253   while ((temp = ARMul_ReadByte (state, addr++)) != 0)
254     (void) fputc ((char) temp, stdout);
255
256   OSptr->ErrorNo = errno;
257 }
258
259 static void 
260 WriteCommandLineTo (ARMul_State *state, ARMword addr)
261 {
262   ARMword temp;
263   char *cptr = state->CommandLine;
264   if (cptr == NULL)
265     cptr = "\0";
266   do {
267     temp = (ARMword) *cptr++;
268     ARMul_WriteByte (state, addr++, temp);
269   } while (temp != 0);
270 }
271
272 static void 
273 SWIopen (ARMul_State *state, ARMword name, ARMword SWIflags)
274 {
275   struct OSblock* OSptr = (struct OSblock*)state->OSptr;
276   char dummy[2000];
277   int flags;
278   int i;
279
280   for (i = 0; 
281        dummy[i] = ARMul_ReadByte (state, name + i);
282        i++)
283     ;
284
285   /* Now we need to decode the Demon open mode */
286   flags = translate_open_mode[SWIflags];
287
288   /* Filename ":tt" is special: it denotes stdin/out */
289   if (strcmp (dummy, ":tt") == 0)
290     {
291       if (flags == O_RDONLY) /* opening tty "r" */
292         state->Reg[0] = 0;  /* stdin */
293       else 
294         state->Reg[0] = 1; /* stdout */
295     }
296   else
297     {
298       state->Reg[0] = (int) open (dummy, flags, 0666);
299       OSptr->ErrorNo = errno;
300     }
301 }
302
303 static void 
304 SWIread (ARMul_State *state, ARMword f, ARMword ptr, ARMword len)
305 {
306   struct OSblock* OSptr = (struct OSblock*) state->OSptr;
307   int res;
308   int i;
309   char *local = malloc (len);
310
311   if (local == NULL)
312     {
313       fprintf (stderr, "sim: Unable to read 0x%x bytes - out of memory\n", len);
314       return;
315     }
316   
317   res = read (f, local, len);
318   if (res > 0)
319     for (i = 0; i < res; i++) 
320       ARMul_WriteByte (state, ptr + i, local[i]);
321   free (local);
322   state->Reg[0] = res == -1 ? -1 : len - res;
323   OSptr->ErrorNo = errno;
324 }
325
326 static void 
327 SWIwrite (ARMul_State *state, ARMword f, ARMword ptr, ARMword len)
328 {
329   struct OSblock* OSptr = (struct OSblock*) state->OSptr;
330   int res;
331   int i;
332   char *local = malloc (len);
333
334   if (local == NULL)
335     {
336       fprintf (stderr, "sim: Unable to write 0x%x bytes - out of memory\n", len);
337       return;
338     }
339   
340   for (i = 0; i < len; i++) 
341     local[i] = ARMul_ReadByte (state, ptr + i);
342
343   res = write (f, local, len);
344   state->Reg[0] = res == -1 ? -1 : len - res;
345   free (local);
346   OSptr->ErrorNo = errno;
347 }
348
349 static void 
350 SWIflen (ARMul_State *state, ARMword fh)
351 {
352   struct OSblock* OSptr = (struct OSblock*) state->OSptr;
353   ARMword addr;
354
355   if (fh == 0 || fh > FOPEN_MAX)
356     {
357       OSptr->ErrorNo = EBADF;
358       state->Reg[0] = -1L;
359       return;
360     }
361
362   addr = lseek (fh, 0, SEEK_CUR);
363   if (addr < 0)
364     state->Reg[0] = -1L;
365   else
366     {
367       state->Reg[0] = lseek (fh, 0L, SEEK_END);
368       (void) lseek (fh, addr, SEEK_SET);
369     }
370
371   OSptr->ErrorNo = errno;
372 }
373
374 /***************************************************************************\
375 * The emulator calls this routine when a SWI instruction is encuntered. The *
376 * parameter passed is the SWI number (lower 24 bits of the instruction).    *
377 \***************************************************************************/
378
379 unsigned 
380 ARMul_OSHandleSWI (ARMul_State *state, ARMword number)
381 {
382   ARMword addr, temp, fildes;
383   char buffer[BUFFERSIZE], *cptr;
384   FILE *fptr;
385   struct OSblock* OSptr = (struct OSblock*)state->OSptr;
386
387   switch (number)
388     {
389     case SWI_Read:
390         SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
391         return TRUE; 
392
393     case SWI_Write:
394         SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
395         return TRUE;     
396
397     case SWI_Open:
398         SWIopen (state, state->Reg[0],state->Reg[1]);
399         return TRUE;
400
401     case SWI_Clock :
402        /* return number of centi-seconds... */
403        state->Reg[0] =
404 #ifdef CLOCKS_PER_SEC
405           (CLOCKS_PER_SEC >= 100)
406              ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
407              : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
408 #else
409      /* presume unix... clock() returns microseconds */
410           (ARMword) (clock() / 10000) ;
411 #endif
412        OSptr->ErrorNo = errno ;
413        return(TRUE) ;
414
415     case SWI_Time :
416        state->Reg[0] = (ARMword)time(NULL) ;
417        OSptr->ErrorNo = errno ;
418        return(TRUE) ;
419    
420     case SWI_Close:
421       state->Reg[0] = close (state->Reg[0]);
422       OSptr->ErrorNo = errno;
423       return TRUE;
424
425     case SWI_Flen :
426       SWIflen (state, state->Reg[0]);
427       return(TRUE) ;
428
429     case SWI_Exit:
430       state->Emulate = FALSE ;
431       return TRUE;
432
433     case SWI_Seek:
434       {
435         /* We must return non-zero for failure */
436         state->Reg[0] = -1 >= lseek (state->Reg[0],
437                                     state->Reg[1],
438                                     SEEK_SET);
439         OSptr->ErrorNo = errno;
440         return TRUE;
441       }
442
443     case SWI_WriteC :
444       (void)fputc((int)state->Reg[0],stdout) ;
445       OSptr->ErrorNo = errno ;
446       return(TRUE) ;
447
448     case SWI_Write0 :
449       SWIWrite0 (state, state->Reg[0]);
450       return(TRUE) ;
451
452     case SWI_GetErrno :
453       state->Reg[0] = OSptr->ErrorNo ;
454       return(TRUE) ;
455
456     case SWI_Breakpoint :
457       state->EndCondition = RDIError_BreakpointReached ;
458       state->Emulate = FALSE ;
459       return(TRUE) ;
460
461     case SWI_GetEnv :
462        state->Reg[0] = ADDRCMDLINE ;
463        if (state->MemSize)
464           state->Reg[1] = state->MemSize ;
465        else
466           state->Reg[1] = ADDRUSERSTACK ;
467
468        WriteCommandLineTo (state, state->Reg[0]);
469        return(TRUE) ;
470
471        /* Handle Angel SWIs as well as Demon ones */
472     case AngelSWI_ARM:
473     case AngelSWI_Thumb:
474       /* R1 is almost always a parameter block */
475       addr = state->Reg[1];
476       /* R0 is a reason code */
477       switch (state->Reg[0])
478         {
479           /* Unimplemented reason codes */
480         case AngelSWI_Reason_ReadC:
481         case AngelSWI_Reason_IsTTY:
482         case AngelSWI_Reason_TmpNam:
483         case AngelSWI_Reason_Remove:
484         case AngelSWI_Reason_Rename:
485         case AngelSWI_Reason_System:
486         case AngelSWI_Reason_EnterSVC:
487         default:
488           state->Emulate = FALSE;
489           return(FALSE);
490
491         case AngelSWI_Reason_Clock:
492        /* return number of centi-seconds... */
493           state->Reg[0] =
494 #ifdef CLOCKS_PER_SEC
495             (CLOCKS_PER_SEC >= 100)
496             ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
497             : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
498 #else
499           /* presume unix... clock() returns microseconds */
500           (ARMword) (clock() / 10000) ;
501 #endif
502           OSptr->ErrorNo = errno;
503           return (TRUE);
504
505         case AngelSWI_Reason_Time:
506           state->Reg[0] = (ARMword) time (NULL);
507           OSptr->ErrorNo = errno;
508           return (TRUE);
509
510         case AngelSWI_Reason_WriteC:
511           (void) fputc ((int) ARMul_ReadByte (state,addr), stdout);
512           OSptr->ErrorNo = errno;
513           return (TRUE);
514
515         case AngelSWI_Reason_Write0:
516           SWIWrite0 (state, addr);
517           return (TRUE);
518
519         case AngelSWI_Reason_Close:
520           state->Reg[0] = close (ARMul_ReadWord (state, addr));
521           OSptr->ErrorNo = errno;
522           return (TRUE);
523
524         case AngelSWI_Reason_Seek:
525           state->Reg[0] = -1 >= lseek (ARMul_ReadWord(state,addr),
526                                        ARMul_ReadWord(state,addr+4),
527                                        SEEK_SET);
528           OSptr->ErrorNo = errno;
529           return (TRUE);
530
531         case AngelSWI_Reason_FLen:
532           SWIflen (state, ARMul_ReadWord (state, addr));
533           return (TRUE);
534
535         case AngelSWI_Reason_GetCmdLine:
536           WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
537           return (TRUE);
538
539         case AngelSWI_Reason_HeapInfo:
540           /* R1 is a pointer to a pointer */
541           addr = ARMul_ReadWord (state, addr);
542
543           /* Pick up the right memory limit */
544           if (state->MemSize)
545             temp = state->MemSize;
546           else
547             temp = ADDRUSERSTACK;
548
549           ARMul_WriteWord (state, addr, 0);       /* Heap base */
550           ARMul_WriteWord (state, addr+4, temp);    /* Heap limit */
551           ARMul_WriteWord (state, addr+8, temp);    /* Stack base */
552           ARMul_WriteWord (state, addr+12, temp);   /* Stack limit */
553           return (TRUE);
554
555         case AngelSWI_Reason_ReportException:
556           if (state->Reg[1] == ADP_Stopped_ApplicationExit)
557             state->Reg[0] = 0;
558           else
559             state->Reg[0] = -1;
560           state->Emulate = FALSE ;      
561           return (TRUE);
562
563         case ADP_Stopped_ApplicationExit:
564           state->Reg[0] = 0;
565           state->Emulate = FALSE ;      
566           return (TRUE);
567           
568         case ADP_Stopped_RunTimeError:
569           state->Reg[0] = -1;
570           state->Emulate = FALSE ;      
571           return (TRUE);
572
573         case AngelSWI_Reason_Errno:
574           state->Reg[0] = OSptr->ErrorNo;
575           return (TRUE);
576
577         case AngelSWI_Reason_Open:
578           SWIopen(state,
579                   ARMul_ReadWord(state, addr),
580                   ARMul_ReadWord(state, addr+4));
581           return TRUE;
582
583         case AngelSWI_Reason_Read:
584           SWIread(state,
585                   ARMul_ReadWord(state, addr),
586                   ARMul_ReadWord(state, addr+4),
587                   ARMul_ReadWord(state, addr+8));
588           return TRUE;
589
590         case AngelSWI_Reason_Write:
591           SWIwrite(state,
592                   ARMul_ReadWord(state, addr),
593                   ARMul_ReadWord(state, addr+4),
594                   ARMul_ReadWord(state, addr+8));
595           return TRUE;
596         }
597
598     default :
599       state->Emulate = FALSE ;      
600       return(FALSE) ;
601     }
602 }
603
604 #else  /* CYGNUS LOCAL: #if 1 */
605
606 unsigned 
607 ARMul_OSHandleSWI (ARMul_State *state, ARMword number)
608 {
609 #ifdef NOOS
610  return(FALSE) ;
611 #else
612 #ifdef VALIDATE
613  switch (number) {
614     case 0x11 :
615        state->Emulate = FALSE ;
616        return(TRUE) ;
617     case 0x01 :
618        if (ARM32BITMODE)
619           ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ;
620        else
621           ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ;
622        return(TRUE) ;
623     default :
624        return(FALSE) ;
625     }
626 #else
627  ARMword addr, temp ;
628  char buffer[BUFFERSIZE], *cptr ;
629  FILE *fptr ;
630  struct OSblock* OSptr = (struct OSblock*)state->OSptr ;
631
632  switch (number) {
633     case SWI_WriteC :
634        (void)fputc((int)state->Reg[0],stderr) ;
635        OSptr->ErrorNo = errno ;
636        return(TRUE) ;
637
638     case SWI_Write0 :
639        addr = state->Reg[0] ;
640        while ((temp = ARMul_ReadByte(state,addr++)) != 0)
641           fputc((char)temp,stderr) ;
642        OSptr->ErrorNo = errno ;
643        return(TRUE) ;
644
645     case SWI_ReadC :
646        state->Reg[0] = (ARMword)fgetc(stdin) ;
647        OSptr->ErrorNo = errno ;
648        return(TRUE) ;
649
650     case SWI_CLI :
651        addr = state->Reg[0] ;
652        getstring(state,state->Reg[0],buffer) ;
653        state->Reg[0] = (ARMword)system(buffer) ;
654        OSptr->ErrorNo = errno ;
655        return(TRUE) ;
656
657     case SWI_GetEnv :
658        state->Reg[0] = ADDRCMDLINE ;
659        if (state->MemSize)
660           state->Reg[1] = state->MemSize ;
661        else
662           state->Reg[1] = ADDRUSERSTACK ;
663
664        addr = state->Reg[0] ;
665        cptr = state->CommandLine ;
666        if (cptr == NULL)
667           cptr = "\0" ;
668        do {
669           temp = (ARMword)*cptr++ ;
670           ARMul_WriteByte(state,addr++,temp) ;
671           } while (temp != 0) ;
672        return(TRUE) ;
673
674     case SWI_Exit :
675 #ifdef ASIM
676        simkernel1_abort_run() ;
677 #else
678        state->Emulate = FALSE ;
679 #endif
680        return(TRUE) ;
681
682     case SWI_EnterOS :
683        if (ARM32BITMODE)
684           ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ;
685        else
686           ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ;
687        return(TRUE) ;
688
689     case SWI_GetErrno :
690        state->Reg[0] = OSptr->ErrorNo ;
691        return(TRUE) ;
692
693     case SWI_Clock :
694        /* return muber of centi-seconds... */
695        state->Reg[0] =
696 #ifdef CLOCKS_PER_SEC
697           (CLOCKS_PER_SEC >= 100)
698              ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
699              : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
700 #else
701      /* presume unix... clock() returns microseconds */
702           (ARMword) (clock() / 10000) ;
703 #endif
704        OSptr->ErrorNo = errno ;
705        return(TRUE) ;
706
707     case SWI_Time :
708        state->Reg[0] = (ARMword)time(NULL) ;
709        OSptr->ErrorNo = errno ;
710        return(TRUE) ;
711
712     case SWI_Remove :
713        getstring(state,state->Reg[0],buffer) ;
714        state->Reg[0] = unlink(buffer) ;
715        OSptr->ErrorNo = errno ;
716        return(TRUE) ;
717
718     case SWI_Rename : {
719        char buffer2[BUFFERSIZE] ;
720
721        getstring(state,state->Reg[0],buffer) ;
722        getstring(state,state->Reg[1],buffer2) ;
723        state->Reg[0] = rename(buffer,buffer2) ;
724        OSptr->ErrorNo = errno ;
725        return(TRUE) ;
726        }
727
728     case SWI_Open : {
729 #if 0
730       /* It seems to me that these are in the wrong order
731          sac@cygnus.com, so I've redone it to use the
732          flags instead, with the functionality which was already
733          there -- ahh, perhaps the TRUNC bit is in a different
734          place on the original host ?*/
735        static char* fmode[] = {"r","rb","r+","r+b",
736                                "w","wb","w+","w+b",
737                                "a","ab","a+","a+b",
738                                "r","r","r","r"} /* last 4 are illegal */ ;
739 #endif
740
741        unsigned type ;
742
743        type = (unsigned)(state->Reg[1] & 3L) ;
744        getstring(state,state->Reg[0],buffer) ;
745        if (strcmp(buffer,":tt")==0 && (type == O_RDONLY )) /* opening tty "r" */
746           fptr = stdin ;
747        else if (strcmp(buffer,":tt")==0 && (type == O_WRONLY)) /* opening tty "w" */
748           fptr = stderr ;
749        else
750          {
751            switch (type) 
752              {
753              case O_RDONLY:
754                fptr = fopen(buffer,"r") ;
755                break;
756              case O_WRONLY:
757                fptr = fopen(buffer,"w") ;
758                break;
759              case O_RDWR:
760                fptr = fopen(buffer,"rw") ;
761                break;
762              }
763          }
764
765        state->Reg[0] = 0 ;
766        if (fptr != NULL) {
767           for (temp = 0 ; temp < FOPEN_MAX ; temp++)
768              if (OSptr->FileTable[temp] == NULL) {
769                 OSptr->FileTable[temp] = fptr ;
770                 OSptr->FileFlags[temp] = type & 1 ; /* preserve the binary bit */
771                 state->Reg[0] = (ARMword)(temp + 1) ;
772                 break ;
773                 }
774           if (state->Reg[0] == 0)
775              OSptr->ErrorNo = EMFILE ; /* too many open files */
776           else
777              OSptr->ErrorNo = errno ;
778           }
779        else
780          OSptr->ErrorNo = errno ;
781        return(TRUE) ;
782        }
783
784     case SWI_Close :
785        temp = state->Reg[0] ;
786        if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
787           OSptr->ErrorNo = EBADF ;
788           state->Reg[0] = -1L ;
789           return(TRUE) ;
790           }
791        temp-- ;
792        fptr = OSptr->FileTable[temp] ;
793        if (fptr == stdin || fptr == stderr)
794           state->Reg[0] = 0 ;
795        else
796           state->Reg[0] = fclose(fptr) ;
797        OSptr->FileTable[temp] = NULL ;
798        OSptr->ErrorNo = errno ;
799        return(TRUE) ;
800
801     case SWI_Write : {
802        unsigned size, upto, type ;
803        char ch ;
804
805        temp = state->Reg[0] ;
806        if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
807           OSptr->ErrorNo = EBADF ;
808           state->Reg[0] = -1L ;
809           return(TRUE) ;
810           }
811        temp-- ;
812        fptr = OSptr->FileTable[temp] ;
813        type = OSptr->FileFlags[temp] ;
814        addr = state->Reg[1] ;
815        size = (unsigned)state->Reg[2] ;
816
817        if (type & READOP)
818           fseek(fptr,0L,SEEK_CUR) ;
819        OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP ; ;
820        while (size > 0) {
821           if (size >= BUFFERSIZE)
822              upto = BUFFERSIZE ;
823           else
824              upto = size ;
825           for (cptr = buffer ; (cptr - buffer) < upto ; cptr++) {
826              ch = (char)ARMul_ReadByte(state,(ARMword)addr++) ;
827              *cptr = FIXCRLF(type,ch) ;
828              }
829           temp = fwrite(buffer,1,upto,fptr) ;
830           if (temp < upto) {
831              state->Reg[0] = (ARMword)(size - temp) ;
832              OSptr->ErrorNo = errno ;
833              return(TRUE) ;
834              }
835           size -= upto ;
836           }
837        state->Reg[0] = 0 ;
838        OSptr->ErrorNo = errno ;
839        return(TRUE) ;
840        }
841
842     case SWI_Read : {
843        unsigned size, upto, type ;
844        char ch ;
845
846        temp = state->Reg[0] ;
847        if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
848           OSptr->ErrorNo = EBADF ;
849           state->Reg[0] = -1L ;
850           return(TRUE) ;
851           }
852        temp-- ;
853        fptr = OSptr->FileTable[temp] ;
854        addr = state->Reg[1] ;
855        size = (unsigned)state->Reg[2] ;
856        type = OSptr->FileFlags[temp] ;
857
858        if (type & WRITEOP)
859           fseek(fptr,0L,SEEK_CUR) ;
860        OSptr->FileFlags[temp] = (type & BINARY) | READOP ; ;
861        while (size > 0) {
862           if (isatty_(fptr)) {
863              upto = (size >= BUFFERSIZE)?BUFFERSIZE:size + 1 ;
864              if (fgets(buffer, upto, fptr) != 0)
865                temp = strlen(buffer) ;
866              else
867                temp = 0 ;
868              upto-- ; /* 1 char used for terminating null */
869              }
870           else {
871              upto = (size>=BUFFERSIZE)?BUFFERSIZE:size ;
872              temp = fread(buffer,1,upto,fptr) ;
873              }
874           for (cptr = buffer ; (cptr - buffer) < temp ; cptr++) {
875              ch = *cptr ;
876              ARMul_WriteByte(state,(ARMword)addr++,FIXCRLF(type,ch)) ;
877              }
878           if (temp < upto) {
879              state->Reg[0] = (ARMword)(size - temp) ;
880              OSptr->ErrorNo = errno ;
881              return(TRUE) ;
882              }
883           size -= upto ;
884           }
885        state->Reg[0] = 0 ;
886        OSptr->ErrorNo = errno ;
887        return(TRUE) ;
888        }
889
890     case SWI_Seek :
891        if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
892            || OSptr->FileTable[state->Reg[0] - 1] == 0) {
893           OSptr->ErrorNo = EBADF ;
894           state->Reg[0] = -1L ;
895           return(TRUE) ;
896           }
897        fptr = OSptr->FileTable[state->Reg[0] - 1] ;
898        state->Reg[0] = fseek(fptr,(long)state->Reg[1],SEEK_SET) ;
899        OSptr->ErrorNo = errno ;
900        return(TRUE) ;
901
902     case SWI_Flen :
903        if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
904            || OSptr->FileTable[state->Reg[0] - 1] == 0) {
905           OSptr->ErrorNo = EBADF ;
906           state->Reg[0] = -1L ;
907           return(TRUE) ;
908           }
909        fptr = OSptr->FileTable[state->Reg[0] - 1] ;
910        addr = (ARMword)ftell(fptr) ;
911        if (fseek(fptr,0L,SEEK_END) < 0)
912           state->Reg[0] = -1 ;
913        else {
914           state->Reg[0] = (ARMword)ftell(fptr) ;
915           (void)fseek(fptr,addr,SEEK_SET) ;
916           }
917        OSptr->ErrorNo = errno ;
918        return(TRUE) ;
919
920     case SWI_IsTTY :
921        if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
922            || OSptr->FileTable[state->Reg[0] - 1] == 0) {
923           OSptr->ErrorNo = EBADF ;
924           state->Reg[0] = -1L ;
925           return(TRUE) ;
926           }
927        fptr = OSptr->FileTable[state->Reg[0] - 1] ;
928        state->Reg[0] = isatty_(fptr) ;
929        OSptr->ErrorNo = errno ;
930        return(TRUE) ;
931
932     case SWI_TmpNam :{
933        ARMword size ;
934
935        addr = state->Reg[0] ;
936        temp = state->Reg[1] & 0xff ;
937        size = state->Reg[2] ;
938        if (OSptr->tempnames[temp] == NULL) {
939           if ((OSptr->tempnames[temp] = malloc(L_tmpnam)) == NULL) {
940              state->Reg[0] = 0 ;
941              return(TRUE) ;
942              }
943           (void)tmpnam(OSptr->tempnames[temp]) ;
944           }
945        cptr = OSptr->tempnames[temp] ;
946        if (strlen(cptr) > state->Reg[2])
947           state->Reg[0] = 0 ;
948        else
949           do {
950              ARMul_WriteByte(state,addr++,*cptr) ;
951              } while (*cptr++ != 0) ;
952        OSptr->ErrorNo = errno ;
953        return(TRUE) ;
954        }
955
956     case SWI_InstallHandler:
957        {  ARMword handlerp = ADDRSOFHANDLERS + state->Reg[0] * 8;
958           ARMword oldr1 = ARMul_ReadWord(state, handlerp),
959                   oldr2 = ARMul_ReadWord(state, handlerp + 4);
960           ARMul_WriteWord(state, handlerp, state->Reg[1]);
961           ARMul_WriteWord(state, handlerp + 4, state->Reg[2]);
962           state->Reg[1] = oldr1;
963           state->Reg[2] = oldr2;
964           return(TRUE);
965        }
966
967     case SWI_GenerateError:
968        ARMul_Abort(state, ARMSWIV) ;
969        if (state->Emulate)
970           ARMul_SetR15(state, ARMul_ReadWord(state, ADDRSOFTVECTORS + ARMErrorV));
971        return(TRUE);
972
973 /* SWI's 0x9x unwind the state of the CPU after an abort of type x */
974
975     case 0x90: /* Branch through zero */
976        {  ARMword oldpsr = ARMul_GetCPSR(state) ;
977           ARMul_SetCPSR(state, (oldpsr & 0xffffffc0) | 0x13) ;
978           ARMul_SetSPSR(state, SVC32MODE, oldpsr) ;
979           state->Reg[14] = 0;
980           goto TidyCommon;
981        }
982
983     case 0x98: /* Error */
984        {  ARMword errorp = state->Reg[0],
985                   regp = state->Reg[1];
986           unsigned i;
987           ARMword errorpsr = ARMul_ReadWord(state, regp + 16*4);
988           for (i = 0; i < 15; i++)
989             ARMul_SetReg(state,errorpsr,i,ARMul_ReadWord(state, regp + i*4L)) ;
990           state->Reg[14] = ARMul_ReadWord(state, regp + 15*4L);
991           state->Reg[10] = errorp;
992           ARMul_SetSPSR(state,state->Mode,errorpsr) ;
993           OSptr->ErrorP = errorp;
994           goto TidyCommon;
995        }
996
997     case 0x94: /* Data abort */
998        {  ARMword addr = state->Reg[14] - 8;
999           ARMword cpsr = ARMul_GetCPSR(state) ;
1000           if (ARM26BITMODE)
1001              addr = addr & 0x3fffffc ;
1002           ARMul_SetCPSR(state,ARMul_GetSPSR(state,cpsr)) ;
1003           UnwindDataAbort(state, addr);
1004           if (addr >= FPESTART && addr < FPEEND) { /* in the FPE */
1005              ARMword sp, spsr ;
1006              unsigned i ;
1007
1008              sp = state->Reg[13] ;
1009              state->Reg[13] += 64 ; /* fix the aborting mode sp */
1010              state->Reg[14] = ARMul_ReadWord(state,sp + 60) ; /* and its lr */
1011              spsr = ARMul_GetSPSR(state,state->Mode) ;
1012              state->Mode = ARMul_SwitchMode(state, state->Mode, spsr);
1013              for (i = 0 ; i < 15 ; i++) {
1014                 ARMul_SetReg(state,spsr,i,ARMul_ReadWord(state,sp)) ;
1015                 sp += 4 ;
1016                 }
1017              ARMul_SetCPSR(state,cpsr) ;
1018              state->Reg[14] = ARMul_ReadWord(state,sp) + 4 ; /* botch it */
1019              ARMul_SetSPSR(state,state->Mode,spsr) ;
1020              }
1021           else
1022              ARMul_SetCPSR(state,cpsr) ;
1023
1024           /* and fall through to correct r14 */
1025        }
1026     case 0x95: /* Address Exception */
1027        state->Reg[14] -= 4;
1028     case 0x91: /* Undefined instruction */
1029     case 0x92: /* SWI */
1030     case 0x93: /* Prefetch abort */
1031     case 0x96: /* IRQ */
1032     case 0x97: /* FIQ */
1033        state->Reg[14] -= 4;
1034     TidyCommon:
1035        if (state->VectorCatch & (1 << (number - 0x90))) {
1036           ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
1037           ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ;
1038           if (number == 0x90)
1039              state->EndCondition = 10 ; /* Branch through Zero Error */
1040           else
1041              state->EndCondition = (unsigned)number - 0x8f;
1042           state->Emulate = FALSE ;
1043           }
1044        else {
1045           ARMword sp = state->Reg[13];
1046           ARMul_WriteWord(state, sp - 4, state->Reg[14]);
1047           ARMul_WriteWord(state, sp - 8, state->Reg[12]);
1048           ARMul_WriteWord(state, sp - 12, state->Reg[11]);
1049           ARMul_WriteWord(state, sp - 16, state->Reg[10]);
1050           state->Reg[13] = sp - 16;
1051           state->Reg[11] = ADDRSOFHANDLERS + 8 * (number - 0x90);
1052           }
1053        return(TRUE);
1054
1055 /* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */
1056
1057     case 0x80: case 0x81: case 0x82: case 0x83:
1058     case 0x84: case 0x85: case 0x86: case 0x87: case 0x88:
1059        {  ARMword sp = state->Reg[13];
1060           state->Reg[10] = ARMul_ReadWord(state, sp);
1061           state->Reg[11] = ARMul_ReadWord(state, sp + 4);
1062           state->Reg[12] = ARMul_ReadWord(state, sp + 8);
1063           state->Reg[14] = ARMul_ReadWord(state, sp + 12);
1064           state->Reg[13] = sp + 16;
1065           ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
1066           ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ;
1067           if (number == 0x80)
1068              state->EndCondition = 10 ; /* Branch through Zero Error */
1069           else
1070              state->EndCondition = (unsigned)number - 0x7f;
1071           state->Emulate = FALSE ;
1072           return(TRUE);
1073        }
1074
1075     default :
1076           state->Emulate = FALSE ;      
1077        return(FALSE) ;
1078     }
1079 #endif
1080 #endif
1081  }
1082 #endif  /* CYGNUS LOCAL: #if 1 */
1083
1084 #ifndef NOOS
1085 #ifndef ASIM
1086
1087 /***************************************************************************\
1088 * The emulator calls this routine when an Exception occurs.  The second     *
1089 * parameter is the address of the relevant exception vector.  Returning     *
1090 * FALSE from this routine causes the trap to be taken, TRUE causes it to    *
1091 * be ignored (so set state->Emulate to FALSE!).                             *
1092 \***************************************************************************/
1093
1094 unsigned 
1095 ARMul_OSException (ARMul_State *state, ARMword vector, ARMword pc)
1096 { /* don't use this here */
1097  return(FALSE) ;
1098 }
1099
1100 #endif
1101
1102 /***************************************************************************\
1103 *                            Unwind a data abort                            *
1104 \***************************************************************************/
1105
1106 static void 
1107 UnwindDataAbort (ARMul_State *state, ARMword addr)
1108 {
1109   ARMword instr = ARMul_ReadWord(state, addr);
1110   ARMword rn = BITS(16, 19);
1111   ARMword itype = BITS(24, 27);
1112   ARMword offset;
1113   if (rn == 15) return;
1114   if (itype == 8 || itype == 9) {
1115     /* LDM or STM */
1116     unsigned long regs = BITS(0, 15);
1117     offset = 0;
1118     if (!BIT(21)) return; /* no wb */
1119     for (; regs != 0; offset++)
1120       regs ^= (regs & -regs);
1121     if (offset == 0) offset = 16;
1122   } else if (itype == 12 ||              /* post-indexed CPDT */
1123              (itype == 13 && BIT(21))) { /* pre_indexed CPDT with WB */
1124     offset = BITS(0, 7);
1125   } else
1126     return;
1127
1128   if (BIT(23))
1129     state->Reg[rn] -= offset * 4;
1130   else
1131     state->Reg[rn] += offset * 4;
1132 }
1133
1134 /***************************************************************************\
1135 *           Copy a string from the debuggee's memory to the host's          *
1136 \***************************************************************************/
1137
1138 static void 
1139 getstring (ARMul_State *state, ARMword from, char *to)
1140 {
1141   do 
1142     {
1143       *to = (char) ARMul_ReadByte (state, from++);
1144     } while (*to++ != '\0');
1145 }
1146
1147 #endif /* NOOS */