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