Detect installation of SWI vector by running program as well as loading program.
[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_ReadByte (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_WriteByte (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_ReadByte (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_WriteByte (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_ReadByte (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, temp;
389 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
390 ARMword saved_number = 0;
391
392 /* Intel do not want DEMON SWI support. */
393 if (state->is_XScale)
394 switch (number)
395 {
396 case SWI_Read:
397 case SWI_Write:
398 case SWI_Open:
399 case SWI_Clock:
400 case SWI_Time:
401 case SWI_Close:
402 case SWI_Flen:
403 case SWI_Exit:
404 case SWI_Seek:
405 case SWI_WriteC:
406 case SWI_Write0:
407 case SWI_GetErrno:
408 case SWI_GetEnv:
409 saved_number = number;
410 number = -1;
411 default:
412 break;
413 }
414
415 switch (number)
416 {
417 case SWI_Read:
418 SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
419 return TRUE;
420
421 case SWI_Write:
422 SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
423 return TRUE;
424
425 case SWI_Open:
426 SWIopen (state, state->Reg[0], state->Reg[1]);
427 return TRUE;
428
429 case SWI_Clock:
430 /* Return number of centi-seconds. */
431 state->Reg[0] =
432 #ifdef CLOCKS_PER_SEC
433 (CLOCKS_PER_SEC >= 100)
434 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
435 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
436 #else
437 /* Presume unix... clock() returns microseconds. */
438 (ARMword) (clock () / 10000);
439 #endif
440 OSptr->ErrorNo = errno;
441 return TRUE;
442
443 case SWI_Time:
444 state->Reg[0] = (ARMword) time (NULL);
445 OSptr->ErrorNo = errno;
446 return TRUE;
447
448 case SWI_Close:
449 state->Reg[0] = close (state->Reg[0]);
450 OSptr->ErrorNo = errno;
451 return TRUE;
452
453 case SWI_Flen:
454 SWIflen (state, state->Reg[0]);
455 return TRUE;
456
457 case SWI_Exit:
458 state->Emulate = FALSE;
459 return TRUE;
460
461 case SWI_Seek:
462 {
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 return TRUE;
467 }
468
469 case SWI_WriteC:
470 (void) fputc ((int) state->Reg[0], stdout);
471 OSptr->ErrorNo = errno;
472 return TRUE;
473
474 case SWI_Write0:
475 SWIWrite0 (state, state->Reg[0]);
476 return TRUE;
477
478 case SWI_GetErrno:
479 state->Reg[0] = OSptr->ErrorNo;
480 return TRUE;
481
482 case SWI_GetEnv:
483 state->Reg[0] = ADDRCMDLINE;
484 if (state->MemSize)
485 state->Reg[1] = state->MemSize;
486 else
487 state->Reg[1] = ADDRUSERSTACK;
488
489 WriteCommandLineTo (state, state->Reg[0]);
490 return TRUE;
491
492 case SWI_Breakpoint:
493 state->EndCondition = RDIError_BreakpointReached;
494 state->Emulate = FALSE;
495 return TRUE;
496
497 /* Handle Angel SWIs as well as Demon ones. */
498 case AngelSWI_ARM:
499 case AngelSWI_Thumb:
500 /* R1 is almost always a parameter block. */
501 addr = state->Reg[1];
502 /* R0 is a reason code. */
503 switch (state->Reg[0])
504 {
505 /* Unimplemented reason codes. */
506 case AngelSWI_Reason_ReadC:
507 case AngelSWI_Reason_IsTTY:
508 case AngelSWI_Reason_TmpNam:
509 case AngelSWI_Reason_Remove:
510 case AngelSWI_Reason_Rename:
511 case AngelSWI_Reason_System:
512 case AngelSWI_Reason_EnterSVC:
513 default:
514 state->Emulate = FALSE;
515 return FALSE;
516
517 case AngelSWI_Reason_Clock:
518 /* Return number of centi-seconds. */
519 state->Reg[0] =
520 #ifdef CLOCKS_PER_SEC
521 (CLOCKS_PER_SEC >= 100)
522 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
523 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
524 #else
525 /* Presume unix... clock() returns microseconds. */
526 (ARMword) (clock () / 10000);
527 #endif
528 OSptr->ErrorNo = errno;
529 return TRUE;
530
531 case AngelSWI_Reason_Time:
532 state->Reg[0] = (ARMword) time (NULL);
533 OSptr->ErrorNo = errno;
534 return TRUE;
535
536 case AngelSWI_Reason_WriteC:
537 (void) fputc ((int) ARMul_ReadByte (state, addr), stdout);
538 OSptr->ErrorNo = errno;
539 return TRUE;
540
541 case AngelSWI_Reason_Write0:
542 SWIWrite0 (state, addr);
543 return TRUE;
544
545 case AngelSWI_Reason_Close:
546 state->Reg[0] = close (ARMul_ReadWord (state, addr));
547 OSptr->ErrorNo = errno;
548 return TRUE;
549
550 case AngelSWI_Reason_Seek:
551 state->Reg[0] = -1 >= lseek (ARMul_ReadWord (state, addr),
552 ARMul_ReadWord (state, addr + 4),
553 SEEK_SET);
554 OSptr->ErrorNo = errno;
555 return TRUE;
556
557 case AngelSWI_Reason_FLen:
558 SWIflen (state, ARMul_ReadWord (state, addr));
559 return TRUE;
560
561 case AngelSWI_Reason_GetCmdLine:
562 WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
563 return TRUE;
564
565 case AngelSWI_Reason_HeapInfo:
566 /* R1 is a pointer to a pointer. */
567 addr = ARMul_ReadWord (state, addr);
568
569 /* Pick up the right memory limit. */
570 if (state->MemSize)
571 temp = state->MemSize;
572 else
573 temp = ADDRUSERSTACK;
574
575 ARMul_WriteWord (state, addr, 0); /* Heap base */
576 ARMul_WriteWord (state, addr + 4, temp); /* Heap limit */
577 ARMul_WriteWord (state, addr + 8, temp); /* Stack base */
578 ARMul_WriteWord (state, addr + 12, temp); /* Stack limit */
579 return TRUE;
580
581 case AngelSWI_Reason_ReportException:
582 if (state->Reg[1] == ADP_Stopped_ApplicationExit)
583 state->Reg[0] = 0;
584 else
585 state->Reg[0] = -1;
586 state->Emulate = FALSE;
587 return TRUE;
588
589 case ADP_Stopped_ApplicationExit:
590 state->Reg[0] = 0;
591 state->Emulate = FALSE;
592 return TRUE;
593
594 case ADP_Stopped_RunTimeError:
595 state->Reg[0] = -1;
596 state->Emulate = FALSE;
597 return TRUE;
598
599 case AngelSWI_Reason_Errno:
600 state->Reg[0] = OSptr->ErrorNo;
601 return TRUE;
602
603 case AngelSWI_Reason_Open:
604 SWIopen (state,
605 ARMul_ReadWord (state, addr),
606 ARMul_ReadWord (state, addr + 4));
607 return TRUE;
608
609 case AngelSWI_Reason_Read:
610 SWIread (state,
611 ARMul_ReadWord (state, addr),
612 ARMul_ReadWord (state, addr + 4),
613 ARMul_ReadWord (state, addr + 8));
614 return TRUE;
615
616 case AngelSWI_Reason_Write:
617 SWIwrite (state,
618 ARMul_ReadWord (state, addr),
619 ARMul_ReadWord (state, addr + 4),
620 ARMul_ReadWord (state, addr + 8));
621 return TRUE;
622 }
623
624 case 0x90:
625 case 0x91:
626 case 0x92:
627 /* These are used by the FPE code. */
628 return TRUE;
629
630 default:
631 {
632 /* If there is a SWI vector installed use it. */
633 if (state->is_XScale && saved_number != -1)
634 number = saved_number;
635
636 if (SWI_vector_installed && number != SWI_Breakpoint)
637 {
638 ARMword cpsr;
639 ARMword i_size;
640
641 cpsr = ARMul_GetCPSR (state);
642 i_size = INSN_SIZE;
643
644 ARMul_SetSPSR (state, SVC32MODE, cpsr);
645
646 cpsr &= ~0xbf;
647 cpsr |= SVC32MODE | 0x80;
648 ARMul_SetCPSR (state, cpsr);
649
650 state->RegBank[SVCBANK][14] = state->Reg[14] = state->Reg[15] - i_size;
651 state->NextInstr = RESUME;
652 state->Reg[15] = state->pc = ARMSWIV;
653 FLUSHPIPE;
654 }
655 else
656 fprintf (stderr, "unknown SWI encountered - %x - ignoring\n", number);
657 return TRUE;
658 }
659 }
660 }
661
662 #ifndef NOOS
663 #ifndef ASIM
664
665 /* The emulator calls this routine when an Exception occurs. The second
666 parameter is the address of the relevant exception vector. Returning
667 FALSE from this routine causes the trap to be taken, TRUE causes it to
668 be ignored (so set state->Emulate to FALSE!). */
669
670 unsigned
671 ARMul_OSException (ARMul_State * state ATTRIBUTE_UNUSED,
672 ARMword vector ATTRIBUTE_UNUSED,
673 ARMword pc ATTRIBUTE_UNUSED)
674 {
675 return FALSE;
676 }
677
678 #endif
679 #endif /* NOOS */
This page took 0.048408 seconds and 4 git commands to generate.