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 | |
dfcd3bfb | 50 | #include <unistd.h> /* For SEEK_SET etc */ |
c906108c SS |
51 | #endif |
52 | ||
53 | #ifdef __riscos | |
dfcd3bfb | 54 | extern int _fisatty (FILE *); |
c906108c SS |
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 | ||
dfcd3bfb JM |
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, | |
87 | ARMword pc); | |
88 | extern ARMword ARMul_OSLastErrorP (ARMul_State * state); | |
89 | extern ARMword ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr); | |
c906108c SS |
90 | |
91 | #define BUFFERSIZE 4096 | |
92 | #ifndef FOPEN_MAX | |
93 | #define FOPEN_MAX 64 | |
94 | #endif | |
95 | #define UNIQUETEMPS 256 | |
96 | ||
97 | #ifndef NOOS | |
dfcd3bfb JM |
98 | static void UnwindDataAbort (ARMul_State * state, ARMword addr); |
99 | static void getstring (ARMul_State * state, ARMword from, char *to); | |
c906108c SS |
100 | #endif |
101 | ||
102 | /***************************************************************************\ | |
103 | * OS private Information * | |
104 | \***************************************************************************/ | |
105 | ||
dfcd3bfb JM |
106 | struct OSblock |
107 | { | |
108 | ARMword Time0; | |
109 | ARMword ErrorP; | |
110 | ARMword ErrorNo; | |
111 | FILE *FileTable[FOPEN_MAX]; | |
112 | char FileFlags[FOPEN_MAX]; | |
113 | char *tempnames[UNIQUETEMPS]; | |
114 | }; | |
c906108c SS |
115 | |
116 | #define NOOP 0 | |
117 | #define BINARY 1 | |
118 | #define READOP 2 | |
119 | #define WRITEOP 4 | |
120 | ||
121 | #ifdef macintosh | |
122 | #define FIXCRLF(t,c) ((t & BINARY) ? \ | |
123 | c : \ | |
124 | ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \ | |
125 | ) | |
dfcd3bfb JM |
126 | #else |
127 | #define FIXCRLF(t,c) c | |
c906108c SS |
128 | #endif |
129 | ||
dfcd3bfb JM |
130 | static ARMword softvectorcode[] = { /* basic: swi tidyexception + event; mov pc, lr; |
131 | ldmia r11,{r11,pc}; swi generateexception + event | |
132 | */ | |
133 | 0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /*Reset */ | |
134 | 0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /*Undef */ | |
135 | 0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /*SWI */ | |
136 | 0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /*Prefetch abort */ | |
137 | 0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /*Data abort */ | |
138 | 0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /*Address exception */ | |
c906108c | 139 | 0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /*IRQ*/ |
dfcd3bfb JM |
140 | 0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /*FIQ*/ |
141 | 0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /*Error */ | |
142 | 0xe1a0f00e /* default handler */ | |
c906108c SS |
143 | }; |
144 | ||
145 | /***************************************************************************\ | |
146 | * Time for the Operating System to initialise itself. * | |
147 | \***************************************************************************/ | |
148 | ||
dfcd3bfb JM |
149 | unsigned |
150 | ARMul_OSInit (ARMul_State * state) | |
c906108c SS |
151 | { |
152 | #ifndef NOOS | |
153 | #ifndef VALIDATE | |
dfcd3bfb JM |
154 | ARMword instr, i, j; |
155 | struct OSblock *OSptr = (struct OSblock *) state->OSptr; | |
156 | ||
157 | if (state->OSptr == NULL) | |
158 | { | |
159 | state->OSptr = (unsigned char *) malloc (sizeof (struct OSblock)); | |
160 | if (state->OSptr == NULL) | |
161 | { | |
162 | perror ("OS Memory"); | |
163 | exit (15); | |
164 | } | |
c906108c | 165 | } |
dfcd3bfb JM |
166 | OSptr = (struct OSblock *) state->OSptr; |
167 | OSptr->ErrorP = 0; | |
168 | state->Reg[13] = ADDRSUPERSTACK; /* set up a stack for the current mode */ | |
169 | ARMul_SetReg (state, SVC32MODE, 13, ADDRSUPERSTACK); /* and for supervisor mode */ | |
170 | ARMul_SetReg (state, ABORT32MODE, 13, ADDRSUPERSTACK); /* and for abort 32 mode */ | |
171 | ARMul_SetReg (state, UNDEF32MODE, 13, ADDRSUPERSTACK); /* and for undef 32 mode */ | |
172 | instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8); /* load pc from soft vector */ | |
173 | for (i = ARMul_ResetV; i <= ARMFIQV; i += 4) | |
174 | ARMul_WriteWord (state, i, instr); /* write hardware vectors */ | |
175 | for (i = ARMul_ResetV; i <= ARMFIQV + 4; i += 4) | |
176 | { | |
177 | ARMul_WriteWord (state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4); | |
178 | ARMul_WriteWord (state, ADDRSOFHANDLERS + 2 * i + 4L, | |
179 | SOFTVECTORCODE + sizeof (softvectorcode) - 4L); | |
c906108c | 180 | } |
dfcd3bfb JM |
181 | for (i = 0; i < sizeof (softvectorcode); i += 4) |
182 | ARMul_WriteWord (state, SOFTVECTORCODE + i, softvectorcode[i / 4]); | |
183 | for (i = 0; i < FOPEN_MAX; i++) | |
184 | OSptr->FileTable[i] = NULL; | |
185 | for (i = 0; i < UNIQUETEMPS; i++) | |
186 | OSptr->tempnames[i] = NULL; | |
187 | ARMul_ConsolePrint (state, ", Demon 1.01"); | |
c906108c SS |
188 | |
189 | /* #ifndef ASIM */ | |
190 | ||
dfcd3bfb JM |
191 | /* install fpe */ |
192 | for (i = 0; i < fpesize; i += 4) /* copy the code */ | |
193 | ARMul_WriteWord (state, FPESTART + i, fpecode[i >> 2]); | |
194 | for (i = FPESTART + fpesize;; i -= 4) | |
195 | { /* reverse the error strings */ | |
196 | if ((j = ARMul_ReadWord (state, i)) == 0xffffffff) | |
197 | break; | |
198 | if (state->bigendSig && j < 0x80000000) | |
199 | { /* it's part of the string so swap it */ | |
200 | j = ((j >> 0x18) & 0x000000ff) | | |
201 | ((j >> 0x08) & 0x0000ff00) | | |
202 | ((j << 0x08) & 0x00ff0000) | ((j << 0x18) & 0xff000000); | |
203 | ARMul_WriteWord (state, i, j); | |
204 | } | |
c906108c | 205 | } |
dfcd3bfb JM |
206 | ARMul_WriteWord (state, FPEOLDVECT, ARMul_ReadWord (state, 4)); /* copy old illegal instr vector */ |
207 | ARMul_WriteWord (state, 4, FPENEWVECT (ARMul_ReadWord (state, i - 4))); /* install new vector */ | |
208 | ARMul_ConsolePrint (state, ", FPE"); | |
c906108c SS |
209 | |
210 | /* #endif /* ASIM */ | |
211 | #endif /* VALIDATE */ | |
212 | #endif /* NOOS */ | |
213 | ||
dfcd3bfb | 214 | return (TRUE); |
c906108c SS |
215 | } |
216 | ||
dfcd3bfb JM |
217 | void |
218 | ARMul_OSExit (ARMul_State * state) | |
c906108c | 219 | { |
dfcd3bfb | 220 | free ((char *) state->OSptr); |
c906108c SS |
221 | } |
222 | ||
223 | ||
224 | /***************************************************************************\ | |
225 | * Return the last Operating System Error. * | |
226 | \***************************************************************************/ | |
227 | ||
dfcd3bfb | 228 | ARMword ARMul_OSLastErrorP (ARMul_State * state) |
c906108c | 229 | { |
dfcd3bfb | 230 | return ((struct OSblock *) state->OSptr)->ErrorP; |
c906108c SS |
231 | } |
232 | ||
dfcd3bfb | 233 | #if 1 /* CYGNUS LOCAL */ |
c906108c SS |
234 | /* This is the cygnus way of doing it, which makes it simple to do our tests */ |
235 | ||
dfcd3bfb JM |
236 | static int translate_open_mode[] = { |
237 | O_RDONLY, /* "r" */ | |
238 | O_RDONLY + O_BINARY, /* "rb" */ | |
239 | O_RDWR, /* "r+" */ | |
240 | O_RDWR + O_BINARY, /* "r+b" */ | |
241 | O_WRONLY + O_CREAT + O_TRUNC, /* "w" */ | |
242 | O_WRONLY + O_BINARY + O_CREAT + O_TRUNC, /* "wb" */ | |
243 | O_RDWR + O_CREAT + O_TRUNC, /* "w+" */ | |
244 | O_RDWR + O_BINARY + O_CREAT + O_TRUNC, /* "w+b" */ | |
245 | O_WRONLY + O_APPEND + O_CREAT, /* "a" */ | |
246 | O_WRONLY + O_BINARY + O_APPEND + O_CREAT, /* "ab" */ | |
247 | O_RDWR + O_APPEND + O_CREAT, /* "a+" */ | |
248 | O_RDWR + O_BINARY + O_APPEND + O_CREAT /* "a+b" */ | |
c906108c SS |
249 | }; |
250 | ||
dfcd3bfb JM |
251 | static void |
252 | SWIWrite0 (ARMul_State * state, ARMword addr) | |
c906108c SS |
253 | { |
254 | ARMword temp; | |
dfcd3bfb | 255 | struct OSblock *OSptr = (struct OSblock *) state->OSptr; |
c906108c SS |
256 | |
257 | while ((temp = ARMul_ReadByte (state, addr++)) != 0) | |
2acceee2 | 258 | (void) fputc ((char) temp, stdout); |
c906108c SS |
259 | |
260 | OSptr->ErrorNo = errno; | |
261 | } | |
262 | ||
dfcd3bfb JM |
263 | static void |
264 | WriteCommandLineTo (ARMul_State * state, ARMword addr) | |
c906108c SS |
265 | { |
266 | ARMword temp; | |
267 | char *cptr = state->CommandLine; | |
268 | if (cptr == NULL) | |
269 | cptr = "\0"; | |
dfcd3bfb JM |
270 | do |
271 | { | |
272 | temp = (ARMword) * cptr++; | |
273 | ARMul_WriteByte (state, addr++, temp); | |
274 | } | |
275 | while (temp != 0); | |
c906108c SS |
276 | } |
277 | ||
dfcd3bfb JM |
278 | static void |
279 | SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags) | |
c906108c | 280 | { |
dfcd3bfb | 281 | struct OSblock *OSptr = (struct OSblock *) state->OSptr; |
c906108c SS |
282 | char dummy[2000]; |
283 | int flags; | |
284 | int i; | |
285 | ||
dfcd3bfb | 286 | for (i = 0; dummy[i] = ARMul_ReadByte (state, name + i); i++) |
c906108c SS |
287 | ; |
288 | ||
289 | /* Now we need to decode the Demon open mode */ | |
290 | flags = translate_open_mode[SWIflags]; | |
291 | ||
292 | /* Filename ":tt" is special: it denotes stdin/out */ | |
293 | if (strcmp (dummy, ":tt") == 0) | |
294 | { | |
dfcd3bfb JM |
295 | if (flags == O_RDONLY) /* opening tty "r" */ |
296 | state->Reg[0] = 0; /* stdin */ | |
297 | else | |
298 | state->Reg[0] = 1; /* stdout */ | |
c906108c SS |
299 | } |
300 | else | |
301 | { | |
2df3850c | 302 | state->Reg[0] = (int) open (dummy, flags, 0666); |
c906108c SS |
303 | OSptr->ErrorNo = errno; |
304 | } | |
305 | } | |
306 | ||
dfcd3bfb JM |
307 | static void |
308 | SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len) | |
c906108c | 309 | { |
dfcd3bfb | 310 | struct OSblock *OSptr = (struct OSblock *) state->OSptr; |
c906108c SS |
311 | int res; |
312 | int i; | |
313 | char *local = malloc (len); | |
314 | ||
c2d11a7d JM |
315 | if (local == NULL) |
316 | { | |
dfcd3bfb JM |
317 | fprintf (stderr, "sim: Unable to read 0x%x bytes - out of memory\n", |
318 | len); | |
c2d11a7d JM |
319 | return; |
320 | } | |
dfcd3bfb | 321 | |
c906108c SS |
322 | res = read (f, local, len); |
323 | if (res > 0) | |
dfcd3bfb | 324 | for (i = 0; i < res; i++) |
c906108c SS |
325 | ARMul_WriteByte (state, ptr + i, local[i]); |
326 | free (local); | |
327 | state->Reg[0] = res == -1 ? -1 : len - res; | |
328 | OSptr->ErrorNo = errno; | |
329 | } | |
330 | ||
dfcd3bfb JM |
331 | static void |
332 | SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len) | |
c906108c | 333 | { |
dfcd3bfb | 334 | struct OSblock *OSptr = (struct OSblock *) state->OSptr; |
c906108c SS |
335 | int res; |
336 | int i; | |
337 | char *local = malloc (len); | |
338 | ||
c2d11a7d | 339 | if (local == NULL) |
c906108c | 340 | { |
dfcd3bfb JM |
341 | fprintf (stderr, "sim: Unable to write 0x%x bytes - out of memory\n", |
342 | len); | |
c2d11a7d | 343 | return; |
c906108c | 344 | } |
dfcd3bfb JM |
345 | |
346 | for (i = 0; i < len; i++) | |
c2d11a7d JM |
347 | local[i] = ARMul_ReadByte (state, ptr + i); |
348 | ||
c906108c SS |
349 | res = write (f, local, len); |
350 | state->Reg[0] = res == -1 ? -1 : len - res; | |
351 | free (local); | |
352 | OSptr->ErrorNo = errno; | |
353 | } | |
354 | ||
dfcd3bfb JM |
355 | static void |
356 | SWIflen (ARMul_State * state, ARMword fh) | |
c906108c | 357 | { |
dfcd3bfb | 358 | struct OSblock *OSptr = (struct OSblock *) state->OSptr; |
c906108c SS |
359 | ARMword addr; |
360 | ||
361 | if (fh == 0 || fh > FOPEN_MAX) | |
362 | { | |
363 | OSptr->ErrorNo = EBADF; | |
364 | state->Reg[0] = -1L; | |
365 | return; | |
366 | } | |
367 | ||
368 | addr = lseek (fh, 0, SEEK_CUR); | |
369 | if (addr < 0) | |
370 | state->Reg[0] = -1L; | |
371 | else | |
372 | { | |
373 | state->Reg[0] = lseek (fh, 0L, SEEK_END); | |
374 | (void) lseek (fh, addr, SEEK_SET); | |
375 | } | |
376 | ||
377 | OSptr->ErrorNo = errno; | |
378 | } | |
379 | ||
380 | /***************************************************************************\ | |
381 | * The emulator calls this routine when a SWI instruction is encuntered. The * | |
382 | * parameter passed is the SWI number (lower 24 bits of the instruction). * | |
383 | \***************************************************************************/ | |
384 | ||
dfcd3bfb JM |
385 | unsigned |
386 | ARMul_OSHandleSWI (ARMul_State * state, ARMword number) | |
c906108c SS |
387 | { |
388 | ARMword addr, temp, fildes; | |
389 | char buffer[BUFFERSIZE], *cptr; | |
390 | FILE *fptr; | |
dfcd3bfb | 391 | struct OSblock *OSptr = (struct OSblock *) state->OSptr; |
c906108c SS |
392 | |
393 | switch (number) | |
394 | { | |
395 | case SWI_Read: | |
dfcd3bfb JM |
396 | SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]); |
397 | return TRUE; | |
c906108c SS |
398 | |
399 | case SWI_Write: | |
dfcd3bfb JM |
400 | SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]); |
401 | return TRUE; | |
c906108c SS |
402 | |
403 | case SWI_Open: | |
dfcd3bfb JM |
404 | SWIopen (state, state->Reg[0], state->Reg[1]); |
405 | return TRUE; | |
c906108c | 406 | |
dfcd3bfb JM |
407 | case SWI_Clock: |
408 | /* return number of centi-seconds... */ | |
409 | state->Reg[0] = | |
c906108c | 410 | #ifdef CLOCKS_PER_SEC |
dfcd3bfb JM |
411 | (CLOCKS_PER_SEC >= 100) |
412 | ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100)) | |
413 | : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC); | |
c906108c | 414 | #else |
dfcd3bfb JM |
415 | /* presume unix... clock() returns microseconds */ |
416 | (ARMword) (clock () / 10000); | |
c906108c | 417 | #endif |
dfcd3bfb JM |
418 | OSptr->ErrorNo = errno; |
419 | return (TRUE); | |
420 | ||
421 | case SWI_Time: | |
422 | state->Reg[0] = (ARMword) time (NULL); | |
423 | OSptr->ErrorNo = errno; | |
424 | return (TRUE); | |
425 | ||
c906108c SS |
426 | case SWI_Close: |
427 | state->Reg[0] = close (state->Reg[0]); | |
428 | OSptr->ErrorNo = errno; | |
429 | return TRUE; | |
430 | ||
dfcd3bfb | 431 | case SWI_Flen: |
c906108c | 432 | SWIflen (state, state->Reg[0]); |
dfcd3bfb | 433 | return (TRUE); |
c906108c SS |
434 | |
435 | case SWI_Exit: | |
dfcd3bfb | 436 | state->Emulate = FALSE; |
c906108c SS |
437 | return TRUE; |
438 | ||
439 | case SWI_Seek: | |
440 | { | |
441 | /* We must return non-zero for failure */ | |
dfcd3bfb | 442 | state->Reg[0] = -1 >= lseek (state->Reg[0], state->Reg[1], SEEK_SET); |
c906108c SS |
443 | OSptr->ErrorNo = errno; |
444 | return TRUE; | |
445 | } | |
446 | ||
dfcd3bfb JM |
447 | case SWI_WriteC: |
448 | (void) fputc ((int) state->Reg[0], stdout); | |
449 | OSptr->ErrorNo = errno; | |
450 | return (TRUE); | |
c906108c | 451 | |
dfcd3bfb | 452 | case SWI_Write0: |
c906108c | 453 | SWIWrite0 (state, state->Reg[0]); |
dfcd3bfb | 454 | return (TRUE); |
c906108c | 455 | |
dfcd3bfb JM |
456 | case SWI_GetErrno: |
457 | state->Reg[0] = OSptr->ErrorNo; | |
458 | return (TRUE); | |
c906108c | 459 | |
dfcd3bfb JM |
460 | case SWI_Breakpoint: |
461 | state->EndCondition = RDIError_BreakpointReached; | |
462 | state->Emulate = FALSE; | |
463 | return (TRUE); | |
c906108c | 464 | |
dfcd3bfb JM |
465 | case SWI_GetEnv: |
466 | state->Reg[0] = ADDRCMDLINE; | |
467 | if (state->MemSize) | |
468 | state->Reg[1] = state->MemSize; | |
469 | else | |
470 | state->Reg[1] = ADDRUSERSTACK; | |
c906108c | 471 | |
dfcd3bfb JM |
472 | WriteCommandLineTo (state, state->Reg[0]); |
473 | return (TRUE); | |
c906108c | 474 | |
dfcd3bfb | 475 | /* Handle Angel SWIs as well as Demon ones */ |
c906108c SS |
476 | case AngelSWI_ARM: |
477 | case AngelSWI_Thumb: | |
478 | /* R1 is almost always a parameter block */ | |
479 | addr = state->Reg[1]; | |
480 | /* R0 is a reason code */ | |
481 | switch (state->Reg[0]) | |
482 | { | |
483 | /* Unimplemented reason codes */ | |
484 | case AngelSWI_Reason_ReadC: | |
485 | case AngelSWI_Reason_IsTTY: | |
486 | case AngelSWI_Reason_TmpNam: | |
487 | case AngelSWI_Reason_Remove: | |
488 | case AngelSWI_Reason_Rename: | |
489 | case AngelSWI_Reason_System: | |
490 | case AngelSWI_Reason_EnterSVC: | |
491 | default: | |
492 | state->Emulate = FALSE; | |
dfcd3bfb | 493 | return (FALSE); |
c906108c SS |
494 | |
495 | case AngelSWI_Reason_Clock: | |
dfcd3bfb | 496 | /* return number of centi-seconds... */ |
c906108c SS |
497 | state->Reg[0] = |
498 | #ifdef CLOCKS_PER_SEC | |
499 | (CLOCKS_PER_SEC >= 100) | |
dfcd3bfb JM |
500 | ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100)) |
501 | : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC); | |
c906108c | 502 | #else |
dfcd3bfb JM |
503 | /* presume unix... clock() returns microseconds */ |
504 | (ARMword) (clock () / 10000); | |
c906108c SS |
505 | #endif |
506 | OSptr->ErrorNo = errno; | |
507 | return (TRUE); | |
508 | ||
509 | case AngelSWI_Reason_Time: | |
510 | state->Reg[0] = (ARMword) time (NULL); | |
511 | OSptr->ErrorNo = errno; | |
512 | return (TRUE); | |
513 | ||
514 | case AngelSWI_Reason_WriteC: | |
dfcd3bfb | 515 | (void) fputc ((int) ARMul_ReadByte (state, addr), stdout); |
c906108c SS |
516 | OSptr->ErrorNo = errno; |
517 | return (TRUE); | |
518 | ||
519 | case AngelSWI_Reason_Write0: | |
520 | SWIWrite0 (state, addr); | |
521 | return (TRUE); | |
522 | ||
523 | case AngelSWI_Reason_Close: | |
524 | state->Reg[0] = close (ARMul_ReadWord (state, addr)); | |
525 | OSptr->ErrorNo = errno; | |
526 | return (TRUE); | |
527 | ||
528 | case AngelSWI_Reason_Seek: | |
dfcd3bfb JM |
529 | state->Reg[0] = -1 >= lseek (ARMul_ReadWord (state, addr), |
530 | ARMul_ReadWord (state, addr + 4), | |
c906108c SS |
531 | SEEK_SET); |
532 | OSptr->ErrorNo = errno; | |
533 | return (TRUE); | |
534 | ||
535 | case AngelSWI_Reason_FLen: | |
536 | SWIflen (state, ARMul_ReadWord (state, addr)); | |
537 | return (TRUE); | |
538 | ||
dfcd3bfb | 539 | case AngelSWI_Reason_GetCmdLine: |
c906108c SS |
540 | WriteCommandLineTo (state, ARMul_ReadWord (state, addr)); |
541 | return (TRUE); | |
542 | ||
543 | case AngelSWI_Reason_HeapInfo: | |
544 | /* R1 is a pointer to a pointer */ | |
545 | addr = ARMul_ReadWord (state, addr); | |
546 | ||
547 | /* Pick up the right memory limit */ | |
548 | if (state->MemSize) | |
549 | temp = state->MemSize; | |
550 | else | |
551 | temp = ADDRUSERSTACK; | |
552 | ||
dfcd3bfb JM |
553 | ARMul_WriteWord (state, addr, 0); /* Heap base */ |
554 | ARMul_WriteWord (state, addr + 4, temp); /* Heap limit */ | |
555 | ARMul_WriteWord (state, addr + 8, temp); /* Stack base */ | |
556 | ARMul_WriteWord (state, addr + 12, temp); /* Stack limit */ | |
c906108c SS |
557 | return (TRUE); |
558 | ||
559 | case AngelSWI_Reason_ReportException: | |
560 | if (state->Reg[1] == ADP_Stopped_ApplicationExit) | |
561 | state->Reg[0] = 0; | |
562 | else | |
563 | state->Reg[0] = -1; | |
dfcd3bfb | 564 | state->Emulate = FALSE; |
c906108c SS |
565 | return (TRUE); |
566 | ||
567 | case ADP_Stopped_ApplicationExit: | |
568 | state->Reg[0] = 0; | |
dfcd3bfb | 569 | state->Emulate = FALSE; |
c906108c | 570 | return (TRUE); |
dfcd3bfb | 571 | |
c906108c SS |
572 | case ADP_Stopped_RunTimeError: |
573 | state->Reg[0] = -1; | |
dfcd3bfb | 574 | state->Emulate = FALSE; |
c906108c SS |
575 | return (TRUE); |
576 | ||
577 | case AngelSWI_Reason_Errno: | |
578 | state->Reg[0] = OSptr->ErrorNo; | |
579 | return (TRUE); | |
580 | ||
581 | case AngelSWI_Reason_Open: | |
dfcd3bfb JM |
582 | SWIopen (state, |
583 | ARMul_ReadWord (state, addr), | |
584 | ARMul_ReadWord (state, addr + 4)); | |
c906108c SS |
585 | return TRUE; |
586 | ||
587 | case AngelSWI_Reason_Read: | |
dfcd3bfb JM |
588 | SWIread (state, |
589 | ARMul_ReadWord (state, addr), | |
590 | ARMul_ReadWord (state, addr + 4), | |
591 | ARMul_ReadWord (state, addr + 8)); | |
c906108c SS |
592 | return TRUE; |
593 | ||
594 | case AngelSWI_Reason_Write: | |
dfcd3bfb JM |
595 | SWIwrite (state, |
596 | ARMul_ReadWord (state, addr), | |
597 | ARMul_ReadWord (state, addr + 4), | |
598 | ARMul_ReadWord (state, addr + 8)); | |
c906108c SS |
599 | return TRUE; |
600 | } | |
601 | ||
dfcd3bfb JM |
602 | default: |
603 | state->Emulate = FALSE; | |
604 | return (FALSE); | |
c906108c SS |
605 | } |
606 | } | |
607 | ||
dfcd3bfb | 608 | #else /* CYGNUS LOCAL: #if 1 */ |
c906108c | 609 | |
dfcd3bfb JM |
610 | unsigned |
611 | ARMul_OSHandleSWI (ARMul_State * state, ARMword number) | |
c906108c SS |
612 | { |
613 | #ifdef NOOS | |
dfcd3bfb | 614 | return (FALSE); |
c906108c SS |
615 | #else |
616 | #ifdef VALIDATE | |
dfcd3bfb JM |
617 | switch (number) |
618 | { | |
619 | case 0x11: | |
620 | state->Emulate = FALSE; | |
621 | return (TRUE); | |
622 | case 0x01: | |
623 | if (ARM32BITMODE) | |
624 | ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x13); | |
625 | else | |
626 | ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x3); | |
627 | return (TRUE); | |
628 | default: | |
629 | return (FALSE); | |
c906108c SS |
630 | } |
631 | #else | |
dfcd3bfb JM |
632 | ARMword addr, temp; |
633 | char buffer[BUFFERSIZE], *cptr; | |
634 | FILE *fptr; | |
635 | struct OSblock *OSptr = (struct OSblock *) state->OSptr; | |
636 | ||
637 | switch (number) | |
638 | { | |
639 | case SWI_WriteC: | |
640 | (void) fputc ((int) state->Reg[0], stderr); | |
641 | OSptr->ErrorNo = errno; | |
642 | return (TRUE); | |
643 | ||
644 | case SWI_Write0: | |
645 | addr = state->Reg[0]; | |
646 | while ((temp = ARMul_ReadByte (state, addr++)) != 0) | |
647 | fputc ((char) temp, stderr); | |
648 | OSptr->ErrorNo = errno; | |
649 | return (TRUE); | |
650 | ||
651 | case SWI_ReadC: | |
652 | state->Reg[0] = (ARMword) fgetc (stdin); | |
653 | OSptr->ErrorNo = errno; | |
654 | return (TRUE); | |
655 | ||
656 | case SWI_CLI: | |
657 | addr = state->Reg[0]; | |
658 | getstring (state, state->Reg[0], buffer); | |
659 | state->Reg[0] = (ARMword) system (buffer); | |
660 | OSptr->ErrorNo = errno; | |
661 | return (TRUE); | |
662 | ||
663 | case SWI_GetEnv: | |
664 | state->Reg[0] = ADDRCMDLINE; | |
665 | if (state->MemSize) | |
666 | state->Reg[1] = state->MemSize; | |
667 | else | |
668 | state->Reg[1] = ADDRUSERSTACK; | |
669 | ||
670 | addr = state->Reg[0]; | |
671 | cptr = state->CommandLine; | |
672 | if (cptr == NULL) | |
673 | cptr = "\0"; | |
674 | do | |
675 | { | |
676 | temp = (ARMword) * cptr++; | |
677 | ARMul_WriteByte (state, addr++, temp); | |
678 | } | |
679 | while (temp != 0); | |
680 | return (TRUE); | |
681 | ||
682 | case SWI_Exit: | |
c906108c | 683 | #ifdef ASIM |
dfcd3bfb | 684 | simkernel1_abort_run (); |
c906108c | 685 | #else |
dfcd3bfb | 686 | state->Emulate = FALSE; |
c906108c | 687 | #endif |
dfcd3bfb JM |
688 | return (TRUE); |
689 | ||
690 | case SWI_EnterOS: | |
691 | if (ARM32BITMODE) | |
692 | ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x13); | |
693 | else | |
694 | ARMul_SetCPSR (state, (ARMul_GetCPSR (state) & 0xffffffc0) | 0x3); | |
695 | return (TRUE); | |
696 | ||
697 | case SWI_GetErrno: | |
698 | state->Reg[0] = OSptr->ErrorNo; | |
699 | return (TRUE); | |
700 | ||
701 | case SWI_Clock: | |
702 | /* return muber of centi-seconds... */ | |
703 | state->Reg[0] = | |
c906108c | 704 | #ifdef CLOCKS_PER_SEC |
dfcd3bfb JM |
705 | (CLOCKS_PER_SEC >= 100) |
706 | ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100)) | |
707 | : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC); | |
c906108c | 708 | #else |
dfcd3bfb JM |
709 | /* presume unix... clock() returns microseconds */ |
710 | (ARMword) (clock () / 10000); | |
c906108c | 711 | #endif |
dfcd3bfb JM |
712 | OSptr->ErrorNo = errno; |
713 | return (TRUE); | |
714 | ||
715 | case SWI_Time: | |
716 | state->Reg[0] = (ARMword) time (NULL); | |
717 | OSptr->ErrorNo = errno; | |
718 | return (TRUE); | |
719 | ||
720 | case SWI_Remove: | |
721 | getstring (state, state->Reg[0], buffer); | |
722 | state->Reg[0] = unlink (buffer); | |
723 | OSptr->ErrorNo = errno; | |
724 | return (TRUE); | |
725 | ||
726 | case SWI_Rename: | |
727 | { | |
728 | char buffer2[BUFFERSIZE]; | |
729 | ||
730 | getstring (state, state->Reg[0], buffer); | |
731 | getstring (state, state->Reg[1], buffer2); | |
732 | state->Reg[0] = rename (buffer, buffer2); | |
733 | OSptr->ErrorNo = errno; | |
734 | return (TRUE); | |
735 | } | |
736 | ||
737 | case SWI_Open: | |
738 | { | |
c906108c | 739 | #if 0 |
dfcd3bfb JM |
740 | /* It seems to me that these are in the wrong order |
741 | sac@cygnus.com, so I've redone it to use the | |
742 | flags instead, with the functionality which was already | |
743 | there -- ahh, perhaps the TRUNC bit is in a different | |
744 | place on the original host ? */ | |
745 | static char *fmode[] = { "r", "rb", "r+", "r+b", | |
746 | "w", "wb", "w+", "w+b", | |
747 | "a", "ab", "a+", "a+b", | |
748 | "r", "r", "r", "r" | |
749 | } /* last 4 are illegal */ ; | |
c906108c SS |
750 | #endif |
751 | ||
dfcd3bfb JM |
752 | unsigned type; |
753 | ||
754 | type = (unsigned) (state->Reg[1] & 3L); | |
755 | getstring (state, state->Reg[0], buffer); | |
756 | if (strcmp (buffer, ":tt") == 0 && (type == O_RDONLY)) /* opening tty "r" */ | |
757 | fptr = stdin; | |
758 | else if (strcmp (buffer, ":tt") == 0 && (type == O_WRONLY)) /* opening tty "w" */ | |
759 | fptr = stderr; | |
760 | else | |
761 | { | |
762 | switch (type) | |
763 | { | |
764 | case O_RDONLY: | |
765 | fptr = fopen (buffer, "r"); | |
766 | break; | |
767 | case O_WRONLY: | |
768 | fptr = fopen (buffer, "w"); | |
769 | break; | |
770 | case O_RDWR: | |
771 | fptr = fopen (buffer, "rw"); | |
772 | break; | |
773 | } | |
774 | } | |
775 | ||
776 | state->Reg[0] = 0; | |
777 | if (fptr != NULL) | |
778 | { | |
779 | for (temp = 0; temp < FOPEN_MAX; temp++) | |
780 | if (OSptr->FileTable[temp] == NULL) | |
781 | { | |
782 | OSptr->FileTable[temp] = fptr; | |
783 | OSptr->FileFlags[temp] = type & 1; /* preserve the binary bit */ | |
784 | state->Reg[0] = (ARMword) (temp + 1); | |
785 | break; | |
786 | } | |
787 | if (state->Reg[0] == 0) | |
788 | OSptr->ErrorNo = EMFILE; /* too many open files */ | |
789 | else | |
790 | OSptr->ErrorNo = errno; | |
791 | } | |
792 | else | |
793 | OSptr->ErrorNo = errno; | |
794 | return (TRUE); | |
795 | } | |
796 | ||
797 | case SWI_Close: | |
798 | temp = state->Reg[0]; | |
799 | if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) | |
800 | { | |
801 | OSptr->ErrorNo = EBADF; | |
802 | state->Reg[0] = -1L; | |
803 | return (TRUE); | |
804 | } | |
805 | temp--; | |
806 | fptr = OSptr->FileTable[temp]; | |
807 | if (fptr == stdin || fptr == stderr) | |
808 | state->Reg[0] = 0; | |
809 | else | |
810 | state->Reg[0] = fclose (fptr); | |
811 | OSptr->FileTable[temp] = NULL; | |
812 | OSptr->ErrorNo = errno; | |
813 | return (TRUE); | |
814 | ||
815 | case SWI_Write: | |
816 | { | |
817 | unsigned size, upto, type; | |
818 | char ch; | |
819 | ||
820 | temp = state->Reg[0]; | |
821 | if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) | |
822 | { | |
823 | OSptr->ErrorNo = EBADF; | |
824 | state->Reg[0] = -1L; | |
825 | return (TRUE); | |
826 | } | |
827 | temp--; | |
828 | fptr = OSptr->FileTable[temp]; | |
829 | type = OSptr->FileFlags[temp]; | |
830 | addr = state->Reg[1]; | |
831 | size = (unsigned) state->Reg[2]; | |
832 | ||
833 | if (type & READOP) | |
834 | fseek (fptr, 0L, SEEK_CUR); | |
835 | OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP;; | |
836 | while (size > 0) | |
837 | { | |
838 | if (size >= BUFFERSIZE) | |
839 | upto = BUFFERSIZE; | |
840 | else | |
841 | upto = size; | |
842 | for (cptr = buffer; (cptr - buffer) < upto; cptr++) | |
843 | { | |
844 | ch = (char) ARMul_ReadByte (state, (ARMword) addr++); | |
845 | *cptr = FIXCRLF (type, ch); | |
846 | } | |
847 | temp = fwrite (buffer, 1, upto, fptr); | |
848 | if (temp < upto) | |
849 | { | |
850 | state->Reg[0] = (ARMword) (size - temp); | |
851 | OSptr->ErrorNo = errno; | |
852 | return (TRUE); | |
853 | } | |
854 | size -= upto; | |
855 | } | |
856 | state->Reg[0] = 0; | |
857 | OSptr->ErrorNo = errno; | |
858 | return (TRUE); | |
859 | } | |
860 | ||
861 | case SWI_Read: | |
862 | { | |
863 | unsigned size, upto, type; | |
864 | char ch; | |
865 | ||
866 | temp = state->Reg[0]; | |
867 | if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) | |
868 | { | |
869 | OSptr->ErrorNo = EBADF; | |
870 | state->Reg[0] = -1L; | |
871 | return (TRUE); | |
872 | } | |
873 | temp--; | |
874 | fptr = OSptr->FileTable[temp]; | |
875 | addr = state->Reg[1]; | |
876 | size = (unsigned) state->Reg[2]; | |
877 | type = OSptr->FileFlags[temp]; | |
878 | ||
879 | if (type & WRITEOP) | |
880 | fseek (fptr, 0L, SEEK_CUR); | |
881 | OSptr->FileFlags[temp] = (type & BINARY) | READOP;; | |
882 | while (size > 0) | |
883 | { | |
884 | if (isatty_ (fptr)) | |
885 | { | |
886 | upto = (size >= BUFFERSIZE) ? BUFFERSIZE : size + 1; | |
887 | if (fgets (buffer, upto, fptr) != 0) | |
888 | temp = strlen (buffer); | |
889 | else | |
890 | temp = 0; | |
891 | upto--; /* 1 char used for terminating null */ | |
892 | } | |
893 | else | |
894 | { | |
895 | upto = (size >= BUFFERSIZE) ? BUFFERSIZE : size; | |
896 | temp = fread (buffer, 1, upto, fptr); | |
897 | } | |
898 | for (cptr = buffer; (cptr - buffer) < temp; cptr++) | |
899 | { | |
900 | ch = *cptr; | |
901 | ARMul_WriteByte (state, (ARMword) addr++, FIXCRLF (type, ch)); | |
902 | } | |
903 | if (temp < upto) | |
904 | { | |
905 | state->Reg[0] = (ARMword) (size - temp); | |
906 | OSptr->ErrorNo = errno; | |
907 | return (TRUE); | |
908 | } | |
909 | size -= upto; | |
910 | } | |
911 | state->Reg[0] = 0; | |
912 | OSptr->ErrorNo = errno; | |
913 | return (TRUE); | |
914 | } | |
915 | ||
916 | case SWI_Seek: | |
917 | if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX | |
918 | || OSptr->FileTable[state->Reg[0] - 1] == 0) | |
919 | { | |
920 | OSptr->ErrorNo = EBADF; | |
921 | state->Reg[0] = -1L; | |
922 | return (TRUE); | |
923 | } | |
924 | fptr = OSptr->FileTable[state->Reg[0] - 1]; | |
925 | state->Reg[0] = fseek (fptr, (long) state->Reg[1], SEEK_SET); | |
926 | OSptr->ErrorNo = errno; | |
927 | return (TRUE); | |
928 | ||
929 | case SWI_Flen: | |
930 | if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX | |
931 | || OSptr->FileTable[state->Reg[0] - 1] == 0) | |
932 | { | |
933 | OSptr->ErrorNo = EBADF; | |
934 | state->Reg[0] = -1L; | |
935 | return (TRUE); | |
936 | } | |
937 | fptr = OSptr->FileTable[state->Reg[0] - 1]; | |
938 | addr = (ARMword) ftell (fptr); | |
939 | if (fseek (fptr, 0L, SEEK_END) < 0) | |
940 | state->Reg[0] = -1; | |
941 | else | |
942 | { | |
943 | state->Reg[0] = (ARMword) ftell (fptr); | |
944 | (void) fseek (fptr, addr, SEEK_SET); | |
945 | } | |
946 | OSptr->ErrorNo = errno; | |
947 | return (TRUE); | |
948 | ||
949 | case SWI_IsTTY: | |
950 | if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX | |
951 | || OSptr->FileTable[state->Reg[0] - 1] == 0) | |
952 | { | |
953 | OSptr->ErrorNo = EBADF; | |
954 | state->Reg[0] = -1L; | |
955 | return (TRUE); | |
956 | } | |
957 | fptr = OSptr->FileTable[state->Reg[0] - 1]; | |
958 | state->Reg[0] = isatty_ (fptr); | |
959 | OSptr->ErrorNo = errno; | |
960 | return (TRUE); | |
961 | ||
962 | case SWI_TmpNam: | |
963 | { | |
964 | ARMword size; | |
965 | ||
966 | addr = state->Reg[0]; | |
967 | temp = state->Reg[1] & 0xff; | |
968 | size = state->Reg[2]; | |
969 | if (OSptr->tempnames[temp] == NULL) | |
970 | { | |
971 | if ((OSptr->tempnames[temp] = malloc (L_tmpnam)) == NULL) | |
972 | { | |
973 | state->Reg[0] = 0; | |
974 | return (TRUE); | |
975 | } | |
976 | (void) tmpnam (OSptr->tempnames[temp]); | |
977 | } | |
978 | cptr = OSptr->tempnames[temp]; | |
979 | if (strlen (cptr) > state->Reg[2]) | |
980 | state->Reg[0] = 0; | |
981 | else | |
982 | do | |
983 | { | |
984 | ARMul_WriteByte (state, addr++, *cptr); | |
985 | } | |
986 | while (*cptr++ != 0); | |
987 | OSptr->ErrorNo = errno; | |
988 | return (TRUE); | |
989 | } | |
c906108c SS |
990 | |
991 | case SWI_InstallHandler: | |
dfcd3bfb JM |
992 | { |
993 | ARMword handlerp = ADDRSOFHANDLERS + state->Reg[0] * 8; | |
994 | ARMword oldr1 = ARMul_ReadWord (state, handlerp), | |
995 | oldr2 = ARMul_ReadWord (state, handlerp + 4); | |
996 | ARMul_WriteWord (state, handlerp, state->Reg[1]); | |
997 | ARMul_WriteWord (state, handlerp + 4, state->Reg[2]); | |
998 | state->Reg[1] = oldr1; | |
999 | state->Reg[2] = oldr2; | |
1000 | return (TRUE); | |
1001 | } | |
c906108c SS |
1002 | |
1003 | case SWI_GenerateError: | |
dfcd3bfb JM |
1004 | ARMul_Abort (state, ARMSWIV); |
1005 | if (state->Emulate) | |
1006 | ARMul_SetR15 (state, | |
1007 | ARMul_ReadWord (state, ADDRSOFTVECTORS + ARMErrorV)); | |
1008 | return (TRUE); | |
c906108c SS |
1009 | |
1010 | /* SWI's 0x9x unwind the state of the CPU after an abort of type x */ | |
1011 | ||
dfcd3bfb JM |
1012 | case 0x90: /* Branch through zero */ |
1013 | { | |
1014 | ARMword oldpsr = ARMul_GetCPSR (state); | |
1015 | ARMul_SetCPSR (state, (oldpsr & 0xffffffc0) | 0x13); | |
1016 | ARMul_SetSPSR (state, SVC32MODE, oldpsr); | |
1017 | state->Reg[14] = 0; | |
1018 | goto TidyCommon; | |
1019 | } | |
1020 | ||
1021 | case 0x98: /* Error */ | |
1022 | { | |
1023 | ARMword errorp = state->Reg[0], regp = state->Reg[1]; | |
1024 | unsigned i; | |
1025 | ARMword errorpsr = ARMul_ReadWord (state, regp + 16 * 4); | |
1026 | for (i = 0; i < 15; i++) | |
1027 | ARMul_SetReg (state, errorpsr, i, | |
1028 | ARMul_ReadWord (state, regp + i * 4L)); | |
1029 | state->Reg[14] = ARMul_ReadWord (state, regp + 15 * 4L); | |
1030 | state->Reg[10] = errorp; | |
1031 | ARMul_SetSPSR (state, state->Mode, errorpsr); | |
1032 | OSptr->ErrorP = errorp; | |
1033 | goto TidyCommon; | |
1034 | } | |
1035 | ||
1036 | case 0x94: /* Data abort */ | |
1037 | { | |
1038 | ARMword addr = state->Reg[14] - 8; | |
1039 | ARMword cpsr = ARMul_GetCPSR (state); | |
1040 | if (ARM26BITMODE) | |
1041 | addr = addr & 0x3fffffc; | |
1042 | ARMul_SetCPSR (state, ARMul_GetSPSR (state, cpsr)); | |
1043 | UnwindDataAbort (state, addr); | |
1044 | if (addr >= FPESTART && addr < FPEEND) | |
1045 | { /* in the FPE */ | |
1046 | ARMword sp, spsr; | |
1047 | unsigned i; | |
1048 | ||
1049 | sp = state->Reg[13]; | |
1050 | state->Reg[13] += 64; /* fix the aborting mode sp */ | |
1051 | state->Reg[14] = ARMul_ReadWord (state, sp + 60); /* and its lr */ | |
1052 | spsr = ARMul_GetSPSR (state, state->Mode); | |
1053 | state->Mode = ARMul_SwitchMode (state, state->Mode, spsr); | |
1054 | for (i = 0; i < 15; i++) | |
1055 | { | |
1056 | ARMul_SetReg (state, spsr, i, ARMul_ReadWord (state, sp)); | |
1057 | sp += 4; | |
1058 | } | |
1059 | ARMul_SetCPSR (state, cpsr); | |
1060 | state->Reg[14] = ARMul_ReadWord (state, sp) + 4; /* botch it */ | |
1061 | ARMul_SetSPSR (state, state->Mode, spsr); | |
1062 | } | |
1063 | else | |
1064 | ARMul_SetCPSR (state, cpsr); | |
1065 | ||
1066 | /* and fall through to correct r14 */ | |
1067 | } | |
1068 | case 0x95: /* Address Exception */ | |
1069 | state->Reg[14] -= 4; | |
1070 | case 0x91: /* Undefined instruction */ | |
1071 | case 0x92: /* SWI */ | |
1072 | case 0x93: /* Prefetch abort */ | |
1073 | case 0x96: /* IRQ */ | |
1074 | case 0x97: /* FIQ */ | |
1075 | state->Reg[14] -= 4; | |
c906108c | 1076 | TidyCommon: |
dfcd3bfb JM |
1077 | if (state->VectorCatch & (1 << (number - 0x90))) |
1078 | { | |
1079 | ARMul_SetR15 (state, state->Reg[14] + 8); /* the 8 is the pipelining the the RDI will undo */ | |
1080 | ARMul_SetCPSR (state, ARMul_GetSPSR (state, ARMul_GetCPSR (state))); | |
1081 | if (number == 0x90) | |
1082 | state->EndCondition = 10; /* Branch through Zero Error */ | |
1083 | else | |
1084 | state->EndCondition = (unsigned) number - 0x8f; | |
1085 | state->Emulate = FALSE; | |
1086 | } | |
1087 | else | |
1088 | { | |
1089 | ARMword sp = state->Reg[13]; | |
1090 | ARMul_WriteWord (state, sp - 4, state->Reg[14]); | |
1091 | ARMul_WriteWord (state, sp - 8, state->Reg[12]); | |
1092 | ARMul_WriteWord (state, sp - 12, state->Reg[11]); | |
1093 | ARMul_WriteWord (state, sp - 16, state->Reg[10]); | |
1094 | state->Reg[13] = sp - 16; | |
1095 | state->Reg[11] = ADDRSOFHANDLERS + 8 * (number - 0x90); | |
1096 | } | |
1097 | return (TRUE); | |
c906108c SS |
1098 | |
1099 | /* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */ | |
1100 | ||
dfcd3bfb JM |
1101 | case 0x80: |
1102 | case 0x81: | |
1103 | case 0x82: | |
1104 | case 0x83: | |
1105 | case 0x84: | |
1106 | case 0x85: | |
1107 | case 0x86: | |
1108 | case 0x87: | |
1109 | case 0x88: | |
1110 | { | |
1111 | ARMword sp = state->Reg[13]; | |
1112 | state->Reg[10] = ARMul_ReadWord (state, sp); | |
1113 | state->Reg[11] = ARMul_ReadWord (state, sp + 4); | |
1114 | state->Reg[12] = ARMul_ReadWord (state, sp + 8); | |
1115 | state->Reg[14] = ARMul_ReadWord (state, sp + 12); | |
1116 | state->Reg[13] = sp + 16; | |
1117 | ARMul_SetR15 (state, state->Reg[14] + 8); /* the 8 is the pipelining the the RDI will undo */ | |
1118 | ARMul_SetCPSR (state, ARMul_GetSPSR (state, ARMul_GetCPSR (state))); | |
1119 | if (number == 0x80) | |
1120 | state->EndCondition = 10; /* Branch through Zero Error */ | |
1121 | else | |
1122 | state->EndCondition = (unsigned) number - 0x7f; | |
1123 | state->Emulate = FALSE; | |
1124 | return (TRUE); | |
1125 | } | |
1126 | ||
1127 | default: | |
1128 | state->Emulate = FALSE; | |
1129 | return (FALSE); | |
c906108c SS |
1130 | } |
1131 | #endif | |
1132 | #endif | |
dfcd3bfb JM |
1133 | } |
1134 | ||
1135 | #endif /* CYGNUS LOCAL: #if 1 */ | |
c906108c SS |
1136 | |
1137 | #ifndef NOOS | |
1138 | #ifndef ASIM | |
1139 | ||
1140 | /***************************************************************************\ | |
1141 | * The emulator calls this routine when an Exception occurs. The second * | |
1142 | * parameter is the address of the relevant exception vector. Returning * | |
1143 | * FALSE from this routine causes the trap to be taken, TRUE causes it to * | |
1144 | * be ignored (so set state->Emulate to FALSE!). * | |
1145 | \***************************************************************************/ | |
1146 | ||
dfcd3bfb JM |
1147 | unsigned |
1148 | ARMul_OSException (ARMul_State * state, ARMword vector, ARMword pc) | |
1149 | { /* don't use this here */ | |
1150 | return (FALSE); | |
c906108c SS |
1151 | } |
1152 | ||
1153 | #endif | |
1154 | ||
1155 | /***************************************************************************\ | |
1156 | * Unwind a data abort * | |
1157 | \***************************************************************************/ | |
1158 | ||
dfcd3bfb JM |
1159 | static void |
1160 | UnwindDataAbort (ARMul_State * state, ARMword addr) | |
c906108c | 1161 | { |
dfcd3bfb JM |
1162 | ARMword instr = ARMul_ReadWord (state, addr); |
1163 | ARMword rn = BITS (16, 19); | |
1164 | ARMword itype = BITS (24, 27); | |
c906108c | 1165 | ARMword offset; |
dfcd3bfb JM |
1166 | if (rn == 15) |
1167 | return; | |
1168 | if (itype == 8 || itype == 9) | |
1169 | { | |
1170 | /* LDM or STM */ | |
1171 | unsigned long regs = BITS (0, 15); | |
1172 | offset = 0; | |
1173 | if (!BIT (21)) | |
1174 | return; /* no wb */ | |
1175 | for (; regs != 0; offset++) | |
1176 | regs ^= (regs & -regs); | |
1177 | if (offset == 0) | |
1178 | offset = 16; | |
1179 | } | |
1180 | else if (itype == 12 || /* post-indexed CPDT */ | |
1181 | (itype == 13 && BIT (21))) | |
1182 | { /* pre_indexed CPDT with WB */ | |
1183 | offset = BITS (0, 7); | |
1184 | } | |
1185 | else | |
c906108c SS |
1186 | return; |
1187 | ||
dfcd3bfb | 1188 | if (BIT (23)) |
c906108c SS |
1189 | state->Reg[rn] -= offset * 4; |
1190 | else | |
1191 | state->Reg[rn] += offset * 4; | |
1192 | } | |
1193 | ||
1194 | /***************************************************************************\ | |
1195 | * Copy a string from the debuggee's memory to the host's * | |
1196 | \***************************************************************************/ | |
1197 | ||
dfcd3bfb JM |
1198 | static void |
1199 | getstring (ARMul_State * state, ARMword from, char *to) | |
c906108c | 1200 | { |
dfcd3bfb | 1201 | do |
c906108c SS |
1202 | { |
1203 | *to = (char) ARMul_ReadByte (state, from++); | |
dfcd3bfb JM |
1204 | } |
1205 | while (*to++ != '\0'); | |
c906108c SS |
1206 | } |
1207 | ||
1208 | #endif /* NOOS */ |