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