1 /* armos.c -- ARMulator OS interface: ARM6 Instruction Emulator.
2 Copyright (C) 1994 Advanced RISC Machines Ltd.
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.
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.
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. */
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. */
46 #define unlink(s) remove(s)
50 #include <unistd.h> /* For SEEK_SET etc */
54 extern int _fisatty (FILE *);
55 #define isatty_(f) _fisatty(f)
59 #define isatty_(f) isatty((f)->_file)
63 #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
65 #define isatty_(f) isatty (fileno (f))
80 /* For RDIError_BreakpointReached. */
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,
88 extern ARMword ARMul_OSLastErrorP (ARMul_State * state);
89 extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr);
91 #define BUFFERSIZE 4096
95 #define UNIQUETEMPS 256
98 static void UnwindDataAbort (ARMul_State * state, ARMword addr);
99 static void getstring (ARMul_State * state, ARMword from, char *to);
102 /***************************************************************************\
103 * OS private Information *
104 \***************************************************************************/
111 FILE *FileTable[FOPEN_MAX];
112 char FileFlags[FOPEN_MAX];
113 char *tempnames[UNIQUETEMPS];
122 #define FIXCRLF(t,c) ((t & BINARY) ? \
124 ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \
127 #define FIXCRLF(t,c) c
130 static ARMword softvectorcode[] = { /* basic: swi tidyexception + event; mov pc, lr;
131 ldmia r11,{r11,pc}; swi generateexception + event
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 */
145 /***************************************************************************\
146 * Time for the Operating System to initialise itself. *
147 \***************************************************************************/
150 ARMul_OSInit (ARMul_State * state)
155 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
157 if (state->OSptr == NULL)
159 state->OSptr = (unsigned char *) malloc (sizeof (struct OSblock));
160 if (state->OSptr == NULL)
162 perror ("OS Memory");
166 OSptr = (struct OSblock *) state->OSptr;
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)
177 ARMul_WriteWord (state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
178 ARMul_WriteWord (state, ADDRSOFHANDLERS + 2 * i + 4L,
179 SOFTVECTORCODE + sizeof (softvectorcode) - 4L);
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");
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)
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);
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");
211 #endif /* VALIDATE */
218 ARMul_OSExit (ARMul_State * state)
220 free ((char *) state->OSptr);
224 /***************************************************************************\
225 * Return the last Operating System Error. *
226 \***************************************************************************/
228 ARMword ARMul_OSLastErrorP (ARMul_State * state)
230 return ((struct OSblock *) state->OSptr)->ErrorP;
233 #if 1 /* CYGNUS LOCAL */
234 /* This is the cygnus way of doing it, which makes it simple to do our tests */
236 static int translate_open_mode[] = {
238 O_RDONLY + O_BINARY, /* "rb" */
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" */
252 SWIWrite0 (ARMul_State * state, ARMword addr)
255 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
257 while ((temp = ARMul_ReadByte (state, addr++)) != 0)
258 (void) fputc ((char) temp, stdout);
260 OSptr->ErrorNo = errno;
264 WriteCommandLineTo (ARMul_State * state, ARMword addr)
267 char *cptr = state->CommandLine;
272 temp = (ARMword) * cptr++;
273 ARMul_WriteByte (state, addr++, temp);
279 SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
281 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
286 for (i = 0; dummy[i] = ARMul_ReadByte (state, name + i); i++)
289 /* Now we need to decode the Demon open mode */
290 flags = translate_open_mode[SWIflags];
292 /* Filename ":tt" is special: it denotes stdin/out */
293 if (strcmp (dummy, ":tt") == 0)
295 if (flags == O_RDONLY) /* opening tty "r" */
296 state->Reg[0] = 0; /* stdin */
298 state->Reg[0] = 1; /* stdout */
302 state->Reg[0] = (int) open (dummy, flags, 0666);
303 OSptr->ErrorNo = errno;
308 SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
310 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
313 char *local = malloc (len);
317 fprintf (stderr, "sim: Unable to read 0x%x bytes - out of memory\n",
322 res = read (f, local, len);
324 for (i = 0; i < res; i++)
325 ARMul_WriteByte (state, ptr + i, local[i]);
327 state->Reg[0] = res == -1 ? -1 : len - res;
328 OSptr->ErrorNo = errno;
332 SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
334 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
337 char *local = malloc (len);
341 fprintf (stderr, "sim: Unable to write 0x%x bytes - out of memory\n",
346 for (i = 0; i < len; i++)
347 local[i] = ARMul_ReadByte (state, ptr + i);
349 res = write (f, local, len);
350 state->Reg[0] = res == -1 ? -1 : len - res;
352 OSptr->ErrorNo = errno;
356 SWIflen (ARMul_State * state, ARMword fh)
358 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
361 if (fh == 0 || fh > FOPEN_MAX)
363 OSptr->ErrorNo = EBADF;
368 addr = lseek (fh, 0, SEEK_CUR);
373 state->Reg[0] = lseek (fh, 0L, SEEK_END);
374 (void) lseek (fh, addr, SEEK_SET);
377 OSptr->ErrorNo = errno;
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 \***************************************************************************/
386 ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
388 ARMword addr, temp, fildes;
389 char buffer[BUFFERSIZE], *cptr;
391 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
396 SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
400 SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
404 SWIopen (state, state->Reg[0], state->Reg[1]);
408 /* return number of centi-seconds... */
410 #ifdef CLOCKS_PER_SEC
411 (CLOCKS_PER_SEC >= 100)
412 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
413 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
415 /* presume unix... clock() returns microseconds */
416 (ARMword) (clock () / 10000);
418 OSptr->ErrorNo = errno;
422 state->Reg[0] = (ARMword) time (NULL);
423 OSptr->ErrorNo = errno;
427 state->Reg[0] = close (state->Reg[0]);
428 OSptr->ErrorNo = errno;
432 SWIflen (state, state->Reg[0]);
436 state->Emulate = FALSE;
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;
448 (void) fputc ((int) state->Reg[0], stdout);
449 OSptr->ErrorNo = errno;
453 SWIWrite0 (state, state->Reg[0]);
457 state->Reg[0] = OSptr->ErrorNo;
461 state->EndCondition = RDIError_BreakpointReached;
462 state->Emulate = FALSE;
466 state->Reg[0] = ADDRCMDLINE;
468 state->Reg[1] = state->MemSize;
470 state->Reg[1] = ADDRUSERSTACK;
472 WriteCommandLineTo (state, state->Reg[0]);
475 /* Handle Angel SWIs as well as Demon ones */
478 /* R1 is almost always a parameter block */
479 addr = state->Reg[1];
480 /* R0 is a reason code */
481 switch (state->Reg[0])
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:
492 state->Emulate = FALSE;
495 case AngelSWI_Reason_Clock:
496 /* return number of centi-seconds... */
498 #ifdef CLOCKS_PER_SEC
499 (CLOCKS_PER_SEC >= 100)
500 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
501 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
503 /* presume unix... clock() returns microseconds */
504 (ARMword) (clock () / 10000);
506 OSptr->ErrorNo = errno;
509 case AngelSWI_Reason_Time:
510 state->Reg[0] = (ARMword) time (NULL);
511 OSptr->ErrorNo = errno;
514 case AngelSWI_Reason_WriteC:
515 (void) fputc ((int) ARMul_ReadByte (state, addr), stdout);
516 OSptr->ErrorNo = errno;
519 case AngelSWI_Reason_Write0:
520 SWIWrite0 (state, addr);
523 case AngelSWI_Reason_Close:
524 state->Reg[0] = close (ARMul_ReadWord (state, addr));
525 OSptr->ErrorNo = errno;
528 case AngelSWI_Reason_Seek:
529 state->Reg[0] = -1 >= lseek (ARMul_ReadWord (state, addr),
530 ARMul_ReadWord (state, addr + 4),
532 OSptr->ErrorNo = errno;
535 case AngelSWI_Reason_FLen:
536 SWIflen (state, ARMul_ReadWord (state, addr));
539 case AngelSWI_Reason_GetCmdLine:
540 WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
543 case AngelSWI_Reason_HeapInfo:
544 /* R1 is a pointer to a pointer */
545 addr = ARMul_ReadWord (state, addr);
547 /* Pick up the right memory limit */
549 temp = state->MemSize;
551 temp = ADDRUSERSTACK;
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 */
559 case AngelSWI_Reason_ReportException:
560 if (state->Reg[1] == ADP_Stopped_ApplicationExit)
564 state->Emulate = FALSE;
567 case ADP_Stopped_ApplicationExit:
569 state->Emulate = FALSE;
572 case ADP_Stopped_RunTimeError:
574 state->Emulate = FALSE;
577 case AngelSWI_Reason_Errno:
578 state->Reg[0] = OSptr->ErrorNo;
581 case AngelSWI_Reason_Open:
583 ARMul_ReadWord (state, addr),
584 ARMul_ReadWord (state, addr + 4));
587 case AngelSWI_Reason_Read:
589 ARMul_ReadWord (state, addr),
590 ARMul_ReadWord (state, addr + 4),
591 ARMul_ReadWord (state, addr + 8));
594 case AngelSWI_Reason_Write:
596 ARMul_ReadWord (state, addr),
597 ARMul_ReadWord (state, addr + 4),
598 ARMul_ReadWord (state, addr + 8));
603 state->Emulate = FALSE;
608 #else /* CYGNUS LOCAL: #if 1 */
611 ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
620 state->Emulate = FALSE;
624 ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x13);
626 ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x3);
633 char buffer[BUFFERSIZE], *cptr;
635 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
640 (void) fputc ((int) state->Reg[0], stderr);
641 OSptr->ErrorNo = errno;
645 addr = state->Reg[0];
646 while ((temp = ARMul_ReadByte (state, addr++)) != 0)
647 fputc ((char) temp, stderr);
648 OSptr->ErrorNo = errno;
652 state->Reg[0] = (ARMword) fgetc (stdin);
653 OSptr->ErrorNo = errno;
657 addr = state->Reg[0];
658 getstring (state, state->Reg[0], buffer);
659 state->Reg[0] = (ARMword) system (buffer);
660 OSptr->ErrorNo = errno;
664 state->Reg[0] = ADDRCMDLINE;
666 state->Reg[1] = state->MemSize;
668 state->Reg[1] = ADDRUSERSTACK;
670 addr = state->Reg[0];
671 cptr = state->CommandLine;
676 temp = (ARMword) * cptr++;
677 ARMul_WriteByte (state, addr++, temp);
684 simkernel1_abort_run ();
686 state->Emulate = FALSE;
692 ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x13);
694 ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x3);
698 state->Reg[0] = OSptr->ErrorNo;
702 /* return muber of centi-seconds... */
704 #ifdef CLOCKS_PER_SEC
705 (CLOCKS_PER_SEC >= 100)
706 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
707 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
709 /* presume unix... clock() returns microseconds */
710 (ARMword) (clock () / 10000);
712 OSptr->ErrorNo = errno;
716 state->Reg[0] = (ARMword) time (NULL);
717 OSptr->ErrorNo = errno;
721 getstring (state, state->Reg[0], buffer);
722 state->Reg[0] = unlink (buffer);
723 OSptr->ErrorNo = errno;
728 char buffer2[BUFFERSIZE];
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;
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",
749 } /* last 4 are illegal */ ;
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" */
758 else if (strcmp (buffer, ":tt") == 0 && (type == O_WRONLY)) /* opening tty "w" */
765 fptr = fopen (buffer, "r");
768 fptr = fopen (buffer, "w");
771 fptr = fopen (buffer, "rw");
779 for (temp = 0; temp < FOPEN_MAX; temp++)
780 if (OSptr->FileTable[temp] == NULL)
782 OSptr->FileTable[temp] = fptr;
783 OSptr->FileFlags[temp] = type & 1; /* preserve the binary bit */
784 state->Reg[0] = (ARMword) (temp + 1);
787 if (state->Reg[0] == 0)
788 OSptr->ErrorNo = EMFILE; /* too many open files */
790 OSptr->ErrorNo = errno;
793 OSptr->ErrorNo = errno;
798 temp = state->Reg[0];
799 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0)
801 OSptr->ErrorNo = EBADF;
806 fptr = OSptr->FileTable[temp];
807 if (fptr == stdin || fptr == stderr)
810 state->Reg[0] = fclose (fptr);
811 OSptr->FileTable[temp] = NULL;
812 OSptr->ErrorNo = errno;
817 unsigned size, upto, type;
820 temp = state->Reg[0];
821 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0)
823 OSptr->ErrorNo = EBADF;
828 fptr = OSptr->FileTable[temp];
829 type = OSptr->FileFlags[temp];
830 addr = state->Reg[1];
831 size = (unsigned) state->Reg[2];
834 fseek (fptr, 0L, SEEK_CUR);
835 OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP;;
838 if (size >= BUFFERSIZE)
842 for (cptr = buffer; (cptr - buffer) < upto; cptr++)
844 ch = (char) ARMul_ReadByte (state, (ARMword) addr++);
845 *cptr = FIXCRLF (type, ch);
847 temp = fwrite (buffer, 1, upto, fptr);
850 state->Reg[0] = (ARMword) (size - temp);
851 OSptr->ErrorNo = errno;
857 OSptr->ErrorNo = errno;
863 unsigned size, upto, type;
866 temp = state->Reg[0];
867 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0)
869 OSptr->ErrorNo = EBADF;
874 fptr = OSptr->FileTable[temp];
875 addr = state->Reg[1];
876 size = (unsigned) state->Reg[2];
877 type = OSptr->FileFlags[temp];
880 fseek (fptr, 0L, SEEK_CUR);
881 OSptr->FileFlags[temp] = (type & BINARY) | READOP;;
886 upto = (size >= BUFFERSIZE) ? BUFFERSIZE : size + 1;
887 if (fgets (buffer, upto, fptr) != 0)
888 temp = strlen (buffer);
891 upto--; /* 1 char used for terminating null */
895 upto = (size >= BUFFERSIZE) ? BUFFERSIZE : size;
896 temp = fread (buffer, 1, upto, fptr);
898 for (cptr = buffer; (cptr - buffer) < temp; cptr++)
901 ARMul_WriteByte (state, (ARMword) addr++, FIXCRLF (type, ch));
905 state->Reg[0] = (ARMword) (size - temp);
906 OSptr->ErrorNo = errno;
912 OSptr->ErrorNo = errno;
917 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
918 || OSptr->FileTable[state->Reg[0] - 1] == 0)
920 OSptr->ErrorNo = EBADF;
924 fptr = OSptr->FileTable[state->Reg[0] - 1];
925 state->Reg[0] = fseek (fptr, (long) state->Reg[1], SEEK_SET);
926 OSptr->ErrorNo = errno;
930 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
931 || OSptr->FileTable[state->Reg[0] - 1] == 0)
933 OSptr->ErrorNo = EBADF;
937 fptr = OSptr->FileTable[state->Reg[0] - 1];
938 addr = (ARMword) ftell (fptr);
939 if (fseek (fptr, 0L, SEEK_END) < 0)
943 state->Reg[0] = (ARMword) ftell (fptr);
944 (void) fseek (fptr, addr, SEEK_SET);
946 OSptr->ErrorNo = errno;
950 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
951 || OSptr->FileTable[state->Reg[0] - 1] == 0)
953 OSptr->ErrorNo = EBADF;
957 fptr = OSptr->FileTable[state->Reg[0] - 1];
958 state->Reg[0] = isatty_ (fptr);
959 OSptr->ErrorNo = errno;
966 addr = state->Reg[0];
967 temp = state->Reg[1] & 0xff;
968 size = state->Reg[2];
969 if (OSptr->tempnames[temp] == NULL)
971 if ((OSptr->tempnames[temp] = malloc (L_tmpnam)) == NULL)
976 (void) tmpnam (OSptr->tempnames[temp]);
978 cptr = OSptr->tempnames[temp];
979 if (strlen (cptr) > state->Reg[2])
984 ARMul_WriteByte (state, addr++, *cptr);
986 while (*cptr++ != 0);
987 OSptr->ErrorNo = errno;
991 case SWI_InstallHandler:
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;
1003 case SWI_GenerateError:
1004 ARMul_Abort (state, ARMSWIV);
1006 ARMul_SetR15 (state,
1007 ARMul_ReadWord (state, ADDRSOFTVECTORS + ARMErrorV));
1010 /* SWI's 0x9x unwind the state of the CPU after an abort of type x */
1012 case 0x90: /* Branch through zero */
1014 ARMword oldpsr = ARMul_GetCPSR (state);
1015 ARMul_SetCPSR (state, (oldpsr & 0xffffffc0) | 0x13);
1016 ARMul_SetSPSR (state, SVC32MODE, oldpsr);
1021 case 0x98: /* Error */
1023 ARMword errorp = state->Reg[0], regp = state->Reg[1];
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;
1036 case 0x94: /* Data abort */
1038 ARMword addr = state->Reg[14] - 8;
1039 ARMword cpsr = ARMul_GetCPSR (state);
1041 addr = addr & 0x3fffffc;
1042 ARMul_SetCPSR (state, ARMul_GetSPSR (state, cpsr));
1043 UnwindDataAbort (state, addr);
1044 if (addr >= FPESTART && addr < FPEEND)
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++)
1056 ARMul_SetReg (state, spsr, i, ARMul_ReadWord (state, sp));
1059 ARMul_SetCPSR (state, cpsr);
1060 state->Reg[14] = ARMul_ReadWord (state, sp) + 4; /* botch it */
1061 ARMul_SetSPSR (state, state->Mode, spsr);
1064 ARMul_SetCPSR (state, cpsr);
1066 /* and fall through to correct r14 */
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;
1077 if (state->VectorCatch & (1 << (number - 0x90)))
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)));
1082 state->EndCondition = 10; /* Branch through Zero Error */
1084 state->EndCondition = (unsigned) number - 0x8f;
1085 state->Emulate = FALSE;
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);
1099 /* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */
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)));
1120 state->EndCondition = 10; /* Branch through Zero Error */
1122 state->EndCondition = (unsigned) number - 0x7f;
1123 state->Emulate = FALSE;
1128 state->Emulate = FALSE;
1135 #endif /* CYGNUS LOCAL: #if 1 */
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 \***************************************************************************/
1148 ARMul_OSException (ARMul_State * state, ARMword vector, ARMword pc)
1149 { /* don't use this here */
1155 /***************************************************************************\
1156 * Unwind a data abort *
1157 \***************************************************************************/
1160 UnwindDataAbort (ARMul_State * state, ARMword addr)
1162 ARMword instr = ARMul_ReadWord (state, addr);
1163 ARMword rn = BITS (16, 19);
1164 ARMword itype = BITS (24, 27);
1168 if (itype == 8 || itype == 9)
1171 unsigned long regs = BITS (0, 15);
1175 for (; regs != 0; offset++)
1176 regs ^= (regs & -regs);
1180 else if (itype == 12 || /* post-indexed CPDT */
1181 (itype == 13 && BIT (21)))
1182 { /* pre_indexed CPDT with WB */
1183 offset = BITS (0, 7);
1189 state->Reg[rn] -= offset * 4;
1191 state->Reg[rn] += offset * 4;
1194 /***************************************************************************\
1195 * Copy a string from the debuggee's memory to the host's *
1196 \***************************************************************************/
1199 getstring (ARMul_State * state, ARMword from, char *to)
1203 *to = (char) ARMul_ReadByte (state, from++);
1205 while (*to++ != '\0');