]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/arm/armos.c
* armos.c (SWIflen): Do not treate file descriptor zero as
[thirdparty/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
380d9419 16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
c906108c
SS
17
18/* This file contains a model of Demon, ARM Ltd's Debug Monitor,
7f53bc35
NC
19 including all the SWI's required to support the C library. The code in
20 it is not really for the faint-hearted (especially the abort handling
21 code), but it is a complete example. Defining NOOS will disable all the
22 fun, and definign VAILDATE will define SWI 1 to enter SVC mode, and SWI
23 0x11 to halt the emulator. */
c906108c
SS
24
25#include "config.h"
6d358e86 26#include "ansidecl.h"
c906108c
SS
27
28#include <time.h>
29#include <errno.h>
2be701a3 30#include <limits.h>
c906108c 31#include <string.h>
a4c9740c 32#include "targ-vals.h"
c906108c 33
a4c9740c
MM
34#ifndef TARGET_O_BINARY
35#define TARGET_O_BINARY 0
c906108c
SS
36#endif
37
c906108c 38#ifdef HAVE_UNISTD_H
d8512e6a 39#include <unistd.h> /* For SEEK_SET etc. */
c906108c
SS
40#endif
41
42#ifdef __riscos
dfcd3bfb 43extern int _fisatty (FILE *);
c906108c
SS
44#define isatty_(f) _fisatty(f)
45#else
46#ifdef __ZTC__
47#include <io.h>
48#define isatty_(f) isatty((f)->_file)
49#else
50#ifdef macintosh
51#include <ioctl.h>
52#define isatty_(f) (~ioctl ((f)->_file, FIOINTERACTIVE, NULL))
53#else
54#define isatty_(f) isatty (fileno (f))
55#endif
56#endif
57#endif
58
59#include "armdefs.h"
60#include "armos.h"
f1129fb8
NC
61#include "armemu.h"
62
c906108c
SS
63#ifndef NOOS
64#ifndef VALIDATE
65/* #ifndef ASIM */
66#include "armfpe.h"
67/* #endif */
68#endif
69#endif
70
71/* For RDIError_BreakpointReached. */
72#include "dbg_rdi.h"
73
3c25f8c7 74#include "gdb/callback.h"
b3ba81f8
KS
75extern host_callback *sim_callback;
76
d8512e6a
NC
77extern unsigned ARMul_OSInit (ARMul_State *);
78extern void ARMul_OSExit (ARMul_State *);
79extern unsigned ARMul_OSHandleSWI (ARMul_State *, ARMword);
80extern unsigned ARMul_OSException (ARMul_State *, ARMword, ARMword);
81extern ARMword ARMul_OSLastErrorP (ARMul_State *);
82extern ARMword ARMul_Debug (ARMul_State *, ARMword, ARMword);
c906108c
SS
83
84#define BUFFERSIZE 4096
85#ifndef FOPEN_MAX
86#define FOPEN_MAX 64
87#endif
88#define UNIQUETEMPS 256
2be701a3
DJ
89#ifndef PATH_MAX
90#define PATH_MAX 1024
91#endif
c906108c 92
7f53bc35 93/* OS private Information. */
c906108c 94
dfcd3bfb
JM
95struct OSblock
96{
97 ARMword Time0;
98 ARMword ErrorP;
99 ARMword ErrorNo;
100 FILE *FileTable[FOPEN_MAX];
101 char FileFlags[FOPEN_MAX];
102 char *tempnames[UNIQUETEMPS];
103};
c906108c
SS
104
105#define NOOP 0
106#define BINARY 1
107#define READOP 2
108#define WRITEOP 4
109
110#ifdef macintosh
111#define FIXCRLF(t,c) ((t & BINARY) ? \
112 c : \
113 ((c == '\n' || c == '\r' ) ? (c ^ 7) : c) \
114 )
dfcd3bfb
JM
115#else
116#define FIXCRLF(t,c) c
c906108c
SS
117#endif
118
de4112fa
NC
119/* Bit mask of enabled SWI implementations. */
120unsigned int swi_mask = -1;
121
122
6d358e86 123static ARMword softvectorcode[] =
7f53bc35 124{
0f026fd0
NC
125 /* Installed instructions:
126 swi tidyexception + event;
127 mov lr, pc;
128 ldmia fp, {fp, pc};
129 swi generateexception + event. */
7f53bc35
NC
130 0xef000090, 0xe1a0e00f, 0xe89b8800, 0xef000080, /* Reset */
131 0xef000091, 0xe1a0e00f, 0xe89b8800, 0xef000081, /* Undef */
132 0xef000092, 0xe1a0e00f, 0xe89b8800, 0xef000082, /* SWI */
133 0xef000093, 0xe1a0e00f, 0xe89b8800, 0xef000083, /* Prefetch abort */
134 0xef000094, 0xe1a0e00f, 0xe89b8800, 0xef000084, /* Data abort */
135 0xef000095, 0xe1a0e00f, 0xe89b8800, 0xef000085, /* Address exception */
136 0xef000096, 0xe1a0e00f, 0xe89b8800, 0xef000086, /* IRQ */
137 0xef000097, 0xe1a0e00f, 0xe89b8800, 0xef000087, /* FIQ */
138 0xef000098, 0xe1a0e00f, 0xe89b8800, 0xef000088, /* Error */
139 0xe1a0f00e /* Default handler */
c906108c
SS
140};
141
7f53bc35 142/* Time for the Operating System to initialise itself. */
c906108c 143
dfcd3bfb
JM
144unsigned
145ARMul_OSInit (ARMul_State * state)
c906108c
SS
146{
147#ifndef NOOS
148#ifndef VALIDATE
dfcd3bfb
JM
149 ARMword instr, i, j;
150 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
151
152 if (state->OSptr == NULL)
153 {
154 state->OSptr = (unsigned char *) malloc (sizeof (struct OSblock));
155 if (state->OSptr == NULL)
156 {
157 perror ("OS Memory");
158 exit (15);
159 }
c906108c 160 }
7f53bc35 161
dfcd3bfb
JM
162 OSptr = (struct OSblock *) state->OSptr;
163 OSptr->ErrorP = 0;
d8512e6a
NC
164 state->Reg[13] = ADDRSUPERSTACK; /* Set up a stack for the current mode... */
165 ARMul_SetReg (state, SVC32MODE, 13, ADDRSUPERSTACK);/* ...and for supervisor mode... */
166 ARMul_SetReg (state, ABORT32MODE, 13, ADDRSUPERSTACK);/* ...and for abort 32 mode... */
167 ARMul_SetReg (state, UNDEF32MODE, 13, ADDRSUPERSTACK);/* ...and for undef 32 mode... */
168 ARMul_SetReg (state, SYSTEMMODE, 13, ADDRSUPERSTACK);/* ...and for system mode. */
169 instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8); /* Load pc from soft vector */
7f53bc35 170
dfcd3bfb 171 for (i = ARMul_ResetV; i <= ARMFIQV; i += 4)
ace4f296
NC
172 /* Write hardware vectors. */
173 ARMul_WriteWord (state, i, instr);
7f53bc35 174
88694af3
NC
175 SWI_vector_installed = 0;
176
dfcd3bfb
JM
177 for (i = ARMul_ResetV; i <= ARMFIQV + 4; i += 4)
178 {
179 ARMul_WriteWord (state, ADDRSOFTVECTORS + i, SOFTVECTORCODE + i * 4);
180 ARMul_WriteWord (state, ADDRSOFHANDLERS + 2 * i + 4L,
181 SOFTVECTORCODE + sizeof (softvectorcode) - 4L);
c906108c 182 }
7f53bc35 183
dfcd3bfb
JM
184 for (i = 0; i < sizeof (softvectorcode); i += 4)
185 ARMul_WriteWord (state, SOFTVECTORCODE + i, softvectorcode[i / 4]);
7f53bc35 186
dfcd3bfb
JM
187 for (i = 0; i < FOPEN_MAX; i++)
188 OSptr->FileTable[i] = NULL;
7f53bc35 189
dfcd3bfb
JM
190 for (i = 0; i < UNIQUETEMPS; i++)
191 OSptr->tempnames[i] = NULL;
7f53bc35 192
dfcd3bfb 193 ARMul_ConsolePrint (state, ", Demon 1.01");
c906108c
SS
194
195/* #ifndef ASIM */
196
d8512e6a
NC
197 /* Install FPE. */
198 for (i = 0; i < fpesize; i += 4)
199 /* Copy the code. */
dfcd3bfb 200 ARMul_WriteWord (state, FPESTART + i, fpecode[i >> 2]);
7f53bc35 201
0f026fd0 202 /* Scan backwards from the end of the code. */
dfcd3bfb 203 for (i = FPESTART + fpesize;; i -= 4)
d8512e6a 204 {
0f026fd0
NC
205 /* When we reach the marker value, break out of
206 the loop, leaving i pointing at the maker. */
dfcd3bfb
JM
207 if ((j = ARMul_ReadWord (state, i)) == 0xffffffff)
208 break;
0f026fd0
NC
209
210 /* If necessary, reverse the error strings. */
dfcd3bfb 211 if (state->bigendSig && j < 0x80000000)
d8512e6a
NC
212 {
213 /* It's part of the string so swap it. */
dfcd3bfb
JM
214 j = ((j >> 0x18) & 0x000000ff) |
215 ((j >> 0x08) & 0x0000ff00) |
216 ((j << 0x08) & 0x00ff0000) | ((j << 0x18) & 0xff000000);
217 ARMul_WriteWord (state, i, j);
218 }
c906108c 219 }
7f53bc35 220
d8512e6a 221 /* Copy old illegal instr vector. */
0f026fd0 222 ARMul_WriteWord (state, FPEOLDVECT, ARMul_ReadWord (state, ARMUndefinedInstrV));
d8512e6a 223 /* Install new vector. */
0f026fd0 224 ARMul_WriteWord (state, ARMUndefinedInstrV, FPENEWVECT (ARMul_ReadWord (state, i - 4)));
dfcd3bfb 225 ARMul_ConsolePrint (state, ", FPE");
c906108c 226
6d358e86 227/* #endif ASIM */
c906108c
SS
228#endif /* VALIDATE */
229#endif /* NOOS */
230
de4112fa
NC
231 /* Intel do not want DEMON SWI support. */
232 if (state->is_XScale)
233 swi_mask = SWI_MASK_ANGEL;
10b57fcb
NC
234
235 return TRUE;
c906108c
SS
236}
237
dfcd3bfb
JM
238void
239ARMul_OSExit (ARMul_State * state)
c906108c 240{
dfcd3bfb 241 free ((char *) state->OSptr);
c906108c
SS
242}
243
244
7f53bc35 245/* Return the last Operating System Error. */
c906108c 246
dfcd3bfb 247ARMword ARMul_OSLastErrorP (ARMul_State * state)
c906108c 248{
dfcd3bfb 249 return ((struct OSblock *) state->OSptr)->ErrorP;
c906108c
SS
250}
251
7f53bc35
NC
252static int translate_open_mode[] =
253{
a4c9740c
MM
254 TARGET_O_RDONLY, /* "r" */
255 TARGET_O_RDONLY + TARGET_O_BINARY, /* "rb" */
256 TARGET_O_RDWR, /* "r+" */
257 TARGET_O_RDWR + TARGET_O_BINARY, /* "r+b" */
258 TARGET_O_WRONLY + TARGET_O_CREAT + TARGET_O_TRUNC, /* "w" */
259 TARGET_O_WRONLY + TARGET_O_BINARY + TARGET_O_CREAT + TARGET_O_TRUNC, /* "wb" */
260 TARGET_O_RDWR + TARGET_O_CREAT + TARGET_O_TRUNC, /* "w+" */
261 TARGET_O_RDWR + TARGET_O_BINARY + TARGET_O_CREAT + TARGET_O_TRUNC, /* "w+b" */
262 TARGET_O_WRONLY + TARGET_O_APPEND + TARGET_O_CREAT, /* "a" */
263 TARGET_O_WRONLY + TARGET_O_BINARY + TARGET_O_APPEND + TARGET_O_CREAT, /* "ab" */
264 TARGET_O_RDWR + TARGET_O_APPEND + TARGET_O_CREAT, /* "a+" */
265 TARGET_O_RDWR + TARGET_O_BINARY + TARGET_O_APPEND + TARGET_O_CREAT /* "a+b" */
c906108c
SS
266};
267
dfcd3bfb
JM
268static void
269SWIWrite0 (ARMul_State * state, ARMword addr)
c906108c
SS
270{
271 ARMword temp;
dfcd3bfb 272 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
c906108c 273
917bca4f 274 while ((temp = ARMul_SafeReadByte (state, addr++)) != 0)
0d9fd8f1
NC
275 {
276 char buffer = temp;
277 /* Note - we cannot just cast 'temp' to a (char *) here,
278 since on a big-endian host the byte value will end
279 up in the wrong place and a nul character will be printed. */
280 (void) sim_callback->write_stdout (sim_callback, & buffer, 1);
281 }
c906108c 282
b3ba81f8 283 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
c906108c
SS
284}
285
dfcd3bfb
JM
286static void
287WriteCommandLineTo (ARMul_State * state, ARMword addr)
c906108c
SS
288{
289 ARMword temp;
290 char *cptr = state->CommandLine;
7f53bc35 291
c906108c
SS
292 if (cptr == NULL)
293 cptr = "\0";
dfcd3bfb
JM
294 do
295 {
296 temp = (ARMword) * cptr++;
917bca4f 297 ARMul_SafeWriteByte (state, addr++, temp);
dfcd3bfb
JM
298 }
299 while (temp != 0);
c906108c
SS
300}
301
2be701a3
DJ
302static int
303ReadFileName (ARMul_State * state, char *buf, ARMword src, size_t n)
304{
305 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
306 char *p = buf;
307
308 while (n--)
309 if ((*p++ = ARMul_SafeReadByte (state, src++)) == '\0')
310 return 0;
311 OSptr->ErrorNo = cb_host_to_target_errno (sim_callback, ENAMETOOLONG);
312 state->Reg[0] = -1;
313 return -1;
314}
315
dfcd3bfb
JM
316static void
317SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags)
c906108c 318{
dfcd3bfb 319 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
2be701a3 320 char buf[PATH_MAX];
c906108c 321 int flags;
c906108c 322
2be701a3
DJ
323 if (ReadFileName (state, buf, name, sizeof buf) == -1)
324 return;
c906108c 325
7f53bc35 326 /* Now we need to decode the Demon open mode. */
c906108c
SS
327 flags = translate_open_mode[SWIflags];
328
7f53bc35 329 /* Filename ":tt" is special: it denotes stdin/out. */
2be701a3 330 if (strcmp (buf, ":tt") == 0)
c906108c 331 {
a4c9740c 332 if (flags == TARGET_O_RDONLY) /* opening tty "r" */
dfcd3bfb
JM
333 state->Reg[0] = 0; /* stdin */
334 else
335 state->Reg[0] = 1; /* stdout */
c906108c
SS
336 }
337 else
338 {
2be701a3 339 state->Reg[0] = sim_callback->open (sim_callback, buf, flags);
b3ba81f8 340 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
c906108c
SS
341 }
342}
343
dfcd3bfb
JM
344static void
345SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
c906108c 346{
dfcd3bfb 347 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
c906108c
SS
348 int res;
349 int i;
350 char *local = malloc (len);
351
c2d11a7d
JM
352 if (local == NULL)
353 {
d8512e6a
NC
354 sim_callback->printf_filtered
355 (sim_callback,
356 "sim: Unable to read 0x%ulx bytes - out of memory\n",
357 len);
c2d11a7d
JM
358 return;
359 }
dfcd3bfb 360
b3ba81f8 361 res = sim_callback->read (sim_callback, f, local, len);
c906108c 362 if (res > 0)
dfcd3bfb 363 for (i = 0; i < res; i++)
917bca4f 364 ARMul_SafeWriteByte (state, ptr + i, local[i]);
7f53bc35 365
c906108c
SS
366 free (local);
367 state->Reg[0] = res == -1 ? -1 : len - res;
b3ba81f8 368 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
c906108c
SS
369}
370
dfcd3bfb
JM
371static void
372SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len)
c906108c 373{
dfcd3bfb 374 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
c906108c 375 int res;
6d358e86 376 ARMword i;
c906108c
SS
377 char *local = malloc (len);
378
c2d11a7d 379 if (local == NULL)
c906108c 380 {
d8512e6a
NC
381 sim_callback->printf_filtered
382 (sim_callback,
383 "sim: Unable to write 0x%lx bytes - out of memory\n",
384 (long) len);
c2d11a7d 385 return;
c906108c 386 }
dfcd3bfb
JM
387
388 for (i = 0; i < len; i++)
917bca4f 389 local[i] = ARMul_SafeReadByte (state, ptr + i);
c2d11a7d 390
b3ba81f8 391 res = sim_callback->write (sim_callback, f, local, len);
c906108c
SS
392 state->Reg[0] = res == -1 ? -1 : len - res;
393 free (local);
7f53bc35 394
b3ba81f8 395 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
c906108c
SS
396}
397
dfcd3bfb
JM
398static void
399SWIflen (ARMul_State * state, ARMword fh)
c906108c 400{
dfcd3bfb 401 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
c906108c
SS
402 ARMword addr;
403
e1c9b6f1 404 if (fh > FOPEN_MAX)
c906108c
SS
405 {
406 OSptr->ErrorNo = EBADF;
407 state->Reg[0] = -1L;
408 return;
409 }
410
b3ba81f8 411 addr = sim_callback->lseek (sim_callback, fh, 0, SEEK_CUR);
6d358e86 412
b3ba81f8
KS
413 state->Reg[0] = sim_callback->lseek (sim_callback, fh, 0L, SEEK_END);
414 (void) sim_callback->lseek (sim_callback, fh, addr, SEEK_SET);
c906108c 415
b3ba81f8 416 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
c906108c
SS
417}
418
2be701a3
DJ
419static void
420SWIremove (ARMul_State * state, ARMword path)
421{
422 char buf[PATH_MAX];
423
424 if (ReadFileName (state, buf, path, sizeof buf) != -1)
425 {
426 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
427 state->Reg[0] = sim_callback->unlink (sim_callback, buf);
428 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
429 }
430}
431
432static void
433SWIrename (ARMul_State * state, ARMword old, ARMword new)
434{
435 char oldbuf[PATH_MAX], newbuf[PATH_MAX];
436
437 if (ReadFileName (state, oldbuf, old, sizeof oldbuf) != -1
438 && ReadFileName (state, newbuf, new, sizeof newbuf) != -1)
439 {
440 struct OSblock *OSptr = (struct OSblock *) state->OSptr;
441 state->Reg[0] = sim_callback->rename (sim_callback, oldbuf, newbuf);
442 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
443 }
444}
445
7f53bc35
NC
446/* The emulator calls this routine when a SWI instruction is encuntered.
447 The parameter passed is the SWI number (lower 24 bits of the instruction). */
c906108c 448
dfcd3bfb
JM
449unsigned
450ARMul_OSHandleSWI (ARMul_State * state, ARMword number)
c906108c 451{
1e5d4e46 452 struct OSblock * OSptr = (struct OSblock *) state->OSptr;
de4112fa
NC
453 int unhandled = FALSE;
454
c906108c
SS
455 switch (number)
456 {
457 case SWI_Read:
de4112fa
NC
458 if (swi_mask & SWI_MASK_DEMON)
459 SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]);
460 else
461 unhandled = TRUE;
1e5d4e46 462 break;
c906108c
SS
463
464 case SWI_Write:
de4112fa
NC
465 if (swi_mask & SWI_MASK_DEMON)
466 SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]);
467 else
468 unhandled = TRUE;
1e5d4e46 469 break;
c906108c
SS
470
471 case SWI_Open:
de4112fa
NC
472 if (swi_mask & SWI_MASK_DEMON)
473 SWIopen (state, state->Reg[0], state->Reg[1]);
474 else
475 unhandled = TRUE;
1e5d4e46 476 break;
c906108c 477
dfcd3bfb 478 case SWI_Clock:
de4112fa
NC
479 if (swi_mask & SWI_MASK_DEMON)
480 {
481 /* Return number of centi-seconds. */
482 state->Reg[0] =
c906108c 483#ifdef CLOCKS_PER_SEC
de4112fa
NC
484 (CLOCKS_PER_SEC >= 100)
485 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
486 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
c906108c 487#else
de4112fa
NC
488 /* Presume unix... clock() returns microseconds. */
489 (ARMword) (clock () / 10000);
c906108c 490#endif
de4112fa
NC
491 OSptr->ErrorNo = errno;
492 }
493 else
494 unhandled = TRUE;
1e5d4e46 495 break;
dfcd3bfb
JM
496
497 case SWI_Time:
de4112fa
NC
498 if (swi_mask & SWI_MASK_DEMON)
499 {
500 state->Reg[0] = (ARMword) sim_callback->time (sim_callback, NULL);
501 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
502 }
503 else
504 unhandled = TRUE;
1e5d4e46 505 break;
dfcd3bfb 506
c906108c 507 case SWI_Close:
de4112fa
NC
508 if (swi_mask & SWI_MASK_DEMON)
509 {
510 state->Reg[0] = sim_callback->close (sim_callback, state->Reg[0]);
511 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
512 }
513 else
514 unhandled = TRUE;
1e5d4e46 515 break;
c906108c 516
dfcd3bfb 517 case SWI_Flen:
de4112fa
NC
518 if (swi_mask & SWI_MASK_DEMON)
519 SWIflen (state, state->Reg[0]);
520 else
521 unhandled = TRUE;
1e5d4e46 522 break;
c906108c
SS
523
524 case SWI_Exit:
de4112fa
NC
525 if (swi_mask & SWI_MASK_DEMON)
526 state->Emulate = FALSE;
527 else
528 unhandled = TRUE;
1e5d4e46 529 break;
c906108c
SS
530
531 case SWI_Seek:
de4112fa
NC
532 if (swi_mask & SWI_MASK_DEMON)
533 {
534 /* We must return non-zero for failure. */
535 state->Reg[0] = -1 >= sim_callback->lseek (sim_callback, state->Reg[0], state->Reg[1], SEEK_SET);
536 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
537 }
538 else
539 unhandled = TRUE;
1e5d4e46 540 break;
c906108c 541
dfcd3bfb 542 case SWI_WriteC:
de4112fa
NC
543 if (swi_mask & SWI_MASK_DEMON)
544 {
545 char tmp = state->Reg[0];
546 (void) sim_callback->write_stdout (sim_callback, &tmp, 1);
547 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
548 }
549 else
550 unhandled = TRUE;
1e5d4e46 551 break;
c906108c 552
dfcd3bfb 553 case SWI_Write0:
de4112fa
NC
554 if (swi_mask & SWI_MASK_DEMON)
555 SWIWrite0 (state, state->Reg[0]);
556 else
557 unhandled = TRUE;
1e5d4e46 558 break;
c906108c 559
dfcd3bfb 560 case SWI_GetErrno:
de4112fa
NC
561 if (swi_mask & SWI_MASK_DEMON)
562 state->Reg[0] = OSptr->ErrorNo;
563 else
564 unhandled = TRUE;
1e5d4e46 565 break;
c906108c 566
dfcd3bfb 567 case SWI_GetEnv:
de4112fa
NC
568 if (swi_mask & SWI_MASK_DEMON)
569 {
570 state->Reg[0] = ADDRCMDLINE;
571 if (state->MemSize)
572 state->Reg[1] = state->MemSize;
573 else
574 state->Reg[1] = ADDRUSERSTACK;
c906108c 575
de4112fa
NC
576 WriteCommandLineTo (state, state->Reg[0]);
577 }
578 else
579 unhandled = TRUE;
1e5d4e46 580 break;
7f53bc35 581
f1129fb8
NC
582 case SWI_Breakpoint:
583 state->EndCondition = RDIError_BreakpointReached;
584 state->Emulate = FALSE;
1e5d4e46 585 break;
c906108c 586
2be701a3
DJ
587 case SWI_Remove:
588 if (swi_mask & SWI_MASK_DEMON)
589 SWIremove (state, state->Reg[0]);
590 else
591 unhandled = TRUE;
592 break;
593
594 case SWI_Rename:
595 if (swi_mask & SWI_MASK_DEMON)
596 SWIrename (state, state->Reg[0], state->Reg[1]);
597 else
598 unhandled = TRUE;
599 break;
600
601 case SWI_IsTTY:
602 if (swi_mask & SWI_MASK_DEMON)
603 {
604 state->Reg[0] = sim_callback->isatty (sim_callback, state->Reg[0]);
605 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
606 }
607 else
608 unhandled = TRUE;
609 break;
610
7f53bc35 611 /* Handle Angel SWIs as well as Demon ones. */
c906108c
SS
612 case AngelSWI_ARM:
613 case AngelSWI_Thumb:
de4112fa 614 if (swi_mask & SWI_MASK_ANGEL)
c906108c 615 {
de4112fa
NC
616 ARMword addr;
617 ARMword temp;
618
619 /* R1 is almost always a parameter block. */
620 addr = state->Reg[1];
621 /* R0 is a reason code. */
622 switch (state->Reg[0])
623 {
c7a7b500
NC
624 case -1:
625 /* This can happen when a SWI is interrupted (eg receiving a
626 ctrl-C whilst processing SWIRead()). The SWI will complete
627 returning -1 in r0 to the caller. If GDB is then used to
628 resume the system call the reason code will now be -1. */
2ec3c90a 629 return TRUE;
c7a7b500 630
de4112fa
NC
631 /* Unimplemented reason codes. */
632 case AngelSWI_Reason_ReadC:
de4112fa 633 case AngelSWI_Reason_TmpNam:
de4112fa
NC
634 case AngelSWI_Reason_System:
635 case AngelSWI_Reason_EnterSVC:
636 default:
637 state->Emulate = FALSE;
638 return FALSE;
639
640 case AngelSWI_Reason_Clock:
641 /* Return number of centi-seconds. */
642 state->Reg[0] =
c906108c 643#ifdef CLOCKS_PER_SEC
de4112fa
NC
644 (CLOCKS_PER_SEC >= 100)
645 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100))
646 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC);
c906108c 647#else
de4112fa
NC
648 /* Presume unix... clock() returns microseconds. */
649 (ARMword) (clock () / 10000);
c906108c 650#endif
de4112fa
NC
651 OSptr->ErrorNo = errno;
652 break;
653
654 case AngelSWI_Reason_Time:
655 state->Reg[0] = (ARMword) sim_callback->time (sim_callback, NULL);
656 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
657 break;
658
659 case AngelSWI_Reason_WriteC:
660 {
661 char tmp = ARMul_SafeReadByte (state, addr);
662 (void) sim_callback->write_stdout (sim_callback, &tmp, 1);
663 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
664 break;
665 }
666
667 case AngelSWI_Reason_Write0:
668 SWIWrite0 (state, addr);
669 break;
670
671 case AngelSWI_Reason_Close:
672 state->Reg[0] = sim_callback->close (sim_callback, ARMul_ReadWord (state, addr));
673 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
674 break;
675
676 case AngelSWI_Reason_Seek:
677 state->Reg[0] = -1 >= sim_callback->lseek (sim_callback, ARMul_ReadWord (state, addr),
678 ARMul_ReadWord (state, addr + 4),
679 SEEK_SET);
680 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
681 break;
682
683 case AngelSWI_Reason_FLen:
684 SWIflen (state, ARMul_ReadWord (state, addr));
685 break;
686
687 case AngelSWI_Reason_GetCmdLine:
688 WriteCommandLineTo (state, ARMul_ReadWord (state, addr));
689 break;
690
691 case AngelSWI_Reason_HeapInfo:
692 /* R1 is a pointer to a pointer. */
693 addr = ARMul_ReadWord (state, addr);
694
695 /* Pick up the right memory limit. */
696 if (state->MemSize)
697 temp = state->MemSize;
698 else
699 temp = ADDRUSERSTACK;
700
701 ARMul_WriteWord (state, addr, 0); /* Heap base. */
702 ARMul_WriteWord (state, addr + 4, temp); /* Heap limit. */
703 ARMul_WriteWord (state, addr + 8, temp); /* Stack base. */
704 ARMul_WriteWord (state, addr + 12, temp); /* Stack limit. */
705 break;
706
707 case AngelSWI_Reason_ReportException:
708 if (state->Reg[1] == ADP_Stopped_ApplicationExit)
709 state->Reg[0] = 0;
710 else
711 state->Reg[0] = -1;
712 state->Emulate = FALSE;
713 break;
714
715 case ADP_Stopped_ApplicationExit:
716 state->Reg[0] = 0;
717 state->Emulate = FALSE;
718 break;
719
720 case ADP_Stopped_RunTimeError:
721 state->Reg[0] = -1;
722 state->Emulate = FALSE;
723 break;
724
725 case AngelSWI_Reason_Errno:
726 state->Reg[0] = OSptr->ErrorNo;
727 break;
728
729 case AngelSWI_Reason_Open:
730 SWIopen (state,
731 ARMul_ReadWord (state, addr),
732 ARMul_ReadWord (state, addr + 4));
733 break;
734
735 case AngelSWI_Reason_Read:
736 SWIread (state,
737 ARMul_ReadWord (state, addr),
738 ARMul_ReadWord (state, addr + 4),
739 ARMul_ReadWord (state, addr + 8));
740 break;
741
742 case AngelSWI_Reason_Write:
743 SWIwrite (state,
744 ARMul_ReadWord (state, addr),
745 ARMul_ReadWord (state, addr + 4),
746 ARMul_ReadWord (state, addr + 8));
747 break;
2be701a3
DJ
748
749 case AngelSWI_Reason_IsTTY:
4b1d9c58
PB
750 state->Reg[0] = sim_callback->isatty (sim_callback,
751 ARMul_ReadWord (state, addr));
2be701a3
DJ
752 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
753 break;
754
755 case AngelSWI_Reason_Remove:
756 SWIremove (state,
757 ARMul_ReadWord (state, addr));
758
759 case AngelSWI_Reason_Rename:
760 SWIrename (state,
761 ARMul_ReadWord (state, addr),
762 ARMul_ReadWord (state, addr + 4));
de4112fa 763 }
c906108c 764 }
de4112fa
NC
765 else
766 unhandled = TRUE;
767 break;
c906108c 768
0f026fd0
NC
769 /* The following SWIs are generated by the softvectorcode[]
770 installed by default by the simulator. */
771 case 0x91: /* Undefined Instruction. */
772 {
773 ARMword addr = state->RegBank[UNDEFBANK][14] - 4;
774
775 sim_callback->printf_filtered
776 (sim_callback, "sim: exception: Unhandled Instruction '0x%08x' at 0x%08x. Stopping.\n",
777 ARMul_ReadWord (state, addr), addr);
778 state->EndCondition = RDIError_SoftwareInterrupt;
779 state->Emulate = FALSE;
780 return FALSE;
781 }
782
783 case 0x90: /* Reset. */
784 case 0x92: /* SWI. */
785 /* These two can be safely ignored. */
786 break;
787
788 case 0x93: /* Prefetch Abort. */
789 case 0x94: /* Data Abort. */
790 case 0x95: /* Address Exception. */
791 case 0x96: /* IRQ. */
792 case 0x97: /* FIQ. */
793 case 0x98: /* Error. */
794 unhandled = TRUE;
1e5d4e46 795 break;
0f026fd0 796
c7a7b500
NC
797 case -1:
798 /* This can happen when a SWI is interrupted (eg receiving a
799 ctrl-C whilst processing SWIRead()). The SWI will complete
800 returning -1 in r0 to the caller. If GDB is then used to
801 resume the system call the reason code will now be -1. */
2ec3c90a 802 return TRUE;
c7a7b500 803
d8512e6a 804 case 0x180001: /* RedBoot's Syscall SWI in ARM mode. */
de4112fa 805 if (swi_mask & SWI_MASK_REDBOOT)
d8512e6a 806 {
de4112fa
NC
807 switch (state->Reg[0])
808 {
809 /* These numbers are defined in libgloss/syscall.h
810 but the simulator should not be dependend upon
811 libgloss being installed. */
812 case 1: /* Exit. */
813 state->Emulate = FALSE;
814 /* Copy exit code into r0. */
815 state->Reg[0] = state->Reg[1];
816 break;
817
818 case 2: /* Open. */
819 SWIopen (state, state->Reg[1], state->Reg[2]);
820 break;
821
822 case 3: /* Close. */
823 state->Reg[0] = sim_callback->close (sim_callback, state->Reg[1]);
824 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
825 break;
826
827 case 4: /* Read. */
828 SWIread (state, state->Reg[1], state->Reg[2], state->Reg[3]);
829 break;
830
831 case 5: /* Write. */
832 SWIwrite (state, state->Reg[1], state->Reg[2], state->Reg[3]);
833 break;
834
835 case 6: /* Lseek. */
836 state->Reg[0] = sim_callback->lseek (sim_callback,
837 state->Reg[1],
838 state->Reg[2],
839 state->Reg[3]);
840 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
841 break;
842
843 case 17: /* Utime. */
844 state->Reg[0] = (ARMword) sim_callback->time (sim_callback,
845 (long *) state->Reg[1]);
846 OSptr->ErrorNo = sim_callback->get_errno (sim_callback);
847 break;
848
849 case 7: /* Unlink. */
850 case 8: /* Getpid. */
851 case 9: /* Kill. */
852 case 10: /* Fstat. */
853 case 11: /* Sbrk. */
854 case 12: /* Argvlen. */
855 case 13: /* Argv. */
856 case 14: /* ChDir. */
857 case 15: /* Stat. */
858 case 16: /* Chmod. */
859 case 18: /* Time. */
860 sim_callback->printf_filtered
861 (sim_callback,
eeea4660
DJ
862 "sim: unhandled RedBoot syscall `%d' encountered - "
863 "returning ENOSYS\n",
de4112fa 864 state->Reg[0]);
eeea4660
DJ
865 state->Reg[0] = -1;
866 OSptr->ErrorNo = cb_host_to_target_errno
867 (sim_callback, ENOSYS);
868 break;
869 case 1001: /* Meminfo. */
870 {
871 ARMword totmem = state->Reg[1],
872 topmem = state->Reg[2];
873 ARMword stack = state->MemSize > 0
874 ? state->MemSize : ADDRUSERSTACK;
875 if (totmem != 0)
876 ARMul_WriteWord (state, totmem, stack);
877 if (topmem != 0)
878 ARMul_WriteWord (state, topmem, stack);
879 state->Reg[0] = 0;
880 break;
881 }
de4112fa
NC
882
883 default:
884 sim_callback->printf_filtered
885 (sim_callback,
886 "sim: unknown RedBoot syscall '%d' encountered - ignoring\n",
887 state->Reg[0]);
888 return FALSE;
889 }
890 break;
d8512e6a 891 }
d8512e6a 892
dfcd3bfb 893 default:
de4112fa
NC
894 unhandled = TRUE;
895 }
896
897 if (unhandled)
898 {
899 if (SWI_vector_installed)
1e5d4e46
NC
900 {
901 ARMword cpsr;
902 ARMword i_size;
94ab9d7b 903
1e5d4e46
NC
904 cpsr = ARMul_GetCPSR (state);
905 i_size = INSN_SIZE;
94ab9d7b 906
1e5d4e46 907 ARMul_SetSPSR (state, SVC32MODE, cpsr);
94ab9d7b 908
1e5d4e46
NC
909 cpsr &= ~0xbf;
910 cpsr |= SVC32MODE | 0x80;
911 ARMul_SetCPSR (state, cpsr);
94ab9d7b 912
1e5d4e46
NC
913 state->RegBank[SVCBANK][14] = state->Reg[14] = state->Reg[15] - i_size;
914 state->NextInstr = RESUME;
915 state->Reg[15] = state->pc = ARMSWIV;
916 FLUSHPIPE;
917 }
918 else
919 {
d8512e6a
NC
920 sim_callback->printf_filtered
921 (sim_callback,
922 "sim: unknown SWI encountered - %x - ignoring\n",
923 number);
1e5d4e46
NC
924 return FALSE;
925 }
c906108c 926 }
1e5d4e46 927
1e5d4e46 928 return TRUE;
c906108c
SS
929}
930
c906108c
SS
931#ifndef NOOS
932#ifndef ASIM
933
f1129fb8
NC
934/* The emulator calls this routine when an Exception occurs. The second
935 parameter is the address of the relevant exception vector. Returning
936 FALSE from this routine causes the trap to be taken, TRUE causes it to
937 be ignored (so set state->Emulate to FALSE!). */
c906108c 938
dfcd3bfb 939unsigned
7f53bc35 940ARMul_OSException (ARMul_State * state ATTRIBUTE_UNUSED,
f1129fb8
NC
941 ARMword vector ATTRIBUTE_UNUSED,
942 ARMword pc ATTRIBUTE_UNUSED)
943{
917bca4f 944 return FALSE;
c906108c
SS
945}
946
947#endif
c906108c 948#endif /* NOOS */