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