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