3095f57a5a069567b0196776bcf9d442de4de350
[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
27 #include <time.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <fcntl.h>
31
32 #ifndef O_RDONLY
33 #define O_RDONLY 0
34 #endif
35 #ifndef O_WRONLY
36 #define O_WRONLY 1
37 #endif
38 #ifndef O_RDWR
39 #define O_RDWR 2
40 #endif
41 #ifndef O_BINARY
42 #define O_BINARY 0
43 #endif
44
45 #ifdef __STDC__
46 #define unlink(s) remove(s)
47 #endif
48
49 #ifdef HAVE_UNISTD_H
50 #include <unistd.h> /* For SEEK_SET etc */
51 #endif
52
53 #ifdef __riscos
54 extern int _fisatty (FILE *);
55 #define isatty_(f) _fisatty(f)
56 #else
57 #ifdef __ZTC__
58 #include <io.h>
59 #define isatty_(f) isatty((f)->_file)
60 #else
61 #ifdef macintosh
62 #include <ioctl.h>
63 #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
64 #else
65 #define isatty_(f) isatty (fileno (f))
66 #endif
67 #endif
68 #endif
69
70 #include "armdefs.h"
71 #include "armos.h"
72 #ifndef NOOS
73 #ifndef VALIDATE
74 /* #ifndef ASIM */
75 #include "armfpe.h"
76 /* #endif */
77 #endif
78 #endif
79
80 /* For RDIError_BreakpointReached. */
81 #include "dbg_rdi.h"
82
83 extern unsigned ARMul_OSInit (ARMul_State * state);
84 extern void ARMul_OSExit (ARMul_State * state);
85 extern unsigned ARMul_OSHandleSWI (ARMul_State * state, ARMword number);
86 extern unsigned ARMul_OSException (ARMul_State * state, ARMword vector,
87 ARMword pc);
88 extern ARMword ARMul_OSLastErrorP (ARMul_State * state);
89 extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr);
90
91 #define BUFFERSIZE 4096
92 #ifndef FOPEN_MAX
93 #define FOPEN_MAX 64
94 #endif
95 #define UNIQUETEMPS 256
96
97 #ifndef NOOS
98 static void UnwindDataAbort (ARMul_State * state, ARMword addr);
99 static void getstring (ARMul_State * state, ARMword from, char *to);
100 #endif
101
102 /***************************************************************************\
103 * OS private Information *
104 \***************************************************************************/
105
106 struct OSblock
107 {
108 ARMword Time0;
109 ARMword ErrorP;
110 ARMword ErrorNo;
111 FILE *FileTable[FOPEN_MAX];
112 char FileFlags[FOPEN_MAX];
113 char *tempnames[UNIQUETEMPS];
114 };
115
116 #define NOOP 0
117 #define BINARY 1
118 #define READOP 2
119 #define WRITEOP 4
120
121 #ifdef macintosh
122 #define FIXCRLF(t,c) ((t & BINARY) ? \
123 c : \
124 ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \
125 )
126 #else
127 #define FIXCRLF(t,c) c
128 #endif
129
130 static ARMword softvectorcode[] = { /* basic: swi tidyexception + event; mov pc, lr;
131 ldmia r11,{r11,pc}; swi generateexception + event
132 */
133 0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /*Reset */
134 0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /*Undef */
135 0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /*SWI */
136 0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /*Prefetch abort */
137 0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /*Data abort */
138 0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /*Address exception */
139 0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /*IRQ*/
140 0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /*FIQ*/
141 0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /*Error */
142 0xe1a0f00e /* default handler */
143 };
144
145 /***************************************************************************\
146 * Time for the Operating System to initialise itself. *
147 \***************************************************************************/
148
149 unsigned
150 ARMul_OSInit (ARMul_State * state)
151 {
152 #ifndef NOOS
153 #ifndef VALIDATE
154 ARMword instr, i, j;
155 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
156
157 if (state->OSptr == NULL)
158 {
159 state->OSptr = (unsigned char *) malloc (sizeof (struct OSblock));
160 if (state->OSptr == NULL)
161 {
162 perror ("OS Memory");
163 exit (15);
164 }
165 }
166 OSptr = (struct OSblock *) state->OSptr;
167 OSptr->ErrorP = 0;
168 state->Reg[13] = ADDRSUPERSTACK; /* set up a stack for the current mode */
169 ARMul_SetReg (state, SVC32MODE, 13, ADDRSUPERSTACK); /* and for supervisor mode */
170 ARMul_SetReg (state, ABORT32MODE, 13, ADDRSUPERSTACK); /* and for abort 32 mode */
171 ARMul_SetReg (state, UNDEF32MODE, 13, ADDRSUPERSTACK); /* and for undef 32 mode */
172 instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8); /* load pc from soft vector */
173 for (i = ARMul_ResetV; i <= ARMFIQV; i += 4)
174 ARMul_WriteWord (state, i, instr); /* write hardware vectors */
175 for (i = ARMul_ResetV; i <= ARMFIQV + 4; i += 4)
176 {
177 ARMul_WriteWord (state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
178 ARMul_WriteWord (state, ADDRSOFHANDLERS + 2 * i + 4L,
179 SOFTVECTORCODE + sizeof (softvectorcode) - 4L);
180 }
181 for (i = 0; i < sizeof (softvectorcode); i += 4)
182 ARMul_WriteWord (state, SOFTVECTORCODE + i, softvectorcode[i / 4]);
183 for (i = 0; i < FOPEN_MAX; i++)
184 OSptr->FileTable[i] = NULL;
185 for (i = 0; i < UNIQUETEMPS; i++)
186 OSptr->tempnames[i] = NULL;
187 ARMul_ConsolePrint (state, ", Demon 1.01");
188
189 /* #ifndef ASIM */
190
191 /* install fpe */
192 for (i = 0; i < fpesize; i += 4) /* copy the code */
193 ARMul_WriteWord (state, FPESTART + i, fpecode[i >> 2]);
194 for (i = FPESTART + fpesize;; i -= 4)
195 { /* reverse the error strings */
196 if ((j = ARMul_ReadWord (state, i)) == 0xffffffff)
197 break;
198 if (state->bigendSig && j < 0x80000000)
199 { /* it's part of the string so swap it */
200 j = ((j >> 0x18) & 0x000000ff) |
201 ((j >> 0x08) & 0x0000ff00) |
202 ((j << 0x08) & 0x00ff0000) | ((j << 0x18) & 0xff000000);
203 ARMul_WriteWord (state, i, j);
204 }
205 }
206 ARMul_WriteWord (state, FPEOLDVECT, ARMul_ReadWord (state, 4)); /* copy old illegal instr vector */
207 ARMul_WriteWord (state, 4, FPENEWVECT (ARMul_ReadWord (state, i - 4))); /* install new vector */
208 ARMul_ConsolePrint (state, ", FPE");
209
210 /* #endif /* ASIM */
211 #endif /* VALIDATE */
212 #endif /* NOOS */
213
214 return (TRUE);
215 }
216
217 void
218 ARMul_OSExit (ARMul_State * state)
219 {
220 free ((char *) state->OSptr);
221 }
222
223
224 /***************************************************************************\
225 * Return the last Operating System Error. *
226 \***************************************************************************/
227
228 ARMword ARMul_OSLastErrorP (ARMul_State * state)
229 {
230 return ((struct OSblock *) state->OSptr)->ErrorP;
231 }
232
233 #if 1 /* CYGNUS LOCAL */
234 /* This is the cygnus way of doing it, which makes it simple to do our tests */
235
236 static int translate_open_mode[] = {
237 O_RDONLY, /* "r" */
238 O_RDONLY + O_BINARY, /* "rb" */
239 O_RDWR, /* "r+" */
240 O_RDWR + O_BINARY, /* "r+b" */
241 O_WRONLY + O_CREAT + O_TRUNC, /* "w" */
242 O_WRONLY + O_BINARY + O_CREAT + O_TRUNC, /* "wb" */
243 O_RDWR + O_CREAT + O_TRUNC, /* "w+" */
244 O_RDWR + O_BINARY + O_CREAT + O_TRUNC, /* "w+b" */
245 O_WRONLY + O_APPEND + O_CREAT, /* "a" */
246 O_WRONLY + O_BINARY + O_APPEND + O_CREAT, /* "ab" */
247 O_RDWR + O_APPEND + O_CREAT, /* "a+" */
248 O_RDWR + O_BINARY + O_APPEND + O_CREAT /* "a+b" */
249 };
250
251 static void
252 SWIWrite0 (ARMul_State * state, ARMword addr)
253 {
254 ARMword temp;
255 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
256
257 while ((temp = ARMul_ReadByte (state, addr++)) != 0)
258 (void) fputc ((char) temp, stdout);
259
260 OSptr->ErrorNo = errno;
261 }
262
263 static void
264 WriteCommandLineTo (ARMul_State * state, ARMword addr)
265 {
266 ARMword temp;
267 char *cptr = state->CommandLine;
268 if (cptr == NULL)
269 cptr = "\0";
270 do
271 {
272 temp = (ARMword) * cptr++;
273 ARMul_WriteByte (state, addr++, temp);
274 }
275 while (temp != 0);
276 }
277
278 static void
279 SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
280 {
281 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
282 char dummy[2000];
283 int flags;
284 int i;
285
286 for (i = 0; dummy[i] = ARMul_ReadByte (state, name + i); i++)
287 ;
288
289 /* Now we need to decode the Demon open mode */
290 flags = translate_open_mode[SWIflags];
291
292 /* Filename ":tt" is special: it denotes stdin/out */
293 if (strcmp (dummy, ":tt") == 0)
294 {
295 if (flags == O_RDONLY) /* opening tty "r" */
296 state->Reg[0] = 0; /* stdin */
297 else
298 state->Reg[0] = 1; /* stdout */
299 }
300 else
301 {
302 state->Reg[0] = (int) open (dummy, flags, 0666);
303 OSptr->ErrorNo = errno;
304 }
305 }
306
307 static void
308 SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
309 {
310 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
311 int res;
312 int i;
313 char *local = malloc (len);
314
315 if (local == NULL)
316 {
317 fprintf (stderr, "sim: Unable to read 0x%x bytes - out of memory\n",
318 len);
319 return;
320 }
321
322 res = read (f, local, len);
323 if (res > 0)
324 for (i = 0; i < res; i++)
325 ARMul_WriteByte (state, ptr + i, local[i]);
326 free (local);
327 state->Reg[0] = res == -1 ? -1 : len - res;
328 OSptr->ErrorNo = errno;
329 }
330
331 static void
332 SWIwrite (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 fprintf (stderr, "sim: Unable to write 0x%x bytes - out of memory\n",
342 len);
343 return;
344 }
345
346 for (i = 0; i < len; i++)
347 local[i] = ARMul_ReadByte (state, ptr + i);
348
349 res = write (f, local, len);
350 state->Reg[0] = res == -1 ? -1 : len - res;
351 free (local);
352 OSptr->ErrorNo = errno;
353 }
354
355 static void
356 SWIflen (ARMul_State * state, ARMword fh)
357 {
358 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
359 ARMword addr;
360
361 if (fh == 0 || fh > FOPEN_MAX)
362 {
363 OSptr->ErrorNo = EBADF;
364 state->Reg[0] = -1L;
365 return;
366 }
367
368 addr = lseek (fh, 0, SEEK_CUR);
369 if (addr < 0)
370 state->Reg[0] = -1L;
371 else
372 {
373 state->Reg[0] = lseek (fh, 0L, SEEK_END);
374 (void) lseek (fh, addr, SEEK_SET);
375 }
376
377 OSptr->ErrorNo = errno;
378 }
379
380 /***************************************************************************\
381 * The emulator calls this routine when a SWI instruction is encuntered. The *
382 * parameter passed is the SWI number (lower 24 bits of the instruction). *
383 \***************************************************************************/
384
385 unsigned
386 ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
387 {
388 ARMword addr, temp, fildes;
389 char buffer[BUFFERSIZE], *cptr;
390 FILE *fptr;
391 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
392
393 switch (number)
394 {
395 case SWI_Read:
396 SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
397 return TRUE;
398
399 case SWI_Write:
400 SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
401 return TRUE;
402
403 case SWI_Open:
404 SWIopen (state, state->Reg[0], state->Reg[1]);
405 return TRUE;
406
407 case SWI_Clock:
408 /* return number of centi-seconds... */
409 state->Reg[0] =
410 #ifdef CLOCKS_PER_SEC
411 (CLOCKS_PER_SEC >= 100)
412 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
413 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
414 #else
415 /* presume unix... clock() returns microseconds */
416 (ARMword) (clock () / 10000);
417 #endif
418 OSptr->ErrorNo = errno;
419 return (TRUE);
420
421 case SWI_Time:
422 state->Reg[0] = (ARMword) time (NULL);
423 OSptr->ErrorNo = errno;
424 return (TRUE);
425
426 case SWI_Close:
427 state->Reg[0] = close (state->Reg[0]);
428 OSptr->ErrorNo = errno;
429 return TRUE;
430
431 case SWI_Flen:
432 SWIflen (state, state->Reg[0]);
433 return (TRUE);
434
435 case SWI_Exit:
436 state->Emulate = FALSE;
437 return TRUE;
438
439 case SWI_Seek:
440 {
441 /* We must return non-zero for failure */
442 state->Reg[0] = -1 >= lseek (state->Reg[0], state->Reg[1], SEEK_SET);
443 OSptr->ErrorNo = errno;
444 return TRUE;
445 }
446
447 case SWI_WriteC:
448 (void) fputc ((int) state->Reg[0], stdout);
449 OSptr->ErrorNo = errno;
450 return (TRUE);
451
452 case SWI_Write0:
453 SWIWrite0 (state, state->Reg[0]);
454 return (TRUE);
455
456 case SWI_GetErrno:
457 state->Reg[0] = OSptr->ErrorNo;
458 return (TRUE);
459
460 case SWI_Breakpoint:
461 state->EndCondition = RDIError_BreakpointReached;
462 state->Emulate = FALSE;
463 return (TRUE);
464
465 case SWI_GetEnv:
466 state->Reg[0] = ADDRCMDLINE;
467 if (state->MemSize)
468 state->Reg[1] = state->MemSize;
469 else
470 state->Reg[1] = ADDRUSERSTACK;
471
472 WriteCommandLineTo (state, state->Reg[0]);
473 return (TRUE);
474
475 /* Handle Angel SWIs as well as Demon ones */
476 case AngelSWI_ARM:
477 case AngelSWI_Thumb:
478 /* R1 is almost always a parameter block */
479 addr = state->Reg[1];
480 /* R0 is a reason code */
481 switch (state->Reg[0])
482 {
483 /* Unimplemented reason codes */
484 case AngelSWI_Reason_ReadC:
485 case AngelSWI_Reason_IsTTY:
486 case AngelSWI_Reason_TmpNam:
487 case AngelSWI_Reason_Remove:
488 case AngelSWI_Reason_Rename:
489 case AngelSWI_Reason_System:
490 case AngelSWI_Reason_EnterSVC:
491 default:
492 state->Emulate = FALSE;
493 return (FALSE);
494
495 case AngelSWI_Reason_Clock:
496 /* return number of centi-seconds... */
497 state->Reg[0] =
498 #ifdef CLOCKS_PER_SEC
499 (CLOCKS_PER_SEC >= 100)
500 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
501 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
502 #else
503 /* presume unix... clock() returns microseconds */
504 (ARMword) (clock () / 10000);
505 #endif
506 OSptr->ErrorNo = errno;
507 return (TRUE);
508
509 case AngelSWI_Reason_Time:
510 state->Reg[0] = (ARMword) time (NULL);
511 OSptr->ErrorNo = errno;
512 return (TRUE);
513
514 case AngelSWI_Reason_WriteC:
515 (void) fputc ((int) ARMul_ReadByte (state, addr), stdout);
516 OSptr->ErrorNo = errno;
517 return (TRUE);
518
519 case AngelSWI_Reason_Write0:
520 SWIWrite0 (state, addr);
521 return (TRUE);
522
523 case AngelSWI_Reason_Close:
524 state->Reg[0] = close (ARMul_ReadWord (state, addr));
525 OSptr->ErrorNo = errno;
526 return (TRUE);
527
528 case AngelSWI_Reason_Seek:
529 state->Reg[0] = -1 >= lseek (ARMul_ReadWord (state, addr),
530 ARMul_ReadWord (state, addr + 4),
531 SEEK_SET);
532 OSptr->ErrorNo = errno;
533 return (TRUE);
534
535 case AngelSWI_Reason_FLen:
536 SWIflen (state, ARMul_ReadWord (state, addr));
537 return (TRUE);
538
539 case AngelSWI_Reason_GetCmdLine:
540 WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
541 return (TRUE);
542
543 case AngelSWI_Reason_HeapInfo:
544 /* R1 is a pointer to a pointer */
545 addr = ARMul_ReadWord (state, addr);
546
547 /* Pick up the right memory limit */
548 if (state->MemSize)
549 temp = state->MemSize;
550 else
551 temp = ADDRUSERSTACK;
552
553 ARMul_WriteWord (state, addr, 0); /* Heap base */
554 ARMul_WriteWord (state, addr + 4, temp); /* Heap limit */
555 ARMul_WriteWord (state, addr + 8, temp); /* Stack base */
556 ARMul_WriteWord (state, addr + 12, temp); /* Stack limit */
557 return (TRUE);
558
559 case AngelSWI_Reason_ReportException:
560 if (state->Reg[1] == ADP_Stopped_ApplicationExit)
561 state->Reg[0] = 0;
562 else
563 state->Reg[0] = -1;
564 state->Emulate = FALSE;
565 return (TRUE);
566
567 case ADP_Stopped_ApplicationExit:
568 state->Reg[0] = 0;
569 state->Emulate = FALSE;
570 return (TRUE);
571
572 case ADP_Stopped_RunTimeError:
573 state->Reg[0] = -1;
574 state->Emulate = FALSE;
575 return (TRUE);
576
577 case AngelSWI_Reason_Errno:
578 state->Reg[0] = OSptr->ErrorNo;
579 return (TRUE);
580
581 case AngelSWI_Reason_Open:
582 SWIopen (state,
583 ARMul_ReadWord (state, addr),
584 ARMul_ReadWord (state, addr + 4));
585 return TRUE;
586
587 case AngelSWI_Reason_Read:
588 SWIread (state,
589 ARMul_ReadWord (state, addr),
590 ARMul_ReadWord (state, addr + 4),
591 ARMul_ReadWord (state, addr + 8));
592 return TRUE;
593
594 case AngelSWI_Reason_Write:
595 SWIwrite (state,
596 ARMul_ReadWord (state, addr),
597 ARMul_ReadWord (state, addr + 4),
598 ARMul_ReadWord (state, addr + 8));
599 return TRUE;
600 }
601
602 default:
603 state->Emulate = FALSE;
604 return (FALSE);
605 }
606 }
607
608 #else /* CYGNUS LOCAL: #if 1 */
609
610 unsigned
611 ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
612 {
613 #ifdef NOOS
614 return (FALSE);
615 #else
616 #ifdef VALIDATE
617 switch (number)
618 {
619 case 0x11:
620 state->Emulate = FALSE;
621 return (TRUE);
622 case 0x01:
623 if (ARM32BITMODE)
624 ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x13);
625 else
626 ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x3);
627 return (TRUE);
628 default:
629 return (FALSE);
630 }
631 #else
632 ARMword addr, temp;
633 char buffer[BUFFERSIZE], *cptr;
634 FILE *fptr;
635 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
636
637 switch (number)
638 {
639 case SWI_WriteC:
640 (void) fputc ((int) state->Reg[0], stderr);
641 OSptr->ErrorNo = errno;
642 return (TRUE);
643
644 case SWI_Write0:
645 addr = state->Reg[0];
646 while ((temp = ARMul_ReadByte (state, addr++)) != 0)
647 fputc ((char) temp, stderr);
648 OSptr->ErrorNo = errno;
649 return (TRUE);
650
651 case SWI_ReadC:
652 state->Reg[0] = (ARMword) fgetc (stdin);
653 OSptr->ErrorNo = errno;
654 return (TRUE);
655
656 case SWI_CLI:
657 addr = state->Reg[0];
658 getstring (state, state->Reg[0], buffer);
659 state->Reg[0] = (ARMword) system (buffer);
660 OSptr->ErrorNo = errno;
661 return (TRUE);
662
663 case SWI_GetEnv:
664 state->Reg[0] = ADDRCMDLINE;
665 if (state->MemSize)
666 state->Reg[1] = state->MemSize;
667 else
668 state->Reg[1] = ADDRUSERSTACK;
669
670 addr = state->Reg[0];
671 cptr = state->CommandLine;
672 if (cptr == NULL)
673 cptr = "\0";
674 do
675 {
676 temp = (ARMword) * cptr++;
677 ARMul_WriteByte (state, addr++, temp);
678 }
679 while (temp != 0);
680 return (TRUE);
681
682 case SWI_Exit:
683 #ifdef ASIM
684 simkernel1_abort_run ();
685 #else
686 state->Emulate = FALSE;
687 #endif
688 return (TRUE);
689
690 case SWI_EnterOS:
691 if (ARM32BITMODE)
692 ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x13);
693 else
694 ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x3);
695 return (TRUE);
696
697 case SWI_GetErrno:
698 state->Reg[0] = OSptr->ErrorNo;
699 return (TRUE);
700
701 case SWI_Clock:
702 /* return muber of centi-seconds... */
703 state->Reg[0] =
704 #ifdef CLOCKS_PER_SEC
705 (CLOCKS_PER_SEC >= 100)
706 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
707 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
708 #else
709 /* presume unix... clock() returns microseconds */
710 (ARMword) (clock () / 10000);
711 #endif
712 OSptr->ErrorNo = errno;
713 return (TRUE);
714
715 case SWI_Time:
716 state->Reg[0] = (ARMword) time (NULL);
717 OSptr->ErrorNo = errno;
718 return (TRUE);
719
720 case SWI_Remove:
721 getstring (state, state->Reg[0], buffer);
722 state->Reg[0] = unlink (buffer);
723 OSptr->ErrorNo = errno;
724 return (TRUE);
725
726 case SWI_Rename:
727 {
728 char buffer2[BUFFERSIZE];
729
730 getstring (state, state->Reg[0], buffer);
731 getstring (state, state->Reg[1], buffer2);
732 state->Reg[0] = rename (buffer, buffer2);
733 OSptr->ErrorNo = errno;
734 return (TRUE);
735 }
736
737 case SWI_Open:
738 {
739 #if 0
740 /* It seems to me that these are in the wrong order
741 sac@cygnus.com, so I've redone it to use the
742 flags instead, with the functionality which was already
743 there -- ahh, perhaps the TRUNC bit is in a different
744 place on the original host ? */
745 static char *fmode[] = { "r", "rb", "r+", "r+b",
746 "w", "wb", "w+", "w+b",
747 "a", "ab", "a+", "a+b",
748 "r", "r", "r", "r"
749 } /* last 4 are illegal */ ;
750 #endif
751
752 unsigned type;
753
754 type = (unsigned) (state->Reg[1] & 3L);
755 getstring (state, state->Reg[0], buffer);
756 if (strcmp (buffer, ":tt") == 0 && (type == O_RDONLY)) /* opening tty "r" */
757 fptr = stdin;
758 else if (strcmp (buffer, ":tt") == 0 && (type == O_WRONLY)) /* opening tty "w" */
759 fptr = stderr;
760 else
761 {
762 switch (type)
763 {
764 case O_RDONLY:
765 fptr = fopen (buffer, "r");
766 break;
767 case O_WRONLY:
768 fptr = fopen (buffer, "w");
769 break;
770 case O_RDWR:
771 fptr = fopen (buffer, "rw");
772 break;
773 }
774 }
775
776 state->Reg[0] = 0;
777 if (fptr != NULL)
778 {
779 for (temp = 0; temp < FOPEN_MAX; temp++)
780 if (OSptr->FileTable[temp] == NULL)
781 {
782 OSptr->FileTable[temp] = fptr;
783 OSptr->FileFlags[temp] = type & 1; /* preserve the binary bit */
784 state->Reg[0] = (ARMword) (temp + 1);
785 break;
786 }
787 if (state->Reg[0] == 0)
788 OSptr->ErrorNo = EMFILE; /* too many open files */
789 else
790 OSptr->ErrorNo = errno;
791 }
792 else
793 OSptr->ErrorNo = errno;
794 return (TRUE);
795 }
796
797 case SWI_Close:
798 temp = state->Reg[0];
799 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0)
800 {
801 OSptr->ErrorNo = EBADF;
802 state->Reg[0] = -1L;
803 return (TRUE);
804 }
805 temp--;
806 fptr = OSptr->FileTable[temp];
807 if (fptr == stdin || fptr == stderr)
808 state->Reg[0] = 0;
809 else
810 state->Reg[0] = fclose (fptr);
811 OSptr->FileTable[temp] = NULL;
812 OSptr->ErrorNo = errno;
813 return (TRUE);
814
815 case SWI_Write:
816 {
817 unsigned size, upto, type;
818 char ch;
819
820 temp = state->Reg[0];
821 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0)
822 {
823 OSptr->ErrorNo = EBADF;
824 state->Reg[0] = -1L;
825 return (TRUE);
826 }
827 temp--;
828 fptr = OSptr->FileTable[temp];
829 type = OSptr->FileFlags[temp];
830 addr = state->Reg[1];
831 size = (unsigned) state->Reg[2];
832
833 if (type & READOP)
834 fseek (fptr, 0L, SEEK_CUR);
835 OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP;;
836 while (size > 0)
837 {
838 if (size >= BUFFERSIZE)
839 upto = BUFFERSIZE;
840 else
841 upto = size;
842 for (cptr = buffer; (cptr - buffer) < upto; cptr++)
843 {
844 ch = (char) ARMul_ReadByte (state, (ARMword) addr++);
845 *cptr = FIXCRLF (type, ch);
846 }
847 temp = fwrite (buffer, 1, upto, fptr);
848 if (temp < upto)
849 {
850 state->Reg[0] = (ARMword) (size - temp);
851 OSptr->ErrorNo = errno;
852 return (TRUE);
853 }
854 size -= upto;
855 }
856 state->Reg[0] = 0;
857 OSptr->ErrorNo = errno;
858 return (TRUE);
859 }
860
861 case SWI_Read:
862 {
863 unsigned size, upto, type;
864 char ch;
865
866 temp = state->Reg[0];
867 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0)
868 {
869 OSptr->ErrorNo = EBADF;
870 state->Reg[0] = -1L;
871 return (TRUE);
872 }
873 temp--;
874 fptr = OSptr->FileTable[temp];
875 addr = state->Reg[1];
876 size = (unsigned) state->Reg[2];
877 type = OSptr->FileFlags[temp];
878
879 if (type & WRITEOP)
880 fseek (fptr, 0L, SEEK_CUR);
881 OSptr->FileFlags[temp] = (type & BINARY) | READOP;;
882 while (size > 0)
883 {
884 if (isatty_ (fptr))
885 {
886 upto = (size >= BUFFERSIZE) ? BUFFERSIZE : size + 1;
887 if (fgets (buffer, upto, fptr) != 0)
888 temp = strlen (buffer);
889 else
890 temp = 0;
891 upto--; /* 1 char used for terminating null */
892 }
893 else
894 {
895 upto = (size >= BUFFERSIZE) ? BUFFERSIZE : size;
896 temp = fread (buffer, 1, upto, fptr);
897 }
898 for (cptr = buffer; (cptr - buffer) < temp; cptr++)
899 {
900 ch = *cptr;
901 ARMul_WriteByte (state, (ARMword) addr++, FIXCRLF (type, ch));
902 }
903 if (temp < upto)
904 {
905 state->Reg[0] = (ARMword) (size - temp);
906 OSptr->ErrorNo = errno;
907 return (TRUE);
908 }
909 size -= upto;
910 }
911 state->Reg[0] = 0;
912 OSptr->ErrorNo = errno;
913 return (TRUE);
914 }
915
916 case SWI_Seek:
917 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
918 || OSptr->FileTable[state->Reg[0] - 1] == 0)
919 {
920 OSptr->ErrorNo = EBADF;
921 state->Reg[0] = -1L;
922 return (TRUE);
923 }
924 fptr = OSptr->FileTable[state->Reg[0] - 1];
925 state->Reg[0] = fseek (fptr, (long) state->Reg[1], SEEK_SET);
926 OSptr->ErrorNo = errno;
927 return (TRUE);
928
929 case SWI_Flen:
930 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
931 || OSptr->FileTable[state->Reg[0] - 1] == 0)
932 {
933 OSptr->ErrorNo = EBADF;
934 state->Reg[0] = -1L;
935 return (TRUE);
936 }
937 fptr = OSptr->FileTable[state->Reg[0] - 1];
938 addr = (ARMword) ftell (fptr);
939 if (fseek (fptr, 0L, SEEK_END) < 0)
940 state->Reg[0] = -1;
941 else
942 {
943 state->Reg[0] = (ARMword) ftell (fptr);
944 (void) fseek (fptr, addr, SEEK_SET);
945 }
946 OSptr->ErrorNo = errno;
947 return (TRUE);
948
949 case SWI_IsTTY:
950 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
951 || OSptr->FileTable[state->Reg[0] - 1] == 0)
952 {
953 OSptr->ErrorNo = EBADF;
954 state->Reg[0] = -1L;
955 return (TRUE);
956 }
957 fptr = OSptr->FileTable[state->Reg[0] - 1];
958 state->Reg[0] = isatty_ (fptr);
959 OSptr->ErrorNo = errno;
960 return (TRUE);
961
962 case SWI_TmpNam:
963 {
964 ARMword size;
965
966 addr = state->Reg[0];
967 temp = state->Reg[1] & 0xff;
968 size = state->Reg[2];
969 if (OSptr->tempnames[temp] == NULL)
970 {
971 if ((OSptr->tempnames[temp] = malloc (L_tmpnam)) == NULL)
972 {
973 state->Reg[0] = 0;
974 return (TRUE);
975 }
976 (void) tmpnam (OSptr->tempnames[temp]);
977 }
978 cptr = OSptr->tempnames[temp];
979 if (strlen (cptr) > state->Reg[2])
980 state->Reg[0] = 0;
981 else
982 do
983 {
984 ARMul_WriteByte (state, addr++, *cptr);
985 }
986 while (*cptr++ != 0);
987 OSptr->ErrorNo = errno;
988 return (TRUE);
989 }
990
991 case SWI_InstallHandler:
992 {
993 ARMword handlerp = ADDRSOFHANDLERS + state->Reg[0] * 8;
994 ARMword oldr1 = ARMul_ReadWord (state, handlerp),
995 oldr2 = ARMul_ReadWord (state, handlerp + 4);
996 ARMul_WriteWord (state, handlerp, state->Reg[1]);
997 ARMul_WriteWord (state, handlerp + 4, state->Reg[2]);
998 state->Reg[1] = oldr1;
999 state->Reg[2] = oldr2;
1000 return (TRUE);
1001 }
1002
1003 case SWI_GenerateError:
1004 ARMul_Abort (state, ARMSWIV);
1005 if (state->Emulate)
1006 ARMul_SetR15 (state,
1007 ARMul_ReadWord (state, ADDRSOFTVECTORS + ARMErrorV));
1008 return (TRUE);
1009
1010 /* SWI's 0x9x unwind the state of the CPU after an abort of type x */
1011
1012 case 0x90: /* Branch through zero */
1013 {
1014 ARMword oldpsr = ARMul_GetCPSR (state);
1015 ARMul_SetCPSR (state, (oldpsr & 0xffffffc0) | 0x13);
1016 ARMul_SetSPSR (state, SVC32MODE, oldpsr);
1017 state->Reg[14] = 0;
1018 goto TidyCommon;
1019 }
1020
1021 case 0x98: /* Error */
1022 {
1023 ARMword errorp = state->Reg[0], regp = state->Reg[1];
1024 unsigned i;
1025 ARMword errorpsr = ARMul_ReadWord (state, regp + 16 * 4);
1026 for (i = 0; i < 15; i++)
1027 ARMul_SetReg (state, errorpsr, i,
1028 ARMul_ReadWord (state, regp + i * 4L));
1029 state->Reg[14] = ARMul_ReadWord (state, regp + 15 * 4L);
1030 state->Reg[10] = errorp;
1031 ARMul_SetSPSR (state, state->Mode, errorpsr);
1032 OSptr->ErrorP = errorp;
1033 goto TidyCommon;
1034 }
1035
1036 case 0x94: /* Data abort */
1037 {
1038 ARMword addr = state->Reg[14] - 8;
1039 ARMword cpsr = ARMul_GetCPSR (state);
1040 if (ARM26BITMODE)
1041 addr = addr & 0x3fffffc;
1042 ARMul_SetCPSR (state, ARMul_GetSPSR (state, cpsr));
1043 UnwindDataAbort (state, addr);
1044 if (addr >= FPESTART && addr < FPEEND)
1045 { /* in the FPE */
1046 ARMword sp, spsr;
1047 unsigned i;
1048
1049 sp = state->Reg[13];
1050 state->Reg[13] += 64; /* fix the aborting mode sp */
1051 state->Reg[14] = ARMul_ReadWord (state, sp + 60); /* and its lr */
1052 spsr = ARMul_GetSPSR (state, state->Mode);
1053 state->Mode = ARMul_SwitchMode (state, state->Mode, spsr);
1054 for (i = 0; i < 15; i++)
1055 {
1056 ARMul_SetReg (state, spsr, i, ARMul_ReadWord (state, sp));
1057 sp += 4;
1058 }
1059 ARMul_SetCPSR (state, cpsr);
1060 state->Reg[14] = ARMul_ReadWord (state, sp) + 4; /* botch it */
1061 ARMul_SetSPSR (state, state->Mode, spsr);
1062 }
1063 else
1064 ARMul_SetCPSR (state, cpsr);
1065
1066 /* and fall through to correct r14 */
1067 }
1068 case 0x95: /* Address Exception */
1069 state->Reg[14] -= 4;
1070 case 0x91: /* Undefined instruction */
1071 case 0x92: /* SWI */
1072 case 0x93: /* Prefetch abort */
1073 case 0x96: /* IRQ */
1074 case 0x97: /* FIQ */
1075 state->Reg[14] -= 4;
1076 TidyCommon:
1077 if (state->VectorCatch & (1 << (number - 0x90)))
1078 {
1079 ARMul_SetR15 (state, state->Reg[14] + 8); /* the 8 is the pipelining the the RDI will undo */
1080 ARMul_SetCPSR (state, ARMul_GetSPSR (state, ARMul_GetCPSR (state)));
1081 if (number == 0x90)
1082 state->EndCondition = 10; /* Branch through Zero Error */
1083 else
1084 state->EndCondition = (unsigned) number - 0x8f;
1085 state->Emulate = FALSE;
1086 }
1087 else
1088 {
1089 ARMword sp = state->Reg[13];
1090 ARMul_WriteWord (state, sp - 4, state->Reg[14]);
1091 ARMul_WriteWord (state, sp - 8, state->Reg[12]);
1092 ARMul_WriteWord (state, sp - 12, state->Reg[11]);
1093 ARMul_WriteWord (state, sp - 16, state->Reg[10]);
1094 state->Reg[13] = sp - 16;
1095 state->Reg[11] = ADDRSOFHANDLERS + 8 * (number - 0x90);
1096 }
1097 return (TRUE);
1098
1099 /* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */
1100
1101 case 0x80:
1102 case 0x81:
1103 case 0x82:
1104 case 0x83:
1105 case 0x84:
1106 case 0x85:
1107 case 0x86:
1108 case 0x87:
1109 case 0x88:
1110 {
1111 ARMword sp = state->Reg[13];
1112 state->Reg[10] = ARMul_ReadWord (state, sp);
1113 state->Reg[11] = ARMul_ReadWord (state, sp + 4);
1114 state->Reg[12] = ARMul_ReadWord (state, sp + 8);
1115 state->Reg[14] = ARMul_ReadWord (state, sp + 12);
1116 state->Reg[13] = sp + 16;
1117 ARMul_SetR15 (state, state->Reg[14] + 8); /* the 8 is the pipelining the the RDI will undo */
1118 ARMul_SetCPSR (state, ARMul_GetSPSR (state, ARMul_GetCPSR (state)));
1119 if (number == 0x80)
1120 state->EndCondition = 10; /* Branch through Zero Error */
1121 else
1122 state->EndCondition = (unsigned) number - 0x7f;
1123 state->Emulate = FALSE;
1124 return (TRUE);
1125 }
1126
1127 default:
1128 state->Emulate = FALSE;
1129 return (FALSE);
1130 }
1131 #endif
1132 #endif
1133 }
1134
1135 #endif /* CYGNUS LOCAL: #if 1 */
1136
1137 #ifndef NOOS
1138 #ifndef ASIM
1139
1140 /***************************************************************************\
1141 * The emulator calls this routine when an Exception occurs. The second *
1142 * parameter is the address of the relevant exception vector. Returning *
1143 * FALSE from this routine causes the trap to be taken, TRUE causes it to *
1144 * be ignored (so set state->Emulate to FALSE!). *
1145 \***************************************************************************/
1146
1147 unsigned
1148 ARMul_OSException (ARMul_State * state, ARMword vector, ARMword pc)
1149 { /* don't use this here */
1150 return (FALSE);
1151 }
1152
1153 #endif
1154
1155 /***************************************************************************\
1156 * Unwind a data abort *
1157 \***************************************************************************/
1158
1159 static void
1160 UnwindDataAbort (ARMul_State * state, ARMword addr)
1161 {
1162 ARMword instr = ARMul_ReadWord (state, addr);
1163 ARMword rn = BITS (16, 19);
1164 ARMword itype = BITS (24, 27);
1165 ARMword offset;
1166 if (rn == 15)
1167 return;
1168 if (itype == 8 || itype == 9)
1169 {
1170 /* LDM or STM */
1171 unsigned long regs = BITS (0, 15);
1172 offset = 0;
1173 if (!BIT (21))
1174 return; /* no wb */
1175 for (; regs != 0; offset++)
1176 regs ^= (regs & -regs);
1177 if (offset == 0)
1178 offset = 16;
1179 }
1180 else if (itype == 12 || /* post-indexed CPDT */
1181 (itype == 13 && BIT (21)))
1182 { /* pre_indexed CPDT with WB */
1183 offset = BITS (0, 7);
1184 }
1185 else
1186 return;
1187
1188 if (BIT (23))
1189 state->Reg[rn] -= offset * 4;
1190 else
1191 state->Reg[rn] += offset * 4;
1192 }
1193
1194 /***************************************************************************\
1195 * Copy a string from the debuggee's memory to the host's *
1196 \***************************************************************************/
1197
1198 static void
1199 getstring (ARMul_State * state, ARMword from, char *to)
1200 {
1201 do
1202 {
1203 *to = (char) ARMul_ReadByte (state, from++);
1204 }
1205 while (*to++ != '\0');
1206 }
1207
1208 #endif /* NOOS */
This page took 0.053236 seconds and 4 git commands to generate.