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