* configure.ac: Check for memmem declaration.
[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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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 <limits.h>
31 #include <string.h>
32 #include "targ-vals.h"
33
34 #ifndef TARGET_O_BINARY
35 #define TARGET_O_BINARY 0
36 #endif
37
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h> /* For SEEK_SET etc. */
40 #endif
41
42 #ifdef __riscos
43 extern int _fisatty (FILE *);
44 #define isatty_(f) _fisatty(f)
45 #else
46 #ifdef __ZTC__
47 #include <io.h>
48 #define isatty_(f) isatty((f)->_file)
49 #else
50 #ifdef macintosh
51 #include <ioctl.h>
52 #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
53 #else
54 #define isatty_(f) isatty (fileno (f))
55 #endif
56 #endif
57 #endif
58
59 #include "armdefs.h"
60 #include "armos.h"
61 #include "armemu.h"
62
63 #ifndef NOOS
64 #ifndef VALIDATE
65 /* #ifndef ASIM */
66 #include "armfpe.h"
67 /* #endif */
68 #endif
69 #endif
70
71 /* For RDIError_BreakpointReached. */
72 #include "dbg_rdi.h"
73
74 #include "gdb/callback.h"
75 extern host_callback *sim_callback;
76
77 extern unsigned ARMul_OSInit (ARMul_State *);
78 extern void ARMul_OSExit (ARMul_State *);
79 extern unsigned ARMul_OSHandleSWI (ARMul_State *, ARMword);
80 extern unsigned ARMul_OSException (ARMul_State *, ARMword, ARMword);
81 extern ARMword ARMul_OSLastErrorP (ARMul_State *);
82 extern ARMword ARMul_Debug (ARMul_State *, ARMword, ARMword);
83
84 #define BUFFERSIZE 4096
85 #ifndef FOPEN_MAX
86 #define FOPEN_MAX 64
87 #endif
88 #define UNIQUETEMPS 256
89 #ifndef PATH_MAX
90 #define PATH_MAX 1024
91 #endif
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 int
303 ReadFileName (ARMul_State * state, char *buf, ARMword src, size_t n)
304 {
305 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
306 char *p = buf;
307
308 while (n--)
309 if ((*p++ = ARMul_SafeReadByte (state, src++)) == '\0')
310 return 0;
311 OSptr->ErrorNo = cb_host_to_target_errno (sim_callback, ENAMETOOLONG);
312 state->Reg[0] = -1;
313 return -1;
314 }
315
316 static void
317 SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
318 {
319 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
320 char buf[PATH_MAX];
321 int flags;
322
323 if (ReadFileName (state, buf, name, sizeof buf) == -1)
324 return;
325
326 /* Now we need to decode the Demon open mode. */
327 flags = translate_open_mode[SWIflags];
328
329 /* Filename ":tt" is special: it denotes stdin/out. */
330 if (strcmp (buf, ":tt") == 0)
331 {
332 if (flags == TARGET_O_RDONLY) /* opening tty "r" */
333 state->Reg[0] = 0; /* stdin */
334 else
335 state->Reg[0] = 1; /* stdout */
336 }
337 else
338 {
339 state->Reg[0] = sim_callback->open (sim_callback, buf, flags);
340 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
341 }
342 }
343
344 static void
345 SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
346 {
347 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
348 int res;
349 int i;
350 char *local = malloc (len);
351
352 if (local == NULL)
353 {
354 sim_callback->printf_filtered
355 (sim_callback,
356 "sim: Unable to read 0x%ulx bytes - out of memory\n",
357 len);
358 return;
359 }
360
361 res = sim_callback->read (sim_callback, f, local, len);
362 if (res > 0)
363 for (i = 0; i < res; i++)
364 ARMul_SafeWriteByte (state, ptr + i, local[i]);
365
366 free (local);
367 state->Reg[0] = res == -1 ? -1 : len - res;
368 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
369 }
370
371 static void
372 SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
373 {
374 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
375 int res;
376 ARMword i;
377 char *local = malloc (len);
378
379 if (local == NULL)
380 {
381 sim_callback->printf_filtered
382 (sim_callback,
383 "sim: Unable to write 0x%lx bytes - out of memory\n",
384 (long) len);
385 return;
386 }
387
388 for (i = 0; i < len; i++)
389 local[i] = ARMul_SafeReadByte (state, ptr + i);
390
391 res = sim_callback->write (sim_callback, f, local, len);
392 state->Reg[0] = res == -1 ? -1 : len - res;
393 free (local);
394
395 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
396 }
397
398 static void
399 SWIflen (ARMul_State * state, ARMword fh)
400 {
401 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
402 ARMword addr;
403
404 if (fh > FOPEN_MAX)
405 {
406 OSptr->ErrorNo = EBADF;
407 state->Reg[0] = -1L;
408 return;
409 }
410
411 addr = sim_callback->lseek (sim_callback, fh, 0, SEEK_CUR);
412
413 state->Reg[0] = sim_callback->lseek (sim_callback, fh, 0L, SEEK_END);
414 (void) sim_callback->lseek (sim_callback, fh, addr, SEEK_SET);
415
416 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
417 }
418
419 static void
420 SWIremove (ARMul_State * state, ARMword path)
421 {
422 char buf[PATH_MAX];
423
424 if (ReadFileName (state, buf, path, sizeof buf) != -1)
425 {
426 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
427 state->Reg[0] = sim_callback->unlink (sim_callback, buf);
428 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
429 }
430 }
431
432 static void
433 SWIrename (ARMul_State * state, ARMword old, ARMword new)
434 {
435 char oldbuf[PATH_MAX], newbuf[PATH_MAX];
436
437 if (ReadFileName (state, oldbuf, old, sizeof oldbuf) != -1
438 && ReadFileName (state, newbuf, new, sizeof newbuf) != -1)
439 {
440 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
441 state->Reg[0] = sim_callback->rename (sim_callback, oldbuf, newbuf);
442 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
443 }
444 }
445
446 /* The emulator calls this routine when a SWI instruction is encuntered.
447 The parameter passed is the SWI number (lower 24 bits of the instruction). */
448
449 unsigned
450 ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
451 {
452 struct OSblock * OSptr = (struct OSblock *) state->OSptr;
453 int unhandled = FALSE;
454
455 switch (number)
456 {
457 case SWI_Read:
458 if (swi_mask & SWI_MASK_DEMON)
459 SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
460 else
461 unhandled = TRUE;
462 break;
463
464 case SWI_Write:
465 if (swi_mask & SWI_MASK_DEMON)
466 SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
467 else
468 unhandled = TRUE;
469 break;
470
471 case SWI_Open:
472 if (swi_mask & SWI_MASK_DEMON)
473 SWIopen (state, state->Reg[0], state->Reg[1]);
474 else
475 unhandled = TRUE;
476 break;
477
478 case SWI_Clock:
479 if (swi_mask & SWI_MASK_DEMON)
480 {
481 /* Return number of centi-seconds. */
482 state->Reg[0] =
483 #ifdef CLOCKS_PER_SEC
484 (CLOCKS_PER_SEC >= 100)
485 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
486 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
487 #else
488 /* Presume unix... clock() returns microseconds. */
489 (ARMword) (clock () / 10000);
490 #endif
491 OSptr->ErrorNo = errno;
492 }
493 else
494 unhandled = TRUE;
495 break;
496
497 case SWI_Time:
498 if (swi_mask & SWI_MASK_DEMON)
499 {
500 state->Reg[0] = (ARMword) sim_callback->time (sim_callback, NULL);
501 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
502 }
503 else
504 unhandled = TRUE;
505 break;
506
507 case SWI_Close:
508 if (swi_mask & SWI_MASK_DEMON)
509 {
510 state->Reg[0] = sim_callback->close (sim_callback, state->Reg[0]);
511 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
512 }
513 else
514 unhandled = TRUE;
515 break;
516
517 case SWI_Flen:
518 if (swi_mask & SWI_MASK_DEMON)
519 SWIflen (state, state->Reg[0]);
520 else
521 unhandled = TRUE;
522 break;
523
524 case SWI_Exit:
525 if (swi_mask & SWI_MASK_DEMON)
526 state->Emulate = FALSE;
527 else
528 unhandled = TRUE;
529 break;
530
531 case SWI_Seek:
532 if (swi_mask & SWI_MASK_DEMON)
533 {
534 /* We must return non-zero for failure. */
535 state->Reg[0] = -1 >= sim_callback->lseek (sim_callback, state->Reg[0], state->Reg[1], SEEK_SET);
536 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
537 }
538 else
539 unhandled = TRUE;
540 break;
541
542 case SWI_WriteC:
543 if (swi_mask & SWI_MASK_DEMON)
544 {
545 char tmp = state->Reg[0];
546 (void) sim_callback->write_stdout (sim_callback, &tmp, 1);
547 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
548 }
549 else
550 unhandled = TRUE;
551 break;
552
553 case SWI_Write0:
554 if (swi_mask & SWI_MASK_DEMON)
555 SWIWrite0 (state, state->Reg[0]);
556 else
557 unhandled = TRUE;
558 break;
559
560 case SWI_GetErrno:
561 if (swi_mask & SWI_MASK_DEMON)
562 state->Reg[0] = OSptr->ErrorNo;
563 else
564 unhandled = TRUE;
565 break;
566
567 case SWI_GetEnv:
568 if (swi_mask & SWI_MASK_DEMON)
569 {
570 state->Reg[0] = ADDRCMDLINE;
571 if (state->MemSize)
572 state->Reg[1] = state->MemSize;
573 else
574 state->Reg[1] = ADDRUSERSTACK;
575
576 WriteCommandLineTo (state, state->Reg[0]);
577 }
578 else
579 unhandled = TRUE;
580 break;
581
582 case SWI_Breakpoint:
583 state->EndCondition = RDIError_BreakpointReached;
584 state->Emulate = FALSE;
585 break;
586
587 case SWI_Remove:
588 if (swi_mask & SWI_MASK_DEMON)
589 SWIremove (state, state->Reg[0]);
590 else
591 unhandled = TRUE;
592 break;
593
594 case SWI_Rename:
595 if (swi_mask & SWI_MASK_DEMON)
596 SWIrename (state, state->Reg[0], state->Reg[1]);
597 else
598 unhandled = TRUE;
599 break;
600
601 case SWI_IsTTY:
602 if (swi_mask & SWI_MASK_DEMON)
603 {
604 state->Reg[0] = sim_callback->isatty (sim_callback, state->Reg[0]);
605 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
606 }
607 else
608 unhandled = TRUE;
609 break;
610
611 /* Handle Angel SWIs as well as Demon ones. */
612 case AngelSWI_ARM:
613 case AngelSWI_Thumb:
614 if (swi_mask & SWI_MASK_ANGEL)
615 {
616 ARMword addr;
617 ARMword temp;
618
619 /* R1 is almost always a parameter block. */
620 addr = state->Reg[1];
621 /* R0 is a reason code. */
622 switch (state->Reg[0])
623 {
624 case -1:
625 /* This can happen when a SWI is interrupted (eg receiving a
626 ctrl-C whilst processing SWIRead()). The SWI will complete
627 returning -1 in r0 to the caller. If GDB is then used to
628 resume the system call the reason code will now be -1. */
629 return TRUE;
630
631 /* Unimplemented reason codes. */
632 case AngelSWI_Reason_ReadC:
633 case AngelSWI_Reason_TmpNam:
634 case AngelSWI_Reason_System:
635 case AngelSWI_Reason_EnterSVC:
636 default:
637 state->Emulate = FALSE;
638 return FALSE;
639
640 case AngelSWI_Reason_Clock:
641 /* Return number of centi-seconds. */
642 state->Reg[0] =
643 #ifdef CLOCKS_PER_SEC
644 (CLOCKS_PER_SEC >= 100)
645 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
646 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
647 #else
648 /* Presume unix... clock() returns microseconds. */
649 (ARMword) (clock () / 10000);
650 #endif
651 OSptr->ErrorNo = errno;
652 break;
653
654 case AngelSWI_Reason_Time:
655 state->Reg[0] = (ARMword) sim_callback->time (sim_callback, NULL);
656 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
657 break;
658
659 case AngelSWI_Reason_WriteC:
660 {
661 char tmp = ARMul_SafeReadByte (state, addr);
662 (void) sim_callback->write_stdout (sim_callback, &tmp, 1);
663 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
664 break;
665 }
666
667 case AngelSWI_Reason_Write0:
668 SWIWrite0 (state, addr);
669 break;
670
671 case AngelSWI_Reason_Close:
672 state->Reg[0] = sim_callback->close (sim_callback, ARMul_ReadWord (state, addr));
673 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
674 break;
675
676 case AngelSWI_Reason_Seek:
677 state->Reg[0] = -1 >= sim_callback->lseek (sim_callback, ARMul_ReadWord (state, addr),
678 ARMul_ReadWord (state, addr + 4),
679 SEEK_SET);
680 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
681 break;
682
683 case AngelSWI_Reason_FLen:
684 SWIflen (state, ARMul_ReadWord (state, addr));
685 break;
686
687 case AngelSWI_Reason_GetCmdLine:
688 WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
689 break;
690
691 case AngelSWI_Reason_HeapInfo:
692 /* R1 is a pointer to a pointer. */
693 addr = ARMul_ReadWord (state, addr);
694
695 /* Pick up the right memory limit. */
696 if (state->MemSize)
697 temp = state->MemSize;
698 else
699 temp = ADDRUSERSTACK;
700
701 ARMul_WriteWord (state, addr, 0); /* Heap base. */
702 ARMul_WriteWord (state, addr + 4, temp); /* Heap limit. */
703 ARMul_WriteWord (state, addr + 8, temp); /* Stack base. */
704 ARMul_WriteWord (state, addr + 12, temp); /* Stack limit. */
705 break;
706
707 case AngelSWI_Reason_ReportException:
708 if (state->Reg[1] == ADP_Stopped_ApplicationExit)
709 state->Reg[0] = 0;
710 else
711 state->Reg[0] = -1;
712 state->Emulate = FALSE;
713 break;
714
715 case ADP_Stopped_ApplicationExit:
716 state->Reg[0] = 0;
717 state->Emulate = FALSE;
718 break;
719
720 case ADP_Stopped_RunTimeError:
721 state->Reg[0] = -1;
722 state->Emulate = FALSE;
723 break;
724
725 case AngelSWI_Reason_Errno:
726 state->Reg[0] = OSptr->ErrorNo;
727 break;
728
729 case AngelSWI_Reason_Open:
730 SWIopen (state,
731 ARMul_ReadWord (state, addr),
732 ARMul_ReadWord (state, addr + 4));
733 break;
734
735 case AngelSWI_Reason_Read:
736 SWIread (state,
737 ARMul_ReadWord (state, addr),
738 ARMul_ReadWord (state, addr + 4),
739 ARMul_ReadWord (state, addr + 8));
740 break;
741
742 case AngelSWI_Reason_Write:
743 SWIwrite (state,
744 ARMul_ReadWord (state, addr),
745 ARMul_ReadWord (state, addr + 4),
746 ARMul_ReadWord (state, addr + 8));
747 break;
748
749 case AngelSWI_Reason_IsTTY:
750 state->Reg[0] = sim_callback->isatty (sim_callback,
751 ARMul_ReadWord (state, addr));
752 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
753 break;
754
755 case AngelSWI_Reason_Remove:
756 SWIremove (state,
757 ARMul_ReadWord (state, addr));
758
759 case AngelSWI_Reason_Rename:
760 SWIrename (state,
761 ARMul_ReadWord (state, addr),
762 ARMul_ReadWord (state, addr + 4));
763 }
764 }
765 else
766 unhandled = TRUE;
767 break;
768
769 /* The following SWIs are generated by the softvectorcode[]
770 installed by default by the simulator. */
771 case 0x91: /* Undefined Instruction. */
772 {
773 ARMword addr = state->RegBank[UNDEFBANK][14] - 4;
774
775 sim_callback->printf_filtered
776 (sim_callback, "sim: exception: Unhandled Instruction '0x%08x' at 0x%08x. Stopping.\n",
777 ARMul_ReadWord (state, addr), addr);
778 state->EndCondition = RDIError_SoftwareInterrupt;
779 state->Emulate = FALSE;
780 return FALSE;
781 }
782
783 case 0x90: /* Reset. */
784 case 0x92: /* SWI. */
785 /* These two can be safely ignored. */
786 break;
787
788 case 0x93: /* Prefetch Abort. */
789 case 0x94: /* Data Abort. */
790 case 0x95: /* Address Exception. */
791 case 0x96: /* IRQ. */
792 case 0x97: /* FIQ. */
793 case 0x98: /* Error. */
794 unhandled = TRUE;
795 break;
796
797 case -1:
798 /* This can happen when a SWI is interrupted (eg receiving a
799 ctrl-C whilst processing SWIRead()). The SWI will complete
800 returning -1 in r0 to the caller. If GDB is then used to
801 resume the system call the reason code will now be -1. */
802 return TRUE;
803
804 case 0x180001: /* RedBoot's Syscall SWI in ARM mode. */
805 if (swi_mask & SWI_MASK_REDBOOT)
806 {
807 switch (state->Reg[0])
808 {
809 /* These numbers are defined in libgloss/syscall.h
810 but the simulator should not be dependend upon
811 libgloss being installed. */
812 case 1: /* Exit. */
813 state->Emulate = FALSE;
814 /* Copy exit code into r0. */
815 state->Reg[0] = state->Reg[1];
816 break;
817
818 case 2: /* Open. */
819 SWIopen (state, state->Reg[1], state->Reg[2]);
820 break;
821
822 case 3: /* Close. */
823 state->Reg[0] = sim_callback->close (sim_callback, state->Reg[1]);
824 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
825 break;
826
827 case 4: /* Read. */
828 SWIread (state, state->Reg[1], state->Reg[2], state->Reg[3]);
829 break;
830
831 case 5: /* Write. */
832 SWIwrite (state, state->Reg[1], state->Reg[2], state->Reg[3]);
833 break;
834
835 case 6: /* Lseek. */
836 state->Reg[0] = sim_callback->lseek (sim_callback,
837 state->Reg[1],
838 state->Reg[2],
839 state->Reg[3]);
840 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
841 break;
842
843 case 17: /* Utime. */
844 state->Reg[0] = (ARMword) sim_callback->time (sim_callback,
845 (long *) state->Reg[1]);
846 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
847 break;
848
849 case 7: /* Unlink. */
850 case 8: /* Getpid. */
851 case 9: /* Kill. */
852 case 10: /* Fstat. */
853 case 11: /* Sbrk. */
854 case 12: /* Argvlen. */
855 case 13: /* Argv. */
856 case 14: /* ChDir. */
857 case 15: /* Stat. */
858 case 16: /* Chmod. */
859 case 18: /* Time. */
860 sim_callback->printf_filtered
861 (sim_callback,
862 "sim: unhandled RedBoot syscall `%d' encountered - "
863 "returning ENOSYS\n",
864 state->Reg[0]);
865 state->Reg[0] = -1;
866 OSptr->ErrorNo = cb_host_to_target_errno
867 (sim_callback, ENOSYS);
868 break;
869 case 1001: /* Meminfo. */
870 {
871 ARMword totmem = state->Reg[1],
872 topmem = state->Reg[2];
873 ARMword stack = state->MemSize > 0
874 ? state->MemSize : ADDRUSERSTACK;
875 if (totmem != 0)
876 ARMul_WriteWord (state, totmem, stack);
877 if (topmem != 0)
878 ARMul_WriteWord (state, topmem, stack);
879 state->Reg[0] = 0;
880 break;
881 }
882
883 default:
884 sim_callback->printf_filtered
885 (sim_callback,
886 "sim: unknown RedBoot syscall '%d' encountered - ignoring\n",
887 state->Reg[0]);
888 return FALSE;
889 }
890 break;
891 }
892
893 default:
894 unhandled = TRUE;
895 }
896
897 if (unhandled)
898 {
899 if (SWI_vector_installed)
900 {
901 ARMword cpsr;
902 ARMword i_size;
903
904 cpsr = ARMul_GetCPSR (state);
905 i_size = INSN_SIZE;
906
907 ARMul_SetSPSR (state, SVC32MODE, cpsr);
908
909 cpsr &= ~0xbf;
910 cpsr |= SVC32MODE | 0x80;
911 ARMul_SetCPSR (state, cpsr);
912
913 state->RegBank[SVCBANK][14] = state->Reg[14] = state->Reg[15] - i_size;
914 state->NextInstr = RESUME;
915 state->Reg[15] = state->pc = ARMSWIV;
916 FLUSHPIPE;
917 }
918 else
919 {
920 sim_callback->printf_filtered
921 (sim_callback,
922 "sim: unknown SWI encountered - %x - ignoring\n",
923 number);
924 return FALSE;
925 }
926 }
927
928 return TRUE;
929 }
930
931 #ifndef NOOS
932 #ifndef ASIM
933
934 /* The emulator calls this routine when an Exception occurs. The second
935 parameter is the address of the relevant exception vector. Returning
936 FALSE from this routine causes the trap to be taken, TRUE causes it to
937 be ignored (so set state->Emulate to FALSE!). */
938
939 unsigned
940 ARMul_OSException (ARMul_State * state ATTRIBUTE_UNUSED,
941 ARMword vector ATTRIBUTE_UNUSED,
942 ARMword pc ATTRIBUTE_UNUSED)
943 {
944 return FALSE;
945 }
946
947 #endif
948 #endif /* NOOS */
This page took 0.051673 seconds and 4 git commands to generate.