4eb672de16dcfd621cf9939edda5d148207254e9
[deliverable/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 for (i = 0;
300 dummy[i] = ARMul_ReadByte(state, state->Reg[0] + i);
301 i++)
302 ;
303
304 /* Now we need to decode the Demon open mode */
305 flags = translate_open_mode[state->Reg[1]];
306
307 /* Filename ":tt" is special: it denotes stdin/out */
308 if (strcmp (dummy, ":tt") == 0)
309 {
310 if (flags == O_RDONLY) /* opening tty "r" */
311 state->Reg[0] = 0 /* stdin */ ;
312 else
313 state->Reg[0] = 1 /* stdout */ ;
314 }
315 else
316 {
317 state->Reg[0] = (int) open (dummy, flags);
318 OSptr->ErrorNo = errno;
319 }
320
321 return TRUE;
322 }
323
324 case SWI_Clock :
325 /* return number of centi-seconds... */
326 state->Reg[0] =
327 #ifdef CLOCKS_PER_SEC
328 (CLOCKS_PER_SEC >= 100)
329 ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
330 : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
331 #else
332 /* presume unix... clock() returns microseconds */
333 (ARMword) (clock() / 10000) ;
334 #endif
335 OSptr->ErrorNo = errno ;
336 return(TRUE) ;
337
338 case SWI_Time :
339 state->Reg[0] = (ARMword)time(NULL) ;
340 OSptr->ErrorNo = errno ;
341 return(TRUE) ;
342
343 case SWI_Close:
344 state->Reg[0] = close (state->Reg[0]);
345 OSptr->ErrorNo = errno;
346 return TRUE;
347
348 case SWI_Flen :
349 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX)
350 {
351 OSptr->ErrorNo = EBADF ;
352 state->Reg[0] = -1L ;
353 return(TRUE) ;
354 }
355 fildes = state->Reg[0];
356 addr = lseek(fildes, 0, SEEK_CUR);
357 if (addr < 0)
358 state->Reg[0] = -1L ;
359 else
360 {
361 state->Reg[0] = lseek(fildes, 0L, SEEK_END);
362 (void)lseek(fildes, addr, SEEK_SET);
363 }
364 OSptr->ErrorNo = errno ;
365 return(TRUE) ;
366
367
368 case SWI_Exit:
369 state->Emulate = FALSE ;
370 return TRUE;
371
372 case SWI_Seek:
373 {
374 /* We must return non-zero for failure */
375 state->Reg[0] = -1 >= lseek (state->Reg[0],
376 state->Reg[1],
377 SEEK_SET);
378 OSptr->ErrorNo = errno;
379 return TRUE;
380 }
381
382 case SWI_WriteC :
383 (void)fputc((int)state->Reg[0],stderr) ;
384 OSptr->ErrorNo = errno ;
385 return(TRUE) ;
386
387 case SWI_Write0 :
388 addr = state->Reg[0] ;
389 while ((temp = ARMul_ReadByte(state,addr++)) != 0)
390 (void)fputc((char)temp,stderr) ;
391 OSptr->ErrorNo = errno ;
392 return(TRUE) ;
393
394 case SWI_GetErrno :
395 state->Reg[0] = OSptr->ErrorNo ;
396 return(TRUE) ;
397
398 case SWI_Breakpoint :
399 state->EndCondition = RDIError_BreakpointReached ;
400 state->Emulate = FALSE ;
401 return(TRUE) ;
402
403 case SWI_GetEnv :
404 state->Reg[0] = ADDRCMDLINE ;
405 if (state->MemSize)
406 state->Reg[1] = state->MemSize ;
407 else
408 state->Reg[1] = ADDRUSERSTACK ;
409
410 addr = state->Reg[0] ;
411 cptr = state->CommandLine ;
412 if (cptr == NULL)
413 cptr = "\0" ;
414 do {
415 temp = (ARMword)*cptr++ ;
416 ARMul_WriteByte(state,addr++,temp) ;
417 } while (temp != 0) ;
418 return(TRUE) ;
419
420 default :
421 state->Emulate = FALSE ;
422 return(FALSE) ;
423 }
424 }
425 #else
426 unsigned ARMul_OSHandleSWI(ARMul_State *state,ARMword number)
427 {
428 #ifdef NOOS
429 return(FALSE) ;
430 #else
431 #ifdef VALIDATE
432 switch (number) {
433 case 0x11 :
434 state->Emulate = FALSE ;
435 return(TRUE) ;
436 case 0x01 :
437 if (ARM32BITMODE)
438 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ;
439 else
440 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ;
441 return(TRUE) ;
442 default :
443 return(FALSE) ;
444 }
445 #else
446 ARMword addr, temp ;
447 char buffer[BUFFERSIZE], *cptr ;
448 FILE *fptr ;
449 struct OSblock* OSptr = (struct OSblock*)state->OSptr ;
450
451 switch (number) {
452 case SWI_WriteC :
453 (void)fputc((int)state->Reg[0],stderr) ;
454 OSptr->ErrorNo = errno ;
455 return(TRUE) ;
456
457 case SWI_Write0 :
458 addr = state->Reg[0] ;
459 while ((temp = ARMul_ReadByte(state,addr++)) != 0)
460 fputc((char)temp,stderr) ;
461 OSptr->ErrorNo = errno ;
462 return(TRUE) ;
463
464 case SWI_ReadC :
465 state->Reg[0] = (ARMword)fgetc(stdin) ;
466 OSptr->ErrorNo = errno ;
467 return(TRUE) ;
468
469 case SWI_CLI :
470 addr = state->Reg[0] ;
471 getstring(state,state->Reg[0],buffer) ;
472 state->Reg[0] = (ARMword)system(buffer) ;
473 OSptr->ErrorNo = errno ;
474 return(TRUE) ;
475
476 case SWI_GetEnv :
477 state->Reg[0] = ADDRCMDLINE ;
478 if (state->MemSize)
479 state->Reg[1] = state->MemSize ;
480 else
481 state->Reg[1] = ADDRUSERSTACK ;
482
483 addr = state->Reg[0] ;
484 cptr = state->CommandLine ;
485 if (cptr == NULL)
486 cptr = "\0" ;
487 do {
488 temp = (ARMword)*cptr++ ;
489 ARMul_WriteByte(state,addr++,temp) ;
490 } while (temp != 0) ;
491 return(TRUE) ;
492
493 case SWI_Exit :
494 #ifdef ASIM
495 simkernel1_abort_run() ;
496 #else
497 state->Emulate = FALSE ;
498 #endif
499 return(TRUE) ;
500
501 case SWI_EnterOS :
502 if (ARM32BITMODE)
503 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x13) ;
504 else
505 ARMul_SetCPSR(state, (ARMul_GetCPSR(state) & 0xffffffc0) | 0x3) ;
506 return(TRUE) ;
507
508 case SWI_GetErrno :
509 state->Reg[0] = OSptr->ErrorNo ;
510 return(TRUE) ;
511
512 case SWI_Clock :
513 /* return muber of centi-seconds... */
514 state->Reg[0] =
515 #ifdef CLOCKS_PER_SEC
516 (CLOCKS_PER_SEC >= 100)
517 ? (ARMword) (clock() / (CLOCKS_PER_SEC / 100))
518 : (ARMword) ((clock() * 100) / CLOCKS_PER_SEC) ;
519 #else
520 /* presume unix... clock() returns microseconds */
521 (ARMword) (clock() / 10000) ;
522 #endif
523 OSptr->ErrorNo = errno ;
524 return(TRUE) ;
525
526 case SWI_Time :
527 state->Reg[0] = (ARMword)time(NULL) ;
528 OSptr->ErrorNo = errno ;
529 return(TRUE) ;
530
531 case SWI_Remove :
532 getstring(state,state->Reg[0],buffer) ;
533 state->Reg[0] = unlink(buffer) ;
534 OSptr->ErrorNo = errno ;
535 return(TRUE) ;
536
537 case SWI_Rename : {
538 char buffer2[BUFFERSIZE] ;
539
540 getstring(state,state->Reg[0],buffer) ;
541 getstring(state,state->Reg[1],buffer2) ;
542 state->Reg[0] = rename(buffer,buffer2) ;
543 OSptr->ErrorNo = errno ;
544 return(TRUE) ;
545 }
546
547 case SWI_Open : {
548 #if 0
549 /* It seems to me that these are in the wrong order
550 sac@cygnus.com, so I've redone it to use the
551 flags instead, with the functionality which was already
552 there -- ahh, perhaps the TRUNC bit is in a different
553 place on the original host ?*/
554 static char* fmode[] = {"r","rb","r+","r+b",
555 "w","wb","w+","w+b",
556 "a","ab","a+","a+b",
557 "r","r","r","r"} /* last 4 are illegal */ ;
558 #endif
559
560 unsigned type ;
561
562 type = (unsigned)(state->Reg[1] & 3L) ;
563 getstring(state,state->Reg[0],buffer) ;
564 if (strcmp(buffer,":tt")==0 && (type == O_RDONLY )) /* opening tty "r" */
565 fptr = stdin ;
566 else if (strcmp(buffer,":tt")==0 && (type == O_WRONLY)) /* opening tty "w" */
567 fptr = stderr ;
568 else
569 {
570 switch (type)
571 {
572 case O_RDONLY:
573 fptr = fopen(buffer,"r") ;
574 break;
575 case O_WRONLY:
576 fptr = fopen(buffer,"w") ;
577 break;
578 case O_RDWR:
579 fptr = fopen(buffer,"rw") ;
580 break;
581 }
582 }
583
584 state->Reg[0] = 0 ;
585 if (fptr != NULL) {
586 for (temp = 0 ; temp < FOPEN_MAX ; temp++)
587 if (OSptr->FileTable[temp] == NULL) {
588 OSptr->FileTable[temp] = fptr ;
589 OSptr->FileFlags[temp] = type & 1 ; /* preserve the binary bit */
590 state->Reg[0] = (ARMword)(temp + 1) ;
591 break ;
592 }
593 if (state->Reg[0] == 0)
594 OSptr->ErrorNo = EMFILE ; /* too many open files */
595 else
596 OSptr->ErrorNo = errno ;
597 }
598 else
599 OSptr->ErrorNo = errno ;
600 return(TRUE) ;
601 }
602
603 case SWI_Close :
604 temp = state->Reg[0] ;
605 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
606 OSptr->ErrorNo = EBADF ;
607 state->Reg[0] = -1L ;
608 return(TRUE) ;
609 }
610 temp-- ;
611 fptr = OSptr->FileTable[temp] ;
612 if (fptr == stdin || fptr == stderr)
613 state->Reg[0] = 0 ;
614 else
615 state->Reg[0] = fclose(fptr) ;
616 OSptr->FileTable[temp] = NULL ;
617 OSptr->ErrorNo = errno ;
618 return(TRUE) ;
619
620 case SWI_Write : {
621 unsigned size, upto, type ;
622 char ch ;
623
624 temp = state->Reg[0] ;
625 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
626 OSptr->ErrorNo = EBADF ;
627 state->Reg[0] = -1L ;
628 return(TRUE) ;
629 }
630 temp-- ;
631 fptr = OSptr->FileTable[temp] ;
632 type = OSptr->FileFlags[temp] ;
633 addr = state->Reg[1] ;
634 size = (unsigned)state->Reg[2] ;
635
636 if (type & READOP)
637 fseek(fptr,0L,SEEK_CUR) ;
638 OSptr->FileFlags[temp] = (type & BINARY) | WRITEOP ; ;
639 while (size > 0) {
640 if (size >= BUFFERSIZE)
641 upto = BUFFERSIZE ;
642 else
643 upto = size ;
644 for (cptr = buffer ; (cptr - buffer) < upto ; cptr++) {
645 ch = (char)ARMul_ReadByte(state,(ARMword)addr++) ;
646 *cptr = FIXCRLF(type,ch) ;
647 }
648 temp = fwrite(buffer,1,upto,fptr) ;
649 if (temp < upto) {
650 state->Reg[0] = (ARMword)(size - temp) ;
651 OSptr->ErrorNo = errno ;
652 return(TRUE) ;
653 }
654 size -= upto ;
655 }
656 state->Reg[0] = 0 ;
657 OSptr->ErrorNo = errno ;
658 return(TRUE) ;
659 }
660
661 case SWI_Read : {
662 unsigned size, upto, type ;
663 char ch ;
664
665 temp = state->Reg[0] ;
666 if (temp == 0 || temp > FOPEN_MAX || OSptr->FileTable[temp - 1] == 0) {
667 OSptr->ErrorNo = EBADF ;
668 state->Reg[0] = -1L ;
669 return(TRUE) ;
670 }
671 temp-- ;
672 fptr = OSptr->FileTable[temp] ;
673 addr = state->Reg[1] ;
674 size = (unsigned)state->Reg[2] ;
675 type = OSptr->FileFlags[temp] ;
676
677 if (type & WRITEOP)
678 fseek(fptr,0L,SEEK_CUR) ;
679 OSptr->FileFlags[temp] = (type & BINARY) | READOP ; ;
680 while (size > 0) {
681 if (isatty_(fptr)) {
682 upto = (size >= BUFFERSIZE)?BUFFERSIZE:size + 1 ;
683 if (fgets(buffer, upto, fptr) != 0)
684 temp = strlen(buffer) ;
685 else
686 temp = 0 ;
687 upto-- ; /* 1 char used for terminating null */
688 }
689 else {
690 upto = (size>=BUFFERSIZE)?BUFFERSIZE:size ;
691 temp = fread(buffer,1,upto,fptr) ;
692 }
693 for (cptr = buffer ; (cptr - buffer) < temp ; cptr++) {
694 ch = *cptr ;
695 ARMul_WriteByte(state,(ARMword)addr++,FIXCRLF(type,ch)) ;
696 }
697 if (temp < upto) {
698 state->Reg[0] = (ARMword)(size - temp) ;
699 OSptr->ErrorNo = errno ;
700 return(TRUE) ;
701 }
702 size -= upto ;
703 }
704 state->Reg[0] = 0 ;
705 OSptr->ErrorNo = errno ;
706 return(TRUE) ;
707 }
708
709 case SWI_Seek :
710 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
711 || OSptr->FileTable[state->Reg[0] - 1] == 0) {
712 OSptr->ErrorNo = EBADF ;
713 state->Reg[0] = -1L ;
714 return(TRUE) ;
715 }
716 fptr = OSptr->FileTable[state->Reg[0] - 1] ;
717 state->Reg[0] = fseek(fptr,(long)state->Reg[1],SEEK_SET) ;
718 OSptr->ErrorNo = errno ;
719 return(TRUE) ;
720
721 case SWI_Flen :
722 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
723 || OSptr->FileTable[state->Reg[0] - 1] == 0) {
724 OSptr->ErrorNo = EBADF ;
725 state->Reg[0] = -1L ;
726 return(TRUE) ;
727 }
728 fptr = OSptr->FileTable[state->Reg[0] - 1] ;
729 addr = (ARMword)ftell(fptr) ;
730 if (fseek(fptr,0L,SEEK_END) < 0)
731 state->Reg[0] = -1 ;
732 else {
733 state->Reg[0] = (ARMword)ftell(fptr) ;
734 (void)fseek(fptr,addr,SEEK_SET) ;
735 }
736 OSptr->ErrorNo = errno ;
737 return(TRUE) ;
738
739 case SWI_IsTTY :
740 if (state->Reg[0] == 0 || state->Reg[0] > FOPEN_MAX
741 || OSptr->FileTable[state->Reg[0] - 1] == 0) {
742 OSptr->ErrorNo = EBADF ;
743 state->Reg[0] = -1L ;
744 return(TRUE) ;
745 }
746 fptr = OSptr->FileTable[state->Reg[0] - 1] ;
747 state->Reg[0] = isatty_(fptr) ;
748 OSptr->ErrorNo = errno ;
749 return(TRUE) ;
750
751 case SWI_TmpNam :{
752 ARMword size ;
753
754 addr = state->Reg[0] ;
755 temp = state->Reg[1] & 0xff ;
756 size = state->Reg[2] ;
757 if (OSptr->tempnames[temp] == NULL) {
758 if ((OSptr->tempnames[temp] = malloc(L_tmpnam)) == NULL) {
759 state->Reg[0] = 0 ;
760 return(TRUE) ;
761 }
762 (void)tmpnam(OSptr->tempnames[temp]) ;
763 }
764 cptr = OSptr->tempnames[temp] ;
765 if (strlen(cptr) > state->Reg[2])
766 state->Reg[0] = 0 ;
767 else
768 do {
769 ARMul_WriteByte(state,addr++,*cptr) ;
770 } while (*cptr++ != 0) ;
771 OSptr->ErrorNo = errno ;
772 return(TRUE) ;
773 }
774
775 case SWI_InstallHandler:
776 { ARMword handlerp = ADDRSOFHANDLERS + state->Reg[0] * 8;
777 ARMword oldr1 = ARMul_ReadWord(state, handlerp),
778 oldr2 = ARMul_ReadWord(state, handlerp + 4);
779 ARMul_WriteWord(state, handlerp, state->Reg[1]);
780 ARMul_WriteWord(state, handlerp + 4, state->Reg[2]);
781 state->Reg[1] = oldr1;
782 state->Reg[2] = oldr2;
783 return(TRUE);
784 }
785
786 case SWI_GenerateError:
787 ARMul_Abort(state, ARMSWIV) ;
788 if (state->Emulate)
789 ARMul_SetR15(state, ARMul_ReadWord(state, ADDRSOFTVECTORS + ARMErrorV));
790 return(TRUE);
791
792 /* SWI's 0x9x unwind the state of the CPU after an abort of type x */
793
794 case 0x90: /* Branch through zero */
795 { ARMword oldpsr = ARMul_GetCPSR(state) ;
796 ARMul_SetCPSR(state, (oldpsr & 0xffffffc0) | 0x13) ;
797 ARMul_SetSPSR(state, SVC32MODE, oldpsr) ;
798 state->Reg[14] = 0;
799 goto TidyCommon;
800 }
801
802 case 0x98: /* Error */
803 { ARMword errorp = state->Reg[0],
804 regp = state->Reg[1];
805 unsigned i;
806 ARMword errorpsr = ARMul_ReadWord(state, regp + 16*4);
807 for (i = 0; i < 15; i++)
808 ARMul_SetReg(state,errorpsr,i,ARMul_ReadWord(state, regp + i*4L)) ;
809 state->Reg[14] = ARMul_ReadWord(state, regp + 15*4L);
810 state->Reg[10] = errorp;
811 ARMul_SetSPSR(state,state->Mode,errorpsr) ;
812 OSptr->ErrorP = errorp;
813 goto TidyCommon;
814 }
815
816 case 0x94: /* Data abort */
817 { ARMword addr = state->Reg[14] - 8;
818 ARMword cpsr = ARMul_GetCPSR(state) ;
819 if (ARM26BITMODE)
820 addr = addr & 0x3fffffc ;
821 ARMul_SetCPSR(state,ARMul_GetSPSR(state,cpsr)) ;
822 UnwindDataAbort(state, addr);
823 if (addr >= FPESTART && addr < FPEEND) { /* in the FPE */
824 ARMword sp, spsr ;
825 unsigned i ;
826
827 sp = state->Reg[13] ;
828 state->Reg[13] += 64 ; /* fix the aborting mode sp */
829 state->Reg[14] = ARMul_ReadWord(state,sp + 60) ; /* and its lr */
830 spsr = ARMul_GetSPSR(state,state->Mode) ;
831 state->Mode = ARMul_SwitchMode(state, state->Mode, spsr);
832 for (i = 0 ; i < 15 ; i++) {
833 ARMul_SetReg(state,spsr,i,ARMul_ReadWord(state,sp)) ;
834 sp += 4 ;
835 }
836 ARMul_SetCPSR(state,cpsr) ;
837 state->Reg[14] = ARMul_ReadWord(state,sp) + 4 ; /* botch it */
838 ARMul_SetSPSR(state,state->Mode,spsr) ;
839 }
840 else
841 ARMul_SetCPSR(state,cpsr) ;
842
843 /* and fall through to correct r14 */
844 }
845 case 0x95: /* Address Exception */
846 state->Reg[14] -= 4;
847 case 0x91: /* Undefined instruction */
848 case 0x92: /* SWI */
849 case 0x93: /* Prefetch abort */
850 case 0x96: /* IRQ */
851 case 0x97: /* FIQ */
852 state->Reg[14] -= 4;
853 TidyCommon:
854 if (state->VectorCatch & (1 << (number - 0x90))) {
855 ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
856 ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ;
857 if (number == 0x90)
858 state->EndCondition = 10 ; /* Branch through Zero Error */
859 else
860 state->EndCondition = (unsigned)number - 0x8f;
861 state->Emulate = FALSE ;
862 }
863 else {
864 ARMword sp = state->Reg[13];
865 ARMul_WriteWord(state, sp - 4, state->Reg[14]);
866 ARMul_WriteWord(state, sp - 8, state->Reg[12]);
867 ARMul_WriteWord(state, sp - 12, state->Reg[11]);
868 ARMul_WriteWord(state, sp - 16, state->Reg[10]);
869 state->Reg[13] = sp - 16;
870 state->Reg[11] = ADDRSOFHANDLERS + 8 * (number - 0x90);
871 }
872 return(TRUE);
873
874 /* SWI's 0x8x pass an abort of type x to the debugger if a handler returns */
875
876 case 0x80: case 0x81: case 0x82: case 0x83:
877 case 0x84: case 0x85: case 0x86: case 0x87: case 0x88:
878 { ARMword sp = state->Reg[13];
879 state->Reg[10] = ARMul_ReadWord(state, sp);
880 state->Reg[11] = ARMul_ReadWord(state, sp + 4);
881 state->Reg[12] = ARMul_ReadWord(state, sp + 8);
882 state->Reg[14] = ARMul_ReadWord(state, sp + 12);
883 state->Reg[13] = sp + 16;
884 ARMul_SetR15(state, state->Reg[14] + 8) ; /* the 8 is the pipelining the the RDI will undo */
885 ARMul_SetCPSR(state,ARMul_GetSPSR(state,ARMul_GetCPSR(state))) ;
886 if (number == 0x80)
887 state->EndCondition = 10 ; /* Branch through Zero Error */
888 else
889 state->EndCondition = (unsigned)number - 0x7f;
890 state->Emulate = FALSE ;
891 return(TRUE);
892 }
893
894 default :
895 state->Emulate = FALSE ;
896 return(FALSE) ;
897 }
898 #endif
899 #endif
900 }
901 #endif
902
903 #ifndef NOOS
904 #ifndef ASIM
905
906 /***************************************************************************\
907 * The emulator calls this routine when an Exception occurs. The second *
908 * parameter is the address of the relevant exception vector. Returning *
909 * FALSE from this routine causes the trap to be taken, TRUE causes it to *
910 * be ignored (so set state->Emulate to FALSE!). *
911 \***************************************************************************/
912
913 unsigned ARMul_OSException(ARMul_State *state, ARMword vector, ARMword pc)
914 { /* don't use this here */
915 return(FALSE) ;
916 }
917
918 #endif
919
920 /***************************************************************************\
921 * Unwind a data abort *
922 \***************************************************************************/
923
924 static void UnwindDataAbort(ARMul_State *state, ARMword addr)
925 {
926 ARMword instr = ARMul_ReadWord(state, addr);
927 ARMword rn = BITS(16, 19);
928 ARMword itype = BITS(24, 27);
929 ARMword offset;
930 if (rn == 15) return;
931 if (itype == 8 || itype == 9) {
932 /* LDM or STM */
933 unsigned long regs = BITS(0, 15);
934 offset = 0;
935 if (!BIT(21)) return; /* no wb */
936 for (; regs != 0; offset++)
937 regs ^= (regs & -regs);
938 if (offset == 0) offset = 16;
939 } else if (itype == 12 || /* post-indexed CPDT */
940 (itype == 13 && BIT(21))) { /* pre_indexed CPDT with WB */
941 offset = BITS(0, 7);
942 } else
943 return;
944
945 if (BIT(23))
946 state->Reg[rn] -= offset * 4;
947 else
948 state->Reg[rn] += offset * 4;
949 }
950
951 /***************************************************************************\
952 * Copy a string from the debuggee's memory to the host's *
953 \***************************************************************************/
954
955 static void getstring(ARMul_State *state, ARMword from, char *to)
956 {do {
957 *to = (char)ARMul_ReadByte(state,from++) ;
958 } while (*to++ != '\0') ;
959 }
960
961 #endif /* NOOS */
This page took 0.071698 seconds and 4 git commands to generate.