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