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
);
311 res
= read (f
, local
, len
);
313 for (i
= 0; i
< res
; i
++)
314 ARMul_WriteByte (state
, ptr
+ i
, local
[i
]);
316 state
->Reg
[0] = res
== -1 ? -1 : len
- res
;
317 OSptr
->ErrorNo
= errno
;
321 SWIwrite (ARMul_State
*state
, ARMword f
, ARMword ptr
, ARMword len
)
323 struct OSblock
* OSptr
= (struct OSblock
*) state
->OSptr
;
326 char *local
= malloc (len
);
328 for (i
= 0; i
< len
; i
++)
330 local
[i
] = ARMul_ReadByte (state
, ptr
+ i
);
332 res
= write (f
, local
, len
);
333 state
->Reg
[0] = res
== -1 ? -1 : len
- res
;
335 OSptr
->ErrorNo
= errno
;
339 SWIflen (ARMul_State
*state
, ARMword fh
)
341 struct OSblock
* OSptr
= (struct OSblock
*) state
->OSptr
;
344 if (fh
== 0 || fh
> FOPEN_MAX
)
346 OSptr
->ErrorNo
= EBADF
;
351 addr
= lseek (fh
, 0, SEEK_CUR
);
356 state
->Reg
[0] = lseek (fh
, 0L, SEEK_END
);
357 (void) lseek (fh
, addr
, SEEK_SET
);
360 OSptr
->ErrorNo
= errno
;
363 /***************************************************************************\
364 * The emulator calls this routine when a SWI instruction is encuntered. The *
365 * parameter passed is the SWI number (lower 24 bits of the instruction). *
366 \***************************************************************************/
369 ARMul_OSHandleSWI (ARMul_State
*state
, ARMword number
)
371 ARMword addr
, temp
, fildes
;
372 char buffer
[BUFFERSIZE
], *cptr
;
374 struct OSblock
* OSptr
= (struct OSblock
*)state
->OSptr
;
379 SWIread (state
, state
->Reg
[0], state
->Reg
[1], state
->Reg
[2]);
383 SWIwrite (state
, state
->Reg
[0], state
->Reg
[1], state
->Reg
[2]);
387 SWIopen (state
, state
->Reg
[0],state
->Reg
[1]);
391 /* return number of centi-seconds... */
393 #ifdef CLOCKS_PER_SEC
394 (CLOCKS_PER_SEC
>= 100)
395 ? (ARMword
) (clock() / (CLOCKS_PER_SEC
/ 100))
396 : (ARMword
) ((clock() * 100) / CLOCKS_PER_SEC
) ;
398 /* presume unix... clock() returns microseconds */
399 (ARMword
) (clock() / 10000) ;
401 OSptr
->ErrorNo
= errno
;
405 state
->Reg
[0] = (ARMword
)time(NULL
) ;
406 OSptr
->ErrorNo
= errno
;
410 state
->Reg
[0] = close (state
->Reg
[0]);
411 OSptr
->ErrorNo
= errno
;
415 SWIflen (state
, state
->Reg
[0]);
419 state
->Emulate
= FALSE
;
424 /* We must return non-zero for failure */
425 state
->Reg
[0] = -1 >= lseek (state
->Reg
[0],
428 OSptr
->ErrorNo
= errno
;
433 (void)fputc((int)state
->Reg
[0],stdout
) ;
434 OSptr
->ErrorNo
= errno
;
438 SWIWrite0 (state
, state
->Reg
[0]);
442 state
->Reg
[0] = OSptr
->ErrorNo
;
445 case SWI_Breakpoint
:
446 state
->EndCondition
= RDIError_BreakpointReached
;
447 state
->Emulate
= FALSE
;
451 state
->Reg
[0] = ADDRCMDLINE
;
453 state
->Reg
[1] = state
->MemSize
;
455 state
->Reg
[1] = ADDRUSERSTACK
;
457 WriteCommandLineTo (state
, state
->Reg
[0]);
460 /* Handle Angel SWIs as well as Demon ones */
463 /* R1 is almost always a parameter block */
464 addr
= state
->Reg
[1];
465 /* R0 is a reason code */
466 switch (state
->Reg
[0])
468 /* Unimplemented reason codes */
469 case AngelSWI_Reason_ReadC
:
470 case AngelSWI_Reason_IsTTY
:
471 case AngelSWI_Reason_TmpNam
:
472 case AngelSWI_Reason_Remove
:
473 case AngelSWI_Reason_Rename
:
474 case AngelSWI_Reason_System
:
475 case AngelSWI_Reason_EnterSVC
:
477 state
->Emulate
= FALSE
;
480 case AngelSWI_Reason_Clock
:
481 /* return number of centi-seconds... */
483 #ifdef CLOCKS_PER_SEC
484 (CLOCKS_PER_SEC
>= 100)
485 ? (ARMword
) (clock() / (CLOCKS_PER_SEC
/ 100))
486 : (ARMword
) ((clock() * 100) / CLOCKS_PER_SEC
) ;
488 /* presume unix... clock() returns microseconds */
489 (ARMword
) (clock() / 10000) ;
491 OSptr
->ErrorNo
= errno
;
494 case AngelSWI_Reason_Time
:
495 state
->Reg
[0] = (ARMword
) time (NULL
);
496 OSptr
->ErrorNo
= errno
;
499 case AngelSWI_Reason_WriteC
:
500 (void) fputc ((int) ARMul_ReadByte (state
,addr
), stdout
);
501 OSptr
->ErrorNo
= errno
;
504 case AngelSWI_Reason_Write0
:
505 SWIWrite0 (state
, addr
);
508 case AngelSWI_Reason_Close
:
509 state
->Reg
[0] = close (ARMul_ReadWord (state
, addr
));
510 OSptr
->ErrorNo
= errno
;
513 case AngelSWI_Reason_Seek
:
514 state
->Reg
[0] = -1 >= lseek (ARMul_ReadWord(state
,addr
),
515 ARMul_ReadWord(state
,addr
+4),
517 OSptr
->ErrorNo
= errno
;
520 case AngelSWI_Reason_FLen
:
521 SWIflen (state
, ARMul_ReadWord (state
, addr
));
524 case AngelSWI_Reason_GetCmdLine
:
525 WriteCommandLineTo (state
, ARMul_ReadWord (state
, addr
));
528 case AngelSWI_Reason_HeapInfo
:
529 /* R1 is a pointer to a pointer */
530 addr
= ARMul_ReadWord (state
, addr
);
532 /* Pick up the right memory limit */
534 temp
= state
->MemSize
;
536 temp
= ADDRUSERSTACK
;
538 ARMul_WriteWord (state
, addr
, 0); /* Heap base */
539 ARMul_WriteWord (state
, addr
+4, temp
); /* Heap limit */
540 ARMul_WriteWord (state
, addr
+8, temp
); /* Stack base */
541 ARMul_WriteWord (state
, addr
+12, temp
); /* Stack limit */
544 case AngelSWI_Reason_ReportException
:
545 if (state
->Reg
[1] == ADP_Stopped_ApplicationExit
)
549 state
->Emulate
= FALSE
;
552 case ADP_Stopped_ApplicationExit
:
554 state
->Emulate
= FALSE
;
557 case ADP_Stopped_RunTimeError
:
559 state
->Emulate
= FALSE
;
562 case AngelSWI_Reason_Errno
:
563 state
->Reg
[0] = OSptr
->ErrorNo
;
566 case AngelSWI_Reason_Open
:
568 ARMul_ReadWord(state
, addr
),
569 ARMul_ReadWord(state
, addr
+4));
572 case AngelSWI_Reason_Read
:
574 ARMul_ReadWord(state
, addr
),
575 ARMul_ReadWord(state
, addr
+4),
576 ARMul_ReadWord(state
, addr
+8));
579 case AngelSWI_Reason_Write
:
581 ARMul_ReadWord(state
, addr
),
582 ARMul_ReadWord(state
, addr
+4),
583 ARMul_ReadWord(state
, addr
+8));
588 state
->Emulate
= FALSE
;
593 #else /* CYGNUS LOCAL: #if 1 */
596 ARMul_OSHandleSWI (ARMul_State
*state
, ARMword number
)
604 state
->Emulate
= FALSE
;
608 ARMul_SetCPSR(state
, (ARMul_GetCPSR(state
) & 0xffffffc0) | 0x13) ;
610 ARMul_SetCPSR(state
, (ARMul_GetCPSR(state
) & 0xffffffc0) | 0x3) ;
617 char buffer
[BUFFERSIZE
], *cptr
;
619 struct OSblock
* OSptr
= (struct OSblock
*)state
->OSptr
;
623 (void)fputc((int)state
->Reg
[0],stderr
) ;
624 OSptr
->ErrorNo
= errno
;
628 addr
= state
->Reg
[0] ;
629 while ((temp
= ARMul_ReadByte(state
,addr
++)) != 0)
630 fputc((char)temp
,stderr
) ;
631 OSptr
->ErrorNo
= errno
;
635 state
->Reg
[0] = (ARMword
)fgetc(stdin
) ;
636 OSptr
->ErrorNo
= errno
;
640 addr
= state
->Reg
[0] ;
641 getstring(state
,state
->Reg
[0],buffer
) ;
642 state
->Reg
[0] = (ARMword
)system(buffer
) ;
643 OSptr
->ErrorNo
= errno
;
647 state
->Reg
[0] = ADDRCMDLINE
;
649 state
->Reg
[1] = state
->MemSize
;
651 state
->Reg
[1] = ADDRUSERSTACK
;
653 addr
= state
->Reg
[0] ;
654 cptr
= state
->CommandLine
;
658 temp
= (ARMword
)*cptr
++ ;
659 ARMul_WriteByte(state
,addr
++,temp
) ;
660 } while (temp
!= 0) ;
665 simkernel1_abort_run() ;
667 state
->Emulate
= FALSE
;
673 ARMul_SetCPSR(state
, (ARMul_GetCPSR(state
) & 0xffffffc0) | 0x13) ;
675 ARMul_SetCPSR(state
, (ARMul_GetCPSR(state
) & 0xffffffc0) | 0x3) ;
679 state
->Reg
[0] = OSptr
->ErrorNo
;
683 /* return muber of centi-seconds... */
685 #ifdef CLOCKS_PER_SEC
686 (CLOCKS_PER_SEC
>= 100)
687 ? (ARMword
) (clock() / (CLOCKS_PER_SEC
/ 100))
688 : (ARMword
) ((clock() * 100) / CLOCKS_PER_SEC
) ;
690 /* presume unix... clock() returns microseconds */
691 (ARMword
) (clock() / 10000) ;
693 OSptr
->ErrorNo
= errno
;
697 state
->Reg
[0] = (ARMword
)time(NULL
) ;
698 OSptr
->ErrorNo
= errno
;
702 getstring(state
,state
->Reg
[0],buffer
) ;
703 state
->Reg
[0] = unlink(buffer
) ;
704 OSptr
->ErrorNo
= errno
;
708 char buffer2
[BUFFERSIZE
] ;
710 getstring(state
,state
->Reg
[0],buffer
) ;
711 getstring(state
,state
->Reg
[1],buffer2
) ;
712 state
->Reg
[0] = rename(buffer
,buffer2
) ;
713 OSptr
->ErrorNo
= errno
;
719 /* It seems to me that these are in the wrong order
720 sac@cygnus.com, so I've redone it to use the
721 flags instead, with the functionality which was already
722 there -- ahh, perhaps the TRUNC bit is in a different
723 place on the original host ?*/
724 static char* fmode
[] = {"r","rb","r+","r+b",
727 "r","r","r","r"} /* last 4 are illegal */ ;
732 type
= (unsigned)(state
->Reg
[1] & 3L) ;
733 getstring(state
,state
->Reg
[0],buffer
) ;
734 if (strcmp(buffer
,":tt")==0 && (type
== O_RDONLY
)) /* opening tty "r" */
736 else if (strcmp(buffer
,":tt")==0 && (type
== O_WRONLY
)) /* opening tty "w" */
743 fptr
= fopen(buffer
,"r") ;
746 fptr
= fopen(buffer
,"w") ;
749 fptr
= fopen(buffer
,"rw") ;
756 for (temp
= 0 ; temp
< FOPEN_MAX
; temp
++)
757 if (OSptr
->FileTable
[temp
] == NULL
) {
758 OSptr
->FileTable
[temp
] = fptr
;
759 OSptr
->FileFlags
[temp
] = type
& 1 ; /* preserve the binary bit */
760 state
->Reg
[0] = (ARMword
)(temp
+ 1) ;
763 if (state
->Reg
[0] == 0)
764 OSptr
->ErrorNo
= EMFILE
; /* too many open files */
766 OSptr
->ErrorNo
= errno
;
769 OSptr
->ErrorNo
= errno
;
774 temp
= state
->Reg
[0] ;
775 if (temp
== 0 || temp
> FOPEN_MAX
|| OSptr
->FileTable
[temp
- 1] == 0) {
776 OSptr
->ErrorNo
= EBADF
;
777 state
->Reg
[0] = -1L ;
781 fptr
= OSptr
->FileTable
[temp
] ;
782 if (fptr
== stdin
|| fptr
== stderr
)
785 state
->Reg
[0] = fclose(fptr
) ;
786 OSptr
->FileTable
[temp
] = NULL
;
787 OSptr
->ErrorNo
= errno
;
791 unsigned size
, upto
, type
;
794 temp
= state
->Reg
[0] ;
795 if (temp
== 0 || temp
> FOPEN_MAX
|| OSptr
->FileTable
[temp
- 1] == 0) {
796 OSptr
->ErrorNo
= EBADF
;
797 state
->Reg
[0] = -1L ;
801 fptr
= OSptr
->FileTable
[temp
] ;
802 type
= OSptr
->FileFlags
[temp
] ;
803 addr
= state
->Reg
[1] ;
804 size
= (unsigned)state
->Reg
[2] ;
807 fseek(fptr
,0L,SEEK_CUR
) ;
808 OSptr
->FileFlags
[temp
] = (type
& BINARY
) | WRITEOP
; ;
810 if (size
>= BUFFERSIZE
)
814 for (cptr
= buffer
; (cptr
- buffer
) < upto
; cptr
++) {
815 ch
= (char)ARMul_ReadByte(state
,(ARMword
)addr
++) ;
816 *cptr
= FIXCRLF(type
,ch
) ;
818 temp
= fwrite(buffer
,1,upto
,fptr
) ;
820 state
->Reg
[0] = (ARMword
)(size
- temp
) ;
821 OSptr
->ErrorNo
= errno
;
827 OSptr
->ErrorNo
= errno
;
832 unsigned size
, upto
, type
;
835 temp
= state
->Reg
[0] ;
836 if (temp
== 0 || temp
> FOPEN_MAX
|| OSptr
->FileTable
[temp
- 1] == 0) {
837 OSptr
->ErrorNo
= EBADF
;
838 state
->Reg
[0] = -1L ;
842 fptr
= OSptr
->FileTable
[temp
] ;
843 addr
= state
->Reg
[1] ;
844 size
= (unsigned)state
->Reg
[2] ;
845 type
= OSptr
->FileFlags
[temp
] ;
848 fseek(fptr
,0L,SEEK_CUR
) ;
849 OSptr
->FileFlags
[temp
] = (type
& BINARY
) | READOP
; ;
852 upto
= (size
>= BUFFERSIZE
)?BUFFERSIZE
:size
+ 1 ;
853 if (fgets(buffer
, upto
, fptr
) != 0)
854 temp
= strlen(buffer
) ;
857 upto
-- ; /* 1 char used for terminating null */
860 upto
= (size
>=BUFFERSIZE
)?BUFFERSIZE
:size
;
861 temp
= fread(buffer
,1,upto
,fptr
) ;
863 for (cptr
= buffer
; (cptr
- buffer
) < temp
; cptr
++) {
865 ARMul_WriteByte(state
,(ARMword
)addr
++,FIXCRLF(type
,ch
)) ;
868 state
->Reg
[0] = (ARMword
)(size
- temp
) ;
869 OSptr
->ErrorNo
= errno
;
875 OSptr
->ErrorNo
= errno
;
880 if (state
->Reg
[0] == 0 || state
->Reg
[0] > FOPEN_MAX
881 || OSptr
->FileTable
[state
->Reg
[0] - 1] == 0) {
882 OSptr
->ErrorNo
= EBADF
;
883 state
->Reg
[0] = -1L ;
886 fptr
= OSptr
->FileTable
[state
->Reg
[0] - 1] ;
887 state
->Reg
[0] = fseek(fptr
,(long)state
->Reg
[1],SEEK_SET
) ;
888 OSptr
->ErrorNo
= errno
;
892 if (state
->Reg
[0] == 0 || state
->Reg
[0] > FOPEN_MAX
893 || OSptr
->FileTable
[state
->Reg
[0] - 1] == 0) {
894 OSptr
->ErrorNo
= EBADF
;
895 state
->Reg
[0] = -1L ;
898 fptr
= OSptr
->FileTable
[state
->Reg
[0] - 1] ;
899 addr
= (ARMword
)ftell(fptr
) ;
900 if (fseek(fptr
,0L,SEEK_END
) < 0)
903 state
->Reg
[0] = (ARMword
)ftell(fptr
) ;
904 (void)fseek(fptr
,addr
,SEEK_SET
) ;
906 OSptr
->ErrorNo
= errno
;
910 if (state
->Reg
[0] == 0 || state
->Reg
[0] > FOPEN_MAX
911 || OSptr
->FileTable
[state
->Reg
[0] - 1] == 0) {
912 OSptr
->ErrorNo
= EBADF
;
913 state
->Reg
[0] = -1L ;
916 fptr
= OSptr
->FileTable
[state
->Reg
[0] - 1] ;
917 state
->Reg
[0] = isatty_(fptr
) ;
918 OSptr
->ErrorNo
= errno
;
924 addr
= state
->Reg
[0] ;
925 temp
= state
->Reg
[1] & 0xff ;
926 size
= state
->Reg
[2] ;
927 if (OSptr
->tempnames
[temp
] == NULL
) {
928 if ((OSptr
->tempnames
[temp
] = malloc(L_tmpnam
)) == NULL
) {
932 (void)tmpnam(OSptr
->tempnames
[temp
]) ;
934 cptr
= OSptr
->tempnames
[temp
] ;
935 if (strlen(cptr
) > state
->Reg
[2])
939 ARMul_WriteByte(state
,addr
++,*cptr
) ;
940 } while (*cptr
++ != 0) ;
941 OSptr
->ErrorNo
= errno
;
945 case SWI_InstallHandler
:
946 { ARMword handlerp
= ADDRSOFHANDLERS
+ state
->Reg
[0] * 8;
947 ARMword oldr1
= ARMul_ReadWord(state
, handlerp
),
948 oldr2
= ARMul_ReadWord(state
, handlerp
+ 4);
949 ARMul_WriteWord(state
, handlerp
, state
->Reg
[1]);
950 ARMul_WriteWord(state
, handlerp
+ 4, state
->Reg
[2]);
951 state
->Reg
[1] = oldr1
;
952 state
->Reg
[2] = oldr2
;
956 case SWI_GenerateError
:
957 ARMul_Abort(state
, ARMSWIV
) ;
959 ARMul_SetR15(state
, ARMul_ReadWord(state
, ADDRSOFTVECTORS
+ ARMErrorV
));
962 /* SWI's 0x9x unwind the state of the CPU after an abort of type x */
964 case 0x90: /* Branch through zero */
965 { ARMword oldpsr
= ARMul_GetCPSR(state
) ;
966 ARMul_SetCPSR(state
, (oldpsr
& 0xffffffc0) | 0x13) ;
967 ARMul_SetSPSR(state
, SVC32MODE
, oldpsr
) ;
972 case 0x98: /* Error */
973 { ARMword errorp
= state
->Reg
[0],
974 regp
= state
->Reg
[1];
976 ARMword errorpsr
= ARMul_ReadWord(state
, regp
+ 16*4);
977 for (i
= 0; i
< 15; i
++)
978 ARMul_SetReg(state
,errorpsr
,i
,ARMul_ReadWord(state
, regp
+ i
*4L)) ;
979 state
->Reg
[14] = ARMul_ReadWord(state
, regp
+ 15*4L);
980 state
->Reg
[10] = errorp
;
981 ARMul_SetSPSR(state
,state
->Mode
,errorpsr
) ;
982 OSptr
->ErrorP
= errorp
;
986 case 0x94: /* Data abort */
987 { ARMword addr
= state
->Reg
[14] - 8;
988 ARMword cpsr
= ARMul_GetCPSR(state
) ;
990 addr
= addr
& 0x3fffffc ;
991 ARMul_SetCPSR(state
,ARMul_GetSPSR(state
,cpsr
)) ;
992 UnwindDataAbort(state
, addr
);
993 if (addr
>= FPESTART
&& addr
< FPEEND
) { /* in the FPE */
997 sp
= state
->Reg
[13] ;
998 state
->Reg
[13] += 64 ; /* fix the aborting mode sp */
999 state
->Reg
[14] = ARMul_ReadWord(state
,sp
+ 60) ; /* and its lr */
1000 spsr
= ARMul_GetSPSR(state
,state
->Mode
) ;
1001 state
->Mode
= ARMul_SwitchMode(state
, state
->Mode
, spsr
);
1002 for (i
= 0 ; i
< 15 ; i
++) {
1003 ARMul_SetReg(state
,spsr
,i
,ARMul_ReadWord(state
,sp
)) ;
1006 ARMul_SetCPSR(state
,cpsr
) ;
1007 state
->Reg
[14] = ARMul_ReadWord(state
,sp
) + 4 ; /* botch it */
1008 ARMul_SetSPSR(state
,state
->Mode
,spsr
) ;
1011 ARMul_SetCPSR(state
,cpsr
) ;
1013 /* and fall through to correct r14 */
1015 case 0x95: /* Address Exception */
1016 state
->Reg
[14] -= 4;
1017 case 0x91: /* Undefined instruction */
1018 case 0x92: /* SWI */
1019 case 0x93: /* Prefetch abort */
1020 case 0x96: /* IRQ */
1021 case 0x97: /* FIQ */
1022 state
->Reg
[14] -= 4;
1024 if (state
->VectorCatch
& (1 << (number
- 0x90))) {
1025 ARMul_SetR15(state
, state
->Reg
[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
1026 ARMul_SetCPSR(state
,ARMul_GetSPSR(state
,ARMul_GetCPSR(state
))) ;
1028 state
->EndCondition
= 10 ; /* Branch through Zero Error */
1030 state
->EndCondition
= (unsigned)number
- 0x8f;
1031 state
->Emulate
= FALSE
;
1034 ARMword sp
= state
->Reg
[13];
1035 ARMul_WriteWord(state
, sp
- 4, state
->Reg
[14]);
1036 ARMul_WriteWord(state
, sp
- 8, state
->Reg
[12]);
1037 ARMul_WriteWord(state
, sp
- 12, state
->Reg
[11]);
1038 ARMul_WriteWord(state
, sp
- 16, state
->Reg
[10]);
1039 state
->Reg
[13] = sp
- 16;
1040 state
->Reg
[11] = ADDRSOFHANDLERS
+ 8 * (number
- 0x90);
1044 /* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */
1046 case 0x80: case 0x81: case 0x82: case 0x83:
1047 case 0x84: case 0x85: case 0x86: case 0x87: case 0x88:
1048 { ARMword sp
= state
->Reg
[13];
1049 state
->Reg
[10] = ARMul_ReadWord(state
, sp
);
1050 state
->Reg
[11] = ARMul_ReadWord(state
, sp
+ 4);
1051 state
->Reg
[12] = ARMul_ReadWord(state
, sp
+ 8);
1052 state
->Reg
[14] = ARMul_ReadWord(state
, sp
+ 12);
1053 state
->Reg
[13] = sp
+ 16;
1054 ARMul_SetR15(state
, state
->Reg
[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
1055 ARMul_SetCPSR(state
,ARMul_GetSPSR(state
,ARMul_GetCPSR(state
))) ;
1057 state
->EndCondition
= 10 ; /* Branch through Zero Error */
1059 state
->EndCondition
= (unsigned)number
- 0x7f;
1060 state
->Emulate
= FALSE
;
1065 state
->Emulate
= FALSE
;
1071 #endif /* CYGNUS LOCAL: #if 1 */
1076 /***************************************************************************\
1077 * The emulator calls this routine when an Exception occurs. The second *
1078 * parameter is the address of the relevant exception vector. Returning *
1079 * FALSE from this routine causes the trap to be taken, TRUE causes it to *
1080 * be ignored (so set state->Emulate to FALSE!). *
1081 \***************************************************************************/
1084 ARMul_OSException (ARMul_State
*state
, ARMword vector
, ARMword pc
)
1085 { /* don't use this here */
1091 /***************************************************************************\
1092 * Unwind a data abort *
1093 \***************************************************************************/
1096 UnwindDataAbort (ARMul_State
*state
, ARMword addr
)
1098 ARMword instr
= ARMul_ReadWord(state
, addr
);
1099 ARMword rn
= BITS(16, 19);
1100 ARMword itype
= BITS(24, 27);
1102 if (rn
== 15) return;
1103 if (itype
== 8 || itype
== 9) {
1105 unsigned long regs
= BITS(0, 15);
1107 if (!BIT(21)) return; /* no wb */
1108 for (; regs
!= 0; offset
++)
1109 regs
^= (regs
& -regs
);
1110 if (offset
== 0) offset
= 16;
1111 } else if (itype
== 12 || /* post-indexed CPDT */
1112 (itype
== 13 && BIT(21))) { /* pre_indexed CPDT with WB */
1113 offset
= BITS(0, 7);
1118 state
->Reg
[rn
] -= offset
* 4;
1120 state
->Reg
[rn
] += offset
* 4;
1123 /***************************************************************************\
1124 * Copy a string from the debuggee's memory to the host's *
1125 \***************************************************************************/
1128 getstring (ARMul_State
*state
, ARMword from
, char *to
)
1132 *to
= (char) ARMul_ReadByte (state
, from
++);
1133 } while (*to
++ != '\0');