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