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 */
143 /* Set to prevent aborts when emulating SWI routines. */
144 static int in_SWI_handler
= 0;
146 /* Time for the Operating System to initialise itself. */
149 ARMul_OSInit (ARMul_State
* state
)
154 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
156 if (state
->OSptr
== NULL
)
158 state
->OSptr
= (unsigned char *) malloc (sizeof (struct OSblock
));
159 if (state
->OSptr
== NULL
)
161 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 ARMul_SetReg (state
, SYSTEMMODE
, 13, ADDRSUPERSTACK
); /* and for system mode */
173 instr
= 0xe59ff000 | (ADDRSOFTVECTORS
- 8); /* load pc from soft vector */
175 for (i
= ARMul_ResetV
; i
<= ARMFIQV
; i
+= 4)
176 ARMul_WriteWord (state
, i
, instr
); /* write hardware vectors */
178 SWI_vector_installed
= 0;
180 for (i
= ARMul_ResetV
; i
<= ARMFIQV
+ 4; i
+= 4)
182 ARMul_WriteWord (state
, ADDRSOFTVECTORS
+ i
, SOFTVECTORCODE
+ i
* 4);
183 ARMul_WriteWord (state
, ADDRSOFHANDLERS
+ 2 * i
+ 4L,
184 SOFTVECTORCODE
+ sizeof (softvectorcode
) - 4L);
187 for (i
= 0; i
< sizeof (softvectorcode
); i
+= 4)
188 ARMul_WriteWord (state
, SOFTVECTORCODE
+ i
, softvectorcode
[i
/ 4]);
190 for (i
= 0; i
< FOPEN_MAX
; i
++)
191 OSptr
->FileTable
[i
] = NULL
;
193 for (i
= 0; i
< UNIQUETEMPS
; i
++)
194 OSptr
->tempnames
[i
] = NULL
;
196 ARMul_ConsolePrint (state
, ", Demon 1.01");
201 for (i
= 0; i
< fpesize
; i
+= 4) /* copy the code */
202 ARMul_WriteWord (state
, FPESTART
+ i
, fpecode
[i
>> 2]);
204 for (i
= FPESTART
+ fpesize
;; i
-= 4)
205 { /* reverse the error strings */
206 if ((j
= ARMul_ReadWord (state
, i
)) == 0xffffffff)
208 if (state
->bigendSig
&& j
< 0x80000000)
209 { /* it's part of the string so swap it */
210 j
= ((j
>> 0x18) & 0x000000ff) |
211 ((j
>> 0x08) & 0x0000ff00) |
212 ((j
<< 0x08) & 0x00ff0000) | ((j
<< 0x18) & 0xff000000);
213 ARMul_WriteWord (state
, i
, j
);
217 ARMul_WriteWord (state
, FPEOLDVECT
, ARMul_ReadWord (state
, 4)); /* copy old illegal instr vector */
218 ARMul_WriteWord (state
, 4, FPENEWVECT (ARMul_ReadWord (state
, i
- 4))); /* install new vector */
219 ARMul_ConsolePrint (state
, ", FPE");
222 #endif /* VALIDATE */
229 ARMul_OSExit (ARMul_State
* state
)
231 free ((char *) state
->OSptr
);
235 /* Return the last Operating System Error. */
237 ARMword
ARMul_OSLastErrorP (ARMul_State
* state
)
239 return ((struct OSblock
*) state
->OSptr
)->ErrorP
;
242 static int translate_open_mode
[] =
245 O_RDONLY
+ O_BINARY
, /* "rb" */
247 O_RDWR
+ O_BINARY
, /* "r+b" */
248 O_WRONLY
+ O_CREAT
+ O_TRUNC
, /* "w" */
249 O_WRONLY
+ O_BINARY
+ O_CREAT
+ O_TRUNC
, /* "wb" */
250 O_RDWR
+ O_CREAT
+ O_TRUNC
, /* "w+" */
251 O_RDWR
+ O_BINARY
+ O_CREAT
+ O_TRUNC
, /* "w+b" */
252 O_WRONLY
+ O_APPEND
+ O_CREAT
, /* "a" */
253 O_WRONLY
+ O_BINARY
+ O_APPEND
+ O_CREAT
, /* "ab" */
254 O_RDWR
+ O_APPEND
+ O_CREAT
, /* "a+" */
255 O_RDWR
+ O_BINARY
+ O_APPEND
+ O_CREAT
/* "a+b" */
259 SWIWrite0 (ARMul_State
* state
, ARMword addr
)
262 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
264 while ((temp
= ARMul_ReadByte (state
, addr
++)) != 0)
265 (void) fputc ((char) temp
, stdout
);
267 OSptr
->ErrorNo
= errno
;
271 WriteCommandLineTo (ARMul_State
* state
, ARMword addr
)
274 char *cptr
= state
->CommandLine
;
280 temp
= (ARMword
) * cptr
++;
281 ARMul_WriteByte (state
, addr
++, temp
);
287 SWIopen (ARMul_State
* state
, ARMword name
, ARMword SWIflags
)
289 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
294 for (i
= 0; (dummy
[i
] = ARMul_ReadByte (state
, name
+ i
)); i
++)
297 /* Now we need to decode the Demon open mode. */
298 flags
= translate_open_mode
[SWIflags
];
300 /* Filename ":tt" is special: it denotes stdin/out. */
301 if (strcmp (dummy
, ":tt") == 0)
303 if (flags
== O_RDONLY
) /* opening tty "r" */
304 state
->Reg
[0] = 0; /* stdin */
306 state
->Reg
[0] = 1; /* stdout */
310 state
->Reg
[0] = (int) open (dummy
, flags
, 0666);
311 OSptr
->ErrorNo
= errno
;
316 SWIread (ARMul_State
* state
, ARMword f
, ARMword ptr
, ARMword len
)
318 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
321 char *local
= malloc (len
);
325 fprintf (stderr
, "sim: Unable to read 0x%ulx bytes - out of memory\n",
330 res
= read (f
, local
, len
);
332 for (i
= 0; i
< res
; i
++)
333 ARMul_WriteByte (state
, ptr
+ i
, local
[i
]);
336 state
->Reg
[0] = res
== -1 ? -1 : len
- res
;
337 OSptr
->ErrorNo
= errno
;
341 SWIwrite (ARMul_State
* state
, ARMword f
, ARMword ptr
, ARMword len
)
343 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
346 char *local
= malloc (len
);
350 fprintf (stderr
, "sim: Unable to write 0x%lx bytes - out of memory\n",
355 for (i
= 0; i
< len
; i
++)
356 local
[i
] = ARMul_ReadByte (state
, ptr
+ i
);
358 res
= write (f
, local
, len
);
359 state
->Reg
[0] = res
== -1 ? -1 : len
- res
;
362 OSptr
->ErrorNo
= errno
;
366 SWIflen (ARMul_State
* state
, ARMword fh
)
368 struct OSblock
*OSptr
= (struct OSblock
*) state
->OSptr
;
371 if (fh
== 0 || fh
> FOPEN_MAX
)
373 OSptr
->ErrorNo
= EBADF
;
378 addr
= lseek (fh
, 0, SEEK_CUR
);
380 state
->Reg
[0] = lseek (fh
, 0L, SEEK_END
);
381 (void) lseek (fh
, addr
, SEEK_SET
);
383 OSptr
->ErrorNo
= errno
;
386 /* The emulator calls this routine when a SWI instruction is encuntered.
387 The parameter passed is the SWI number (lower 24 bits of the instruction). */
390 ARMul_OSHandleSWI (ARMul_State
* state
, ARMword number
)
394 ARMword saved_number
= 0;
395 struct OSblock
* OSptr
= (struct OSblock
*) state
->OSptr
;
399 /* Intel do not want DEMON SWI support. */
400 if (state
->is_XScale
)
416 saved_number
= number
;
425 SWIread (state
, state
->Reg
[0], state
->Reg
[1], state
->Reg
[2]);
429 SWIwrite (state
, state
->Reg
[0], state
->Reg
[1], state
->Reg
[2]);
433 SWIopen (state
, state
->Reg
[0], state
->Reg
[1]);
437 /* Return number of centi-seconds. */
439 #ifdef CLOCKS_PER_SEC
440 (CLOCKS_PER_SEC
>= 100)
441 ? (ARMword
) (clock () / (CLOCKS_PER_SEC
/ 100))
442 : (ARMword
) ((clock () * 100) / CLOCKS_PER_SEC
);
444 /* Presume unix... clock() returns microseconds. */
445 (ARMword
) (clock () / 10000);
447 OSptr
->ErrorNo
= errno
;
451 state
->Reg
[0] = (ARMword
) time (NULL
);
452 OSptr
->ErrorNo
= errno
;
456 state
->Reg
[0] = close (state
->Reg
[0]);
457 OSptr
->ErrorNo
= errno
;
461 SWIflen (state
, state
->Reg
[0]);
465 state
->Emulate
= FALSE
;
469 /* We must return non-zero for failure. */
470 state
->Reg
[0] = -1 >= lseek (state
->Reg
[0], state
->Reg
[1], SEEK_SET
);
471 OSptr
->ErrorNo
= errno
;
475 (void) fputc ((int) state
->Reg
[0], stdout
);
476 OSptr
->ErrorNo
= errno
;
480 SWIWrite0 (state
, state
->Reg
[0]);
484 state
->Reg
[0] = OSptr
->ErrorNo
;
488 state
->Reg
[0] = ADDRCMDLINE
;
490 state
->Reg
[1] = state
->MemSize
;
492 state
->Reg
[1] = ADDRUSERSTACK
;
494 WriteCommandLineTo (state
, state
->Reg
[0]);
498 state
->EndCondition
= RDIError_BreakpointReached
;
499 state
->Emulate
= FALSE
;
502 /* Handle Angel SWIs as well as Demon ones. */
505 /* R1 is almost always a parameter block. */
506 addr
= state
->Reg
[1];
507 /* R0 is a reason code. */
508 switch (state
->Reg
[0])
510 /* Unimplemented reason codes. */
511 case AngelSWI_Reason_ReadC
:
512 case AngelSWI_Reason_IsTTY
:
513 case AngelSWI_Reason_TmpNam
:
514 case AngelSWI_Reason_Remove
:
515 case AngelSWI_Reason_Rename
:
516 case AngelSWI_Reason_System
:
517 case AngelSWI_Reason_EnterSVC
:
519 state
->Emulate
= FALSE
;
523 case AngelSWI_Reason_Clock
:
524 /* Return number of centi-seconds. */
526 #ifdef CLOCKS_PER_SEC
527 (CLOCKS_PER_SEC
>= 100)
528 ? (ARMword
) (clock () / (CLOCKS_PER_SEC
/ 100))
529 : (ARMword
) ((clock () * 100) / CLOCKS_PER_SEC
);
531 /* Presume unix... clock() returns microseconds. */
532 (ARMword
) (clock () / 10000);
534 OSptr
->ErrorNo
= errno
;
537 case AngelSWI_Reason_Time
:
538 state
->Reg
[0] = (ARMword
) time (NULL
);
539 OSptr
->ErrorNo
= errno
;
542 case AngelSWI_Reason_WriteC
:
543 (void) fputc ((int) ARMul_ReadByte (state
, addr
), stdout
);
544 OSptr
->ErrorNo
= errno
;
546 case AngelSWI_Reason_Write0
:
547 SWIWrite0 (state
, addr
);
550 case AngelSWI_Reason_Close
:
551 state
->Reg
[0] = close (ARMul_ReadWord (state
, addr
));
552 OSptr
->ErrorNo
= errno
;
555 case AngelSWI_Reason_Seek
:
556 state
->Reg
[0] = -1 >= lseek (ARMul_ReadWord (state
, addr
),
557 ARMul_ReadWord (state
, addr
+ 4),
559 OSptr
->ErrorNo
= errno
;
562 case AngelSWI_Reason_FLen
:
563 SWIflen (state
, ARMul_ReadWord (state
, addr
));
566 case AngelSWI_Reason_GetCmdLine
:
567 WriteCommandLineTo (state
, ARMul_ReadWord (state
, addr
));
570 case AngelSWI_Reason_HeapInfo
:
571 /* R1 is a pointer to a pointer. */
572 addr
= ARMul_ReadWord (state
, addr
);
574 /* Pick up the right memory limit. */
576 temp
= state
->MemSize
;
578 temp
= ADDRUSERSTACK
;
580 ARMul_WriteWord (state
, addr
, 0); /* Heap base */
581 ARMul_WriteWord (state
, addr
+ 4, temp
); /* Heap limit */
582 ARMul_WriteWord (state
, addr
+ 8, temp
); /* Stack base */
583 ARMul_WriteWord (state
, addr
+ 12, temp
); /* Stack limit */
586 case AngelSWI_Reason_ReportException
:
587 if (state
->Reg
[1] == ADP_Stopped_ApplicationExit
)
591 state
->Emulate
= FALSE
;
594 case ADP_Stopped_ApplicationExit
:
596 state
->Emulate
= FALSE
;
599 case ADP_Stopped_RunTimeError
:
601 state
->Emulate
= FALSE
;
604 case AngelSWI_Reason_Errno
:
605 state
->Reg
[0] = OSptr
->ErrorNo
;
608 case AngelSWI_Reason_Open
:
610 ARMul_ReadWord (state
, addr
),
611 ARMul_ReadWord (state
, addr
+ 4));
614 case AngelSWI_Reason_Read
:
616 ARMul_ReadWord (state
, addr
),
617 ARMul_ReadWord (state
, addr
+ 4),
618 ARMul_ReadWord (state
, addr
+ 8));
621 case AngelSWI_Reason_Write
:
623 ARMul_ReadWord (state
, addr
),
624 ARMul_ReadWord (state
, addr
+ 4),
625 ARMul_ReadWord (state
, addr
+ 8));
632 /* These are used by the FPE code. */
638 /* If there is a SWI vector installed use it. */
639 if (state
->is_XScale
&& saved_number
!= -1)
640 number
= saved_number
;
642 if (SWI_vector_installed
&& number
!= SWI_Breakpoint
)
647 cpsr
= ARMul_GetCPSR (state
);
650 ARMul_SetSPSR (state
, SVC32MODE
, cpsr
);
653 cpsr
|= SVC32MODE
| 0x80;
654 ARMul_SetCPSR (state
, cpsr
);
656 state
->RegBank
[SVCBANK
][14] = state
->Reg
[14] = state
->Reg
[15] - i_size
;
657 state
->NextInstr
= RESUME
;
658 state
->Reg
[15] = state
->pc
= ARMSWIV
;
663 fprintf (stderr
, "unknown SWI encountered - %x - ignoring\n", number
);
675 /* The emulator calls this routine when an Exception occurs. The second
676 parameter is the address of the relevant exception vector. Returning
677 FALSE from this routine causes the trap to be taken, TRUE causes it to
678 be ignored (so set state->Emulate to FALSE!). */
681 ARMul_OSException (ARMul_State
* state ATTRIBUTE_UNUSED
,
682 ARMword vector ATTRIBUTE_UNUSED
,
683 ARMword pc ATTRIBUTE_UNUSED
)
685 /* If we are inside a SWI handler routine, then ignore any exceptions.
686 They could be caused by data exceptions for misaligned reads, for
687 example, but for the purposes of emulating a SWI, we do not care. */
689 return in_SWI_handler
;