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. */
47 #define unlink(s) remove(s)
51 #include <unistd.h> /* For SEEK_SET etc */
55 extern int _fisatty (FILE *);
56 #define isatty_(f) _fisatty(f)
60 #define isatty_(f) isatty((f)->_file)
64 #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
66 #define isatty_(f) isatty (fileno (f))
83 /* For RDIError_BreakpointReached. */
86 extern unsigned ARMul_OSInit (ARMul_State
* state
);
87 extern void ARMul_OSExit (ARMul_State
* state
);
88 extern unsigned ARMul_OSHandleSWI (ARMul_State
* state
, ARMword number
);
89 extern unsigned ARMul_OSException (ARMul_State
* state
, ARMword vector
,
91 extern ARMword
ARMul_OSLastErrorP (ARMul_State
* state
);
92 extern ARMword
ARMul_Debug (ARMul_State
* state
, ARMword pc
, ARMword instr
);
94 #define BUFFERSIZE 4096
98 #define UNIQUETEMPS 256
100 /* OS private Information. */
107 FILE *FileTable
[FOPEN_MAX
];
108 char FileFlags
[FOPEN_MAX
];
109 char *tempnames
[UNIQUETEMPS
];
118 #define FIXCRLF(t,c) ((t & BINARY) ? \
120 ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \
123 #define FIXCRLF(t,c) c
126 static ARMword softvectorcode
[] =
128 /* Basic: swi tidyexception + event; mov pc, lr;
129 ldmia r11,{r11,pc}; swi generateexception + event. */
130 0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /* Reset */
131 0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /* Undef */
132 0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /* SWI */
133 0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /* Prefetch abort */
134 0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /* Data abort */
135 0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /* Address exception */
136 0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /* IRQ */
137 0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /* FIQ */
138 0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /* Error */
139 0xe1a0f00e /* Default handler */
142 /* Time for the Operating System to initialise itself. */
145 ARMul_OSInit (ARMul_State
* state
)
150 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
152 if (state
->OSptr
== NULL
)
154 state
->OSptr
= (unsigned char *) malloc (sizeof (struct OSblock
));
155 if (state
->OSptr
== NULL
)
157 perror ("OS Memory");
162 OSptr
= (struct OSblock
*) state
->OSptr
;
164 state
->Reg
[13] = ADDRSUPERSTACK
; /* set up a stack for the current mode */
165 ARMul_SetReg (state
, SVC32MODE
, 13, ADDRSUPERSTACK
); /* and for supervisor mode */
166 ARMul_SetReg (state
, ABORT32MODE
, 13, ADDRSUPERSTACK
); /* and for abort 32 mode */
167 ARMul_SetReg (state
, UNDEF32MODE
, 13, ADDRSUPERSTACK
); /* and for undef 32 mode */
168 ARMul_SetReg (state
, SYSTEMMODE
, 13, ADDRSUPERSTACK
); /* and for system mode */
169 instr
= 0xe59ff000 | (ADDRSOFTVECTORS
- 8); /* load pc from soft vector */
171 for (i
= ARMul_ResetV
; i
<= ARMFIQV
; i
+= 4)
172 ARMul_WriteWord (state
, i
, instr
); /* write hardware vectors */
174 SWI_vector_installed
= 0;
176 for (i
= ARMul_ResetV
; i
<= ARMFIQV
+ 4; i
+= 4)
178 ARMul_WriteWord (state
, ADDRSOFTVECTORS
+ i
, SOFTVECTORCODE
+ i
* 4);
179 ARMul_WriteWord (state
, ADDRSOFHANDLERS
+ 2 * i
+ 4L,
180 SOFTVECTORCODE
+ sizeof (softvectorcode
) - 4L);
183 for (i
= 0; i
< sizeof (softvectorcode
); i
+= 4)
184 ARMul_WriteWord (state
, SOFTVECTORCODE
+ i
, softvectorcode
[i
/ 4]);
186 for (i
= 0; i
< FOPEN_MAX
; i
++)
187 OSptr
->FileTable
[i
] = NULL
;
189 for (i
= 0; i
< UNIQUETEMPS
; i
++)
190 OSptr
->tempnames
[i
] = NULL
;
192 ARMul_ConsolePrint (state
, ", Demon 1.01");
197 for (i
= 0; i
< fpesize
; i
+= 4) /* copy the code */
198 ARMul_WriteWord (state
, FPESTART
+ i
, fpecode
[i
>> 2]);
200 for (i
= FPESTART
+ fpesize
;; i
-= 4)
201 { /* reverse the error strings */
202 if ((j
= ARMul_ReadWord (state
, i
)) == 0xffffffff)
204 if (state
->bigendSig
&& j
< 0x80000000)
205 { /* it's part of the string so swap it */
206 j
= ((j
>> 0x18) & 0x000000ff) |
207 ((j
>> 0x08) & 0x0000ff00) |
208 ((j
<< 0x08) & 0x00ff0000) | ((j
<< 0x18) & 0xff000000);
209 ARMul_WriteWord (state
, i
, j
);
213 ARMul_WriteWord (state
, FPEOLDVECT
, ARMul_ReadWord (state
, 4)); /* copy old illegal instr vector */
214 ARMul_WriteWord (state
, 4, FPENEWVECT (ARMul_ReadWord (state
, i
- 4))); /* install new vector */
215 ARMul_ConsolePrint (state
, ", FPE");
218 #endif /* VALIDATE */
225 ARMul_OSExit (ARMul_State
* state
)
227 free ((char *) state
->OSptr
);
231 /* Return the last Operating System Error. */
233 ARMword
ARMul_OSLastErrorP (ARMul_State
* state
)
235 return ((struct OSblock
*) state
->OSptr
)->ErrorP
;
238 static int translate_open_mode
[] =
241 O_RDONLY
+ O_BINARY
, /* "rb" */
243 O_RDWR
+ O_BINARY
, /* "r+b" */
244 O_WRONLY
+ O_CREAT
+ O_TRUNC
, /* "w" */
245 O_WRONLY
+ O_BINARY
+ O_CREAT
+ O_TRUNC
, /* "wb" */
246 O_RDWR
+ O_CREAT
+ O_TRUNC
, /* "w+" */
247 O_RDWR
+ O_BINARY
+ O_CREAT
+ O_TRUNC
, /* "w+b" */
248 O_WRONLY
+ O_APPEND
+ O_CREAT
, /* "a" */
249 O_WRONLY
+ O_BINARY
+ O_APPEND
+ O_CREAT
, /* "ab" */
250 O_RDWR
+ O_APPEND
+ O_CREAT
, /* "a+" */
251 O_RDWR
+ O_BINARY
+ O_APPEND
+ O_CREAT
/* "a+b" */
255 SWIWrite0 (ARMul_State
* state
, ARMword addr
)
258 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
260 while ((temp
= ARMul_SafeReadByte (state
, addr
++)) != 0)
261 (void) fputc ((char) temp
, stdout
);
263 OSptr
->ErrorNo
= errno
;
267 WriteCommandLineTo (ARMul_State
* state
, ARMword addr
)
270 char *cptr
= state
->CommandLine
;
276 temp
= (ARMword
) * cptr
++;
277 ARMul_SafeWriteByte (state
, addr
++, temp
);
283 SWIopen (ARMul_State
* state
, ARMword name
, ARMword SWIflags
)
285 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
290 for (i
= 0; (dummy
[i
] = ARMul_SafeReadByte (state
, name
+ i
)); i
++)
293 /* Now we need to decode the Demon open mode. */
294 flags
= translate_open_mode
[SWIflags
];
296 /* Filename ":tt" is special: it denotes stdin/out. */
297 if (strcmp (dummy
, ":tt") == 0)
299 if (flags
== O_RDONLY
) /* opening tty "r" */
300 state
->Reg
[0] = 0; /* stdin */
302 state
->Reg
[0] = 1; /* stdout */
306 state
->Reg
[0] = (int) open (dummy
, flags
, 0666);
307 OSptr
->ErrorNo
= errno
;
312 SWIread (ARMul_State
* state
, ARMword f
, ARMword ptr
, ARMword len
)
314 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
317 char *local
= malloc (len
);
321 fprintf (stderr
, "sim: Unable to read 0x%ulx bytes - out of memory\n",
326 res
= read (f
, local
, len
);
328 for (i
= 0; i
< res
; i
++)
329 ARMul_SafeWriteByte (state
, ptr
+ i
, local
[i
]);
332 state
->Reg
[0] = res
== -1 ? -1 : len
- res
;
333 OSptr
->ErrorNo
= errno
;
337 SWIwrite (ARMul_State
* state
, ARMword f
, ARMword ptr
, ARMword len
)
339 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
342 char *local
= malloc (len
);
346 fprintf (stderr
, "sim: Unable to write 0x%lx bytes - out of memory\n",
351 for (i
= 0; i
< len
; i
++)
352 local
[i
] = ARMul_SafeReadByte (state
, ptr
+ i
);
354 res
= write (f
, local
, len
);
355 state
->Reg
[0] = res
== -1 ? -1 : len
- res
;
358 OSptr
->ErrorNo
= errno
;
362 SWIflen (ARMul_State
* state
, ARMword fh
)
364 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
367 if (fh
== 0 || fh
> FOPEN_MAX
)
369 OSptr
->ErrorNo
= EBADF
;
374 addr
= lseek (fh
, 0, SEEK_CUR
);
376 state
->Reg
[0] = lseek (fh
, 0L, SEEK_END
);
377 (void) lseek (fh
, addr
, SEEK_SET
);
379 OSptr
->ErrorNo
= errno
;
382 /* The emulator calls this routine when a SWI instruction is encuntered.
383 The parameter passed is the SWI number (lower 24 bits of the instruction). */
386 ARMul_OSHandleSWI (ARMul_State
* state
, ARMword number
)
390 ARMword saved_number
= 0;
391 struct OSblock
* OSptr
= (struct OSblock
*) state
->OSptr
;
393 /* Intel do not want DEMON SWI support. */
394 if (state
->is_XScale
)
410 saved_number
= number
;
419 SWIread (state
, state
->Reg
[0], state
->Reg
[1], state
->Reg
[2]);
423 SWIwrite (state
, state
->Reg
[0], state
->Reg
[1], state
->Reg
[2]);
427 SWIopen (state
, state
->Reg
[0], state
->Reg
[1]);
431 /* Return number of centi-seconds. */
433 #ifdef CLOCKS_PER_SEC
434 (CLOCKS_PER_SEC
>= 100)
435 ? (ARMword
) (clock () / (CLOCKS_PER_SEC
/ 100))
436 : (ARMword
) ((clock () * 100) / CLOCKS_PER_SEC
);
438 /* Presume unix... clock() returns microseconds. */
439 (ARMword
) (clock () / 10000);
441 OSptr
->ErrorNo
= errno
;
445 state
->Reg
[0] = (ARMword
) time (NULL
);
446 OSptr
->ErrorNo
= errno
;
450 state
->Reg
[0] = close (state
->Reg
[0]);
451 OSptr
->ErrorNo
= errno
;
455 SWIflen (state
, state
->Reg
[0]);
459 state
->Emulate
= FALSE
;
463 /* We must return non-zero for failure. */
464 state
->Reg
[0] = -1 >= lseek (state
->Reg
[0], state
->Reg
[1], SEEK_SET
);
465 OSptr
->ErrorNo
= errno
;
469 (void) fputc ((int) state
->Reg
[0], stdout
);
470 OSptr
->ErrorNo
= errno
;
474 SWIWrite0 (state
, state
->Reg
[0]);
478 state
->Reg
[0] = OSptr
->ErrorNo
;
482 state
->Reg
[0] = ADDRCMDLINE
;
484 state
->Reg
[1] = state
->MemSize
;
486 state
->Reg
[1] = ADDRUSERSTACK
;
488 WriteCommandLineTo (state
, state
->Reg
[0]);
492 state
->EndCondition
= RDIError_BreakpointReached
;
493 state
->Emulate
= FALSE
;
496 /* Handle Angel SWIs as well as Demon ones. */
499 /* R1 is almost always a parameter block. */
500 addr
= state
->Reg
[1];
501 /* R0 is a reason code. */
502 switch (state
->Reg
[0])
504 /* Unimplemented reason codes. */
505 case AngelSWI_Reason_ReadC
:
506 case AngelSWI_Reason_IsTTY
:
507 case AngelSWI_Reason_TmpNam
:
508 case AngelSWI_Reason_Remove
:
509 case AngelSWI_Reason_Rename
:
510 case AngelSWI_Reason_System
:
511 case AngelSWI_Reason_EnterSVC
:
513 state
->Emulate
= FALSE
;
516 case AngelSWI_Reason_Clock
:
517 /* Return number of centi-seconds. */
519 #ifdef CLOCKS_PER_SEC
520 (CLOCKS_PER_SEC
>= 100)
521 ? (ARMword
) (clock () / (CLOCKS_PER_SEC
/ 100))
522 : (ARMword
) ((clock () * 100) / CLOCKS_PER_SEC
);
524 /* Presume unix... clock() returns microseconds. */
525 (ARMword
) (clock () / 10000);
527 OSptr
->ErrorNo
= errno
;
530 case AngelSWI_Reason_Time
:
531 state
->Reg
[0] = (ARMword
) time (NULL
);
532 OSptr
->ErrorNo
= errno
;
535 case AngelSWI_Reason_WriteC
:
536 (void) fputc ((int) ARMul_SafeReadByte (state
, addr
), stdout
);
537 OSptr
->ErrorNo
= errno
;
540 case AngelSWI_Reason_Write0
:
541 SWIWrite0 (state
, addr
);
544 case AngelSWI_Reason_Close
:
545 state
->Reg
[0] = close (ARMul_ReadWord (state
, addr
));
546 OSptr
->ErrorNo
= errno
;
549 case AngelSWI_Reason_Seek
:
550 state
->Reg
[0] = -1 >= lseek (ARMul_ReadWord (state
, addr
),
551 ARMul_ReadWord (state
, addr
+ 4),
553 OSptr
->ErrorNo
= errno
;
556 case AngelSWI_Reason_FLen
:
557 SWIflen (state
, ARMul_ReadWord (state
, addr
));
560 case AngelSWI_Reason_GetCmdLine
:
561 WriteCommandLineTo (state
, ARMul_ReadWord (state
, addr
));
564 case AngelSWI_Reason_HeapInfo
:
565 /* R1 is a pointer to a pointer. */
566 addr
= ARMul_ReadWord (state
, addr
);
568 /* Pick up the right memory limit. */
570 temp
= state
->MemSize
;
572 temp
= ADDRUSERSTACK
;
574 ARMul_WriteWord (state
, addr
, 0); /* Heap base */
575 ARMul_WriteWord (state
, addr
+ 4, temp
); /* Heap limit */
576 ARMul_WriteWord (state
, addr
+ 8, temp
); /* Stack base */
577 ARMul_WriteWord (state
, addr
+ 12, temp
); /* Stack limit */
580 case AngelSWI_Reason_ReportException
:
581 if (state
->Reg
[1] == ADP_Stopped_ApplicationExit
)
585 state
->Emulate
= FALSE
;
588 case ADP_Stopped_ApplicationExit
:
590 state
->Emulate
= FALSE
;
593 case ADP_Stopped_RunTimeError
:
595 state
->Emulate
= FALSE
;
598 case AngelSWI_Reason_Errno
:
599 state
->Reg
[0] = OSptr
->ErrorNo
;
602 case AngelSWI_Reason_Open
:
604 ARMul_ReadWord (state
, addr
),
605 ARMul_ReadWord (state
, addr
+ 4));
608 case AngelSWI_Reason_Read
:
610 ARMul_ReadWord (state
, addr
),
611 ARMul_ReadWord (state
, addr
+ 4),
612 ARMul_ReadWord (state
, addr
+ 8));
615 case AngelSWI_Reason_Write
:
617 ARMul_ReadWord (state
, addr
),
618 ARMul_ReadWord (state
, addr
+ 4),
619 ARMul_ReadWord (state
, addr
+ 8));
626 /* These are used by the FPE code. */
630 /* If there is a SWI vector installed use it. */
631 if (state
->is_XScale
&& saved_number
!= -1)
632 number
= saved_number
;
634 if (SWI_vector_installed
&& number
!= SWI_Breakpoint
)
639 cpsr
= ARMul_GetCPSR (state
);
642 ARMul_SetSPSR (state
, SVC32MODE
, cpsr
);
645 cpsr
|= SVC32MODE
| 0x80;
646 ARMul_SetCPSR (state
, cpsr
);
648 state
->RegBank
[SVCBANK
][14] = state
->Reg
[14] = state
->Reg
[15] - i_size
;
649 state
->NextInstr
= RESUME
;
650 state
->Reg
[15] = state
->pc
= ARMSWIV
;
655 fprintf (stderr
, "unknown SWI encountered - %x - ignoring\n", number
);
666 /* The emulator calls this routine when an Exception occurs. The second
667 parameter is the address of the relevant exception vector. Returning
668 FALSE from this routine causes the trap to be taken, TRUE causes it to
669 be ignored (so set state->Emulate to FALSE!). */
672 ARMul_OSException (ARMul_State
* state ATTRIBUTE_UNUSED
,
673 ARMword vector ATTRIBUTE_UNUSED
,
674 ARMword pc ATTRIBUTE_UNUSED
)