Commit | Line | Data |
---|---|---|
c906108c SS |
1 | /* armos.c -- ARMulator OS interface: ARM6 Instruction Emulator. |
2 | Copyright (C) 1994 Advanced RISC Machines Ltd. | |
3 | ||
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. | |
8 | ||
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. | |
13 | ||
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. */ | |
17 | ||
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. */ | |
24 | ||
25 | #include "config.h" | |
26 | ||
27 | #include <time.h> | |
28 | #include <errno.h> | |
29 | #include <string.h> | |
30 | #include <fcntl.h> | |
31 | ||
32 | #ifndef O_RDONLY | |
33 | #define O_RDONLY 0 | |
34 | #endif | |
35 | #ifndef O_WRONLY | |
36 | #define O_WRONLY 1 | |
37 | #endif | |
38 | #ifndef O_RDWR | |
39 | #define O_RDWR 2 | |
40 | #endif | |
41 | #ifndef O_BINARY | |
42 | #define O_BINARY 0 | |
43 | #endif | |
44 | ||
45 | #ifdef __STDC__ | |
46 | #define unlink(s) remove(s) | |
47 | #endif | |
48 | ||
49 | #ifdef HAVE_UNISTD_H | |
50 | #include <unistd.h> /* For SEEK_SET etc */ | |
51 | #endif | |
52 | ||
53 | #ifdef __riscos | |
54 | extern int _fisatty(FILE *); | |
55 | #define isatty_(f) _fisatty(f) | |
56 | #else | |
57 | #ifdef __ZTC__ | |
58 | #include <io.h> | |
59 | #define isatty_(f) isatty((f)->_file) | |
60 | #else | |
61 | #ifdef macintosh | |
62 | #include <ioctl.h> | |
63 | #define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL)) | |
64 | #else | |
65 | #define isatty_(f) isatty (fileno (f)) | |
66 | #endif | |
67 | #endif | |
68 | #endif | |
69 | ||
70 | #include "armdefs.h" | |
71 | #include "armos.h" | |
72 | #ifndef NOOS | |
73 | #ifndef VALIDATE | |
74 | /* #ifndef ASIM */ | |
75 | #include "armfpe.h" | |
76 | /* #endif */ | |
77 | #endif | |
78 | #endif | |
79 | ||
80 | /* For RDIError_BreakpointReached. */ | |
81 | #include "dbg_rdi.h" | |
82 | ||
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) ; | |
89 | ||
90 | #define BUFFERSIZE 4096 | |
91 | #ifndef FOPEN_MAX | |
92 | #define FOPEN_MAX 64 | |
93 | #endif | |
94 | #define UNIQUETEMPS 256 | |
95 | ||
96 | #ifndef NOOS | |
97 | static void UnwindDataAbort(ARMul_State *state, ARMword addr); | |
98 | static void getstring(ARMul_State *state, ARMword from, char *to) ; | |
99 | #endif | |
100 | ||
101 | /***************************************************************************\ | |
102 | * OS private Information * | |
103 | \***************************************************************************/ | |
104 | ||
105 | struct OSblock { | |
106 | ARMword Time0 ; | |
107 | ARMword ErrorP ; | |
108 | ARMword ErrorNo ; | |
109 | FILE *FileTable[FOPEN_MAX] ; | |
110 | char FileFlags[FOPEN_MAX] ; | |
111 | char *tempnames[UNIQUETEMPS] ; | |
112 | } ; | |
113 | ||
114 | #define NOOP 0 | |
115 | #define BINARY 1 | |
116 | #define READOP 2 | |
117 | #define WRITEOP 4 | |
118 | ||
119 | #ifdef macintosh | |
120 | #define FIXCRLF(t,c) ((t & BINARY) ? \ | |
121 | c : \ | |
122 | ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \ | |
123 | ) | |
124 | #else | |
125 | #define FIXCRLF(t,c) c | |
126 | #endif | |
127 | ||
128 | static ARMword softvectorcode[] = | |
129 | { /* basic: swi tidyexception + event; mov pc, lr; | |
130 | ldmia r11,{r11,pc}; swi generateexception + event | |
131 | */ | |
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 */ | |
142 | }; | |
143 | ||
144 | /***************************************************************************\ | |
145 | * Time for the Operating System to initialise itself. * | |
146 | \***************************************************************************/ | |
147 | ||
148 | unsigned | |
149 | ARMul_OSInit (ARMul_State *state) | |
150 | { | |
151 | #ifndef NOOS | |
152 | #ifndef VALIDATE | |
153 | ARMword instr, i , j ; | |
154 | struct OSblock* OSptr = (struct OSblock*)state->OSptr; | |
155 | ||
156 | if (state->OSptr == NULL) { | |
157 | state->OSptr = (unsigned char *)malloc(sizeof(struct OSblock)); | |
158 | if (state->OSptr == NULL) { | |
159 | perror("OS Memory"); | |
160 | exit(15); | |
161 | } | |
162 | } | |
163 | OSptr = (struct OSblock*)state->OSptr; | |
164 | OSptr->ErrorP = 0; | |
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); | |
175 | } | |
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"); | |
183 | ||
184 | /* #ifndef ASIM */ | |
185 | ||
186 | /* install fpe */ | |
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) | |
191 | break ; | |
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) ; | |
198 | } | |
199 | } | |
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") ; | |
203 | ||
204 | /* #endif /* ASIM */ | |
205 | #endif /* VALIDATE */ | |
206 | #endif /* NOOS */ | |
207 | ||
208 | return(TRUE) ; | |
209 | } | |
210 | ||
211 | void | |
212 | ARMul_OSExit (ARMul_State *state) | |
213 | { | |
214 | free((char *)state->OSptr); | |
215 | } | |
216 | ||
217 | ||
218 | /***************************************************************************\ | |
219 | * Return the last Operating System Error. * | |
220 | \***************************************************************************/ | |
221 | ||
222 | ARMword | |
223 | ARMul_OSLastErrorP (ARMul_State *state) | |
224 | { | |
225 | return ((struct OSblock *)state->OSptr)->ErrorP; | |
226 | } | |
227 | ||
228 | #if 1 /* CYGNUS LOCAL */ | |
229 | /* This is the cygnus way of doing it, which makes it simple to do our tests */ | |
230 | ||
231 | static int translate_open_mode[] = | |
232 | { | |
233 | O_RDONLY, /* "r" */ | |
234 | O_RDONLY+O_BINARY, /* "rb" */ | |
235 | O_RDWR, /* "r+" */ | |
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" */ | |
245 | }; | |
246 | ||
247 | static void | |
248 | SWIWrite0 (ARMul_State *state, ARMword addr) | |
249 | { | |
250 | ARMword temp; | |
251 | struct OSblock* OSptr = (struct OSblock*) state->OSptr; | |
252 | ||
253 | while ((temp = ARMul_ReadByte (state, addr++)) != 0) | |
2acceee2 | 254 | (void) fputc ((char) temp, stdout); |
c906108c SS |
255 | |
256 | OSptr->ErrorNo = errno; | |
257 | } | |
258 | ||
259 | static void | |
260 | WriteCommandLineTo (ARMul_State *state, ARMword addr) | |
261 | { | |
262 | ARMword temp; | |
263 | char *cptr = state->CommandLine; | |
264 | if (cptr == NULL) | |
265 | cptr = "\0"; | |
266 | do { | |
267 | temp = (ARMword) *cptr++; | |
268 | ARMul_WriteByte (state, addr++, temp); | |
269 | } while (temp != 0); | |
270 | } | |
271 | ||
272 | static void | |
273 | SWIopen (ARMul_State *state, ARMword name, ARMword SWIflags) | |
274 | { | |
275 | struct OSblock* OSptr = (struct OSblock*)state->OSptr; | |
276 | char dummy[2000]; | |
277 | int flags; | |
278 | int i; | |
279 | ||
280 | for (i = 0; | |
281 | dummy[i] = ARMul_ReadByte (state, name + i); | |
282 | i++) | |
283 | ; | |
284 | ||
285 | /* Now we need to decode the Demon open mode */ | |
286 | flags = translate_open_mode[SWIflags]; | |
287 | ||
288 | /* Filename ":tt" is special: it denotes stdin/out */ | |
289 | if (strcmp (dummy, ":tt") == 0) | |
290 | { | |
291 | if (flags == O_RDONLY) /* opening tty "r" */ | |
292 | state->Reg[0] = 0; /* stdin */ | |
293 | else | |
294 | state->Reg[0] = 1; /* stdout */ | |
295 | } | |
296 | else | |
297 | { | |
2df3850c | 298 | state->Reg[0] = (int) open (dummy, flags, 0666); |
c906108c SS |
299 | OSptr->ErrorNo = errno; |
300 | } | |
301 | } | |
302 | ||
303 | static void | |
304 | SWIread (ARMul_State *state, ARMword f, ARMword ptr, ARMword len) | |
305 | { | |
306 | struct OSblock* OSptr = (struct OSblock*) state->OSptr; | |
307 | int res; | |
308 | int i; | |
309 | char *local = malloc (len); | |
310 | ||
c2d11a7d JM |
311 | if (local == NULL) |
312 | { | |
313 | fprintf (stderr, "sim: Unable to read 0x%x bytes - out of memory\n", len); | |
314 | return; | |
315 | } | |
316 | ||
c906108c SS |
317 | res = read (f, local, len); |
318 | if (res > 0) | |
319 | for (i = 0; i < res; i++) | |
320 | ARMul_WriteByte (state, ptr + i, local[i]); | |
321 | free (local); | |
322 | state->Reg[0] = res == -1 ? -1 : len - res; | |
323 | OSptr->ErrorNo = errno; | |
324 | } | |
325 | ||
326 | static void | |
327 | SWIwrite (ARMul_State *state, ARMword f, ARMword ptr, ARMword len) | |
328 | { | |
329 | struct OSblock* OSptr = (struct OSblock*) state->OSptr; | |
330 | int res; | |
331 | int i; | |
332 | char *local = malloc (len); | |
333 | ||
c2d11a7d | 334 | if (local == NULL) |
c906108c | 335 | { |
c2d11a7d JM |
336 | fprintf (stderr, "sim: Unable to write 0x%x bytes - out of memory\n", len); |
337 | return; | |
c906108c | 338 | } |
c2d11a7d JM |
339 | |
340 | for (i = 0; i < len; i++) | |
341 | local[i] = ARMul_ReadByte (state, ptr + i); | |
342 | ||
c906108c SS |
343 | res = write (f, local, len); |
344 | state->Reg[0] = res == -1 ? -1 : len - res; | |
345 | free (local); | |
346 | OSptr->ErrorNo = errno; | |
347 | } | |
348 | ||
349 | static void | |
350 | SWIflen (ARMul_State *state, ARMword fh) | |
351 | { | |
352 | struct OSblock* OSptr = (struct OSblock*) state->OSptr; | |
353 | ARMword addr; | |
354 | ||
355 | if (fh == 0 || fh > FOPEN_MAX) | |
356 | { | |
357 | OSptr->ErrorNo = EBADF; | |
358 | state->Reg[0] = -1L; | |
359 | return; | |
360 | } | |
361 | ||
362 | addr = lseek (fh, 0, SEEK_CUR); | |
363 | if (addr < 0) | |
364 | state->Reg[0] = -1L; | |
365 | else | |
366 | { | |
367 | state->Reg[0] = lseek (fh, 0L, SEEK_END); | |
368 | (void) lseek (fh, addr, SEEK_SET); | |
369 | } | |
370 | ||
371 | OSptr->ErrorNo = errno; | |
372 | } | |
373 | ||
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 | \***************************************************************************/ | |
378 | ||
379 | unsigned | |
380 | ARMul_OSHandleSWI (ARMul_State *state, ARMword number) | |
381 | { | |
382 | ARMword addr, temp, fildes; | |
383 | char buffer[BUFFERSIZE], *cptr; | |
384 | FILE *fptr; | |
385 | struct OSblock* OSptr = (struct OSblock*)state->OSptr; | |
386 | ||
387 | switch (number) | |
388 | { | |
389 | case SWI_Read: | |
390 | SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]); | |
391 | return TRUE; | |
392 | ||
393 | case SWI_Write: | |
394 | SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]); | |
395 | return TRUE; | |
396 | ||
397 | case SWI_Open: | |
398 | SWIopen (state, state->Reg[0],state->Reg[1]); | |
399 | return TRUE; | |
400 | ||
401 | case SWI_Clock : | |
402 | /* return number of centi-seconds... */ | |
403 | state->Reg[0] = | |
404 | #ifdef CLOCKS_PER_SEC | |
405 | (CLOCKS_PER_SEC >= 100) | |
406 | ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100)) | |
407 | : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ; | |
408 | #else | |
409 | /* presume unix... clock() returns microseconds */ | |
410 | (ARMword) (clock() / 10000) ; | |
411 | #endif | |
412 | OSptr->ErrorNo = errno ; | |
413 | return(TRUE) ; | |
414 | ||
415 | case SWI_Time : | |
416 | state->Reg[0] = (ARMword)time(NULL) ; | |
417 | OSptr->ErrorNo = errno ; | |
418 | return(TRUE) ; | |
419 | ||
420 | case SWI_Close: | |
421 | state->Reg[0] = close (state->Reg[0]); | |
422 | OSptr->ErrorNo = errno; | |
423 | return TRUE; | |
424 | ||
425 | case SWI_Flen : | |
426 | SWIflen (state, state->Reg[0]); | |
427 | return(TRUE) ; | |
428 | ||
429 | case SWI_Exit: | |
430 | state->Emulate = FALSE ; | |
431 | return TRUE; | |
432 | ||
433 | case SWI_Seek: | |
434 | { | |
435 | /* We must return non-zero for failure */ | |
436 | state->Reg[0] = -1 >= lseek (state->Reg[0], | |
437 | state->Reg[1], | |
438 | SEEK_SET); | |
439 | OSptr->ErrorNo = errno; | |
440 | return TRUE; | |
441 | } | |
442 | ||
443 | case SWI_WriteC : | |
2acceee2 | 444 | (void)fputc((int)state->Reg[0],stdout) ; |
c906108c SS |
445 | OSptr->ErrorNo = errno ; |
446 | return(TRUE) ; | |
447 | ||
448 | case SWI_Write0 : | |
449 | SWIWrite0 (state, state->Reg[0]); | |
450 | return(TRUE) ; | |
451 | ||
452 | case SWI_GetErrno : | |
453 | state->Reg[0] = OSptr->ErrorNo ; | |
454 | return(TRUE) ; | |
455 | ||
456 | case SWI_Breakpoint : | |
457 | state->EndCondition = RDIError_BreakpointReached ; | |
458 | state->Emulate = FALSE ; | |
459 | return(TRUE) ; | |
460 | ||
461 | case SWI_GetEnv : | |
462 | state->Reg[0] = ADDRCMDLINE ; | |
463 | if (state->MemSize) | |
464 | state->Reg[1] = state->MemSize ; | |
465 | else | |
466 | state->Reg[1] = ADDRUSERSTACK ; | |
467 | ||
468 | WriteCommandLineTo (state, state->Reg[0]); | |
469 | return(TRUE) ; | |
470 | ||
471 | /* Handle Angel SWIs as well as Demon ones */ | |
472 | case AngelSWI_ARM: | |
473 | case AngelSWI_Thumb: | |
474 | /* R1 is almost always a parameter block */ | |
475 | addr = state->Reg[1]; | |
476 | /* R0 is a reason code */ | |
477 | switch (state->Reg[0]) | |
478 | { | |
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: | |
487 | default: | |
488 | state->Emulate = FALSE; | |
489 | return(FALSE); | |
490 | ||
491 | case AngelSWI_Reason_Clock: | |
492 | /* return number of centi-seconds... */ | |
493 | state->Reg[0] = | |
494 | #ifdef CLOCKS_PER_SEC | |
495 | (CLOCKS_PER_SEC >= 100) | |
496 | ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100)) | |
497 | : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ; | |
498 | #else | |
499 | /* presume unix... clock() returns microseconds */ | |
500 | (ARMword) (clock() / 10000) ; | |
501 | #endif | |
502 | OSptr->ErrorNo = errno; | |
503 | return (TRUE); | |
504 | ||
505 | case AngelSWI_Reason_Time: | |
506 | state->Reg[0] = (ARMword) time (NULL); | |
507 | OSptr->ErrorNo = errno; | |
508 | return (TRUE); | |
509 | ||
510 | case AngelSWI_Reason_WriteC: | |
2acceee2 | 511 | (void) fputc ((int) ARMul_ReadByte (state,addr), stdout); |
c906108c SS |
512 | OSptr->ErrorNo = errno; |
513 | return (TRUE); | |
514 | ||
515 | case AngelSWI_Reason_Write0: | |
516 | SWIWrite0 (state, addr); | |
517 | return (TRUE); | |
518 | ||
519 | case AngelSWI_Reason_Close: | |
520 | state->Reg[0] = close (ARMul_ReadWord (state, addr)); | |
521 | OSptr->ErrorNo = errno; | |
522 | return (TRUE); | |
523 | ||
524 | case AngelSWI_Reason_Seek: | |
525 | state->Reg[0] = -1 >= lseek (ARMul_ReadWord(state,addr), | |
526 | ARMul_ReadWord(state,addr+4), | |
527 | SEEK_SET); | |
528 | OSptr->ErrorNo = errno; | |
529 | return (TRUE); | |
530 | ||
531 | case AngelSWI_Reason_FLen: | |
532 | SWIflen (state, ARMul_ReadWord (state, addr)); | |
533 | return (TRUE); | |
534 | ||
535 | case AngelSWI_Reason_GetCmdLine: | |
536 | WriteCommandLineTo (state, ARMul_ReadWord (state, addr)); | |
537 | return (TRUE); | |
538 | ||
539 | case AngelSWI_Reason_HeapInfo: | |
540 | /* R1 is a pointer to a pointer */ | |
541 | addr = ARMul_ReadWord (state, addr); | |
542 | ||
543 | /* Pick up the right memory limit */ | |
544 | if (state->MemSize) | |
545 | temp = state->MemSize; | |
546 | else | |
547 | temp = ADDRUSERSTACK; | |
548 | ||
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 */ | |
553 | return (TRUE); | |
554 | ||
555 | case AngelSWI_Reason_ReportException: | |
556 | if (state->Reg[1] == ADP_Stopped_ApplicationExit) | |
557 | state->Reg[0] = 0; | |
558 | else | |
559 | state->Reg[0] = -1; | |
560 | state->Emulate = FALSE ; | |
561 | return (TRUE); | |
562 | ||
563 | case ADP_Stopped_ApplicationExit: | |
564 | state->Reg[0] = 0; | |
565 | state->Emulate = FALSE ; | |
566 | return (TRUE); | |
567 | ||
568 | case ADP_Stopped_RunTimeError: | |
569 | state->Reg[0] = -1; | |
570 | state->Emulate = FALSE ; | |
571 | return (TRUE); | |
572 | ||
573 | case AngelSWI_Reason_Errno: | |
574 | state->Reg[0] = OSptr->ErrorNo; | |
575 | return (TRUE); | |
576 | ||
577 | case AngelSWI_Reason_Open: | |
578 | SWIopen(state, | |
579 | ARMul_ReadWord(state, addr), | |
580 | ARMul_ReadWord(state, addr+4)); | |
581 | return TRUE; | |
582 | ||
583 | case AngelSWI_Reason_Read: | |
584 | SWIread(state, | |
585 | ARMul_ReadWord(state, addr), | |
586 | ARMul_ReadWord(state, addr+4), | |
587 | ARMul_ReadWord(state, addr+8)); | |
588 | return TRUE; | |
589 | ||
590 | case AngelSWI_Reason_Write: | |
591 | SWIwrite(state, | |
592 | ARMul_ReadWord(state, addr), | |
593 | ARMul_ReadWord(state, addr+4), | |
594 | ARMul_ReadWord(state, addr+8)); | |
595 | return TRUE; | |
596 | } | |
597 | ||
598 | default : | |
599 | state->Emulate = FALSE ; | |
600 | return(FALSE) ; | |
601 | } | |
602 | } | |
603 | ||
604 | #else /* CYGNUS LOCAL: #if 1 */ | |
605 | ||
606 | unsigned | |
607 | ARMul_OSHandleSWI (ARMul_State *state, ARMword number) | |
608 | { | |
609 | #ifdef NOOS | |
610 | return(FALSE) ; | |
611 | #else | |
612 | #ifdef VALIDATE | |
613 | switch (number) { | |
614 | case 0x11 : | |
615 | state->Emulate = FALSE ; | |
616 | return(TRUE) ; | |
617 | case 0x01 : | |
618 | if (ARM32BITMODE) | |
619 | ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ; | |
620 | else | |
621 | ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ; | |
622 | return(TRUE) ; | |
623 | default : | |
624 | return(FALSE) ; | |
625 | } | |
626 | #else | |
627 | ARMword addr, temp ; | |
628 | char buffer[BUFFERSIZE], *cptr ; | |
629 | FILE *fptr ; | |
630 | struct OSblock* OSptr = (struct OSblock*)state->OSptr ; | |
631 | ||
632 | switch (number) { | |
633 | case SWI_WriteC : | |
634 | (void)fputc((int)state->Reg[0],stderr) ; | |
635 | OSptr->ErrorNo = errno ; | |
636 | return(TRUE) ; | |
637 | ||
638 | case SWI_Write0 : | |
639 | addr = state->Reg[0] ; | |
640 | while ((temp = ARMul_ReadByte(state,addr++)) != 0) | |
641 | fputc((char)temp,stderr) ; | |
642 | OSptr->ErrorNo = errno ; | |
643 | return(TRUE) ; | |
644 | ||
645 | case SWI_ReadC : | |
646 | state->Reg[0] = (ARMword)fgetc(stdin) ; | |
647 | OSptr->ErrorNo = errno ; | |
648 | return(TRUE) ; | |
649 | ||
650 | case SWI_CLI : | |
651 | addr = state->Reg[0] ; | |
652 | getstring(state,state->Reg[0],buffer) ; | |
653 | state->Reg[0] = (ARMword)system(buffer) ; | |
654 | OSptr->ErrorNo = errno ; | |
655 | return(TRUE) ; | |
656 | ||
657 | case SWI_GetEnv : | |
658 | state->Reg[0] = ADDRCMDLINE ; | |
659 | if (state->MemSize) | |
660 | state->Reg[1] = state->MemSize ; | |
661 | else | |
662 | state->Reg[1] = ADDRUSERSTACK ; | |
663 | ||
664 | addr = state->Reg[0] ; | |
665 | cptr = state->CommandLine ; | |
666 | if (cptr == NULL) | |
667 | cptr = "\0" ; | |
668 | do { | |
669 | temp = (ARMword)*cptr++ ; | |
670 | ARMul_WriteByte(state,addr++,temp) ; | |
671 | } while (temp != 0) ; | |
672 | return(TRUE) ; | |
673 | ||
674 | case SWI_Exit : | |
675 | #ifdef ASIM | |
676 | simkernel1_abort_run() ; | |
677 | #else | |
678 | state->Emulate = FALSE ; | |
679 | #endif | |
680 | return(TRUE) ; | |
681 | ||
682 | case SWI_EnterOS : | |
683 | if (ARM32BITMODE) | |
684 | ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ; | |
685 | else | |
686 | ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ; | |
687 | return(TRUE) ; | |
688 | ||
689 | case SWI_GetErrno : | |
690 | state->Reg[0] = OSptr->ErrorNo ; | |
691 | return(TRUE) ; | |
692 | ||
693 | case SWI_Clock : | |
694 | /* return muber of centi-seconds... */ | |
695 | state->Reg[0] = | |
696 | #ifdef CLOCKS_PER_SEC | |
697 | (CLOCKS_PER_SEC >= 100) | |
698 | ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100)) | |
699 | : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ; | |
700 | #else | |
701 | /* presume unix... clock() returns microseconds */ | |
702 | (ARMword) (clock() / 10000) ; | |
703 | #endif | |
704 | OSptr->ErrorNo = errno ; | |
705 | return(TRUE) ; | |
706 | ||
707 | case SWI_Time : | |
708 | state->Reg[0] = (ARMword)time(NULL) ; | |
709 | OSptr->ErrorNo = errno ; | |
710 | return(TRUE) ; | |
711 | ||
712 | case SWI_Remove : | |
713 | getstring(state,state->Reg[0],buffer) ; | |
714 | state->Reg[0] = unlink(buffer) ; | |
715 | OSptr->ErrorNo = errno ; | |
716 | return(TRUE) ; | |
717 | ||
718 | case SWI_Rename : { | |
719 | char buffer2[BUFFERSIZE] ; | |
720 | ||
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 ; | |
725 | return(TRUE) ; | |
726 | } | |
727 | ||
728 | case SWI_Open : { | |
729 | #if 0 | |
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", | |
736 | "w","wb","w+","w+b", | |
737 | "a","ab","a+","a+b", | |
738 | "r","r","r","r"} /* last 4 are illegal */ ; | |
739 | #endif | |
740 | ||
741 | unsigned type ; | |
742 | ||
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" */ | |
746 | fptr = stdin ; | |
747 | else if (strcmp(buffer,":tt")==0 && (type == O_WRONLY)) /* opening tty "w" */ | |
748 | fptr = stderr ; | |
749 | else | |
750 | { | |
751 | switch (type) | |
752 | { | |
753 | case O_RDONLY: | |
754 | fptr = fopen(buffer,"r") ; | |
755 | break; | |
756 | case O_WRONLY: | |
757 | fptr = fopen(buffer,"w") ; | |
758 | break; | |
759 | case O_RDWR: | |
760 | fptr = fopen(buffer,"rw") ; | |
761 | break; | |
762 | } | |
763 | } | |
764 | ||
765 | state->Reg[0] = 0 ; | |
766 | if (fptr != NULL) { | |
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) ; | |
772 | break ; | |
773 | } | |
774 | if (state->Reg[0] == 0) | |
775 | OSptr->ErrorNo = EMFILE ; /* too many open files */ | |
776 | else | |
777 | OSptr->ErrorNo = errno ; | |
778 | } | |
779 | else | |
780 | OSptr->ErrorNo = errno ; | |
781 | return(TRUE) ; | |
782 | } | |
783 | ||
784 | case SWI_Close : | |
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 ; | |
789 | return(TRUE) ; | |
790 | } | |
791 | temp-- ; | |
792 | fptr = OSptr->FileTable[temp] ; | |
793 | if (fptr == stdin || fptr == stderr) | |
794 | state->Reg[0] = 0 ; | |
795 | else | |
796 | state->Reg[0] = fclose(fptr) ; | |
797 | OSptr->FileTable[temp] = NULL ; | |
798 | OSptr->ErrorNo = errno ; | |
799 | return(TRUE) ; | |
800 | ||
801 | case SWI_Write : { | |
802 | unsigned size, upto, type ; | |
803 | char ch ; | |
804 | ||
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 ; | |
809 | return(TRUE) ; | |
810 | } | |
811 | temp-- ; | |
812 | fptr = OSptr->FileTable[temp] ; | |
813 | type = OSptr->FileFlags[temp] ; | |
814 | addr = state->Reg[1] ; | |
815 | size = (unsigned)state->Reg[2] ; | |
816 | ||
817 | if (type & READOP) | |
818 | fseek(fptr,0L,SEEK_CUR) ; | |
819 | OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP ; ; | |
820 | while (size > 0) { | |
821 | if (size >= BUFFERSIZE) | |
822 | upto = BUFFERSIZE ; | |
823 | else | |
824 | upto = size ; | |
825 | for (cptr = buffer ; (cptr - buffer) < upto ; cptr++) { | |
826 | ch = (char)ARMul_ReadByte(state,(ARMword)addr++) ; | |
827 | *cptr = FIXCRLF(type,ch) ; | |
828 | } | |
829 | temp = fwrite(buffer,1,upto,fptr) ; | |
830 | if (temp < upto) { | |
831 | state->Reg[0] = (ARMword)(size - temp) ; | |
832 | OSptr->ErrorNo = errno ; | |
833 | return(TRUE) ; | |
834 | } | |
835 | size -= upto ; | |
836 | } | |
837 | state->Reg[0] = 0 ; | |
838 | OSptr->ErrorNo = errno ; | |
839 | return(TRUE) ; | |
840 | } | |
841 | ||
842 | case SWI_Read : { | |
843 | unsigned size, upto, type ; | |
844 | char ch ; | |
845 | ||
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 ; | |
850 | return(TRUE) ; | |
851 | } | |
852 | temp-- ; | |
853 | fptr = OSptr->FileTable[temp] ; | |
854 | addr = state->Reg[1] ; | |
855 | size = (unsigned)state->Reg[2] ; | |
856 | type = OSptr->FileFlags[temp] ; | |
857 | ||
858 | if (type & WRITEOP) | |
859 | fseek(fptr,0L,SEEK_CUR) ; | |
860 | OSptr->FileFlags[temp] = (type & BINARY) | READOP ; ; | |
861 | while (size > 0) { | |
862 | if (isatty_(fptr)) { | |
863 | upto = (size >= BUFFERSIZE)?BUFFERSIZE:size + 1 ; | |
864 | if (fgets(buffer, upto, fptr) != 0) | |
865 | temp = strlen(buffer) ; | |
866 | else | |
867 | temp = 0 ; | |
868 | upto-- ; /* 1 char used for terminating null */ | |
869 | } | |
870 | else { | |
871 | upto = (size>=BUFFERSIZE)?BUFFERSIZE:size ; | |
872 | temp = fread(buffer,1,upto,fptr) ; | |
873 | } | |
874 | for (cptr = buffer ; (cptr - buffer) < temp ; cptr++) { | |
875 | ch = *cptr ; | |
876 | ARMul_WriteByte(state,(ARMword)addr++,FIXCRLF(type,ch)) ; | |
877 | } | |
878 | if (temp < upto) { | |
879 | state->Reg[0] = (ARMword)(size - temp) ; | |
880 | OSptr->ErrorNo = errno ; | |
881 | return(TRUE) ; | |
882 | } | |
883 | size -= upto ; | |
884 | } | |
885 | state->Reg[0] = 0 ; | |
886 | OSptr->ErrorNo = errno ; | |
887 | return(TRUE) ; | |
888 | } | |
889 | ||
890 | case SWI_Seek : | |
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 ; | |
895 | return(TRUE) ; | |
896 | } | |
897 | fptr = OSptr->FileTable[state->Reg[0] - 1] ; | |
898 | state->Reg[0] = fseek(fptr,(long)state->Reg[1],SEEK_SET) ; | |
899 | OSptr->ErrorNo = errno ; | |
900 | return(TRUE) ; | |
901 | ||
902 | case SWI_Flen : | |
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 ; | |
907 | return(TRUE) ; | |
908 | } | |
909 | fptr = OSptr->FileTable[state->Reg[0] - 1] ; | |
910 | addr = (ARMword)ftell(fptr) ; | |
911 | if (fseek(fptr,0L,SEEK_END) < 0) | |
912 | state->Reg[0] = -1 ; | |
913 | else { | |
914 | state->Reg[0] = (ARMword)ftell(fptr) ; | |
915 | (void)fseek(fptr,addr,SEEK_SET) ; | |
916 | } | |
917 | OSptr->ErrorNo = errno ; | |
918 | return(TRUE) ; | |
919 | ||
920 | case SWI_IsTTY : | |
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 ; | |
925 | return(TRUE) ; | |
926 | } | |
927 | fptr = OSptr->FileTable[state->Reg[0] - 1] ; | |
928 | state->Reg[0] = isatty_(fptr) ; | |
929 | OSptr->ErrorNo = errno ; | |
930 | return(TRUE) ; | |
931 | ||
932 | case SWI_TmpNam :{ | |
933 | ARMword size ; | |
934 | ||
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) { | |
940 | state->Reg[0] = 0 ; | |
941 | return(TRUE) ; | |
942 | } | |
943 | (void)tmpnam(OSptr->tempnames[temp]) ; | |
944 | } | |
945 | cptr = OSptr->tempnames[temp] ; | |
946 | if (strlen(cptr) > state->Reg[2]) | |
947 | state->Reg[0] = 0 ; | |
948 | else | |
949 | do { | |
950 | ARMul_WriteByte(state,addr++,*cptr) ; | |
951 | } while (*cptr++ != 0) ; | |
952 | OSptr->ErrorNo = errno ; | |
953 | return(TRUE) ; | |
954 | } | |
955 | ||
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; | |
964 | return(TRUE); | |
965 | } | |
966 | ||
967 | case SWI_GenerateError: | |
968 | ARMul_Abort(state, ARMSWIV) ; | |
969 | if (state->Emulate) | |
970 | ARMul_SetR15(state, ARMul_ReadWord(state, ADDRSOFTVECTORS + ARMErrorV)); | |
971 | return(TRUE); | |
972 | ||
973 | /* SWI's 0x9x unwind the state of the CPU after an abort of type x */ | |
974 | ||
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) ; | |
979 | state->Reg[14] = 0; | |
980 | goto TidyCommon; | |
981 | } | |
982 | ||
983 | case 0x98: /* Error */ | |
984 | { ARMword errorp = state->Reg[0], | |
985 | regp = state->Reg[1]; | |
986 | unsigned i; | |
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; | |
994 | goto TidyCommon; | |
995 | } | |
996 | ||
997 | case 0x94: /* Data abort */ | |
998 | { ARMword addr = state->Reg[14] - 8; | |
999 | ARMword cpsr = ARMul_GetCPSR(state) ; | |
1000 | if (ARM26BITMODE) | |
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 */ | |
1005 | ARMword sp, spsr ; | |
1006 | unsigned i ; | |
1007 | ||
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)) ; | |
1015 | sp += 4 ; | |
1016 | } | |
1017 | ARMul_SetCPSR(state,cpsr) ; | |
1018 | state->Reg[14] = ARMul_ReadWord(state,sp) + 4 ; /* botch it */ | |
1019 | ARMul_SetSPSR(state,state->Mode,spsr) ; | |
1020 | } | |
1021 | else | |
1022 | ARMul_SetCPSR(state,cpsr) ; | |
1023 | ||
1024 | /* and fall through to correct r14 */ | |
1025 | } | |
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; | |
1034 | TidyCommon: | |
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))) ; | |
1038 | if (number == 0x90) | |
1039 | state->EndCondition = 10 ; /* Branch through Zero Error */ | |
1040 | else | |
1041 | state->EndCondition = (unsigned)number - 0x8f; | |
1042 | state->Emulate = FALSE ; | |
1043 | } | |
1044 | else { | |
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); | |
1052 | } | |
1053 | return(TRUE); | |
1054 | ||
1055 | /* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */ | |
1056 | ||
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))) ; | |
1067 | if (number == 0x80) | |
1068 | state->EndCondition = 10 ; /* Branch through Zero Error */ | |
1069 | else | |
1070 | state->EndCondition = (unsigned)number - 0x7f; | |
1071 | state->Emulate = FALSE ; | |
1072 | return(TRUE); | |
1073 | } | |
1074 | ||
1075 | default : | |
1076 | state->Emulate = FALSE ; | |
1077 | return(FALSE) ; | |
1078 | } | |
1079 | #endif | |
1080 | #endif | |
1081 | } | |
1082 | #endif /* CYGNUS LOCAL: #if 1 */ | |
1083 | ||
1084 | #ifndef NOOS | |
1085 | #ifndef ASIM | |
1086 | ||
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 | \***************************************************************************/ | |
1093 | ||
1094 | unsigned | |
1095 | ARMul_OSException (ARMul_State *state, ARMword vector, ARMword pc) | |
1096 | { /* don't use this here */ | |
1097 | return(FALSE) ; | |
1098 | } | |
1099 | ||
1100 | #endif | |
1101 | ||
1102 | /***************************************************************************\ | |
1103 | * Unwind a data abort * | |
1104 | \***************************************************************************/ | |
1105 | ||
1106 | static void | |
1107 | UnwindDataAbort (ARMul_State *state, ARMword addr) | |
1108 | { | |
1109 | ARMword instr = ARMul_ReadWord(state, addr); | |
1110 | ARMword rn = BITS(16, 19); | |
1111 | ARMword itype = BITS(24, 27); | |
1112 | ARMword offset; | |
1113 | if (rn == 15) return; | |
1114 | if (itype == 8 || itype == 9) { | |
1115 | /* LDM or STM */ | |
1116 | unsigned long regs = BITS(0, 15); | |
1117 | offset = 0; | |
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); | |
1125 | } else | |
1126 | return; | |
1127 | ||
1128 | if (BIT(23)) | |
1129 | state->Reg[rn] -= offset * 4; | |
1130 | else | |
1131 | state->Reg[rn] += offset * 4; | |
1132 | } | |
1133 | ||
1134 | /***************************************************************************\ | |
1135 | * Copy a string from the debuggee's memory to the host's * | |
1136 | \***************************************************************************/ | |
1137 | ||
1138 | static void | |
1139 | getstring (ARMul_State *state, ARMword from, char *to) | |
1140 | { | |
1141 | do | |
1142 | { | |
1143 | *to = (char) ARMul_ReadByte (state, from++); | |
1144 | } while (*to++ != '\0'); | |
1145 | } | |
1146 | ||
1147 | #endif /* NOOS */ |