]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/arm/armos.c
* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[thirdparty/binutils-gdb.git] / sim / arm / armos.c
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)?c:((c=='\n'||c=='\r')?(c ^ 7):c))
121 #else
122 #define FIXCRLF(t,c) c
123 #endif
124
125 static ARMword softvectorcode[] =
126 { /* basic: swi tidyexception + event; mov pc, lr;
127 ldmia r11,{r11,pc}; swi generateexception + event
128 */
129 0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /*Reset*/
130 0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /*Undef*/
131 0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /*SWI */
132 0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /*Prefetch abort*/
133 0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /*Data abort*/
134 0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /*Address exception*/
135 0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /*IRQ*/
136 0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /*FIQ*/
137 0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /*Error*/
138 0xe1a0f00e /* default handler */
139 };
140
141 /***************************************************************************\
142 * Time for the Operating System to initialise itself. *
143 \***************************************************************************/
144
145 unsigned ARMul_OSInit(ARMul_State *state)
146 {
147 #ifndef NOOS
148 #ifndef VALIDATE
149 ARMword instr, i , j ;
150 struct OSblock* OSptr = (struct OSblock*)state->OSptr;
151
152 if (state->OSptr == NULL) {
153 state->OSptr = (unsigned char *)malloc(sizeof(struct OSblock));
154 if (state->OSptr == NULL) {
155 perror("OS Memory");
156 exit(15);
157 }
158 }
159 OSptr = (struct OSblock*)state->OSptr;
160 OSptr->ErrorP = 0;
161 state->Reg[13] = ADDRSUPERSTACK; /* set up a stack for the current mode */
162 ARMul_SetReg(state,SVC32MODE,13,ADDRSUPERSTACK); /* and for supervisor mode */
163 ARMul_SetReg(state,ABORT32MODE,13,ADDRSUPERSTACK); /* and for abort 32 mode */
164 ARMul_SetReg(state,UNDEF32MODE,13,ADDRSUPERSTACK); /* and for undef 32 mode */
165 instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8); /* load pc from soft vector */
166 for (i = ARMul_ResetV ; i <= ARMFIQV ; i += 4)
167 ARMul_WriteWord(state, i, instr); /* write hardware vectors */
168 for (i = ARMul_ResetV ; i <= ARMFIQV + 4 ; i += 4) {
169 ARMul_WriteWord(state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
170 ARMul_WriteWord(state, ADDRSOFHANDLERS + 2*i + 4L, SOFTVECTORCODE + sizeof(softvectorcode) - 4L);
171 }
172 for (i = 0 ; i < sizeof(softvectorcode) ; i += 4)
173 ARMul_WriteWord(state, SOFTVECTORCODE + i, softvectorcode[i/4]);
174 for (i = 0 ; i < FOPEN_MAX ; i++)
175 OSptr->FileTable[i] = NULL ;
176 for (i = 0 ; i < UNIQUETEMPS ; i++)
177 OSptr->tempnames[i] = NULL ;
178 ARMul_ConsolePrint (state, ", Demon 1.01");
179
180 /* #ifndef ASIM */
181
182 /* install fpe */
183 for (i = 0 ; i < fpesize ; i+=4) /* copy the code */
184 ARMul_WriteWord(state,FPESTART + i,fpecode[i >> 2]) ;
185 for (i = FPESTART + fpesize ; ; i-=4) { /* reverse the error strings */
186 if ((j = ARMul_ReadWord(state,i)) == 0xffffffff)
187 break ;
188 if (state->bigendSig && j < 0x80000000) { /* it's part of the string so swap it */
189 j = ((j >> 0x18) & 0x000000ff) |
190 ((j >> 0x08) & 0x0000ff00) |
191 ((j << 0x08) & 0x00ff0000) |
192 ((j << 0x18) & 0xff000000) ;
193 ARMul_WriteWord(state,i,j) ;
194 }
195 }
196 ARMul_WriteWord(state,FPEOLDVECT,ARMul_ReadWord(state,4)) ; /* copy old illegal instr vector */
197 ARMul_WriteWord(state,4,FPENEWVECT(ARMul_ReadWord(state,i-4))) ; /* install new vector */
198 ARMul_ConsolePrint (state, ", FPE") ;
199
200 /* #endif /* ASIM */
201 #endif /* VALIDATE */
202 #endif /* NOOS */
203
204 return(TRUE) ;
205 }
206
207 void ARMul_OSExit(ARMul_State *state)
208 {
209 free((char *)state->OSptr) ;
210 }
211
212
213 /***************************************************************************\
214 * Return the last Operating System Error. *
215 \***************************************************************************/
216
217 ARMword ARMul_OSLastErrorP(ARMul_State *state)
218 {
219 return ((struct OSblock *)state->OSptr)->ErrorP;
220 }
221
222 /***************************************************************************\
223 * The emulator calls this routine when a SWI instruction is encuntered. The *
224 * parameter passed is the SWI number (lower 24 bits of the instruction). *
225 \***************************************************************************/
226
227 #if 1
228 /* This is the cygnus way of doing it, which makes it simple
229 to do our tests */
230
231
232 static int translate_open_mode[] =
233 {
234 O_RDONLY, /* "r" */
235 O_RDONLY+O_BINARY, /* "rb" */
236 O_RDWR, /* "r+" */
237 O_RDWR +O_BINARY, /* "r+b" */
238 O_WRONLY +O_CREAT+O_TRUNC, /* "w" */
239 O_WRONLY+O_BINARY+O_CREAT+O_TRUNC, /* "wb" */
240 O_RDWR +O_CREAT+O_TRUNC, /* "w+" */
241 O_RDWR +O_BINARY+O_CREAT+O_TRUNC, /* "w+b" */
242 O_WRONLY +O_APPEND+O_CREAT,/* "a" */
243 O_WRONLY+O_BINARY+O_APPEND+O_CREAT,/* "ab" */
244 O_RDWR +O_APPEND+O_CREAT,/* "a+" */
245 O_RDWR +O_BINARY+O_APPEND+O_CREAT /* "a+b" */
246 };
247
248 unsigned ARMul_OSHandleSWI(ARMul_State *state,ARMword number)
249 {
250 ARMword addr, temp, fildes ;
251 char buffer[BUFFERSIZE], *cptr ;
252 FILE *fptr ;
253 struct OSblock* OSptr = (struct OSblock*)state->OSptr ;
254
255 switch (number)
256 {
257 case SWI_Read:
258 {
259 int f = state->Reg[0];
260 int ptr = state->Reg[1];
261 int len = state->Reg[2];
262 int res;
263 int i;
264 char *local = malloc (len);
265 res = read (f,local, len);
266 if (res > 0)
267 for (i = 0; i < res; i++)
268 ARMul_WriteByte(state, ptr + i, local[i]) ;
269 free (local);
270 state->Reg[0] = res == -1 ? -1 : len - res;
271 OSptr->ErrorNo = errno;
272 return TRUE;
273 }
274
275 case SWI_Write:
276 {
277 int f = state->Reg[0];
278 int ptr = state->Reg[1];
279 int len = state->Reg[2];
280 int res;
281 int i;
282 char *local = malloc (len);
283
284 for (i = 0; i < len; i++)
285 {
286 local[i] = ARMul_ReadByte(state, ptr + i);
287 }
288 res = write (f, local, len);
289 state->Reg[0] = res == -1 ? -1 : len - res;
290 free (local);
291 OSptr->ErrorNo = errno;
292 return TRUE;
293 }
294
295 case SWI_Open:
296 {
297 char dummy[2000];
298 int i;
299 int flags;
300
301 for (i = 0;
302 dummy[i] = ARMul_ReadByte(state, state->Reg[0] + i);
303 i++)
304 ;
305
306 /* Now we need to decode the Demon open mode */
307 flags = translate_open_mode[state->Reg[1]];
308
309 /* Filename ":tt" is special: it denotes stdin/out */
310 if (strcmp (dummy, ":tt") == 0)
311 {
312 if (flags == O_RDONLY) /* opening tty "r" */
313 state->Reg[0] = 0 /* stdin */ ;
314 else
315 state->Reg[0] = 1 /* stdout */ ;
316 }
317 else
318 {
319 state->Reg[0] = (int) open (dummy, flags);
320 OSptr->ErrorNo = errno;
321 }
322
323 return TRUE;
324 }
325
326 case SWI_Clock :
327 /* return number of centi-seconds... */
328 state->Reg[0] =
329 #ifdef CLOCKS_PER_SEC
330 (CLOCKS_PER_SEC >= 100)
331 ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
332 : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
333 #else
334 /* presume unix... clock() returns microseconds */
335 (ARMword) (clock() / 10000) ;
336 #endif
337 OSptr->ErrorNo = errno ;
338 return(TRUE) ;
339
340 case SWI_Time :
341 state->Reg[0] = (ARMword)time(NULL) ;
342 OSptr->ErrorNo = errno ;
343 return(TRUE) ;
344
345 case SWI_Close:
346 state->Reg[0] = close (state->Reg[0]);
347 OSptr->ErrorNo = errno;
348 return TRUE;
349
350 case SWI_Flen :
351 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX)
352 {
353 OSptr->ErrorNo = EBADF ;
354 state->Reg[0] = -1L ;
355 return(TRUE) ;
356 }
357 fildes = state->Reg[0];
358 addr = lseek(fildes, 0, SEEK_CUR);
359 if (addr < 0)
360 state->Reg[0] = -1L ;
361 else
362 {
363 state->Reg[0] = lseek(fildes, 0L, SEEK_END);
364 (void)lseek(fildes, addr, SEEK_SET);
365 }
366 OSptr->ErrorNo = errno ;
367 return(TRUE) ;
368
369
370 case SWI_Exit:
371 state->Emulate = FALSE ;
372 return TRUE;
373
374 case SWI_Seek:
375 {
376 /* We must return non-zero for failure */
377 state->Reg[0] = -1 >= lseek (state->Reg[0],
378 state->Reg[1],
379 SEEK_SET);
380 OSptr->ErrorNo = errno;
381 return TRUE;
382 }
383
384 case SWI_WriteC :
385 (void)fputc((int)state->Reg[0],stderr) ;
386 OSptr->ErrorNo = errno ;
387 return(TRUE) ;
388
389 case SWI_Write0 :
390 addr = state->Reg[0] ;
391 while ((temp = ARMul_ReadByte(state,addr++)) != 0)
392 (void)fputc((char)temp,stderr) ;
393 OSptr->ErrorNo = errno ;
394 return(TRUE) ;
395
396 case SWI_GetErrno :
397 state->Reg[0] = OSptr->ErrorNo ;
398 return(TRUE) ;
399
400 case SWI_Breakpoint :
401 state->EndCondition = RDIError_BreakpointReached ;
402 state->Emulate = FALSE ;
403 return(TRUE) ;
404
405 case SWI_GetEnv :
406 state->Reg[0] = ADDRCMDLINE ;
407 if (state->MemSize)
408 state->Reg[1] = state->MemSize ;
409 else
410 state->Reg[1] = ADDRUSERSTACK ;
411
412 addr = state->Reg[0] ;
413 cptr = state->CommandLine ;
414 if (cptr == NULL)
415 cptr = "\0" ;
416 do {
417 temp = (ARMword)*cptr++ ;
418 ARMul_WriteByte(state,addr++,temp) ;
419 } while (temp != 0) ;
420 return(TRUE) ;
421
422 case AngelSWI_ARM:
423 case AngelSWI_Thumb:
424 /* Ignore these SWIs (for now). */
425 return TRUE;
426
427 default :
428 state->Emulate = FALSE ;
429 return(FALSE) ;
430 }
431 }
432 #else
433 unsigned ARMul_OSHandleSWI(ARMul_State *state,ARMword number)
434 {
435 #ifdef NOOS
436 return(FALSE) ;
437 #else
438 #ifdef VALIDATE
439 switch (number) {
440 case 0x11 :
441 state->Emulate = FALSE ;
442 return(TRUE) ;
443 case 0x01 :
444 if (ARM32BITMODE)
445 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ;
446 else
447 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ;
448 return(TRUE) ;
449 default :
450 return(FALSE) ;
451 }
452 #else
453 ARMword addr, temp ;
454 char buffer[BUFFERSIZE], *cptr ;
455 FILE *fptr ;
456 struct OSblock* OSptr = (struct OSblock*)state->OSptr ;
457
458 switch (number) {
459 case SWI_WriteC :
460 (void)fputc((int)state->Reg[0],stderr) ;
461 OSptr->ErrorNo = errno ;
462 return(TRUE) ;
463
464 case SWI_Write0 :
465 addr = state->Reg[0] ;
466 while ((temp = ARMul_ReadByte(state,addr++)) != 0)
467 fputc((char)temp,stderr) ;
468 OSptr->ErrorNo = errno ;
469 return(TRUE) ;
470
471 case SWI_ReadC :
472 state->Reg[0] = (ARMword)fgetc(stdin) ;
473 OSptr->ErrorNo = errno ;
474 return(TRUE) ;
475
476 case SWI_CLI :
477 addr = state->Reg[0] ;
478 getstring(state,state->Reg[0],buffer) ;
479 state->Reg[0] = (ARMword)system(buffer) ;
480 OSptr->ErrorNo = errno ;
481 return(TRUE) ;
482
483 case SWI_GetEnv :
484 state->Reg[0] = ADDRCMDLINE ;
485 if (state->MemSize)
486 state->Reg[1] = state->MemSize ;
487 else
488 state->Reg[1] = ADDRUSERSTACK ;
489
490 addr = state->Reg[0] ;
491 cptr = state->CommandLine ;
492 if (cptr == NULL)
493 cptr = "\0" ;
494 do {
495 temp = (ARMword)*cptr++ ;
496 ARMul_WriteByte(state,addr++,temp) ;
497 } while (temp != 0) ;
498 return(TRUE) ;
499
500 case SWI_Exit :
501 #ifdef ASIM
502 simkernel1_abort_run() ;
503 #else
504 state->Emulate = FALSE ;
505 #endif
506 return(TRUE) ;
507
508 case SWI_EnterOS :
509 if (ARM32BITMODE)
510 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ;
511 else
512 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ;
513 return(TRUE) ;
514
515 case SWI_GetErrno :
516 state->Reg[0] = OSptr->ErrorNo ;
517 return(TRUE) ;
518
519 case SWI_Clock :
520 /* return muber of centi-seconds... */
521 state->Reg[0] =
522 #ifdef CLOCKS_PER_SEC
523 (CLOCKS_PER_SEC >= 100)
524 ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
525 : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
526 #else
527 /* presume unix... clock() returns microseconds */
528 (ARMword) (clock() / 10000) ;
529 #endif
530 OSptr->ErrorNo = errno ;
531 return(TRUE) ;
532
533 case SWI_Time :
534 state->Reg[0] = (ARMword)time(NULL) ;
535 OSptr->ErrorNo = errno ;
536 return(TRUE) ;
537
538 case SWI_Remove :
539 getstring(state,state->Reg[0],buffer) ;
540 state->Reg[0] = unlink(buffer) ;
541 OSptr->ErrorNo = errno ;
542 return(TRUE) ;
543
544 case SWI_Rename : {
545 char buffer2[BUFFERSIZE] ;
546
547 getstring(state,state->Reg[0],buffer) ;
548 getstring(state,state->Reg[1],buffer2) ;
549 state->Reg[0] = rename(buffer,buffer2) ;
550 OSptr->ErrorNo = errno ;
551 return(TRUE) ;
552 }
553
554 case SWI_Open : {
555 #if 0
556 /* It seems to me that these are in the wrong order
557 sac@cygnus.com, so I've redone it to use the
558 flags instead, with the functionality which was already
559 there -- ahh, perhaps the TRUNC bit is in a different
560 place on the original host ?*/
561 static char* fmode[] = {"r","rb","r+","r+b",
562 "w","wb","w+","w+b",
563 "a","ab","a+","a+b",
564 "r","r","r","r"} /* last 4 are illegal */ ;
565 #endif
566
567 unsigned type ;
568
569 type = (unsigned)(state->Reg[1] & 3L) ;
570 getstring(state,state->Reg[0],buffer) ;
571 if (strcmp(buffer,":tt")==0 && (type == O_RDONLY )) /* opening tty "r" */
572 fptr = stdin ;
573 else if (strcmp(buffer,":tt")==0 && (type == O_WRONLY)) /* opening tty "w" */
574 fptr = stderr ;
575 else
576 {
577 switch (type)
578 {
579 case O_RDONLY:
580 fptr = fopen(buffer,"r") ;
581 break;
582 case O_WRONLY:
583 fptr = fopen(buffer,"w") ;
584 break;
585 case O_RDWR:
586 fptr = fopen(buffer,"rw") ;
587 break;
588 }
589 }
590
591 state->Reg[0] = 0 ;
592 if (fptr != NULL) {
593 for (temp = 0 ; temp < FOPEN_MAX ; temp++)
594 if (OSptr->FileTable[temp] == NULL) {
595 OSptr->FileTable[temp] = fptr ;
596 OSptr->FileFlags[temp] = type & 1 ; /* preserve the binary bit */
597 state->Reg[0] = (ARMword)(temp + 1) ;
598 break ;
599 }
600 if (state->Reg[0] == 0)
601 OSptr->ErrorNo = EMFILE ; /* too many open files */
602 else
603 OSptr->ErrorNo = errno ;
604 }
605 else
606 OSptr->ErrorNo = errno ;
607 return(TRUE) ;
608 }
609
610 case SWI_Close :
611 temp = state->Reg[0] ;
612 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
613 OSptr->ErrorNo = EBADF ;
614 state->Reg[0] = -1L ;
615 return(TRUE) ;
616 }
617 temp-- ;
618 fptr = OSptr->FileTable[temp] ;
619 if (fptr == stdin || fptr == stderr)
620 state->Reg[0] = 0 ;
621 else
622 state->Reg[0] = fclose(fptr) ;
623 OSptr->FileTable[temp] = NULL ;
624 OSptr->ErrorNo = errno ;
625 return(TRUE) ;
626
627 case SWI_Write : {
628 unsigned size, upto, type ;
629 char ch ;
630
631 temp = state->Reg[0] ;
632 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
633 OSptr->ErrorNo = EBADF ;
634 state->Reg[0] = -1L ;
635 return(TRUE) ;
636 }
637 temp-- ;
638 fptr = OSptr->FileTable[temp] ;
639 type = OSptr->FileFlags[temp] ;
640 addr = state->Reg[1] ;
641 size = (unsigned)state->Reg[2] ;
642
643 if (type & READOP)
644 fseek(fptr,0L,SEEK_CUR) ;
645 OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP ; ;
646 while (size > 0) {
647 if (size >= BUFFERSIZE)
648 upto = BUFFERSIZE ;
649 else
650 upto = size ;
651 for (cptr = buffer ; (cptr - buffer) < upto ; cptr++) {
652 ch = (char)ARMul_ReadByte(state,(ARMword)addr++) ;
653 *cptr = FIXCRLF(type,ch) ;
654 }
655 temp = fwrite(buffer,1,upto,fptr) ;
656 if (temp < upto) {
657 state->Reg[0] = (ARMword)(size - temp) ;
658 OSptr->ErrorNo = errno ;
659 return(TRUE) ;
660 }
661 size -= upto ;
662 }
663 state->Reg[0] = 0 ;
664 OSptr->ErrorNo = errno ;
665 return(TRUE) ;
666 }
667
668 case SWI_Read : {
669 unsigned size, upto, type ;
670 char ch ;
671
672 temp = state->Reg[0] ;
673 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
674 OSptr->ErrorNo = EBADF ;
675 state->Reg[0] = -1L ;
676 return(TRUE) ;
677 }
678 temp-- ;
679 fptr = OSptr->FileTable[temp] ;
680 addr = state->Reg[1] ;
681 size = (unsigned)state->Reg[2] ;
682 type = OSptr->FileFlags[temp] ;
683
684 if (type & WRITEOP)
685 fseek(fptr,0L,SEEK_CUR) ;
686 OSptr->FileFlags[temp] = (type & BINARY) | READOP ; ;
687 while (size > 0) {
688 if (isatty_(fptr)) {
689 upto = (size >= BUFFERSIZE)?BUFFERSIZE:size + 1 ;
690 if (fgets(buffer, upto, fptr) != 0)
691 temp = strlen(buffer) ;
692 else
693 temp = 0 ;
694 upto-- ; /* 1 char used for terminating null */
695 }
696 else {
697 upto = (size>=BUFFERSIZE)?BUFFERSIZE:size ;
698 temp = fread(buffer,1,upto,fptr) ;
699 }
700 for (cptr = buffer ; (cptr - buffer) < temp ; cptr++) {
701 ch = *cptr ;
702 ARMul_WriteByte(state,(ARMword)addr++,FIXCRLF(type,ch)) ;
703 }
704 if (temp < upto) {
705 state->Reg[0] = (ARMword)(size - temp) ;
706 OSptr->ErrorNo = errno ;
707 return(TRUE) ;
708 }
709 size -= upto ;
710 }
711 state->Reg[0] = 0 ;
712 OSptr->ErrorNo = errno ;
713 return(TRUE) ;
714 }
715
716 case SWI_Seek :
717 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
718 || OSptr->FileTable[state->Reg[0] - 1] == 0) {
719 OSptr->ErrorNo = EBADF ;
720 state->Reg[0] = -1L ;
721 return(TRUE) ;
722 }
723 fptr = OSptr->FileTable[state->Reg[0] - 1] ;
724 state->Reg[0] = fseek(fptr,(long)state->Reg[1],SEEK_SET) ;
725 OSptr->ErrorNo = errno ;
726 return(TRUE) ;
727
728 case SWI_Flen :
729 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
730 || OSptr->FileTable[state->Reg[0] - 1] == 0) {
731 OSptr->ErrorNo = EBADF ;
732 state->Reg[0] = -1L ;
733 return(TRUE) ;
734 }
735 fptr = OSptr->FileTable[state->Reg[0] - 1] ;
736 addr = (ARMword)ftell(fptr) ;
737 if (fseek(fptr,0L,SEEK_END) < 0)
738 state->Reg[0] = -1 ;
739 else {
740 state->Reg[0] = (ARMword)ftell(fptr) ;
741 (void)fseek(fptr,addr,SEEK_SET) ;
742 }
743 OSptr->ErrorNo = errno ;
744 return(TRUE) ;
745
746 case SWI_IsTTY :
747 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
748 || OSptr->FileTable[state->Reg[0] - 1] == 0) {
749 OSptr->ErrorNo = EBADF ;
750 state->Reg[0] = -1L ;
751 return(TRUE) ;
752 }
753 fptr = OSptr->FileTable[state->Reg[0] - 1] ;
754 state->Reg[0] = isatty_(fptr) ;
755 OSptr->ErrorNo = errno ;
756 return(TRUE) ;
757
758 case SWI_TmpNam :{
759 ARMword size ;
760
761 addr = state->Reg[0] ;
762 temp = state->Reg[1] & 0xff ;
763 size = state->Reg[2] ;
764 if (OSptr->tempnames[temp] == NULL) {
765 if ((OSptr->tempnames[temp] = malloc(L_tmpnam)) == NULL) {
766 state->Reg[0] = 0 ;
767 return(TRUE) ;
768 }
769 (void)tmpnam(OSptr->tempnames[temp]) ;
770 }
771 cptr = OSptr->tempnames[temp] ;
772 if (strlen(cptr) > state->Reg[2])
773 state->Reg[0] = 0 ;
774 else
775 do {
776 ARMul_WriteByte(state,addr++,*cptr) ;
777 } while (*cptr++ != 0) ;
778 OSptr->ErrorNo = errno ;
779 return(TRUE) ;
780 }
781
782 case SWI_InstallHandler:
783 { ARMword handlerp = ADDRSOFHANDLERS + state->Reg[0] * 8;
784 ARMword oldr1 = ARMul_ReadWord(state, handlerp),
785 oldr2 = ARMul_ReadWord(state, handlerp + 4);
786 ARMul_WriteWord(state, handlerp, state->Reg[1]);
787 ARMul_WriteWord(state, handlerp + 4, state->Reg[2]);
788 state->Reg[1] = oldr1;
789 state->Reg[2] = oldr2;
790 return(TRUE);
791 }
792
793 case SWI_GenerateError:
794 ARMul_Abort(state, ARMSWIV) ;
795 if (state->Emulate)
796 ARMul_SetR15(state, ARMul_ReadWord(state, ADDRSOFTVECTORS + ARMErrorV));
797 return(TRUE);
798
799 /* SWI's 0x9x unwind the state of the CPU after an abort of type x */
800
801 case 0x90: /* Branch through zero */
802 { ARMword oldpsr = ARMul_GetCPSR(state) ;
803 ARMul_SetCPSR(state, (oldpsr & 0xffffffc0) | 0x13) ;
804 ARMul_SetSPSR(state, SVC32MODE, oldpsr) ;
805 state->Reg[14] = 0;
806 goto TidyCommon;
807 }
808
809 case 0x98: /* Error */
810 { ARMword errorp = state->Reg[0],
811 regp = state->Reg[1];
812 unsigned i;
813 ARMword errorpsr = ARMul_ReadWord(state, regp + 16*4);
814 for (i = 0; i < 15; i++)
815 ARMul_SetReg(state,errorpsr,i,ARMul_ReadWord(state, regp + i*4L)) ;
816 state->Reg[14] = ARMul_ReadWord(state, regp + 15*4L);
817 state->Reg[10] = errorp;
818 ARMul_SetSPSR(state,state->Mode,errorpsr) ;
819 OSptr->ErrorP = errorp;
820 goto TidyCommon;
821 }
822
823 case 0x94: /* Data abort */
824 { ARMword addr = state->Reg[14] - 8;
825 ARMword cpsr = ARMul_GetCPSR(state) ;
826 if (ARM26BITMODE)
827 addr = addr & 0x3fffffc ;
828 ARMul_SetCPSR(state,ARMul_GetSPSR(state,cpsr)) ;
829 UnwindDataAbort(state, addr);
830 if (addr >= FPESTART && addr < FPEEND) { /* in the FPE */
831 ARMword sp, spsr ;
832 unsigned i ;
833
834 sp = state->Reg[13] ;
835 state->Reg[13] += 64 ; /* fix the aborting mode sp */
836 state->Reg[14] = ARMul_ReadWord(state,sp + 60) ; /* and its lr */
837 spsr = ARMul_GetSPSR(state,state->Mode) ;
838 state->Mode = ARMul_SwitchMode(state, state->Mode, spsr);
839 for (i = 0 ; i < 15 ; i++) {
840 ARMul_SetReg(state,spsr,i,ARMul_ReadWord(state,sp)) ;
841 sp += 4 ;
842 }
843 ARMul_SetCPSR(state,cpsr) ;
844 state->Reg[14] = ARMul_ReadWord(state,sp) + 4 ; /* botch it */
845 ARMul_SetSPSR(state,state->Mode,spsr) ;
846 }
847 else
848 ARMul_SetCPSR(state,cpsr) ;
849
850 /* and fall through to correct r14 */
851 }
852 case 0x95: /* Address Exception */
853 state->Reg[14] -= 4;
854 case 0x91: /* Undefined instruction */
855 case 0x92: /* SWI */
856 case 0x93: /* Prefetch abort */
857 case 0x96: /* IRQ */
858 case 0x97: /* FIQ */
859 state->Reg[14] -= 4;
860 TidyCommon:
861 if (state->VectorCatch & (1 << (number - 0x90))) {
862 ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
863 ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ;
864 if (number == 0x90)
865 state->EndCondition = 10 ; /* Branch through Zero Error */
866 else
867 state->EndCondition = (unsigned)number - 0x8f;
868 state->Emulate = FALSE ;
869 }
870 else {
871 ARMword sp = state->Reg[13];
872 ARMul_WriteWord(state, sp - 4, state->Reg[14]);
873 ARMul_WriteWord(state, sp - 8, state->Reg[12]);
874 ARMul_WriteWord(state, sp - 12, state->Reg[11]);
875 ARMul_WriteWord(state, sp - 16, state->Reg[10]);
876 state->Reg[13] = sp - 16;
877 state->Reg[11] = ADDRSOFHANDLERS + 8 * (number - 0x90);
878 }
879 return(TRUE);
880
881 /* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */
882
883 case 0x80: case 0x81: case 0x82: case 0x83:
884 case 0x84: case 0x85: case 0x86: case 0x87: case 0x88:
885 { ARMword sp = state->Reg[13];
886 state->Reg[10] = ARMul_ReadWord(state, sp);
887 state->Reg[11] = ARMul_ReadWord(state, sp + 4);
888 state->Reg[12] = ARMul_ReadWord(state, sp + 8);
889 state->Reg[14] = ARMul_ReadWord(state, sp + 12);
890 state->Reg[13] = sp + 16;
891 ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
892 ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ;
893 if (number == 0x80)
894 state->EndCondition = 10 ; /* Branch through Zero Error */
895 else
896 state->EndCondition = (unsigned)number - 0x7f;
897 state->Emulate = FALSE ;
898 return(TRUE);
899 }
900
901 default :
902 state->Emulate = FALSE ;
903 return(FALSE) ;
904 }
905 #endif
906 #endif
907 }
908 #endif
909
910 #ifndef NOOS
911 #ifndef ASIM
912
913 /***************************************************************************\
914 * The emulator calls this routine when an Exception occurs. The second *
915 * parameter is the address of the relevant exception vector. Returning *
916 * FALSE from this routine causes the trap to be taken, TRUE causes it to *
917 * be ignored (so set state->Emulate to FALSE!). *
918 \***************************************************************************/
919
920 unsigned ARMul_OSException(ARMul_State *state, ARMword vector, ARMword pc)
921 { /* don't use this here */
922 return(FALSE) ;
923 }
924
925 #endif
926
927 /***************************************************************************\
928 * Unwind a data abort *
929 \***************************************************************************/
930
931 static void UnwindDataAbort(ARMul_State *state, ARMword addr)
932 {
933 ARMword instr = ARMul_ReadWord(state, addr);
934 ARMword rn = BITS(16, 19);
935 ARMword itype = BITS(24, 27);
936 ARMword offset;
937 if (rn == 15) return;
938 if (itype == 8 || itype == 9) {
939 /* LDM or STM */
940 unsigned long regs = BITS(0, 15);
941 offset = 0;
942 if (!BIT(21)) return; /* no wb */
943 for (; regs != 0; offset++)
944 regs ^= (regs & -regs);
945 if (offset == 0) offset = 16;
946 } else if (itype == 12 || /* post-indexed CPDT */
947 (itype == 13 && BIT(21))) { /* pre_indexed CPDT with WB */
948 offset = BITS(0, 7);
949 } else
950 return;
951
952 if (BIT(23))
953 state->Reg[rn] -= offset * 4;
954 else
955 state->Reg[rn] += offset * 4;
956 }
957
958 /***************************************************************************\
959 * Copy a string from the debuggee's memory to the host's *
960 \***************************************************************************/
961
962 static void getstring(ARMul_State *state, ARMword from, char *to)
963 {do {
964 *to = (char)ARMul_ReadByte(state,from++) ;
965 } while (*to++ != '\0') ;
966 }
967
968 #endif /* NOOS */