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 | ||
311 | res = read (f, local, len); | |
312 | if (res > 0) | |
313 | for (i = 0; i < res; i++) | |
314 | ARMul_WriteByte (state, ptr + i, local[i]); | |
315 | free (local); | |
316 | state->Reg[0] = res == -1 ? -1 : len - res; | |
317 | OSptr->ErrorNo = errno; | |
318 | } | |
319 | ||
320 | static void | |
321 | SWIwrite (ARMul_State *state, ARMword f, ARMword ptr, ARMword len) | |
322 | { | |
323 | struct OSblock* OSptr = (struct OSblock*) state->OSptr; | |
324 | int res; | |
325 | int i; | |
326 | char *local = malloc (len); | |
327 | ||
328 | for (i = 0; i < len; i++) | |
329 | { | |
330 | local[i] = ARMul_ReadByte (state, ptr + i); | |
331 | } | |
332 | res = write (f, local, len); | |
333 | state->Reg[0] = res == -1 ? -1 : len - res; | |
334 | free (local); | |
335 | OSptr->ErrorNo = errno; | |
336 | } | |
337 | ||
338 | static void | |
339 | SWIflen (ARMul_State *state, ARMword fh) | |
340 | { | |
341 | struct OSblock* OSptr = (struct OSblock*) state->OSptr; | |
342 | ARMword addr; | |
343 | ||
344 | if (fh == 0 || fh > FOPEN_MAX) | |
345 | { | |
346 | OSptr->ErrorNo = EBADF; | |
347 | state->Reg[0] = -1L; | |
348 | return; | |
349 | } | |
350 | ||
351 | addr = lseek (fh, 0, SEEK_CUR); | |
352 | if (addr < 0) | |
353 | state->Reg[0] = -1L; | |
354 | else | |
355 | { | |
356 | state->Reg[0] = lseek (fh, 0L, SEEK_END); | |
357 | (void) lseek (fh, addr, SEEK_SET); | |
358 | } | |
359 | ||
360 | OSptr->ErrorNo = errno; | |
361 | } | |
362 | ||
363 | /***************************************************************************\ | |
364 | * The emulator calls this routine when a SWI instruction is encuntered. The * | |
365 | * parameter passed is the SWI number (lower 24 bits of the instruction). * | |
366 | \***************************************************************************/ | |
367 | ||
368 | unsigned | |
369 | ARMul_OSHandleSWI (ARMul_State *state, ARMword number) | |
370 | { | |
371 | ARMword addr, temp, fildes; | |
372 | char buffer[BUFFERSIZE], *cptr; | |
373 | FILE *fptr; | |
374 | struct OSblock* OSptr = (struct OSblock*)state->OSptr; | |
375 | ||
376 | switch (number) | |
377 | { | |
378 | case SWI_Read: | |
379 | SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]); | |
380 | return TRUE; | |
381 | ||
382 | case SWI_Write: | |
383 | SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]); | |
384 | return TRUE; | |
385 | ||
386 | case SWI_Open: | |
387 | SWIopen (state, state->Reg[0],state->Reg[1]); | |
388 | return TRUE; | |
389 | ||
390 | case SWI_Clock : | |
391 | /* return number of centi-seconds... */ | |
392 | state->Reg[0] = | |
393 | #ifdef CLOCKS_PER_SEC | |
394 | (CLOCKS_PER_SEC >= 100) | |
395 | ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100)) | |
396 | : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ; | |
397 | #else | |
398 | /* presume unix... clock() returns microseconds */ | |
399 | (ARMword) (clock() / 10000) ; | |
400 | #endif | |
401 | OSptr->ErrorNo = errno ; | |
402 | return(TRUE) ; | |
403 | ||
404 | case SWI_Time : | |
405 | state->Reg[0] = (ARMword)time(NULL) ; | |
406 | OSptr->ErrorNo = errno ; | |
407 | return(TRUE) ; | |
408 | ||
409 | case SWI_Close: | |
410 | state->Reg[0] = close (state->Reg[0]); | |
411 | OSptr->ErrorNo = errno; | |
412 | return TRUE; | |
413 | ||
414 | case SWI_Flen : | |
415 | SWIflen (state, state->Reg[0]); | |
416 | return(TRUE) ; | |
417 | ||
418 | case SWI_Exit: | |
419 | state->Emulate = FALSE ; | |
420 | return TRUE; | |
421 | ||
422 | case SWI_Seek: | |
423 | { | |
424 | /* We must return non-zero for failure */ | |
425 | state->Reg[0] = -1 >= lseek (state->Reg[0], | |
426 | state->Reg[1], | |
427 | SEEK_SET); | |
428 | OSptr->ErrorNo = errno; | |
429 | return TRUE; | |
430 | } | |
431 | ||
432 | case SWI_WriteC : | |
2acceee2 | 433 | (void)fputc((int)state->Reg[0],stdout) ; |
c906108c SS |
434 | OSptr->ErrorNo = errno ; |
435 | return(TRUE) ; | |
436 | ||
437 | case SWI_Write0 : | |
438 | SWIWrite0 (state, state->Reg[0]); | |
439 | return(TRUE) ; | |
440 | ||
441 | case SWI_GetErrno : | |
442 | state->Reg[0] = OSptr->ErrorNo ; | |
443 | return(TRUE) ; | |
444 | ||
445 | case SWI_Breakpoint : | |
446 | state->EndCondition = RDIError_BreakpointReached ; | |
447 | state->Emulate = FALSE ; | |
448 | return(TRUE) ; | |
449 | ||
450 | case SWI_GetEnv : | |
451 | state->Reg[0] = ADDRCMDLINE ; | |
452 | if (state->MemSize) | |
453 | state->Reg[1] = state->MemSize ; | |
454 | else | |
455 | state->Reg[1] = ADDRUSERSTACK ; | |
456 | ||
457 | WriteCommandLineTo (state, state->Reg[0]); | |
458 | return(TRUE) ; | |
459 | ||
460 | /* Handle Angel SWIs as well as Demon ones */ | |
461 | case AngelSWI_ARM: | |
462 | case AngelSWI_Thumb: | |
463 | /* R1 is almost always a parameter block */ | |
464 | addr = state->Reg[1]; | |
465 | /* R0 is a reason code */ | |
466 | switch (state->Reg[0]) | |
467 | { | |
468 | /* Unimplemented reason codes */ | |
469 | case AngelSWI_Reason_ReadC: | |
470 | case AngelSWI_Reason_IsTTY: | |
471 | case AngelSWI_Reason_TmpNam: | |
472 | case AngelSWI_Reason_Remove: | |
473 | case AngelSWI_Reason_Rename: | |
474 | case AngelSWI_Reason_System: | |
475 | case AngelSWI_Reason_EnterSVC: | |
476 | default: | |
477 | state->Emulate = FALSE; | |
478 | return(FALSE); | |
479 | ||
480 | case AngelSWI_Reason_Clock: | |
481 | /* return number of centi-seconds... */ | |
482 | state->Reg[0] = | |
483 | #ifdef CLOCKS_PER_SEC | |
484 | (CLOCKS_PER_SEC >= 100) | |
485 | ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100)) | |
486 | : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ; | |
487 | #else | |
488 | /* presume unix... clock() returns microseconds */ | |
489 | (ARMword) (clock() / 10000) ; | |
490 | #endif | |
491 | OSptr->ErrorNo = errno; | |
492 | return (TRUE); | |
493 | ||
494 | case AngelSWI_Reason_Time: | |
495 | state->Reg[0] = (ARMword) time (NULL); | |
496 | OSptr->ErrorNo = errno; | |
497 | return (TRUE); | |
498 | ||
499 | case AngelSWI_Reason_WriteC: | |
2acceee2 | 500 | (void) fputc ((int) ARMul_ReadByte (state,addr), stdout); |
c906108c SS |
501 | OSptr->ErrorNo = errno; |
502 | return (TRUE); | |
503 | ||
504 | case AngelSWI_Reason_Write0: | |
505 | SWIWrite0 (state, addr); | |
506 | return (TRUE); | |
507 | ||
508 | case AngelSWI_Reason_Close: | |
509 | state->Reg[0] = close (ARMul_ReadWord (state, addr)); | |
510 | OSptr->ErrorNo = errno; | |
511 | return (TRUE); | |
512 | ||
513 | case AngelSWI_Reason_Seek: | |
514 | state->Reg[0] = -1 >= lseek (ARMul_ReadWord(state,addr), | |
515 | ARMul_ReadWord(state,addr+4), | |
516 | SEEK_SET); | |
517 | OSptr->ErrorNo = errno; | |
518 | return (TRUE); | |
519 | ||
520 | case AngelSWI_Reason_FLen: | |
521 | SWIflen (state, ARMul_ReadWord (state, addr)); | |
522 | return (TRUE); | |
523 | ||
524 | case AngelSWI_Reason_GetCmdLine: | |
525 | WriteCommandLineTo (state, ARMul_ReadWord (state, addr)); | |
526 | return (TRUE); | |
527 | ||
528 | case AngelSWI_Reason_HeapInfo: | |
529 | /* R1 is a pointer to a pointer */ | |
530 | addr = ARMul_ReadWord (state, addr); | |
531 | ||
532 | /* Pick up the right memory limit */ | |
533 | if (state->MemSize) | |
534 | temp = state->MemSize; | |
535 | else | |
536 | temp = ADDRUSERSTACK; | |
537 | ||
538 | ARMul_WriteWord (state, addr, 0); /* Heap base */ | |
539 | ARMul_WriteWord (state, addr+4, temp); /* Heap limit */ | |
540 | ARMul_WriteWord (state, addr+8, temp); /* Stack base */ | |
541 | ARMul_WriteWord (state, addr+12, temp); /* Stack limit */ | |
542 | return (TRUE); | |
543 | ||
544 | case AngelSWI_Reason_ReportException: | |
545 | if (state->Reg[1] == ADP_Stopped_ApplicationExit) | |
546 | state->Reg[0] = 0; | |
547 | else | |
548 | state->Reg[0] = -1; | |
549 | state->Emulate = FALSE ; | |
550 | return (TRUE); | |
551 | ||
552 | case ADP_Stopped_ApplicationExit: | |
553 | state->Reg[0] = 0; | |
554 | state->Emulate = FALSE ; | |
555 | return (TRUE); | |
556 | ||
557 | case ADP_Stopped_RunTimeError: | |
558 | state->Reg[0] = -1; | |
559 | state->Emulate = FALSE ; | |
560 | return (TRUE); | |
561 | ||
562 | case AngelSWI_Reason_Errno: | |
563 | state->Reg[0] = OSptr->ErrorNo; | |
564 | return (TRUE); | |
565 | ||
566 | case AngelSWI_Reason_Open: | |
567 | SWIopen(state, | |
568 | ARMul_ReadWord(state, addr), | |
569 | ARMul_ReadWord(state, addr+4)); | |
570 | return TRUE; | |
571 | ||
572 | case AngelSWI_Reason_Read: | |
573 | SWIread(state, | |
574 | ARMul_ReadWord(state, addr), | |
575 | ARMul_ReadWord(state, addr+4), | |
576 | ARMul_ReadWord(state, addr+8)); | |
577 | return TRUE; | |
578 | ||
579 | case AngelSWI_Reason_Write: | |
580 | SWIwrite(state, | |
581 | ARMul_ReadWord(state, addr), | |
582 | ARMul_ReadWord(state, addr+4), | |
583 | ARMul_ReadWord(state, addr+8)); | |
584 | return TRUE; | |
585 | } | |
586 | ||
587 | default : | |
588 | state->Emulate = FALSE ; | |
589 | return(FALSE) ; | |
590 | } | |
591 | } | |
592 | ||
593 | #else /* CYGNUS LOCAL: #if 1 */ | |
594 | ||
595 | unsigned | |
596 | ARMul_OSHandleSWI (ARMul_State *state, ARMword number) | |
597 | { | |
598 | #ifdef NOOS | |
599 | return(FALSE) ; | |
600 | #else | |
601 | #ifdef VALIDATE | |
602 | switch (number) { | |
603 | case 0x11 : | |
604 | state->Emulate = FALSE ; | |
605 | return(TRUE) ; | |
606 | case 0x01 : | |
607 | if (ARM32BITMODE) | |
608 | ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ; | |
609 | else | |
610 | ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ; | |
611 | return(TRUE) ; | |
612 | default : | |
613 | return(FALSE) ; | |
614 | } | |
615 | #else | |
616 | ARMword addr, temp ; | |
617 | char buffer[BUFFERSIZE], *cptr ; | |
618 | FILE *fptr ; | |
619 | struct OSblock* OSptr = (struct OSblock*)state->OSptr ; | |
620 | ||
621 | switch (number) { | |
622 | case SWI_WriteC : | |
623 | (void)fputc((int)state->Reg[0],stderr) ; | |
624 | OSptr->ErrorNo = errno ; | |
625 | return(TRUE) ; | |
626 | ||
627 | case SWI_Write0 : | |
628 | addr = state->Reg[0] ; | |
629 | while ((temp = ARMul_ReadByte(state,addr++)) != 0) | |
630 | fputc((char)temp,stderr) ; | |
631 | OSptr->ErrorNo = errno ; | |
632 | return(TRUE) ; | |
633 | ||
634 | case SWI_ReadC : | |
635 | state->Reg[0] = (ARMword)fgetc(stdin) ; | |
636 | OSptr->ErrorNo = errno ; | |
637 | return(TRUE) ; | |
638 | ||
639 | case SWI_CLI : | |
640 | addr = state->Reg[0] ; | |
641 | getstring(state,state->Reg[0],buffer) ; | |
642 | state->Reg[0] = (ARMword)system(buffer) ; | |
643 | OSptr->ErrorNo = errno ; | |
644 | return(TRUE) ; | |
645 | ||
646 | case SWI_GetEnv : | |
647 | state->Reg[0] = ADDRCMDLINE ; | |
648 | if (state->MemSize) | |
649 | state->Reg[1] = state->MemSize ; | |
650 | else | |
651 | state->Reg[1] = ADDRUSERSTACK ; | |
652 | ||
653 | addr = state->Reg[0] ; | |
654 | cptr = state->CommandLine ; | |
655 | if (cptr == NULL) | |
656 | cptr = "\0" ; | |
657 | do { | |
658 | temp = (ARMword)*cptr++ ; | |
659 | ARMul_WriteByte(state,addr++,temp) ; | |
660 | } while (temp != 0) ; | |
661 | return(TRUE) ; | |
662 | ||
663 | case SWI_Exit : | |
664 | #ifdef ASIM | |
665 | simkernel1_abort_run() ; | |
666 | #else | |
667 | state->Emulate = FALSE ; | |
668 | #endif | |
669 | return(TRUE) ; | |
670 | ||
671 | case SWI_EnterOS : | |
672 | if (ARM32BITMODE) | |
673 | ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ; | |
674 | else | |
675 | ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ; | |
676 | return(TRUE) ; | |
677 | ||
678 | case SWI_GetErrno : | |
679 | state->Reg[0] = OSptr->ErrorNo ; | |
680 | return(TRUE) ; | |
681 | ||
682 | case SWI_Clock : | |
683 | /* return muber of centi-seconds... */ | |
684 | state->Reg[0] = | |
685 | #ifdef CLOCKS_PER_SEC | |
686 | (CLOCKS_PER_SEC >= 100) | |
687 | ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100)) | |
688 | : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ; | |
689 | #else | |
690 | /* presume unix... clock() returns microseconds */ | |
691 | (ARMword) (clock() / 10000) ; | |
692 | #endif | |
693 | OSptr->ErrorNo = errno ; | |
694 | return(TRUE) ; | |
695 | ||
696 | case SWI_Time : | |
697 | state->Reg[0] = (ARMword)time(NULL) ; | |
698 | OSptr->ErrorNo = errno ; | |
699 | return(TRUE) ; | |
700 | ||
701 | case SWI_Remove : | |
702 | getstring(state,state->Reg[0],buffer) ; | |
703 | state->Reg[0] = unlink(buffer) ; | |
704 | OSptr->ErrorNo = errno ; | |
705 | return(TRUE) ; | |
706 | ||
707 | case SWI_Rename : { | |
708 | char buffer2[BUFFERSIZE] ; | |
709 | ||
710 | getstring(state,state->Reg[0],buffer) ; | |
711 | getstring(state,state->Reg[1],buffer2) ; | |
712 | state->Reg[0] = rename(buffer,buffer2) ; | |
713 | OSptr->ErrorNo = errno ; | |
714 | return(TRUE) ; | |
715 | } | |
716 | ||
717 | case SWI_Open : { | |
718 | #if 0 | |
719 | /* It seems to me that these are in the wrong order | |
720 | sac@cygnus.com, so I've redone it to use the | |
721 | flags instead, with the functionality which was already | |
722 | there -- ahh, perhaps the TRUNC bit is in a different | |
723 | place on the original host ?*/ | |
724 | static char* fmode[] = {"r","rb","r+","r+b", | |
725 | "w","wb","w+","w+b", | |
726 | "a","ab","a+","a+b", | |
727 | "r","r","r","r"} /* last 4 are illegal */ ; | |
728 | #endif | |
729 | ||
730 | unsigned type ; | |
731 | ||
732 | type = (unsigned)(state->Reg[1] & 3L) ; | |
733 | getstring(state,state->Reg[0],buffer) ; | |
734 | if (strcmp(buffer,":tt")==0 && (type == O_RDONLY )) /* opening tty "r" */ | |
735 | fptr = stdin ; | |
736 | else if (strcmp(buffer,":tt")==0 && (type == O_WRONLY)) /* opening tty "w" */ | |
737 | fptr = stderr ; | |
738 | else | |
739 | { | |
740 | switch (type) | |
741 | { | |
742 | case O_RDONLY: | |
743 | fptr = fopen(buffer,"r") ; | |
744 | break; | |
745 | case O_WRONLY: | |
746 | fptr = fopen(buffer,"w") ; | |
747 | break; | |
748 | case O_RDWR: | |
749 | fptr = fopen(buffer,"rw") ; | |
750 | break; | |
751 | } | |
752 | } | |
753 | ||
754 | state->Reg[0] = 0 ; | |
755 | if (fptr != NULL) { | |
756 | for (temp = 0 ; temp < FOPEN_MAX ; temp++) | |
757 | if (OSptr->FileTable[temp] == NULL) { | |
758 | OSptr->FileTable[temp] = fptr ; | |
759 | OSptr->FileFlags[temp] = type & 1 ; /* preserve the binary bit */ | |
760 | state->Reg[0] = (ARMword)(temp + 1) ; | |
761 | break ; | |
762 | } | |
763 | if (state->Reg[0] == 0) | |
764 | OSptr->ErrorNo = EMFILE ; /* too many open files */ | |
765 | else | |
766 | OSptr->ErrorNo = errno ; | |
767 | } | |
768 | else | |
769 | OSptr->ErrorNo = errno ; | |
770 | return(TRUE) ; | |
771 | } | |
772 | ||
773 | case SWI_Close : | |
774 | temp = state->Reg[0] ; | |
775 | if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) { | |
776 | OSptr->ErrorNo = EBADF ; | |
777 | state->Reg[0] = -1L ; | |
778 | return(TRUE) ; | |
779 | } | |
780 | temp-- ; | |
781 | fptr = OSptr->FileTable[temp] ; | |
782 | if (fptr == stdin || fptr == stderr) | |
783 | state->Reg[0] = 0 ; | |
784 | else | |
785 | state->Reg[0] = fclose(fptr) ; | |
786 | OSptr->FileTable[temp] = NULL ; | |
787 | OSptr->ErrorNo = errno ; | |
788 | return(TRUE) ; | |
789 | ||
790 | case SWI_Write : { | |
791 | unsigned size, upto, type ; | |
792 | char ch ; | |
793 | ||
794 | temp = state->Reg[0] ; | |
795 | if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) { | |
796 | OSptr->ErrorNo = EBADF ; | |
797 | state->Reg[0] = -1L ; | |
798 | return(TRUE) ; | |
799 | } | |
800 | temp-- ; | |
801 | fptr = OSptr->FileTable[temp] ; | |
802 | type = OSptr->FileFlags[temp] ; | |
803 | addr = state->Reg[1] ; | |
804 | size = (unsigned)state->Reg[2] ; | |
805 | ||
806 | if (type & READOP) | |
807 | fseek(fptr,0L,SEEK_CUR) ; | |
808 | OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP ; ; | |
809 | while (size > 0) { | |
810 | if (size >= BUFFERSIZE) | |
811 | upto = BUFFERSIZE ; | |
812 | else | |
813 | upto = size ; | |
814 | for (cptr = buffer ; (cptr - buffer) < upto ; cptr++) { | |
815 | ch = (char)ARMul_ReadByte(state,(ARMword)addr++) ; | |
816 | *cptr = FIXCRLF(type,ch) ; | |
817 | } | |
818 | temp = fwrite(buffer,1,upto,fptr) ; | |
819 | if (temp < upto) { | |
820 | state->Reg[0] = (ARMword)(size - temp) ; | |
821 | OSptr->ErrorNo = errno ; | |
822 | return(TRUE) ; | |
823 | } | |
824 | size -= upto ; | |
825 | } | |
826 | state->Reg[0] = 0 ; | |
827 | OSptr->ErrorNo = errno ; | |
828 | return(TRUE) ; | |
829 | } | |
830 | ||
831 | case SWI_Read : { | |
832 | unsigned size, upto, type ; | |
833 | char ch ; | |
834 | ||
835 | temp = state->Reg[0] ; | |
836 | if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) { | |
837 | OSptr->ErrorNo = EBADF ; | |
838 | state->Reg[0] = -1L ; | |
839 | return(TRUE) ; | |
840 | } | |
841 | temp-- ; | |
842 | fptr = OSptr->FileTable[temp] ; | |
843 | addr = state->Reg[1] ; | |
844 | size = (unsigned)state->Reg[2] ; | |
845 | type = OSptr->FileFlags[temp] ; | |
846 | ||
847 | if (type & WRITEOP) | |
848 | fseek(fptr,0L,SEEK_CUR) ; | |
849 | OSptr->FileFlags[temp] = (type & BINARY) | READOP ; ; | |
850 | while (size > 0) { | |
851 | if (isatty_(fptr)) { | |
852 | upto = (size >= BUFFERSIZE)?BUFFERSIZE:size + 1 ; | |
853 | if (fgets(buffer, upto, fptr) != 0) | |
854 | temp = strlen(buffer) ; | |
855 | else | |
856 | temp = 0 ; | |
857 | upto-- ; /* 1 char used for terminating null */ | |
858 | } | |
859 | else { | |
860 | upto = (size>=BUFFERSIZE)?BUFFERSIZE:size ; | |
861 | temp = fread(buffer,1,upto,fptr) ; | |
862 | } | |
863 | for (cptr = buffer ; (cptr - buffer) < temp ; cptr++) { | |
864 | ch = *cptr ; | |
865 | ARMul_WriteByte(state,(ARMword)addr++,FIXCRLF(type,ch)) ; | |
866 | } | |
867 | if (temp < upto) { | |
868 | state->Reg[0] = (ARMword)(size - temp) ; | |
869 | OSptr->ErrorNo = errno ; | |
870 | return(TRUE) ; | |
871 | } | |
872 | size -= upto ; | |
873 | } | |
874 | state->Reg[0] = 0 ; | |
875 | OSptr->ErrorNo = errno ; | |
876 | return(TRUE) ; | |
877 | } | |
878 | ||
879 | case SWI_Seek : | |
880 | if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX | |
881 | || OSptr->FileTable[state->Reg[0] - 1] == 0) { | |
882 | OSptr->ErrorNo = EBADF ; | |
883 | state->Reg[0] = -1L ; | |
884 | return(TRUE) ; | |
885 | } | |
886 | fptr = OSptr->FileTable[state->Reg[0] - 1] ; | |
887 | state->Reg[0] = fseek(fptr,(long)state->Reg[1],SEEK_SET) ; | |
888 | OSptr->ErrorNo = errno ; | |
889 | return(TRUE) ; | |
890 | ||
891 | case SWI_Flen : | |
892 | if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX | |
893 | || OSptr->FileTable[state->Reg[0] - 1] == 0) { | |
894 | OSptr->ErrorNo = EBADF ; | |
895 | state->Reg[0] = -1L ; | |
896 | return(TRUE) ; | |
897 | } | |
898 | fptr = OSptr->FileTable[state->Reg[0] - 1] ; | |
899 | addr = (ARMword)ftell(fptr) ; | |
900 | if (fseek(fptr,0L,SEEK_END) < 0) | |
901 | state->Reg[0] = -1 ; | |
902 | else { | |
903 | state->Reg[0] = (ARMword)ftell(fptr) ; | |
904 | (void)fseek(fptr,addr,SEEK_SET) ; | |
905 | } | |
906 | OSptr->ErrorNo = errno ; | |
907 | return(TRUE) ; | |
908 | ||
909 | case SWI_IsTTY : | |
910 | if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX | |
911 | || OSptr->FileTable[state->Reg[0] - 1] == 0) { | |
912 | OSptr->ErrorNo = EBADF ; | |
913 | state->Reg[0] = -1L ; | |
914 | return(TRUE) ; | |
915 | } | |
916 | fptr = OSptr->FileTable[state->Reg[0] - 1] ; | |
917 | state->Reg[0] = isatty_(fptr) ; | |
918 | OSptr->ErrorNo = errno ; | |
919 | return(TRUE) ; | |
920 | ||
921 | case SWI_TmpNam :{ | |
922 | ARMword size ; | |
923 | ||
924 | addr = state->Reg[0] ; | |
925 | temp = state->Reg[1] & 0xff ; | |
926 | size = state->Reg[2] ; | |
927 | if (OSptr->tempnames[temp] == NULL) { | |
928 | if ((OSptr->tempnames[temp] = malloc(L_tmpnam)) == NULL) { | |
929 | state->Reg[0] = 0 ; | |
930 | return(TRUE) ; | |
931 | } | |
932 | (void)tmpnam(OSptr->tempnames[temp]) ; | |
933 | } | |
934 | cptr = OSptr->tempnames[temp] ; | |
935 | if (strlen(cptr) > state->Reg[2]) | |
936 | state->Reg[0] = 0 ; | |
937 | else | |
938 | do { | |
939 | ARMul_WriteByte(state,addr++,*cptr) ; | |
940 | } while (*cptr++ != 0) ; | |
941 | OSptr->ErrorNo = errno ; | |
942 | return(TRUE) ; | |
943 | } | |
944 | ||
945 | case SWI_InstallHandler: | |
946 | { ARMword handlerp = ADDRSOFHANDLERS + state->Reg[0] * 8; | |
947 | ARMword oldr1 = ARMul_ReadWord(state, handlerp), | |
948 | oldr2 = ARMul_ReadWord(state, handlerp + 4); | |
949 | ARMul_WriteWord(state, handlerp, state->Reg[1]); | |
950 | ARMul_WriteWord(state, handlerp + 4, state->Reg[2]); | |
951 | state->Reg[1] = oldr1; | |
952 | state->Reg[2] = oldr2; | |
953 | return(TRUE); | |
954 | } | |
955 | ||
956 | case SWI_GenerateError: | |
957 | ARMul_Abort(state, ARMSWIV) ; | |
958 | if (state->Emulate) | |
959 | ARMul_SetR15(state, ARMul_ReadWord(state, ADDRSOFTVECTORS + ARMErrorV)); | |
960 | return(TRUE); | |
961 | ||
962 | /* SWI's 0x9x unwind the state of the CPU after an abort of type x */ | |
963 | ||
964 | case 0x90: /* Branch through zero */ | |
965 | { ARMword oldpsr = ARMul_GetCPSR(state) ; | |
966 | ARMul_SetCPSR(state, (oldpsr & 0xffffffc0) | 0x13) ; | |
967 | ARMul_SetSPSR(state, SVC32MODE, oldpsr) ; | |
968 | state->Reg[14] = 0; | |
969 | goto TidyCommon; | |
970 | } | |
971 | ||
972 | case 0x98: /* Error */ | |
973 | { ARMword errorp = state->Reg[0], | |
974 | regp = state->Reg[1]; | |
975 | unsigned i; | |
976 | ARMword errorpsr = ARMul_ReadWord(state, regp + 16*4); | |
977 | for (i = 0; i < 15; i++) | |
978 | ARMul_SetReg(state,errorpsr,i,ARMul_ReadWord(state, regp + i*4L)) ; | |
979 | state->Reg[14] = ARMul_ReadWord(state, regp + 15*4L); | |
980 | state->Reg[10] = errorp; | |
981 | ARMul_SetSPSR(state,state->Mode,errorpsr) ; | |
982 | OSptr->ErrorP = errorp; | |
983 | goto TidyCommon; | |
984 | } | |
985 | ||
986 | case 0x94: /* Data abort */ | |
987 | { ARMword addr = state->Reg[14] - 8; | |
988 | ARMword cpsr = ARMul_GetCPSR(state) ; | |
989 | if (ARM26BITMODE) | |
990 | addr = addr & 0x3fffffc ; | |
991 | ARMul_SetCPSR(state,ARMul_GetSPSR(state,cpsr)) ; | |
992 | UnwindDataAbort(state, addr); | |
993 | if (addr >= FPESTART && addr < FPEEND) { /* in the FPE */ | |
994 | ARMword sp, spsr ; | |
995 | unsigned i ; | |
996 | ||
997 | sp = state->Reg[13] ; | |
998 | state->Reg[13] += 64 ; /* fix the aborting mode sp */ | |
999 | state->Reg[14] = ARMul_ReadWord(state,sp + 60) ; /* and its lr */ | |
1000 | spsr = ARMul_GetSPSR(state,state->Mode) ; | |
1001 | state->Mode = ARMul_SwitchMode(state, state->Mode, spsr); | |
1002 | for (i = 0 ; i < 15 ; i++) { | |
1003 | ARMul_SetReg(state,spsr,i,ARMul_ReadWord(state,sp)) ; | |
1004 | sp += 4 ; | |
1005 | } | |
1006 | ARMul_SetCPSR(state,cpsr) ; | |
1007 | state->Reg[14] = ARMul_ReadWord(state,sp) + 4 ; /* botch it */ | |
1008 | ARMul_SetSPSR(state,state->Mode,spsr) ; | |
1009 | } | |
1010 | else | |
1011 | ARMul_SetCPSR(state,cpsr) ; | |
1012 | ||
1013 | /* and fall through to correct r14 */ | |
1014 | } | |
1015 | case 0x95: /* Address Exception */ | |
1016 | state->Reg[14] -= 4; | |
1017 | case 0x91: /* Undefined instruction */ | |
1018 | case 0x92: /* SWI */ | |
1019 | case 0x93: /* Prefetch abort */ | |
1020 | case 0x96: /* IRQ */ | |
1021 | case 0x97: /* FIQ */ | |
1022 | state->Reg[14] -= 4; | |
1023 | TidyCommon: | |
1024 | if (state->VectorCatch & (1 << (number - 0x90))) { | |
1025 | ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */ | |
1026 | ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ; | |
1027 | if (number == 0x90) | |
1028 | state->EndCondition = 10 ; /* Branch through Zero Error */ | |
1029 | else | |
1030 | state->EndCondition = (unsigned)number - 0x8f; | |
1031 | state->Emulate = FALSE ; | |
1032 | } | |
1033 | else { | |
1034 | ARMword sp = state->Reg[13]; | |
1035 | ARMul_WriteWord(state, sp - 4, state->Reg[14]); | |
1036 | ARMul_WriteWord(state, sp - 8, state->Reg[12]); | |
1037 | ARMul_WriteWord(state, sp - 12, state->Reg[11]); | |
1038 | ARMul_WriteWord(state, sp - 16, state->Reg[10]); | |
1039 | state->Reg[13] = sp - 16; | |
1040 | state->Reg[11] = ADDRSOFHANDLERS + 8 * (number - 0x90); | |
1041 | } | |
1042 | return(TRUE); | |
1043 | ||
1044 | /* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */ | |
1045 | ||
1046 | case 0x80: case 0x81: case 0x82: case 0x83: | |
1047 | case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: | |
1048 | { ARMword sp = state->Reg[13]; | |
1049 | state->Reg[10] = ARMul_ReadWord(state, sp); | |
1050 | state->Reg[11] = ARMul_ReadWord(state, sp + 4); | |
1051 | state->Reg[12] = ARMul_ReadWord(state, sp + 8); | |
1052 | state->Reg[14] = ARMul_ReadWord(state, sp + 12); | |
1053 | state->Reg[13] = sp + 16; | |
1054 | ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */ | |
1055 | ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ; | |
1056 | if (number == 0x80) | |
1057 | state->EndCondition = 10 ; /* Branch through Zero Error */ | |
1058 | else | |
1059 | state->EndCondition = (unsigned)number - 0x7f; | |
1060 | state->Emulate = FALSE ; | |
1061 | return(TRUE); | |
1062 | } | |
1063 | ||
1064 | default : | |
1065 | state->Emulate = FALSE ; | |
1066 | return(FALSE) ; | |
1067 | } | |
1068 | #endif | |
1069 | #endif | |
1070 | } | |
1071 | #endif /* CYGNUS LOCAL: #if 1 */ | |
1072 | ||
1073 | #ifndef NOOS | |
1074 | #ifndef ASIM | |
1075 | ||
1076 | /***************************************************************************\ | |
1077 | * The emulator calls this routine when an Exception occurs. The second * | |
1078 | * parameter is the address of the relevant exception vector. Returning * | |
1079 | * FALSE from this routine causes the trap to be taken, TRUE causes it to * | |
1080 | * be ignored (so set state->Emulate to FALSE!). * | |
1081 | \***************************************************************************/ | |
1082 | ||
1083 | unsigned | |
1084 | ARMul_OSException (ARMul_State *state, ARMword vector, ARMword pc) | |
1085 | { /* don't use this here */ | |
1086 | return(FALSE) ; | |
1087 | } | |
1088 | ||
1089 | #endif | |
1090 | ||
1091 | /***************************************************************************\ | |
1092 | * Unwind a data abort * | |
1093 | \***************************************************************************/ | |
1094 | ||
1095 | static void | |
1096 | UnwindDataAbort (ARMul_State *state, ARMword addr) | |
1097 | { | |
1098 | ARMword instr = ARMul_ReadWord(state, addr); | |
1099 | ARMword rn = BITS(16, 19); | |
1100 | ARMword itype = BITS(24, 27); | |
1101 | ARMword offset; | |
1102 | if (rn == 15) return; | |
1103 | if (itype == 8 || itype == 9) { | |
1104 | /* LDM or STM */ | |
1105 | unsigned long regs = BITS(0, 15); | |
1106 | offset = 0; | |
1107 | if (!BIT(21)) return; /* no wb */ | |
1108 | for (; regs != 0; offset++) | |
1109 | regs ^= (regs & -regs); | |
1110 | if (offset == 0) offset = 16; | |
1111 | } else if (itype == 12 || /* post-indexed CPDT */ | |
1112 | (itype == 13 && BIT(21))) { /* pre_indexed CPDT with WB */ | |
1113 | offset = BITS(0, 7); | |
1114 | } else | |
1115 | return; | |
1116 | ||
1117 | if (BIT(23)) | |
1118 | state->Reg[rn] -= offset * 4; | |
1119 | else | |
1120 | state->Reg[rn] += offset * 4; | |
1121 | } | |
1122 | ||
1123 | /***************************************************************************\ | |
1124 | * Copy a string from the debuggee's memory to the host's * | |
1125 | \***************************************************************************/ | |
1126 | ||
1127 | static void | |
1128 | getstring (ARMul_State *state, ARMword from, char *to) | |
1129 | { | |
1130 | do | |
1131 | { | |
1132 | *to = (char) ARMul_ReadByte (state, from++); | |
1133 | } while (*to++ != '\0'); | |
1134 | } | |
1135 | ||
1136 | #endif /* NOOS */ |