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