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');