5c26b2b0b9a7a961825f066cd200b1116114476f
[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 "targ-vals.h"
32
33 #ifndef TARGET_O_BINARY
34 #define TARGET_O_BINARY 0
35 #endif
36
37 #ifdef __STDC__
38 #define unlink(s) remove(s)
39 #endif
40
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h> /* For SEEK_SET etc. */
43 #endif
44
45 #ifdef __riscos
46 extern int _fisatty (FILE *);
47 #define isatty_(f) _fisatty(f)
48 #else
49 #ifdef __ZTC__
50 #include <io.h>
51 #define isatty_(f) isatty((f)->_file)
52 #else
53 #ifdef macintosh
54 #include <ioctl.h>
55 #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
56 #else
57 #define isatty_(f) isatty (fileno (f))
58 #endif
59 #endif
60 #endif
61
62 #include "armdefs.h"
63 #include "armos.h"
64 #include "armemu.h"
65
66 #ifndef NOOS
67 #ifndef VALIDATE
68 /* #ifndef ASIM */
69 #include "armfpe.h"
70 /* #endif */
71 #endif
72 #endif
73
74 /* For RDIError_BreakpointReached. */
75 #include "dbg_rdi.h"
76
77 #include "gdb/callback.h"
78 extern host_callback *sim_callback;
79
80 extern unsigned ARMul_OSInit (ARMul_State *);
81 extern void ARMul_OSExit (ARMul_State *);
82 extern unsigned ARMul_OSHandleSWI (ARMul_State *, ARMword);
83 extern unsigned ARMul_OSException (ARMul_State *, ARMword, ARMword);
84 extern ARMword ARMul_OSLastErrorP (ARMul_State *);
85 extern ARMword ARMul_Debug (ARMul_State *, ARMword, ARMword);
86
87 #define BUFFERSIZE 4096
88 #ifndef FOPEN_MAX
89 #define FOPEN_MAX 64
90 #endif
91 #define UNIQUETEMPS 256
92
93 /* OS private Information. */
94
95 struct OSblock
96 {
97 ARMword Time0;
98 ARMword ErrorP;
99 ARMword ErrorNo;
100 FILE *FileTable[FOPEN_MAX];
101 char FileFlags[FOPEN_MAX];
102 char *tempnames[UNIQUETEMPS];
103 };
104
105 #define NOOP 0
106 #define BINARY 1
107 #define READOP 2
108 #define WRITEOP 4
109
110 #ifdef macintosh
111 #define FIXCRLF(t,c) ((t & BINARY) ? \
112 c : \
113 ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \
114 )
115 #else
116 #define FIXCRLF(t,c) c
117 #endif
118
119 /* Bit mask of enabled SWI implementations. */
120 unsigned int swi_mask = -1;
121
122
123 static ARMword softvectorcode[] =
124 {
125 /* Installed instructions:
126 swi tidyexception + event;
127 mov lr, pc;
128 ldmia fp, {fp, pc};
129 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 /* Write hardware vectors. */
173 ARMul_WriteWord (state, i, instr);
174
175 SWI_vector_installed = 0;
176
177 for (i = ARMul_ResetV; i <= ARMFIQV + 4; i += 4)
178 {
179 ARMul_WriteWord (state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
180 ARMul_WriteWord (state, ADDRSOFHANDLERS + 2 * i + 4L,
181 SOFTVECTORCODE + sizeof (softvectorcode) - 4L);
182 }
183
184 for (i = 0; i < sizeof (softvectorcode); i += 4)
185 ARMul_WriteWord (state, SOFTVECTORCODE + i, softvectorcode[i / 4]);
186
187 for (i = 0; i < FOPEN_MAX; i++)
188 OSptr->FileTable[i] = NULL;
189
190 for (i = 0; i < UNIQUETEMPS; i++)
191 OSptr->tempnames[i] = NULL;
192
193 ARMul_ConsolePrint (state, ", Demon 1.01");
194
195 /* #ifndef ASIM */
196
197 /* Install FPE. */
198 for (i = 0; i < fpesize; i += 4)
199 /* Copy the code. */
200 ARMul_WriteWord (state, FPESTART + i, fpecode[i >> 2]);
201
202 /* Scan backwards from the end of the code. */
203 for (i = FPESTART + fpesize;; i -= 4)
204 {
205 /* When we reach the marker value, break out of
206 the loop, leaving i pointing at the maker. */
207 if ((j = ARMul_ReadWord (state, i)) == 0xffffffff)
208 break;
209
210 /* If necessary, reverse the error strings. */
211 if (state->bigendSig && j < 0x80000000)
212 {
213 /* It's part of the string so swap it. */
214 j = ((j >> 0x18) & 0x000000ff) |
215 ((j >> 0x08) & 0x0000ff00) |
216 ((j << 0x08) & 0x00ff0000) | ((j << 0x18) & 0xff000000);
217 ARMul_WriteWord (state, i, j);
218 }
219 }
220
221 /* Copy old illegal instr vector. */
222 ARMul_WriteWord (state, FPEOLDVECT, ARMul_ReadWord (state, ARMUndefinedInstrV));
223 /* Install new vector. */
224 ARMul_WriteWord (state, ARMUndefinedInstrV, FPENEWVECT (ARMul_ReadWord (state, i - 4)));
225 ARMul_ConsolePrint (state, ", FPE");
226
227 /* #endif ASIM */
228 #endif /* VALIDATE */
229 #endif /* NOOS */
230
231 /* Intel do not want DEMON SWI support. */
232 if (state->is_XScale)
233 swi_mask = SWI_MASK_ANGEL;
234
235 return TRUE;
236 }
237
238 void
239 ARMul_OSExit (ARMul_State * state)
240 {
241 free ((char *) state->OSptr);
242 }
243
244
245 /* Return the last Operating System Error. */
246
247 ARMword ARMul_OSLastErrorP (ARMul_State * state)
248 {
249 return ((struct OSblock *) state->OSptr)->ErrorP;
250 }
251
252 static int translate_open_mode[] =
253 {
254 TARGET_O_RDONLY, /* "r" */
255 TARGET_O_RDONLY + TARGET_O_BINARY, /* "rb" */
256 TARGET_O_RDWR, /* "r+" */
257 TARGET_O_RDWR + TARGET_O_BINARY, /* "r+b" */
258 TARGET_O_WRONLY + TARGET_O_CREAT + TARGET_O_TRUNC, /* "w" */
259 TARGET_O_WRONLY + TARGET_O_BINARY + TARGET_O_CREAT + TARGET_O_TRUNC, /* "wb" */
260 TARGET_O_RDWR + TARGET_O_CREAT + TARGET_O_TRUNC, /* "w+" */
261 TARGET_O_RDWR + TARGET_O_BINARY + TARGET_O_CREAT + TARGET_O_TRUNC, /* "w+b" */
262 TARGET_O_WRONLY + TARGET_O_APPEND + TARGET_O_CREAT, /* "a" */
263 TARGET_O_WRONLY + TARGET_O_BINARY + TARGET_O_APPEND + TARGET_O_CREAT, /* "ab" */
264 TARGET_O_RDWR + TARGET_O_APPEND + TARGET_O_CREAT, /* "a+" */
265 TARGET_O_RDWR + TARGET_O_BINARY + TARGET_O_APPEND + TARGET_O_CREAT /* "a+b" */
266 };
267
268 static void
269 SWIWrite0 (ARMul_State * state, ARMword addr)
270 {
271 ARMword temp;
272 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
273
274 while ((temp = ARMul_SafeReadByte (state, addr++)) != 0)
275 {
276 char buffer = temp;
277 /* Note - we cannot just cast 'temp' to a (char *) here,
278 since on a big-endian host the byte value will end
279 up in the wrong place and a nul character will be printed. */
280 (void) sim_callback->write_stdout (sim_callback, & buffer, 1);
281 }
282
283 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
284 }
285
286 static void
287 WriteCommandLineTo (ARMul_State * state, ARMword addr)
288 {
289 ARMword temp;
290 char *cptr = state->CommandLine;
291
292 if (cptr == NULL)
293 cptr = "\0";
294 do
295 {
296 temp = (ARMword) * cptr++;
297 ARMul_SafeWriteByte (state, addr++, temp);
298 }
299 while (temp != 0);
300 }
301
302 static void
303 SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
304 {
305 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
306 char dummy[2000];
307 int flags;
308 int i;
309
310 for (i = 0; (dummy[i] = ARMul_SafeReadByte (state, name + i)); i++)
311 ;
312
313 /* Now we need to decode the Demon open mode. */
314 flags = translate_open_mode[SWIflags];
315
316 /* Filename ":tt" is special: it denotes stdin/out. */
317 if (strcmp (dummy, ":tt") == 0)
318 {
319 if (flags == TARGET_O_RDONLY) /* opening tty "r" */
320 state->Reg[0] = 0; /* stdin */
321 else
322 state->Reg[0] = 1; /* stdout */
323 }
324 else
325 {
326 state->Reg[0] = sim_callback->open (sim_callback, dummy, flags);
327 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
328 }
329 }
330
331 static void
332 SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
333 {
334 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
335 int res;
336 int i;
337 char *local = malloc (len);
338
339 if (local == NULL)
340 {
341 sim_callback->printf_filtered
342 (sim_callback,
343 "sim: Unable to read 0x%ulx bytes - out of memory\n",
344 len);
345 return;
346 }
347
348 res = sim_callback->read (sim_callback, f, local, len);
349 if (res > 0)
350 for (i = 0; i < res; i++)
351 ARMul_SafeWriteByte (state, ptr + i, local[i]);
352
353 free (local);
354 state->Reg[0] = res == -1 ? -1 : len - res;
355 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
356 }
357
358 static void
359 SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
360 {
361 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
362 int res;
363 ARMword i;
364 char *local = malloc (len);
365
366 if (local == NULL)
367 {
368 sim_callback->printf_filtered
369 (sim_callback,
370 "sim: Unable to write 0x%lx bytes - out of memory\n",
371 (long) len);
372 return;
373 }
374
375 for (i = 0; i < len; i++)
376 local[i] = ARMul_SafeReadByte (state, ptr + i);
377
378 res = sim_callback->write (sim_callback, f, local, len);
379 state->Reg[0] = res == -1 ? -1 : len - res;
380 free (local);
381
382 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
383 }
384
385 static void
386 SWIflen (ARMul_State * state, ARMword fh)
387 {
388 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
389 ARMword addr;
390
391 if (fh == 0 || fh > FOPEN_MAX)
392 {
393 OSptr->ErrorNo = EBADF;
394 state->Reg[0] = -1L;
395 return;
396 }
397
398 addr = sim_callback->lseek (sim_callback, fh, 0, SEEK_CUR);
399
400 state->Reg[0] = sim_callback->lseek (sim_callback, fh, 0L, SEEK_END);
401 (void) sim_callback->lseek (sim_callback, fh, addr, SEEK_SET);
402
403 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
404 }
405
406 /* The emulator calls this routine when a SWI instruction is encuntered.
407 The parameter passed is the SWI number (lower 24 bits of the instruction). */
408
409 unsigned
410 ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
411 {
412 struct OSblock * OSptr = (struct OSblock *) state->OSptr;
413 int unhandled = FALSE;
414
415 switch (number)
416 {
417 case SWI_Read:
418 if (swi_mask & SWI_MASK_DEMON)
419 SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
420 else
421 unhandled = TRUE;
422 break;
423
424 case SWI_Write:
425 if (swi_mask & SWI_MASK_DEMON)
426 SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
427 else
428 unhandled = TRUE;
429 break;
430
431 case SWI_Open:
432 if (swi_mask & SWI_MASK_DEMON)
433 SWIopen (state, state->Reg[0], state->Reg[1]);
434 else
435 unhandled = TRUE;
436 break;
437
438 case SWI_Clock:
439 if (swi_mask & SWI_MASK_DEMON)
440 {
441 /* Return number of centi-seconds. */
442 state->Reg[0] =
443 #ifdef CLOCKS_PER_SEC
444 (CLOCKS_PER_SEC >= 100)
445 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
446 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
447 #else
448 /* Presume unix... clock() returns microseconds. */
449 (ARMword) (clock () / 10000);
450 #endif
451 OSptr->ErrorNo = errno;
452 }
453 else
454 unhandled = TRUE;
455 break;
456
457 case SWI_Time:
458 if (swi_mask & SWI_MASK_DEMON)
459 {
460 state->Reg[0] = (ARMword) sim_callback->time (sim_callback, NULL);
461 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
462 }
463 else
464 unhandled = TRUE;
465 break;
466
467 case SWI_Close:
468 if (swi_mask & SWI_MASK_DEMON)
469 {
470 state->Reg[0] = sim_callback->close (sim_callback, state->Reg[0]);
471 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
472 }
473 else
474 unhandled = TRUE;
475 break;
476
477 case SWI_Flen:
478 if (swi_mask & SWI_MASK_DEMON)
479 SWIflen (state, state->Reg[0]);
480 else
481 unhandled = TRUE;
482 break;
483
484 case SWI_Exit:
485 if (swi_mask & SWI_MASK_DEMON)
486 state->Emulate = FALSE;
487 else
488 unhandled = TRUE;
489 break;
490
491 case SWI_Seek:
492 if (swi_mask & SWI_MASK_DEMON)
493 {
494 /* We must return non-zero for failure. */
495 state->Reg[0] = -1 >= sim_callback->lseek (sim_callback, state->Reg[0], state->Reg[1], SEEK_SET);
496 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
497 }
498 else
499 unhandled = TRUE;
500 break;
501
502 case SWI_WriteC:
503 if (swi_mask & SWI_MASK_DEMON)
504 {
505 char tmp = state->Reg[0];
506 (void) sim_callback->write_stdout (sim_callback, &tmp, 1);
507 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
508 }
509 else
510 unhandled = TRUE;
511 break;
512
513 case SWI_Write0:
514 if (swi_mask & SWI_MASK_DEMON)
515 SWIWrite0 (state, state->Reg[0]);
516 else
517 unhandled = TRUE;
518 break;
519
520 case SWI_GetErrno:
521 if (swi_mask & SWI_MASK_DEMON)
522 state->Reg[0] = OSptr->ErrorNo;
523 else
524 unhandled = TRUE;
525 break;
526
527 case SWI_GetEnv:
528 if (swi_mask & SWI_MASK_DEMON)
529 {
530 state->Reg[0] = ADDRCMDLINE;
531 if (state->MemSize)
532 state->Reg[1] = state->MemSize;
533 else
534 state->Reg[1] = ADDRUSERSTACK;
535
536 WriteCommandLineTo (state, state->Reg[0]);
537 }
538 else
539 unhandled = TRUE;
540 break;
541
542 case SWI_Breakpoint:
543 state->EndCondition = RDIError_BreakpointReached;
544 state->Emulate = FALSE;
545 break;
546
547 /* Handle Angel SWIs as well as Demon ones. */
548 case AngelSWI_ARM:
549 case AngelSWI_Thumb:
550 if (swi_mask & SWI_MASK_ANGEL)
551 {
552 ARMword addr;
553 ARMword temp;
554
555 /* R1 is almost always a parameter block. */
556 addr = state->Reg[1];
557 /* R0 is a reason code. */
558 switch (state->Reg[0])
559 {
560 case -1:
561 /* This can happen when a SWI is interrupted (eg receiving a
562 ctrl-C whilst processing SWIRead()). The SWI will complete
563 returning -1 in r0 to the caller. If GDB is then used to
564 resume the system call the reason code will now be -1. */
565 return TRUE;
566
567 /* Unimplemented reason codes. */
568 case AngelSWI_Reason_ReadC:
569 case AngelSWI_Reason_IsTTY:
570 case AngelSWI_Reason_TmpNam:
571 case AngelSWI_Reason_Remove:
572 case AngelSWI_Reason_Rename:
573 case AngelSWI_Reason_System:
574 case AngelSWI_Reason_EnterSVC:
575 default:
576 state->Emulate = FALSE;
577 return FALSE;
578
579 case AngelSWI_Reason_Clock:
580 /* Return number of centi-seconds. */
581 state->Reg[0] =
582 #ifdef CLOCKS_PER_SEC
583 (CLOCKS_PER_SEC >= 100)
584 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
585 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
586 #else
587 /* Presume unix... clock() returns microseconds. */
588 (ARMword) (clock () / 10000);
589 #endif
590 OSptr->ErrorNo = errno;
591 break;
592
593 case AngelSWI_Reason_Time:
594 state->Reg[0] = (ARMword) sim_callback->time (sim_callback, NULL);
595 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
596 break;
597
598 case AngelSWI_Reason_WriteC:
599 {
600 char tmp = ARMul_SafeReadByte (state, addr);
601 (void) sim_callback->write_stdout (sim_callback, &tmp, 1);
602 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
603 break;
604 }
605
606 case AngelSWI_Reason_Write0:
607 SWIWrite0 (state, addr);
608 break;
609
610 case AngelSWI_Reason_Close:
611 state->Reg[0] = sim_callback->close (sim_callback, ARMul_ReadWord (state, addr));
612 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
613 break;
614
615 case AngelSWI_Reason_Seek:
616 state->Reg[0] = -1 >= sim_callback->lseek (sim_callback, ARMul_ReadWord (state, addr),
617 ARMul_ReadWord (state, addr + 4),
618 SEEK_SET);
619 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
620 break;
621
622 case AngelSWI_Reason_FLen:
623 SWIflen (state, ARMul_ReadWord (state, addr));
624 break;
625
626 case AngelSWI_Reason_GetCmdLine:
627 WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
628 break;
629
630 case AngelSWI_Reason_HeapInfo:
631 /* R1 is a pointer to a pointer. */
632 addr = ARMul_ReadWord (state, addr);
633
634 /* Pick up the right memory limit. */
635 if (state->MemSize)
636 temp = state->MemSize;
637 else
638 temp = ADDRUSERSTACK;
639
640 ARMul_WriteWord (state, addr, 0); /* Heap base. */
641 ARMul_WriteWord (state, addr + 4, temp); /* Heap limit. */
642 ARMul_WriteWord (state, addr + 8, temp); /* Stack base. */
643 ARMul_WriteWord (state, addr + 12, temp); /* Stack limit. */
644 break;
645
646 case AngelSWI_Reason_ReportException:
647 if (state->Reg[1] == ADP_Stopped_ApplicationExit)
648 state->Reg[0] = 0;
649 else
650 state->Reg[0] = -1;
651 state->Emulate = FALSE;
652 break;
653
654 case ADP_Stopped_ApplicationExit:
655 state->Reg[0] = 0;
656 state->Emulate = FALSE;
657 break;
658
659 case ADP_Stopped_RunTimeError:
660 state->Reg[0] = -1;
661 state->Emulate = FALSE;
662 break;
663
664 case AngelSWI_Reason_Errno:
665 state->Reg[0] = OSptr->ErrorNo;
666 break;
667
668 case AngelSWI_Reason_Open:
669 SWIopen (state,
670 ARMul_ReadWord (state, addr),
671 ARMul_ReadWord (state, addr + 4));
672 break;
673
674 case AngelSWI_Reason_Read:
675 SWIread (state,
676 ARMul_ReadWord (state, addr),
677 ARMul_ReadWord (state, addr + 4),
678 ARMul_ReadWord (state, addr + 8));
679 break;
680
681 case AngelSWI_Reason_Write:
682 SWIwrite (state,
683 ARMul_ReadWord (state, addr),
684 ARMul_ReadWord (state, addr + 4),
685 ARMul_ReadWord (state, addr + 8));
686 break;
687 }
688 }
689 else
690 unhandled = TRUE;
691 break;
692
693 /* The following SWIs are generated by the softvectorcode[]
694 installed by default by the simulator. */
695 case 0x91: /* Undefined Instruction. */
696 {
697 ARMword addr = state->RegBank[UNDEFBANK][14] - 4;
698
699 sim_callback->printf_filtered
700 (sim_callback, "sim: exception: Unhandled Instruction '0x%08x' at 0x%08x. Stopping.\n",
701 ARMul_ReadWord (state, addr), addr);
702 state->EndCondition = RDIError_SoftwareInterrupt;
703 state->Emulate = FALSE;
704 return FALSE;
705 }
706
707 case 0x90: /* Reset. */
708 case 0x92: /* SWI. */
709 /* These two can be safely ignored. */
710 break;
711
712 case 0x93: /* Prefetch Abort. */
713 case 0x94: /* Data Abort. */
714 case 0x95: /* Address Exception. */
715 case 0x96: /* IRQ. */
716 case 0x97: /* FIQ. */
717 case 0x98: /* Error. */
718 unhandled = TRUE;
719 break;
720
721 case -1:
722 /* This can happen when a SWI is interrupted (eg receiving a
723 ctrl-C whilst processing SWIRead()). The SWI will complete
724 returning -1 in r0 to the caller. If GDB is then used to
725 resume the system call the reason code will now be -1. */
726 return TRUE;
727
728 case 0x180001: /* RedBoot's Syscall SWI in ARM mode. */
729 if (swi_mask & SWI_MASK_REDBOOT)
730 {
731 switch (state->Reg[0])
732 {
733 /* These numbers are defined in libgloss/syscall.h
734 but the simulator should not be dependend upon
735 libgloss being installed. */
736 case 1: /* Exit. */
737 state->Emulate = FALSE;
738 /* Copy exit code into r0. */
739 state->Reg[0] = state->Reg[1];
740 break;
741
742 case 2: /* Open. */
743 SWIopen (state, state->Reg[1], state->Reg[2]);
744 break;
745
746 case 3: /* Close. */
747 state->Reg[0] = sim_callback->close (sim_callback, state->Reg[1]);
748 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
749 break;
750
751 case 4: /* Read. */
752 SWIread (state, state->Reg[1], state->Reg[2], state->Reg[3]);
753 break;
754
755 case 5: /* Write. */
756 SWIwrite (state, state->Reg[1], state->Reg[2], state->Reg[3]);
757 break;
758
759 case 6: /* Lseek. */
760 state->Reg[0] = sim_callback->lseek (sim_callback,
761 state->Reg[1],
762 state->Reg[2],
763 state->Reg[3]);
764 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
765 break;
766
767 case 17: /* Utime. */
768 state->Reg[0] = (ARMword) sim_callback->time (sim_callback,
769 (long *) state->Reg[1]);
770 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
771 break;
772
773 case 7: /* Unlink. */
774 case 8: /* Getpid. */
775 case 9: /* Kill. */
776 case 10: /* Fstat. */
777 case 11: /* Sbrk. */
778 case 12: /* Argvlen. */
779 case 13: /* Argv. */
780 case 14: /* ChDir. */
781 case 15: /* Stat. */
782 case 16: /* Chmod. */
783 case 18: /* Time. */
784 sim_callback->printf_filtered
785 (sim_callback,
786 "sim: unhandled RedBoot syscall '%d' encountered - ignoring\n",
787 state->Reg[0]);
788 return FALSE;
789
790 default:
791 sim_callback->printf_filtered
792 (sim_callback,
793 "sim: unknown RedBoot syscall '%d' encountered - ignoring\n",
794 state->Reg[0]);
795 return FALSE;
796 }
797 break;
798 }
799
800 default:
801 unhandled = TRUE;
802 }
803
804 if (unhandled)
805 {
806 if (SWI_vector_installed)
807 {
808 ARMword cpsr;
809 ARMword i_size;
810
811 cpsr = ARMul_GetCPSR (state);
812 i_size = INSN_SIZE;
813
814 ARMul_SetSPSR (state, SVC32MODE, cpsr);
815
816 cpsr &= ~0xbf;
817 cpsr |= SVC32MODE | 0x80;
818 ARMul_SetCPSR (state, cpsr);
819
820 state->RegBank[SVCBANK][14] = state->Reg[14] = state->Reg[15] - i_size;
821 state->NextInstr = RESUME;
822 state->Reg[15] = state->pc = ARMSWIV;
823 FLUSHPIPE;
824 }
825 else
826 {
827 sim_callback->printf_filtered
828 (sim_callback,
829 "sim: unknown SWI encountered - %x - ignoring\n",
830 number);
831 return FALSE;
832 }
833 }
834
835 return TRUE;
836 }
837
838 #ifndef NOOS
839 #ifndef ASIM
840
841 /* The emulator calls this routine when an Exception occurs. The second
842 parameter is the address of the relevant exception vector. Returning
843 FALSE from this routine causes the trap to be taken, TRUE causes it to
844 be ignored (so set state->Emulate to FALSE!). */
845
846 unsigned
847 ARMul_OSException (ARMul_State * state ATTRIBUTE_UNUSED,
848 ARMword vector ATTRIBUTE_UNUSED,
849 ARMword pc ATTRIBUTE_UNUSED)
850 {
851 return FALSE;
852 }
853
854 #endif
855 #endif /* NOOS */
This page took 0.045826 seconds and 4 git commands to generate.