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