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, ARMword pc) ;
87 extern ARMword ARMul_OSLastErrorP(ARMul_State *state) ;
88 extern ARMword ARMul_Debug(ARMul_State *state, ARMword pc, ARMword instr) ;
90 #define BUFFERSIZE 4096
94 #define UNIQUETEMPS 256
97 static void UnwindDataAbort(ARMul_State *state, ARMword addr);
98 static void getstring(ARMul_State *state, ARMword from, char *to) ;
101 /***************************************************************************\
102 * OS private Information *
103 \***************************************************************************/
109 FILE *FileTable[FOPEN_MAX] ;
110 char FileFlags[FOPEN_MAX] ;
111 char *tempnames[UNIQUETEMPS] ;
120 #define FIXCRLF(t,c) ((t & BINARY) ? \
122 ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \
125 #define FIXCRLF(t,c) c
128 static ARMword softvectorcode[] =
129 { /* basic: swi tidyexception + event; mov pc, lr;
130 ldmia r11,{r11,pc}; swi generateexception + event
132 0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /*Reset*/
133 0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /*Undef*/
134 0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /*SWI */
135 0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /*Prefetch abort*/
136 0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /*Data abort*/
137 0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /*Address exception*/
138 0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /*IRQ*/
139 0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /*FIQ*/
140 0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /*Error*/
141 0xe1a0f00e /* default handler */
144 /***************************************************************************\
145 * Time for the Operating System to initialise itself. *
146 \***************************************************************************/
149 ARMul_OSInit (ARMul_State *state)
153 ARMword instr, i , j ;
154 struct OSblock* OSptr = (struct OSblock*)state->OSptr;
156 if (state->OSptr == NULL) {
157 state->OSptr = (unsigned char *)malloc(sizeof(struct OSblock));
158 if (state->OSptr == NULL) {
163 OSptr = (struct OSblock*)state->OSptr;
165 state->Reg[13] = ADDRSUPERSTACK; /* set up a stack for the current mode */
166 ARMul_SetReg(state,SVC32MODE,13,ADDRSUPERSTACK); /* and for supervisor mode */
167 ARMul_SetReg(state,ABORT32MODE,13,ADDRSUPERSTACK); /* and for abort 32 mode */
168 ARMul_SetReg(state,UNDEF32MODE,13,ADDRSUPERSTACK); /* and for undef 32 mode */
169 instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8); /* load pc from soft vector */
170 for (i = ARMul_ResetV ; i <= ARMFIQV ; i += 4)
171 ARMul_WriteWord(state, i, instr); /* write hardware vectors */
172 for (i = ARMul_ResetV ; i <= ARMFIQV + 4 ; i += 4) {
173 ARMul_WriteWord(state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
174 ARMul_WriteWord(state, ADDRSOFHANDLERS + 2*i + 4L, SOFTVECTORCODE + sizeof(softvectorcode) - 4L);
176 for (i = 0 ; i < sizeof(softvectorcode) ; i += 4)
177 ARMul_WriteWord(state, SOFTVECTORCODE + i, softvectorcode[i/4]);
178 for (i = 0 ; i < FOPEN_MAX ; i++)
179 OSptr->FileTable[i] = NULL ;
180 for (i = 0 ; i < UNIQUETEMPS ; i++)
181 OSptr->tempnames[i] = NULL ;
182 ARMul_ConsolePrint (state, ", Demon 1.01");
187 for (i = 0 ; i < fpesize ; i+=4) /* copy the code */
188 ARMul_WriteWord(state,FPESTART + i,fpecode[i >> 2]) ;
189 for (i = FPESTART + fpesize ; ; i-=4) { /* reverse the error strings */
190 if ((j = ARMul_ReadWord(state,i)) == 0xffffffff)
192 if (state->bigendSig && j < 0x80000000) { /* it's part of the string so swap it */
193 j = ((j >> 0x18) & 0x000000ff) |
194 ((j >> 0x08) & 0x0000ff00) |
195 ((j << 0x08) & 0x00ff0000) |
196 ((j << 0x18) & 0xff000000) ;
197 ARMul_WriteWord(state,i,j) ;
200 ARMul_WriteWord(state,FPEOLDVECT,ARMul_ReadWord(state,4)) ; /* copy old illegal instr vector */
201 ARMul_WriteWord(state,4,FPENEWVECT(ARMul_ReadWord(state,i-4))) ; /* install new vector */
202 ARMul_ConsolePrint (state, ", FPE") ;
205 #endif /* VALIDATE */
212 ARMul_OSExit (ARMul_State *state)
214 free((char *)state->OSptr);
218 /***************************************************************************\
219 * Return the last Operating System Error. *
220 \***************************************************************************/
223 ARMul_OSLastErrorP (ARMul_State *state)
225 return ((struct OSblock *)state->OSptr)->ErrorP;
228 #if 1 /* CYGNUS LOCAL */
229 /* This is the cygnus way of doing it, which makes it simple to do our tests */
231 static int translate_open_mode[] =
234 O_RDONLY+O_BINARY, /* "rb" */
236 O_RDWR +O_BINARY, /* "r+b" */
237 O_WRONLY +O_CREAT+O_TRUNC, /* "w" */
238 O_WRONLY+O_BINARY+O_CREAT+O_TRUNC, /* "wb" */
239 O_RDWR +O_CREAT+O_TRUNC, /* "w+" */
240 O_RDWR +O_BINARY+O_CREAT+O_TRUNC, /* "w+b" */
241 O_WRONLY +O_APPEND+O_CREAT,/* "a" */
242 O_WRONLY+O_BINARY+O_APPEND+O_CREAT,/* "ab" */
243 O_RDWR +O_APPEND+O_CREAT,/* "a+" */
244 O_RDWR +O_BINARY+O_APPEND+O_CREAT /* "a+b" */
248 SWIWrite0 (ARMul_State *state, ARMword addr)
251 struct OSblock* OSptr = (struct OSblock*) state->OSptr;
253 while ((temp = ARMul_ReadByte (state, addr++)) != 0)
254 (void) fputc ((char) temp, stdout);
256 OSptr->ErrorNo = errno;
260 WriteCommandLineTo (ARMul_State *state, ARMword addr)
263 char *cptr = state->CommandLine;
267 temp = (ARMword) *cptr++;
268 ARMul_WriteByte (state, addr++, temp);
273 SWIopen (ARMul_State *state, ARMword name, ARMword SWIflags)
275 struct OSblock* OSptr = (struct OSblock*)state->OSptr;
281 dummy[i] = ARMul_ReadByte (state, name + i);
285 /* Now we need to decode the Demon open mode */
286 flags = translate_open_mode[SWIflags];
288 /* Filename ":tt" is special: it denotes stdin/out */
289 if (strcmp (dummy, ":tt") == 0)
291 if (flags == O_RDONLY) /* opening tty "r" */
292 state->Reg[0] = 0; /* stdin */
294 state->Reg[0] = 1; /* stdout */
298 state->Reg[0] = (int) open (dummy, flags, 0666);
299 OSptr->ErrorNo = errno;
304 SWIread (ARMul_State *state, ARMword f, ARMword ptr, ARMword len)
306 struct OSblock* OSptr = (struct OSblock*) state->OSptr;
309 char *local = malloc (len);
313 fprintf (stderr, "sim: Unable to read 0x%x bytes - out of memory\n", len);
317 res = read (f, local, len);
319 for (i = 0; i < res; i++)
320 ARMul_WriteByte (state, ptr + i, local[i]);
322 state->Reg[0] = res == -1 ? -1 : len - res;
323 OSptr->ErrorNo = errno;
327 SWIwrite (ARMul_State *state, ARMword f, ARMword ptr, ARMword len)
329 struct OSblock* OSptr = (struct OSblock*) state->OSptr;
332 char *local = malloc (len);
336 fprintf (stderr, "sim: Unable to write 0x%x bytes - out of memory\n", len);
340 for (i = 0; i < len; i++)
341 local[i] = ARMul_ReadByte (state, ptr + i);
343 res = write (f, local, len);
344 state->Reg[0] = res == -1 ? -1 : len - res;
346 OSptr->ErrorNo = errno;
350 SWIflen (ARMul_State *state, ARMword fh)
352 struct OSblock* OSptr = (struct OSblock*) state->OSptr;
355 if (fh == 0 || fh > FOPEN_MAX)
357 OSptr->ErrorNo = EBADF;
362 addr = lseek (fh, 0, SEEK_CUR);
367 state->Reg[0] = lseek (fh, 0L, SEEK_END);
368 (void) lseek (fh, addr, SEEK_SET);
371 OSptr->ErrorNo = errno;
374 /***************************************************************************\
375 * The emulator calls this routine when a SWI instruction is encuntered. The *
376 * parameter passed is the SWI number (lower 24 bits of the instruction). *
377 \***************************************************************************/
380 ARMul_OSHandleSWI (ARMul_State *state, ARMword number)
382 ARMword addr, temp, fildes;
383 char buffer[BUFFERSIZE], *cptr;
385 struct OSblock* OSptr = (struct OSblock*)state->OSptr;
390 SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
394 SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
398 SWIopen (state, state->Reg[0],state->Reg[1]);
402 /* return number of centi-seconds... */
404 #ifdef CLOCKS_PER_SEC
405 (CLOCKS_PER_SEC >= 100)
406 ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
407 : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
409 /* presume unix... clock() returns microseconds */
410 (ARMword) (clock() / 10000) ;
412 OSptr->ErrorNo = errno ;
416 state->Reg[0] = (ARMword)time(NULL) ;
417 OSptr->ErrorNo = errno ;
421 state->Reg[0] = close (state->Reg[0]);
422 OSptr->ErrorNo = errno;
426 SWIflen (state, state->Reg[0]);
430 state->Emulate = FALSE ;
435 /* We must return non-zero for failure */
436 state->Reg[0] = -1 >= lseek (state->Reg[0],
439 OSptr->ErrorNo = errno;
444 (void)fputc((int)state->Reg[0],stdout) ;
445 OSptr->ErrorNo = errno ;
449 SWIWrite0 (state, state->Reg[0]);
453 state->Reg[0] = OSptr->ErrorNo ;
456 case SWI_Breakpoint :
457 state->EndCondition = RDIError_BreakpointReached ;
458 state->Emulate = FALSE ;
462 state->Reg[0] = ADDRCMDLINE ;
464 state->Reg[1] = state->MemSize ;
466 state->Reg[1] = ADDRUSERSTACK ;
468 WriteCommandLineTo (state, state->Reg[0]);
471 /* Handle Angel SWIs as well as Demon ones */
474 /* R1 is almost always a parameter block */
475 addr = state->Reg[1];
476 /* R0 is a reason code */
477 switch (state->Reg[0])
479 /* Unimplemented reason codes */
480 case AngelSWI_Reason_ReadC:
481 case AngelSWI_Reason_IsTTY:
482 case AngelSWI_Reason_TmpNam:
483 case AngelSWI_Reason_Remove:
484 case AngelSWI_Reason_Rename:
485 case AngelSWI_Reason_System:
486 case AngelSWI_Reason_EnterSVC:
488 state->Emulate = FALSE;
491 case AngelSWI_Reason_Clock:
492 /* return number of centi-seconds... */
494 #ifdef CLOCKS_PER_SEC
495 (CLOCKS_PER_SEC >= 100)
496 ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
497 : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
499 /* presume unix... clock() returns microseconds */
500 (ARMword) (clock() / 10000) ;
502 OSptr->ErrorNo = errno;
505 case AngelSWI_Reason_Time:
506 state->Reg[0] = (ARMword) time (NULL);
507 OSptr->ErrorNo = errno;
510 case AngelSWI_Reason_WriteC:
511 (void) fputc ((int) ARMul_ReadByte (state,addr), stdout);
512 OSptr->ErrorNo = errno;
515 case AngelSWI_Reason_Write0:
516 SWIWrite0 (state, addr);
519 case AngelSWI_Reason_Close:
520 state->Reg[0] = close (ARMul_ReadWord (state, addr));
521 OSptr->ErrorNo = errno;
524 case AngelSWI_Reason_Seek:
525 state->Reg[0] = -1 >= lseek (ARMul_ReadWord(state,addr),
526 ARMul_ReadWord(state,addr+4),
528 OSptr->ErrorNo = errno;
531 case AngelSWI_Reason_FLen:
532 SWIflen (state, ARMul_ReadWord (state, addr));
535 case AngelSWI_Reason_GetCmdLine:
536 WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
539 case AngelSWI_Reason_HeapInfo:
540 /* R1 is a pointer to a pointer */
541 addr = ARMul_ReadWord (state, addr);
543 /* Pick up the right memory limit */
545 temp = state->MemSize;
547 temp = ADDRUSERSTACK;
549 ARMul_WriteWord (state, addr, 0); /* Heap base */
550 ARMul_WriteWord (state, addr+4, temp); /* Heap limit */
551 ARMul_WriteWord (state, addr+8, temp); /* Stack base */
552 ARMul_WriteWord (state, addr+12, temp); /* Stack limit */
555 case AngelSWI_Reason_ReportException:
556 if (state->Reg[1] == ADP_Stopped_ApplicationExit)
560 state->Emulate = FALSE ;
563 case ADP_Stopped_ApplicationExit:
565 state->Emulate = FALSE ;
568 case ADP_Stopped_RunTimeError:
570 state->Emulate = FALSE ;
573 case AngelSWI_Reason_Errno:
574 state->Reg[0] = OSptr->ErrorNo;
577 case AngelSWI_Reason_Open:
579 ARMul_ReadWord(state, addr),
580 ARMul_ReadWord(state, addr+4));
583 case AngelSWI_Reason_Read:
585 ARMul_ReadWord(state, addr),
586 ARMul_ReadWord(state, addr+4),
587 ARMul_ReadWord(state, addr+8));
590 case AngelSWI_Reason_Write:
592 ARMul_ReadWord(state, addr),
593 ARMul_ReadWord(state, addr+4),
594 ARMul_ReadWord(state, addr+8));
599 state->Emulate = FALSE ;
604 #else /* CYGNUS LOCAL: #if 1 */
607 ARMul_OSHandleSWI (ARMul_State *state, ARMword number)
615 state->Emulate = FALSE ;
619 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ;
621 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ;
628 char buffer[BUFFERSIZE], *cptr ;
630 struct OSblock* OSptr = (struct OSblock*)state->OSptr ;
634 (void)fputc((int)state->Reg[0],stderr) ;
635 OSptr->ErrorNo = errno ;
639 addr = state->Reg[0] ;
640 while ((temp = ARMul_ReadByte(state,addr++)) != 0)
641 fputc((char)temp,stderr) ;
642 OSptr->ErrorNo = errno ;
646 state->Reg[0] = (ARMword)fgetc(stdin) ;
647 OSptr->ErrorNo = errno ;
651 addr = state->Reg[0] ;
652 getstring(state,state->Reg[0],buffer) ;
653 state->Reg[0] = (ARMword)system(buffer) ;
654 OSptr->ErrorNo = errno ;
658 state->Reg[0] = ADDRCMDLINE ;
660 state->Reg[1] = state->MemSize ;
662 state->Reg[1] = ADDRUSERSTACK ;
664 addr = state->Reg[0] ;
665 cptr = state->CommandLine ;
669 temp = (ARMword)*cptr++ ;
670 ARMul_WriteByte(state,addr++,temp) ;
671 } while (temp != 0) ;
676 simkernel1_abort_run() ;
678 state->Emulate = FALSE ;
684 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ;
686 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ;
690 state->Reg[0] = OSptr->ErrorNo ;
694 /* return muber of centi-seconds... */
696 #ifdef CLOCKS_PER_SEC
697 (CLOCKS_PER_SEC >= 100)
698 ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
699 : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
701 /* presume unix... clock() returns microseconds */
702 (ARMword) (clock() / 10000) ;
704 OSptr->ErrorNo = errno ;
708 state->Reg[0] = (ARMword)time(NULL) ;
709 OSptr->ErrorNo = errno ;
713 getstring(state,state->Reg[0],buffer) ;
714 state->Reg[0] = unlink(buffer) ;
715 OSptr->ErrorNo = errno ;
719 char buffer2[BUFFERSIZE] ;
721 getstring(state,state->Reg[0],buffer) ;
722 getstring(state,state->Reg[1],buffer2) ;
723 state->Reg[0] = rename(buffer,buffer2) ;
724 OSptr->ErrorNo = errno ;
730 /* It seems to me that these are in the wrong order
731 sac@cygnus.com, so I've redone it to use the
732 flags instead, with the functionality which was already
733 there -- ahh, perhaps the TRUNC bit is in a different
734 place on the original host ?*/
735 static char* fmode[] = {"r","rb","r+","r+b",
738 "r","r","r","r"} /* last 4 are illegal */ ;
743 type = (unsigned)(state->Reg[1] & 3L) ;
744 getstring(state,state->Reg[0],buffer) ;
745 if (strcmp(buffer,":tt")==0 && (type == O_RDONLY )) /* opening tty "r" */
747 else if (strcmp(buffer,":tt")==0 && (type == O_WRONLY)) /* opening tty "w" */
754 fptr = fopen(buffer,"r") ;
757 fptr = fopen(buffer,"w") ;
760 fptr = fopen(buffer,"rw") ;
767 for (temp = 0 ; temp < FOPEN_MAX ; temp++)
768 if (OSptr->FileTable[temp] == NULL) {
769 OSptr->FileTable[temp] = fptr ;
770 OSptr->FileFlags[temp] = type & 1 ; /* preserve the binary bit */
771 state->Reg[0] = (ARMword)(temp + 1) ;
774 if (state->Reg[0] == 0)
775 OSptr->ErrorNo = EMFILE ; /* too many open files */
777 OSptr->ErrorNo = errno ;
780 OSptr->ErrorNo = errno ;
785 temp = state->Reg[0] ;
786 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
787 OSptr->ErrorNo = EBADF ;
788 state->Reg[0] = -1L ;
792 fptr = OSptr->FileTable[temp] ;
793 if (fptr == stdin || fptr == stderr)
796 state->Reg[0] = fclose(fptr) ;
797 OSptr->FileTable[temp] = NULL ;
798 OSptr->ErrorNo = errno ;
802 unsigned size, upto, type ;
805 temp = state->Reg[0] ;
806 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
807 OSptr->ErrorNo = EBADF ;
808 state->Reg[0] = -1L ;
812 fptr = OSptr->FileTable[temp] ;
813 type = OSptr->FileFlags[temp] ;
814 addr = state->Reg[1] ;
815 size = (unsigned)state->Reg[2] ;
818 fseek(fptr,0L,SEEK_CUR) ;
819 OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP ; ;
821 if (size >= BUFFERSIZE)
825 for (cptr = buffer ; (cptr - buffer) < upto ; cptr++) {
826 ch = (char)ARMul_ReadByte(state,(ARMword)addr++) ;
827 *cptr = FIXCRLF(type,ch) ;
829 temp = fwrite(buffer,1,upto,fptr) ;
831 state->Reg[0] = (ARMword)(size - temp) ;
832 OSptr->ErrorNo = errno ;
838 OSptr->ErrorNo = errno ;
843 unsigned size, upto, type ;
846 temp = state->Reg[0] ;
847 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
848 OSptr->ErrorNo = EBADF ;
849 state->Reg[0] = -1L ;
853 fptr = OSptr->FileTable[temp] ;
854 addr = state->Reg[1] ;
855 size = (unsigned)state->Reg[2] ;
856 type = OSptr->FileFlags[temp] ;
859 fseek(fptr,0L,SEEK_CUR) ;
860 OSptr->FileFlags[temp] = (type & BINARY) | READOP ; ;
863 upto = (size >= BUFFERSIZE)?BUFFERSIZE:size + 1 ;
864 if (fgets(buffer, upto, fptr) != 0)
865 temp = strlen(buffer) ;
868 upto-- ; /* 1 char used for terminating null */
871 upto = (size>=BUFFERSIZE)?BUFFERSIZE:size ;
872 temp = fread(buffer,1,upto,fptr) ;
874 for (cptr = buffer ; (cptr - buffer) < temp ; cptr++) {
876 ARMul_WriteByte(state,(ARMword)addr++,FIXCRLF(type,ch)) ;
879 state->Reg[0] = (ARMword)(size - temp) ;
880 OSptr->ErrorNo = errno ;
886 OSptr->ErrorNo = errno ;
891 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
892 || OSptr->FileTable[state->Reg[0] - 1] == 0) {
893 OSptr->ErrorNo = EBADF ;
894 state->Reg[0] = -1L ;
897 fptr = OSptr->FileTable[state->Reg[0] - 1] ;
898 state->Reg[0] = fseek(fptr,(long)state->Reg[1],SEEK_SET) ;
899 OSptr->ErrorNo = errno ;
903 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
904 || OSptr->FileTable[state->Reg[0] - 1] == 0) {
905 OSptr->ErrorNo = EBADF ;
906 state->Reg[0] = -1L ;
909 fptr = OSptr->FileTable[state->Reg[0] - 1] ;
910 addr = (ARMword)ftell(fptr) ;
911 if (fseek(fptr,0L,SEEK_END) < 0)
914 state->Reg[0] = (ARMword)ftell(fptr) ;
915 (void)fseek(fptr,addr,SEEK_SET) ;
917 OSptr->ErrorNo = errno ;
921 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
922 || OSptr->FileTable[state->Reg[0] - 1] == 0) {
923 OSptr->ErrorNo = EBADF ;
924 state->Reg[0] = -1L ;
927 fptr = OSptr->FileTable[state->Reg[0] - 1] ;
928 state->Reg[0] = isatty_(fptr) ;
929 OSptr->ErrorNo = errno ;
935 addr = state->Reg[0] ;
936 temp = state->Reg[1] & 0xff ;
937 size = state->Reg[2] ;
938 if (OSptr->tempnames[temp] == NULL) {
939 if ((OSptr->tempnames[temp] = malloc(L_tmpnam)) == NULL) {
943 (void)tmpnam(OSptr->tempnames[temp]) ;
945 cptr = OSptr->tempnames[temp] ;
946 if (strlen(cptr) > state->Reg[2])
950 ARMul_WriteByte(state,addr++,*cptr) ;
951 } while (*cptr++ != 0) ;
952 OSptr->ErrorNo = errno ;
956 case SWI_InstallHandler:
957 { ARMword handlerp = ADDRSOFHANDLERS + state->Reg[0] * 8;
958 ARMword oldr1 = ARMul_ReadWord(state, handlerp),
959 oldr2 = ARMul_ReadWord(state, handlerp + 4);
960 ARMul_WriteWord(state, handlerp, state->Reg[1]);
961 ARMul_WriteWord(state, handlerp + 4, state->Reg[2]);
962 state->Reg[1] = oldr1;
963 state->Reg[2] = oldr2;
967 case SWI_GenerateError:
968 ARMul_Abort(state, ARMSWIV) ;
970 ARMul_SetR15(state, ARMul_ReadWord(state, ADDRSOFTVECTORS + ARMErrorV));
973 /* SWI's 0x9x unwind the state of the CPU after an abort of type x */
975 case 0x90: /* Branch through zero */
976 { ARMword oldpsr = ARMul_GetCPSR(state) ;
977 ARMul_SetCPSR(state, (oldpsr & 0xffffffc0) | 0x13) ;
978 ARMul_SetSPSR(state, SVC32MODE, oldpsr) ;
983 case 0x98: /* Error */
984 { ARMword errorp = state->Reg[0],
985 regp = state->Reg[1];
987 ARMword errorpsr = ARMul_ReadWord(state, regp + 16*4);
988 for (i = 0; i < 15; i++)
989 ARMul_SetReg(state,errorpsr,i,ARMul_ReadWord(state, regp + i*4L)) ;
990 state->Reg[14] = ARMul_ReadWord(state, regp + 15*4L);
991 state->Reg[10] = errorp;
992 ARMul_SetSPSR(state,state->Mode,errorpsr) ;
993 OSptr->ErrorP = errorp;
997 case 0x94: /* Data abort */
998 { ARMword addr = state->Reg[14] - 8;
999 ARMword cpsr = ARMul_GetCPSR(state) ;
1001 addr = addr & 0x3fffffc ;
1002 ARMul_SetCPSR(state,ARMul_GetSPSR(state,cpsr)) ;
1003 UnwindDataAbort(state, addr);
1004 if (addr >= FPESTART && addr < FPEEND) { /* in the FPE */
1008 sp = state->Reg[13] ;
1009 state->Reg[13] += 64 ; /* fix the aborting mode sp */
1010 state->Reg[14] = ARMul_ReadWord(state,sp + 60) ; /* and its lr */
1011 spsr = ARMul_GetSPSR(state,state->Mode) ;
1012 state->Mode = ARMul_SwitchMode(state, state->Mode, spsr);
1013 for (i = 0 ; i < 15 ; i++) {
1014 ARMul_SetReg(state,spsr,i,ARMul_ReadWord(state,sp)) ;
1017 ARMul_SetCPSR(state,cpsr) ;
1018 state->Reg[14] = ARMul_ReadWord(state,sp) + 4 ; /* botch it */
1019 ARMul_SetSPSR(state,state->Mode,spsr) ;
1022 ARMul_SetCPSR(state,cpsr) ;
1024 /* and fall through to correct r14 */
1026 case 0x95: /* Address Exception */
1027 state->Reg[14] -= 4;
1028 case 0x91: /* Undefined instruction */
1029 case 0x92: /* SWI */
1030 case 0x93: /* Prefetch abort */
1031 case 0x96: /* IRQ */
1032 case 0x97: /* FIQ */
1033 state->Reg[14] -= 4;
1035 if (state->VectorCatch & (1 << (number - 0x90))) {
1036 ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
1037 ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ;
1039 state->EndCondition = 10 ; /* Branch through Zero Error */
1041 state->EndCondition = (unsigned)number - 0x8f;
1042 state->Emulate = FALSE ;
1045 ARMword sp = state->Reg[13];
1046 ARMul_WriteWord(state, sp - 4, state->Reg[14]);
1047 ARMul_WriteWord(state, sp - 8, state->Reg[12]);
1048 ARMul_WriteWord(state, sp - 12, state->Reg[11]);
1049 ARMul_WriteWord(state, sp - 16, state->Reg[10]);
1050 state->Reg[13] = sp - 16;
1051 state->Reg[11] = ADDRSOFHANDLERS + 8 * (number - 0x90);
1055 /* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */
1057 case 0x80: case 0x81: case 0x82: case 0x83:
1058 case 0x84: case 0x85: case 0x86: case 0x87: case 0x88:
1059 { ARMword sp = state->Reg[13];
1060 state->Reg[10] = ARMul_ReadWord(state, sp);
1061 state->Reg[11] = ARMul_ReadWord(state, sp + 4);
1062 state->Reg[12] = ARMul_ReadWord(state, sp + 8);
1063 state->Reg[14] = ARMul_ReadWord(state, sp + 12);
1064 state->Reg[13] = sp + 16;
1065 ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
1066 ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ;
1068 state->EndCondition = 10 ; /* Branch through Zero Error */
1070 state->EndCondition = (unsigned)number - 0x7f;
1071 state->Emulate = FALSE ;
1076 state->Emulate = FALSE ;
1082 #endif /* CYGNUS LOCAL: #if 1 */
1087 /***************************************************************************\
1088 * The emulator calls this routine when an Exception occurs. The second *
1089 * parameter is the address of the relevant exception vector. Returning *
1090 * FALSE from this routine causes the trap to be taken, TRUE causes it to *
1091 * be ignored (so set state->Emulate to FALSE!). *
1092 \***************************************************************************/
1095 ARMul_OSException (ARMul_State *state, ARMword vector, ARMword pc)
1096 { /* don't use this here */
1102 /***************************************************************************\
1103 * Unwind a data abort *
1104 \***************************************************************************/
1107 UnwindDataAbort (ARMul_State *state, ARMword addr)
1109 ARMword instr = ARMul_ReadWord(state, addr);
1110 ARMword rn = BITS(16, 19);
1111 ARMword itype = BITS(24, 27);
1113 if (rn == 15) return;
1114 if (itype == 8 || itype == 9) {
1116 unsigned long regs = BITS(0, 15);
1118 if (!BIT(21)) return; /* no wb */
1119 for (; regs != 0; offset++)
1120 regs ^= (regs & -regs);
1121 if (offset == 0) offset = 16;
1122 } else if (itype == 12 || /* post-indexed CPDT */
1123 (itype == 13 && BIT(21))) { /* pre_indexed CPDT with WB */
1124 offset = BITS(0, 7);
1129 state->Reg[rn] -= offset * 4;
1131 state->Reg[rn] += offset * 4;
1134 /***************************************************************************\
1135 * Copy a string from the debuggee's memory to the host's *
1136 \***************************************************************************/
1139 getstring (ARMul_State *state, ARMword from, char *to)
1143 *to = (char) ARMul_ReadByte (state, from++);
1144 } while (*to++ != '\0');