* pe-dll.c (fill_edata): don't strip underscores
[deliverable/binutils-gdb.git] / sim / arm / armos.c
CommitLineData
7d449b44
JM
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,
19including all the SWI's required to support the C library. The code in
20it is not really for the faint-hearted (especially the abort handling
21code), but it is a complete example. Defining NOOS will disable all the
22fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI
230x11 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
54extern 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
83extern unsigned ARMul_OSInit(ARMul_State *state) ;
84extern void ARMul_OSExit(ARMul_State *state) ;
85extern unsigned ARMul_OSHandleSWI(ARMul_State *state,ARMword number) ;
86extern unsigned ARMul_OSException(ARMul_State *state, ARMword vector, ARMword pc) ;
87extern ARMword ARMul_OSLastErrorP(ARMul_State *state) ;
88extern 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
97static void UnwindDataAbort(ARMul_State *state, ARMword addr);
98static void getstring(ARMul_State *state, ARMword from, char *to) ;
99#endif
100
101/***************************************************************************\
102* OS private Information *
103\***************************************************************************/
104
105struct 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
125static 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
145unsigned 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
207void ARMul_OSExit(ARMul_State *state)
208{
209 free((char *)state->OSptr) ;
210}
211
212
213/***************************************************************************\
214* Return the last Operating System Error. *
215\***************************************************************************/
216
217ARMword 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
232static 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
248unsigned 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;
e3ace30a
NC
299 int flags;
300
7d449b44
JM
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
e3ace30a
NC
422 case AngelSWI_ARM:
423 case AngelSWI_Thumb:
424 /* Ignore these SWIs (for now). */
425 return TRUE;
426
7d449b44
JM
427 default :
428 state->Emulate = FALSE ;
429 return(FALSE) ;
430 }
431}
432#else
433unsigned 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
920unsigned 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
931static 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
962static 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 */
This page took 0.067 seconds and 4 git commands to generate.