6545cc824749cae1774b66356e8041723f98a1c6
[deliverable/binutils-gdb.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 #include "armemu.h"
74
75 #ifndef NOOS
76 #ifndef VALIDATE
77 /* #ifndef ASIM */
78 #include "armfpe.h"
79 /* #endif */
80 #endif
81 #endif
82
83 /* For RDIError_BreakpointReached. */
84 #include "dbg_rdi.h"
85
86 extern unsigned ARMul_OSInit (ARMul_State * state);
87 extern void ARMul_OSExit (ARMul_State * state);
88 extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number);
89 extern unsigned ARMul_OSException (ARMul_State * state, ARMword vector,
90 ARMword pc);
91 extern ARMword ARMul_OSLastErrorP (ARMul_State * state);
92 extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr);
93
94 #define BUFFERSIZE 4096
95 #ifndef FOPEN_MAX
96 #define FOPEN_MAX 64
97 #endif
98 #define UNIQUETEMPS 256
99
100 /* OS private Information. */
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 {
128 /* Basic: swi tidyexception + event; mov pc, lr;
129 ldmia r11,{r11,pc}; swi generateexception + event. */
130 0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /* Reset */
131 0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /* Undef */
132 0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /* SWI */
133 0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /* Prefetch abort */
134 0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /* Data abort */
135 0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /* Address exception */
136 0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /* IRQ */
137 0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /* FIQ */
138 0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /* Error */
139 0xe1a0f00e /* Default handler */
140 };
141
142
143 /* Set to prevent aborts when emulating SWI routines. */
144 static int in_SWI_handler = 0;
145
146 /* Time for the Operating System to initialise itself. */
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 {
158 state->OSptr = (unsigned char *) malloc (sizeof (struct OSblock));
159 if (state->OSptr == NULL)
160 {
161 perror ("OS Memory");
162 exit (15);
163 }
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 ARMul_SetReg (state, SYSTEMMODE, 13, ADDRSUPERSTACK); /* and for system mode */
173 instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8); /* load pc from soft vector */
174
175 for (i = ARMul_ResetV; i <= ARMFIQV; i += 4)
176 ARMul_WriteWord (state, i, instr); /* write hardware vectors */
177
178 SWI_vector_installed = 0;
179
180 for (i = ARMul_ResetV; i <= ARMFIQV + 4; i += 4)
181 {
182 ARMul_WriteWord (state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
183 ARMul_WriteWord (state, ADDRSOFHANDLERS + 2 * i + 4L,
184 SOFTVECTORCODE + sizeof (softvectorcode) - 4L);
185 }
186
187 for (i = 0; i < sizeof (softvectorcode); i += 4)
188 ARMul_WriteWord (state, SOFTVECTORCODE + i, softvectorcode[i / 4]);
189
190 for (i = 0; i < FOPEN_MAX; i++)
191 OSptr->FileTable[i] = NULL;
192
193 for (i = 0; i < UNIQUETEMPS; i++)
194 OSptr->tempnames[i] = NULL;
195
196 ARMul_ConsolePrint (state, ", Demon 1.01");
197
198 /* #ifndef ASIM */
199
200 /* install fpe */
201 for (i = 0; i < fpesize; i += 4) /* copy the code */
202 ARMul_WriteWord (state, FPESTART + i, fpecode[i >> 2]);
203
204 for (i = FPESTART + fpesize;; i -= 4)
205 { /* reverse the error strings */
206 if ((j = ARMul_ReadWord (state, i)) == 0xffffffff)
207 break;
208 if (state->bigendSig && j < 0x80000000)
209 { /* it's part of the string so swap it */
210 j = ((j >> 0x18) & 0x000000ff) |
211 ((j >> 0x08) & 0x0000ff00) |
212 ((j << 0x08) & 0x00ff0000) | ((j << 0x18) & 0xff000000);
213 ARMul_WriteWord (state, i, j);
214 }
215 }
216
217 ARMul_WriteWord (state, FPEOLDVECT, ARMul_ReadWord (state, 4)); /* copy old illegal instr vector */
218 ARMul_WriteWord (state, 4, FPENEWVECT (ARMul_ReadWord (state, i - 4))); /* install new vector */
219 ARMul_ConsolePrint (state, ", FPE");
220
221 /* #endif ASIM */
222 #endif /* VALIDATE */
223 #endif /* NOOS */
224
225 return TRUE;
226 }
227
228 void
229 ARMul_OSExit (ARMul_State * state)
230 {
231 free ((char *) state->OSptr);
232 }
233
234
235 /* Return the last Operating System Error. */
236
237 ARMword ARMul_OSLastErrorP (ARMul_State * state)
238 {
239 return ((struct OSblock *) state->OSptr)->ErrorP;
240 }
241
242 static int translate_open_mode[] =
243 {
244 O_RDONLY, /* "r" */
245 O_RDONLY + O_BINARY, /* "rb" */
246 O_RDWR, /* "r+" */
247 O_RDWR + O_BINARY, /* "r+b" */
248 O_WRONLY + O_CREAT + O_TRUNC, /* "w" */
249 O_WRONLY + O_BINARY + O_CREAT + O_TRUNC, /* "wb" */
250 O_RDWR + O_CREAT + O_TRUNC, /* "w+" */
251 O_RDWR + O_BINARY + O_CREAT + O_TRUNC, /* "w+b" */
252 O_WRONLY + O_APPEND + O_CREAT, /* "a" */
253 O_WRONLY + O_BINARY + O_APPEND + O_CREAT, /* "ab" */
254 O_RDWR + O_APPEND + O_CREAT, /* "a+" */
255 O_RDWR + O_BINARY + O_APPEND + O_CREAT /* "a+b" */
256 };
257
258 static void
259 SWIWrite0 (ARMul_State * state, ARMword addr)
260 {
261 ARMword temp;
262 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
263
264 while ((temp = ARMul_ReadByte (state, addr++)) != 0)
265 (void) fputc ((char) temp, stdout);
266
267 OSptr->ErrorNo = errno;
268 }
269
270 static void
271 WriteCommandLineTo (ARMul_State * state, ARMword addr)
272 {
273 ARMword temp;
274 char *cptr = state->CommandLine;
275
276 if (cptr == NULL)
277 cptr = "\0";
278 do
279 {
280 temp = (ARMword) * cptr++;
281 ARMul_WriteByte (state, addr++, temp);
282 }
283 while (temp != 0);
284 }
285
286 static void
287 SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
288 {
289 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
290 char dummy[2000];
291 int flags;
292 int i;
293
294 for (i = 0; (dummy[i] = ARMul_ReadByte (state, name + i)); i++)
295 ;
296
297 /* Now we need to decode the Demon open mode. */
298 flags = translate_open_mode[SWIflags];
299
300 /* Filename ":tt" is special: it denotes stdin/out. */
301 if (strcmp (dummy, ":tt") == 0)
302 {
303 if (flags == O_RDONLY) /* opening tty "r" */
304 state->Reg[0] = 0; /* stdin */
305 else
306 state->Reg[0] = 1; /* stdout */
307 }
308 else
309 {
310 state->Reg[0] = (int) open (dummy, flags, 0666);
311 OSptr->ErrorNo = errno;
312 }
313 }
314
315 static void
316 SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
317 {
318 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
319 int res;
320 int i;
321 char *local = malloc (len);
322
323 if (local == NULL)
324 {
325 fprintf (stderr, "sim: Unable to read 0x%ulx bytes - out of memory\n",
326 len);
327 return;
328 }
329
330 res = read (f, local, len);
331 if (res > 0)
332 for (i = 0; i < res; i++)
333 ARMul_WriteByte (state, ptr + i, local[i]);
334
335 free (local);
336 state->Reg[0] = res == -1 ? -1 : len - res;
337 OSptr->ErrorNo = errno;
338 }
339
340 static void
341 SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
342 {
343 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
344 int res;
345 ARMword i;
346 char *local = malloc (len);
347
348 if (local == NULL)
349 {
350 fprintf (stderr, "sim: Unable to write 0x%lx bytes - out of memory\n",
351 (long) len);
352 return;
353 }
354
355 for (i = 0; i < len; i++)
356 local[i] = ARMul_ReadByte (state, ptr + i);
357
358 res = write (f, local, len);
359 state->Reg[0] = res == -1 ? -1 : len - res;
360 free (local);
361
362 OSptr->ErrorNo = errno;
363 }
364
365 static void
366 SWIflen (ARMul_State * state, ARMword fh)
367 {
368 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
369 ARMword addr;
370
371 if (fh == 0 || fh > FOPEN_MAX)
372 {
373 OSptr->ErrorNo = EBADF;
374 state->Reg[0] = -1L;
375 return;
376 }
377
378 addr = lseek (fh, 0, SEEK_CUR);
379
380 state->Reg[0] = lseek (fh, 0L, SEEK_END);
381 (void) lseek (fh, addr, SEEK_SET);
382
383 OSptr->ErrorNo = errno;
384 }
385
386 /* The emulator calls this routine when a SWI instruction is encuntered.
387 The parameter passed is the SWI number (lower 24 bits of the instruction). */
388
389 unsigned
390 ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
391 {
392 ARMword addr;
393 ARMword temp;
394 ARMword saved_number = 0;
395 struct OSblock * OSptr = (struct OSblock *) state->OSptr;
396
397 in_SWI_handler = 1;
398
399 /* Intel do not want DEMON SWI support. */
400 if (state->is_XScale)
401 switch (number)
402 {
403 case SWI_Read:
404 case SWI_Write:
405 case SWI_Open:
406 case SWI_Clock:
407 case SWI_Time:
408 case SWI_Close:
409 case SWI_Flen:
410 case SWI_Exit:
411 case SWI_Seek:
412 case SWI_WriteC:
413 case SWI_Write0:
414 case SWI_GetErrno:
415 case SWI_GetEnv:
416 saved_number = number;
417 number = -1;
418 default:
419 break;
420 }
421
422 switch (number)
423 {
424 case SWI_Read:
425 SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
426 break;
427
428 case SWI_Write:
429 SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
430 break;
431
432 case SWI_Open:
433 SWIopen (state, state->Reg[0], state->Reg[1]);
434 break;
435
436 case SWI_Clock:
437 /* Return number of centi-seconds. */
438 state->Reg[0] =
439 #ifdef CLOCKS_PER_SEC
440 (CLOCKS_PER_SEC >= 100)
441 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
442 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
443 #else
444 /* Presume unix... clock() returns microseconds. */
445 (ARMword) (clock () / 10000);
446 #endif
447 OSptr->ErrorNo = errno;
448 break;
449
450 case SWI_Time:
451 state->Reg[0] = (ARMword) time (NULL);
452 OSptr->ErrorNo = errno;
453 break;
454
455 case SWI_Close:
456 state->Reg[0] = close (state->Reg[0]);
457 OSptr->ErrorNo = errno;
458 break;
459
460 case SWI_Flen:
461 SWIflen (state, state->Reg[0]);
462 break;
463
464 case SWI_Exit:
465 state->Emulate = FALSE;
466 break;
467
468 case SWI_Seek:
469 /* We must return non-zero for failure. */
470 state->Reg[0] = -1 >= lseek (state->Reg[0], state->Reg[1], SEEK_SET);
471 OSptr->ErrorNo = errno;
472 break;
473
474 case SWI_WriteC:
475 (void) fputc ((int) state->Reg[0], stdout);
476 OSptr->ErrorNo = errno;
477 break;
478
479 case SWI_Write0:
480 SWIWrite0 (state, state->Reg[0]);
481 break;
482
483 case SWI_GetErrno:
484 state->Reg[0] = OSptr->ErrorNo;
485 break;
486
487 case SWI_GetEnv:
488 state->Reg[0] = ADDRCMDLINE;
489 if (state->MemSize)
490 state->Reg[1] = state->MemSize;
491 else
492 state->Reg[1] = ADDRUSERSTACK;
493
494 WriteCommandLineTo (state, state->Reg[0]);
495 break;
496
497 case SWI_Breakpoint:
498 state->EndCondition = RDIError_BreakpointReached;
499 state->Emulate = FALSE;
500 break;
501
502 /* Handle Angel SWIs as well as Demon ones. */
503 case AngelSWI_ARM:
504 case AngelSWI_Thumb:
505 /* R1 is almost always a parameter block. */
506 addr = state->Reg[1];
507 /* R0 is a reason code. */
508 switch (state->Reg[0])
509 {
510 /* Unimplemented reason codes. */
511 case AngelSWI_Reason_ReadC:
512 case AngelSWI_Reason_IsTTY:
513 case AngelSWI_Reason_TmpNam:
514 case AngelSWI_Reason_Remove:
515 case AngelSWI_Reason_Rename:
516 case AngelSWI_Reason_System:
517 case AngelSWI_Reason_EnterSVC:
518 default:
519 state->Emulate = FALSE;
520 in_SWI_handler = 0;
521 return FALSE;
522
523 case AngelSWI_Reason_Clock:
524 /* Return number of centi-seconds. */
525 state->Reg[0] =
526 #ifdef CLOCKS_PER_SEC
527 (CLOCKS_PER_SEC >= 100)
528 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
529 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
530 #else
531 /* Presume unix... clock() returns microseconds. */
532 (ARMword) (clock () / 10000);
533 #endif
534 OSptr->ErrorNo = errno;
535 break;
536
537 case AngelSWI_Reason_Time:
538 state->Reg[0] = (ARMword) time (NULL);
539 OSptr->ErrorNo = errno;
540 break;
541
542 case AngelSWI_Reason_WriteC:
543 (void) fputc ((int) ARMul_ReadByte (state, addr), stdout);
544 OSptr->ErrorNo = errno;
545
546 case AngelSWI_Reason_Write0:
547 SWIWrite0 (state, addr);
548 break;
549
550 case AngelSWI_Reason_Close:
551 state->Reg[0] = close (ARMul_ReadWord (state, addr));
552 OSptr->ErrorNo = errno;
553 break;
554
555 case AngelSWI_Reason_Seek:
556 state->Reg[0] = -1 >= lseek (ARMul_ReadWord (state, addr),
557 ARMul_ReadWord (state, addr + 4),
558 SEEK_SET);
559 OSptr->ErrorNo = errno;
560 break;
561
562 case AngelSWI_Reason_FLen:
563 SWIflen (state, ARMul_ReadWord (state, addr));
564 break;
565
566 case AngelSWI_Reason_GetCmdLine:
567 WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
568 break;
569
570 case AngelSWI_Reason_HeapInfo:
571 /* R1 is a pointer to a pointer. */
572 addr = ARMul_ReadWord (state, addr);
573
574 /* Pick up the right memory limit. */
575 if (state->MemSize)
576 temp = state->MemSize;
577 else
578 temp = ADDRUSERSTACK;
579
580 ARMul_WriteWord (state, addr, 0); /* Heap base */
581 ARMul_WriteWord (state, addr + 4, temp); /* Heap limit */
582 ARMul_WriteWord (state, addr + 8, temp); /* Stack base */
583 ARMul_WriteWord (state, addr + 12, temp); /* Stack limit */
584 break;
585
586 case AngelSWI_Reason_ReportException:
587 if (state->Reg[1] == ADP_Stopped_ApplicationExit)
588 state->Reg[0] = 0;
589 else
590 state->Reg[0] = -1;
591 state->Emulate = FALSE;
592 break;
593
594 case ADP_Stopped_ApplicationExit:
595 state->Reg[0] = 0;
596 state->Emulate = FALSE;
597 break;
598
599 case ADP_Stopped_RunTimeError:
600 state->Reg[0] = -1;
601 state->Emulate = FALSE;
602 break;
603
604 case AngelSWI_Reason_Errno:
605 state->Reg[0] = OSptr->ErrorNo;
606 break;
607
608 case AngelSWI_Reason_Open:
609 SWIopen (state,
610 ARMul_ReadWord (state, addr),
611 ARMul_ReadWord (state, addr + 4));
612 break;
613
614 case AngelSWI_Reason_Read:
615 SWIread (state,
616 ARMul_ReadWord (state, addr),
617 ARMul_ReadWord (state, addr + 4),
618 ARMul_ReadWord (state, addr + 8));
619 break;
620
621 case AngelSWI_Reason_Write:
622 SWIwrite (state,
623 ARMul_ReadWord (state, addr),
624 ARMul_ReadWord (state, addr + 4),
625 ARMul_ReadWord (state, addr + 8));
626 break;
627 }
628
629 case 0x90:
630 case 0x91:
631 case 0x92:
632 /* These are used by the FPE code. */
633 break;
634
635 default:
636 in_SWI_handler = 0;
637
638 /* If there is a SWI vector installed use it. */
639 if (state->is_XScale && saved_number != -1)
640 number = saved_number;
641
642 if (SWI_vector_installed && number != SWI_Breakpoint)
643 {
644 ARMword cpsr;
645 ARMword i_size;
646
647 cpsr = ARMul_GetCPSR (state);
648 i_size = INSN_SIZE;
649
650 ARMul_SetSPSR (state, SVC32MODE, cpsr);
651
652 cpsr &= ~0xbf;
653 cpsr |= SVC32MODE | 0x80;
654 ARMul_SetCPSR (state, cpsr);
655
656 state->RegBank[SVCBANK][14] = state->Reg[14] = state->Reg[15] - i_size;
657 state->NextInstr = RESUME;
658 state->Reg[15] = state->pc = ARMSWIV;
659 FLUSHPIPE;
660 }
661 else
662 {
663 fprintf (stderr, "unknown SWI encountered - %x - ignoring\n", number);
664 return FALSE;
665 }
666 }
667
668 in_SWI_handler = 0;
669 return TRUE;
670 }
671
672 #ifndef NOOS
673 #ifndef ASIM
674
675 /* The emulator calls this routine when an Exception occurs. The second
676 parameter is the address of the relevant exception vector. Returning
677 FALSE from this routine causes the trap to be taken, TRUE causes it to
678 be ignored (so set state->Emulate to FALSE!). */
679
680 unsigned
681 ARMul_OSException (ARMul_State * state ATTRIBUTE_UNUSED,
682 ARMword vector ATTRIBUTE_UNUSED,
683 ARMword pc ATTRIBUTE_UNUSED)
684 {
685 /* If we are inside a SWI handler routine, then ignore any exceptions.
686 They could be caused by data exceptions for misaligned reads, for
687 example, but for the purposes of emulating a SWI, we do not care. */
688
689 return in_SWI_handler;
690 }
691
692 #endif
693 #endif /* NOOS */
This page took 0.072188 seconds and 4 git commands to generate.