]> Git Repo - binutils.git/blob - sim/arm/armos.c
Fix compile time warning messages.
[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 #include "ansidecl.h"
27
28 #include <time.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <fcntl.h>
32
33 #ifndef O_RDONLY
34 #define O_RDONLY 0
35 #endif
36 #ifndef O_WRONLY
37 #define O_WRONLY 1
38 #endif
39 #ifndef O_RDWR
40 #define O_RDWR   2
41 #endif
42 #ifndef O_BINARY
43 #define O_BINARY 0
44 #endif
45
46 #ifdef __STDC__
47 #define unlink(s) remove(s)
48 #endif
49
50 #ifdef HAVE_UNISTD_H
51 #include <unistd.h>             /* For SEEK_SET etc */
52 #endif
53
54 #ifdef __riscos
55 extern int _fisatty (FILE *);
56 #define isatty_(f) _fisatty(f)
57 #else
58 #ifdef __ZTC__
59 #include <io.h>
60 #define isatty_(f) isatty((f)->_file)
61 #else
62 #ifdef macintosh
63 #include <ioctl.h>
64 #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
65 #else
66 #define isatty_(f) isatty (fileno (f))
67 #endif
68 #endif
69 #endif
70
71 #include "armdefs.h"
72 #include "armos.h"
73 #ifndef NOOS
74 #ifndef VALIDATE
75 /* #ifndef ASIM */
76 #include "armfpe.h"
77 /* #endif */
78 #endif
79 #endif
80
81 /* For RDIError_BreakpointReached.  */
82 #include "dbg_rdi.h"
83
84 extern unsigned ARMul_OSInit (ARMul_State * state);
85 extern void ARMul_OSExit (ARMul_State * state);
86 extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number);
87 extern unsigned ARMul_OSException (ARMul_State * state, ARMword vector,
88                                    ARMword pc);
89 extern ARMword ARMul_OSLastErrorP (ARMul_State * state);
90 extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr);
91
92 #define BUFFERSIZE 4096
93 #ifndef FOPEN_MAX
94 #define FOPEN_MAX 64
95 #endif
96 #define UNIQUETEMPS 256
97
98 /***************************************************************************\
99 *                          OS private Information                           *
100 \***************************************************************************/
101
102 struct OSblock
103 {
104   ARMword Time0;
105   ARMword ErrorP;
106   ARMword ErrorNo;
107   FILE *FileTable[FOPEN_MAX];
108   char FileFlags[FOPEN_MAX];
109   char *tempnames[UNIQUETEMPS];
110 };
111
112 #define NOOP 0
113 #define BINARY 1
114 #define READOP 2
115 #define WRITEOP 4
116
117 #ifdef macintosh
118 #define FIXCRLF(t,c) ((t & BINARY) ? \
119                       c : \
120                       ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \
121                      )
122 #else
123 #define FIXCRLF(t,c) c
124 #endif
125
126 static ARMword softvectorcode[] =
127 {       /* basic: swi tidyexception + event; mov pc, lr;
128            ldmia r11,{r11,pc}; swi generateexception  + event.  */
129   0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080,       /*Reset */
130   0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081,       /*Undef */
131   0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082,       /*SWI  */
132   0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083,       /*Prefetch abort */
133   0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084,       /*Data abort */
134   0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085,       /*Address exception */
135   0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /*IRQ*/
136   0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /*FIQ*/
137   0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088,       /*Error */
138   0xe1a0f00e                    /* default handler */
139 };
140
141 /***************************************************************************\
142 *            Time for the Operating System to initialise itself.            *
143 \***************************************************************************/
144
145 unsigned
146 ARMul_OSInit (ARMul_State * state)
147 {
148 #ifndef NOOS
149 #ifndef VALIDATE
150   ARMword instr, i, j;
151   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
152
153   if (state->OSptr == NULL)
154     {
155       state->OSptr = (unsigned char *) malloc (sizeof (struct OSblock));
156       if (state->OSptr == NULL)
157         {
158           perror ("OS Memory");
159           exit (15);
160         }
161     }
162   OSptr = (struct OSblock *) state->OSptr;
163   OSptr->ErrorP = 0;
164   state->Reg[13] = ADDRSUPERSTACK;      /* set up a stack for the current mode */
165   ARMul_SetReg (state, SVC32MODE, 13, ADDRSUPERSTACK);  /* and for supervisor mode */
166   ARMul_SetReg (state, ABORT32MODE, 13, ADDRSUPERSTACK);        /* and for abort 32 mode */
167   ARMul_SetReg (state, UNDEF32MODE, 13, ADDRSUPERSTACK);        /* and for undef 32 mode */
168   instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8);   /* load pc from soft vector */
169   for (i = ARMul_ResetV; i <= ARMFIQV; i += 4)
170     ARMul_WriteWord (state, i, instr);  /* write hardware vectors */
171   for (i = ARMul_ResetV; i <= ARMFIQV + 4; i += 4)
172     {
173       ARMul_WriteWord (state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
174       ARMul_WriteWord (state, ADDRSOFHANDLERS + 2 * i + 4L,
175                        SOFTVECTORCODE + sizeof (softvectorcode) - 4L);
176     }
177   for (i = 0; i < sizeof (softvectorcode); i += 4)
178     ARMul_WriteWord (state, SOFTVECTORCODE + i, softvectorcode[i / 4]);
179   for (i = 0; i < FOPEN_MAX; i++)
180     OSptr->FileTable[i] = NULL;
181   for (i = 0; i < UNIQUETEMPS; i++)
182     OSptr->tempnames[i] = NULL;
183   ARMul_ConsolePrint (state, ", Demon 1.01");
184
185 /* #ifndef ASIM */
186
187   /* install fpe */
188   for (i = 0; i < fpesize; i += 4)      /* copy the code */
189     ARMul_WriteWord (state, FPESTART + i, fpecode[i >> 2]);
190   for (i = FPESTART + fpesize;; i -= 4)
191     {                           /* reverse the error strings */
192       if ((j = ARMul_ReadWord (state, i)) == 0xffffffff)
193         break;
194       if (state->bigendSig && j < 0x80000000)
195         {                       /* it's part of the string so swap it */
196           j = ((j >> 0x18) & 0x000000ff) |
197             ((j >> 0x08) & 0x0000ff00) |
198             ((j << 0x08) & 0x00ff0000) | ((j << 0x18) & 0xff000000);
199           ARMul_WriteWord (state, i, j);
200         }
201     }
202   ARMul_WriteWord (state, FPEOLDVECT, ARMul_ReadWord (state, 4));       /* copy old illegal instr vector */
203   ARMul_WriteWord (state, 4, FPENEWVECT (ARMul_ReadWord (state, i - 4)));       /* install new vector */
204   ARMul_ConsolePrint (state, ", FPE");
205
206 /* #endif  ASIM */
207 #endif /* VALIDATE */
208 #endif /* NOOS */
209
210   return (TRUE);
211 }
212
213 void
214 ARMul_OSExit (ARMul_State * state)
215 {
216   free ((char *) state->OSptr);
217 }
218
219
220 /***************************************************************************\
221 *                  Return the last Operating System Error.                  *
222 \***************************************************************************/
223
224 ARMword ARMul_OSLastErrorP (ARMul_State * state)
225 {
226   return ((struct OSblock *) state->OSptr)->ErrorP;
227 }
228
229 static int translate_open_mode[] = {
230   O_RDONLY,                     /* "r"   */
231   O_RDONLY + O_BINARY,          /* "rb"  */
232   O_RDWR,                       /* "r+"  */
233   O_RDWR + O_BINARY,            /* "r+b" */
234   O_WRONLY + O_CREAT + O_TRUNC, /* "w"   */
235   O_WRONLY + O_BINARY + O_CREAT + O_TRUNC,      /* "wb"  */
236   O_RDWR + O_CREAT + O_TRUNC,   /* "w+"  */
237   O_RDWR + O_BINARY + O_CREAT + O_TRUNC,        /* "w+b" */
238   O_WRONLY + O_APPEND + O_CREAT,        /* "a"   */
239   O_WRONLY + O_BINARY + O_APPEND + O_CREAT,     /* "ab"  */
240   O_RDWR + O_APPEND + O_CREAT,  /* "a+"  */
241   O_RDWR + O_BINARY + O_APPEND + O_CREAT        /* "a+b" */
242 };
243
244 static void
245 SWIWrite0 (ARMul_State * state, ARMword addr)
246 {
247   ARMword temp;
248   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
249
250   while ((temp = ARMul_ReadByte (state, addr++)) != 0)
251     (void) fputc ((char) temp, stdout);
252
253   OSptr->ErrorNo = errno;
254 }
255
256 static void
257 WriteCommandLineTo (ARMul_State * state, ARMword addr)
258 {
259   ARMword temp;
260   char *cptr = state->CommandLine;
261   if (cptr == NULL)
262     cptr = "\0";
263   do
264     {
265       temp = (ARMword) * cptr++;
266       ARMul_WriteByte (state, addr++, temp);
267     }
268   while (temp != 0);
269 }
270
271 static void
272 SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
273 {
274   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
275   char dummy[2000];
276   int flags;
277   int i;
278
279   for (i = 0; (dummy[i] = ARMul_ReadByte (state, name + i)); i++)
280     ;
281
282   /* Now we need to decode the Demon open mode */
283   flags = translate_open_mode[SWIflags];
284
285   /* Filename ":tt" is special: it denotes stdin/out */
286   if (strcmp (dummy, ":tt") == 0)
287     {
288       if (flags == O_RDONLY)    /* opening tty "r" */
289         state->Reg[0] = 0;      /* stdin */
290       else
291         state->Reg[0] = 1;      /* stdout */
292     }
293   else
294     {
295       state->Reg[0] = (int) open (dummy, flags, 0666);
296       OSptr->ErrorNo = errno;
297     }
298 }
299
300 static void
301 SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
302 {
303   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
304   int res;
305   int i;
306   char *local = malloc (len);
307
308   if (local == NULL)
309     {
310       fprintf (stderr, "sim: Unable to read 0x%ulx bytes - out of memory\n",
311                len);
312       return;
313     }
314
315   res = read (f, local, len);
316   if (res > 0)
317     for (i = 0; i < res; i++)
318       ARMul_WriteByte (state, ptr + i, local[i]);
319   free (local);
320   state->Reg[0] = res == -1 ? -1 : len - res;
321   OSptr->ErrorNo = errno;
322 }
323
324 static void
325 SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
326 {
327   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
328   int res;
329   ARMword i;
330   char *local = malloc (len);
331
332   if (local == NULL)
333     {
334       fprintf (stderr, "sim: Unable to write 0x%lx bytes - out of memory\n",
335                (long) len);
336       return;
337     }
338
339   for (i = 0; i < len; i++)
340     local[i] = ARMul_ReadByte (state, ptr + i);
341
342   res = write (f, local, len);
343   state->Reg[0] = res == -1 ? -1 : len - res;
344   free (local);
345   OSptr->ErrorNo = errno;
346 }
347
348 static void
349 SWIflen (ARMul_State * state, ARMword fh)
350 {
351   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
352   ARMword addr;
353
354   if (fh == 0 || fh > FOPEN_MAX)
355     {
356       OSptr->ErrorNo = EBADF;
357       state->Reg[0] = -1L;
358       return;
359     }
360
361   addr = lseek (fh, 0, SEEK_CUR);
362
363   state->Reg[0] = lseek (fh, 0L, SEEK_END);
364   (void) lseek (fh, addr, SEEK_SET);
365
366   OSptr->ErrorNo = errno;
367 }
368
369 /***************************************************************************\
370 * The emulator calls this routine when a SWI instruction is encuntered. The *
371 * parameter passed is the SWI number (lower 24 bits of the instruction).    *
372 \***************************************************************************/
373
374 unsigned
375 ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
376 {
377   ARMword addr, temp;
378   struct OSblock *OSptr = (struct OSblock *) state->OSptr;
379
380   switch (number)
381     {
382     case SWI_Read:
383       SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
384       return TRUE;
385
386     case SWI_Write:
387       SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
388       return TRUE;
389
390     case SWI_Open:
391       SWIopen (state, state->Reg[0], state->Reg[1]);
392       return TRUE;
393
394     case SWI_Clock:
395       /* return number of centi-seconds... */
396       state->Reg[0] =
397 #ifdef CLOCKS_PER_SEC
398         (CLOCKS_PER_SEC >= 100)
399         ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
400         : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
401 #else
402         /* presume unix... clock() returns microseconds */
403         (ARMword) (clock () / 10000);
404 #endif
405       OSptr->ErrorNo = errno;
406       return (TRUE);
407
408     case SWI_Time:
409       state->Reg[0] = (ARMword) time (NULL);
410       OSptr->ErrorNo = errno;
411       return (TRUE);
412
413     case SWI_Close:
414       state->Reg[0] = close (state->Reg[0]);
415       OSptr->ErrorNo = errno;
416       return TRUE;
417
418     case SWI_Flen:
419       SWIflen (state, state->Reg[0]);
420       return (TRUE);
421
422     case SWI_Exit:
423       state->Emulate = FALSE;
424       return TRUE;
425
426     case SWI_Seek:
427       {
428         /* We must return non-zero for failure */
429         state->Reg[0] = -1 >= lseek (state->Reg[0], state->Reg[1], SEEK_SET);
430         OSptr->ErrorNo = errno;
431         return TRUE;
432       }
433
434     case SWI_WriteC:
435       (void) fputc ((int) state->Reg[0], stdout);
436       OSptr->ErrorNo = errno;
437       return (TRUE);
438
439     case SWI_Write0:
440       SWIWrite0 (state, state->Reg[0]);
441       return (TRUE);
442
443     case SWI_GetErrno:
444       state->Reg[0] = OSptr->ErrorNo;
445       return (TRUE);
446
447     case SWI_Breakpoint:
448       state->EndCondition = RDIError_BreakpointReached;
449       state->Emulate = FALSE;
450       return (TRUE);
451
452     case SWI_GetEnv:
453       state->Reg[0] = ADDRCMDLINE;
454       if (state->MemSize)
455         state->Reg[1] = state->MemSize;
456       else
457         state->Reg[1] = ADDRUSERSTACK;
458
459       WriteCommandLineTo (state, state->Reg[0]);
460       return (TRUE);
461
462       /* Handle Angel SWIs as well as Demon ones */
463     case AngelSWI_ARM:
464     case AngelSWI_Thumb:
465       /* R1 is almost always a parameter block */
466       addr = state->Reg[1];
467       /* R0 is a reason code */
468       switch (state->Reg[0])
469         {
470           /* Unimplemented reason codes */
471         case AngelSWI_Reason_ReadC:
472         case AngelSWI_Reason_IsTTY:
473         case AngelSWI_Reason_TmpNam:
474         case AngelSWI_Reason_Remove:
475         case AngelSWI_Reason_Rename:
476         case AngelSWI_Reason_System:
477         case AngelSWI_Reason_EnterSVC:
478         default:
479           state->Emulate = FALSE;
480           return (FALSE);
481
482         case AngelSWI_Reason_Clock:
483           /* return number of centi-seconds... */
484           state->Reg[0] =
485 #ifdef CLOCKS_PER_SEC
486             (CLOCKS_PER_SEC >= 100)
487             ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
488             : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
489 #else
490             /* presume unix... clock() returns microseconds */
491             (ARMword) (clock () / 10000);
492 #endif
493           OSptr->ErrorNo = errno;
494           return (TRUE);
495
496         case AngelSWI_Reason_Time:
497           state->Reg[0] = (ARMword) time (NULL);
498           OSptr->ErrorNo = errno;
499           return (TRUE);
500
501         case AngelSWI_Reason_WriteC:
502           (void) fputc ((int) ARMul_ReadByte (state, addr), stdout);
503           OSptr->ErrorNo = errno;
504           return (TRUE);
505
506         case AngelSWI_Reason_Write0:
507           SWIWrite0 (state, addr);
508           return (TRUE);
509
510         case AngelSWI_Reason_Close:
511           state->Reg[0] = close (ARMul_ReadWord (state, addr));
512           OSptr->ErrorNo = errno;
513           return (TRUE);
514
515         case AngelSWI_Reason_Seek:
516           state->Reg[0] = -1 >= lseek (ARMul_ReadWord (state, addr),
517                                        ARMul_ReadWord (state, addr + 4),
518                                        SEEK_SET);
519           OSptr->ErrorNo = errno;
520           return (TRUE);
521
522         case AngelSWI_Reason_FLen:
523           SWIflen (state, ARMul_ReadWord (state, addr));
524           return (TRUE);
525
526         case AngelSWI_Reason_GetCmdLine:
527           WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
528           return (TRUE);
529
530         case AngelSWI_Reason_HeapInfo:
531           /* R1 is a pointer to a pointer */
532           addr = ARMul_ReadWord (state, addr);
533
534           /* Pick up the right memory limit */
535           if (state->MemSize)
536             temp = state->MemSize;
537           else
538             temp = ADDRUSERSTACK;
539
540           ARMul_WriteWord (state, addr, 0);     /* Heap base */
541           ARMul_WriteWord (state, addr + 4, temp);      /* Heap limit */
542           ARMul_WriteWord (state, addr + 8, temp);      /* Stack base */
543           ARMul_WriteWord (state, addr + 12, temp);     /* Stack limit */
544           return (TRUE);
545
546         case AngelSWI_Reason_ReportException:
547           if (state->Reg[1] == ADP_Stopped_ApplicationExit)
548             state->Reg[0] = 0;
549           else
550             state->Reg[0] = -1;
551           state->Emulate = FALSE;
552           return TRUE;
553
554         case ADP_Stopped_ApplicationExit:
555           state->Reg[0] = 0;
556           state->Emulate = FALSE;
557           return (TRUE);
558
559         case ADP_Stopped_RunTimeError:
560           state->Reg[0] = -1;
561           state->Emulate = FALSE;
562           return (TRUE);
563
564         case AngelSWI_Reason_Errno:
565           state->Reg[0] = OSptr->ErrorNo;
566           return (TRUE);
567
568         case AngelSWI_Reason_Open:
569           SWIopen (state,
570                    ARMul_ReadWord (state, addr),
571                    ARMul_ReadWord (state, addr + 4));
572           return TRUE;
573
574         case AngelSWI_Reason_Read:
575           SWIread (state,
576                    ARMul_ReadWord (state, addr),
577                    ARMul_ReadWord (state, addr + 4),
578                    ARMul_ReadWord (state, addr + 8));
579           return TRUE;
580
581         case AngelSWI_Reason_Write:
582           SWIwrite (state,
583                     ARMul_ReadWord (state, addr),
584                     ARMul_ReadWord (state, addr + 4),
585                     ARMul_ReadWord (state, addr + 8));
586           return TRUE;
587         }
588
589     default:
590       state->Emulate = FALSE;
591       return (FALSE);
592     }
593 }
594
595 #ifndef NOOS
596 #ifndef ASIM
597
598 /***************************************************************************\
599 * The emulator calls this routine when an Exception occurs.  The second     *
600 * parameter is the address of the relevant exception vector.  Returning     *
601 * FALSE from this routine causes the trap to be taken, TRUE causes it to    *
602 * be ignored (so set state->Emulate to FALSE!).                             *
603 \***************************************************************************/
604
605 unsigned
606 ARMul_OSException (ARMul_State * state ATTRIBUTE_UNUSED, ARMword vector ATTRIBUTE_UNUSED, ARMword pc ATTRIBUTE_UNUSED)
607 {                               /* don't use this here */
608   return (FALSE);
609 }
610
611 #endif
612
613
614 #endif /* NOOS */
This page took 0.059068 seconds and 4 git commands to generate.