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