1/* armos.c -- ARMulator OS interface: ARM6 Instruction Emulator. 2 Copyright (C) 1994 Advanced RISC Machines Ltd. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software 16 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 17 18/* This file contains a model of Demon, ARM Ltd's Debug Monitor, 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. */ 24 25#include "config.h" 26#include "ansidecl.h" 27 28#include <time.h> 29#include <errno.h> 30#include <limits.h> 31#include <string.h> 32#include "targ-vals.h" 33 34#ifndef TARGET_O_BINARY 35#define TARGET_O_BINARY 0 36#endif 37 38#ifdef HAVE_UNISTD_H 39#include <unistd.h> /* For SEEK_SET etc. */ 40#endif 41 42#ifdef __riscos 43extern int _fisatty (FILE *); 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" 61#include "armemu.h" 62 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 74#include "gdb/callback.h" 75extern host_callback *sim_callback; 76 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); 83 84#define BUFFERSIZE 4096 85#ifndef FOPEN_MAX 86#define FOPEN_MAX 64 87#endif 88#define UNIQUETEMPS 256 89#ifndef PATH_MAX 90#define PATH_MAX 1024 91#endif 92 93/* OS private Information. */ 94 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}; 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 ) 115#else 116#define FIXCRLF(t,c) c 117#endif 118 119/* Bit mask of enabled SWI implementations. */ 120unsigned int swi_mask = -1; 121 122 123static ARMword softvectorcode[] = 124{ 125 /* Installed instructions: 126 swi tidyexception + event; 127 mov lr, pc; 128 ldmia fp, {fp, pc}; 129 swi generateexception + event. */ 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 */ 140}; 141 142/* Time for the Operating System to initialise itself. */ 143 144unsigned 145ARMul_OSInit (ARMul_State * state) 146{ 147#ifndef NOOS 148#ifndef VALIDATE 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 } 160 } 161 162 OSptr = (struct OSblock *) state->OSptr; 163 OSptr->ErrorP = 0; 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 */ 170 171 for (i = ARMul_ResetV; i <= ARMFIQV; i += 4) 172 /* Write hardware vectors. */ 173 ARMul_WriteWord (state, i, instr); 174 175 SWI_vector_installed = 0; 176 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); 182 } 183 184 for (i = 0; i < sizeof (softvectorcode); i += 4) 185 ARMul_WriteWord (state, SOFTVECTORCODE + i, softvectorcode[i / 4]); 186 187 for (i = 0; i < FOPEN_MAX; i++) 188 OSptr->FileTable[i] = NULL; 189 190 for (i = 0; i < UNIQUETEMPS; i++) 191 OSptr->tempnames[i] = NULL; 192 193 ARMul_ConsolePrint (state, ", Demon 1.01"); 194 195/* #ifndef ASIM */ 196 197 /* Install FPE. */ 198 for (i = 0; i < fpesize; i += 4) 199 /* Copy the code. */ 200 ARMul_WriteWord (state, FPESTART + i, fpecode[i >> 2]); 201 202 /* Scan backwards from the end of the code. */ 203 for (i = FPESTART + fpesize;; i -= 4) 204 { 205 /* When we reach the marker value, break out of 206 the loop, leaving i pointing at the maker. */ 207 if ((j = ARMul_ReadWord (state, i)) == 0xffffffff) 208 break; 209 210 /* If necessary, reverse the error strings. */ 211 if (state->bigendSig && j < 0x80000000) 212 { 213 /* It's part of the string so swap it. */ 214 j = ((j >> 0x18) & 0x000000ff) | 215 ((j >> 0x08) & 0x0000ff00) | 216 ((j << 0x08) & 0x00ff0000) | ((j << 0x18) & 0xff000000); 217 ARMul_WriteWord (state, i, j); 218 } 219 } 220 221 /* Copy old illegal instr vector. */ 222 ARMul_WriteWord (state, FPEOLDVECT, ARMul_ReadWord (state, ARMUndefinedInstrV)); 223 /* Install new vector. */ 224 ARMul_WriteWord (state, ARMUndefinedInstrV, FPENEWVECT (ARMul_ReadWord (state, i - 4))); 225 ARMul_ConsolePrint (state, ", FPE"); 226 227/* #endif ASIM */ 228#endif /* VALIDATE */ 229#endif /* NOOS */ 230 231 /* Intel do not want DEMON SWI support. */ 232 if (state->is_XScale) 233 swi_mask = SWI_MASK_ANGEL; 234 235 return TRUE; 236} 237 238void 239ARMul_OSExit (ARMul_State * state) 240{ 241 free ((char *) state->OSptr); 242} 243 244 245/* Return the last Operating System Error. */ 246 247ARMword ARMul_OSLastErrorP (ARMul_State * state) 248{ 249 return ((struct OSblock *) state->OSptr)->ErrorP; 250} 251 252static int translate_open_mode[] = 253{ 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" */ 266}; 267 268static void 269SWIWrite0 (ARMul_State * state, ARMword addr) 270{ 271 ARMword temp; 272 struct OSblock *OSptr = (struct OSblock *) state->OSptr; 273 274 while ((temp = ARMul_SafeReadByte (state, addr++)) != 0) 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 } 282 283 OSptr->ErrorNo = sim_callback->get_errno (sim_callback); 284} 285 286static void 287WriteCommandLineTo (ARMul_State * state, ARMword addr) 288{ 289 ARMword temp; 290 char *cptr = state->CommandLine; 291 292 if (cptr == NULL) 293 cptr = "\0"; 294 do 295 { 296 temp = (ARMword) * cptr++; 297 ARMul_SafeWriteByte (state, addr++, temp); 298 } 299 while (temp != 0); 300} 301 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 316static void 317SWIopen (ARMul_State * state, ARMword name, ARMword SWIflags) 318{ 319 struct OSblock *OSptr = (struct OSblock *) state->OSptr; 320 char buf[PATH_MAX]; 321 int flags; 322 323 if (ReadFileName (state, buf, name, sizeof buf) == -1) 324 return; 325 326 /* Now we need to decode the Demon open mode. */ 327 flags = translate_open_mode[SWIflags]; 328 329 /* Filename ":tt" is special: it denotes stdin/out. */ 330 if (strcmp (buf, ":tt") == 0) 331 { 332 if (flags == TARGET_O_RDONLY) /* opening tty "r" */ 333 state->Reg[0] = 0; /* stdin */ 334 else 335 state->Reg[0] = 1; /* stdout */ 336 } 337 else 338 { 339 state->Reg[0] = sim_callback->open (sim_callback, buf, flags); 340 OSptr->ErrorNo = sim_callback->get_errno (sim_callback); 341 } 342} 343 344static void 345SWIread (ARMul_State * state, ARMword f, ARMword ptr, ARMword len) 346{ 347 struct OSblock *OSptr = (struct OSblock *) state->OSptr; 348 int res; 349 int i; 350 char *local = malloc (len); 351 352 if (local == NULL) 353 { 354 sim_callback->printf_filtered 355 (sim_callback, 356 "sim: Unable to read 0x%ulx bytes - out of memory\n", 357 len); 358 return; 359 } 360 361 res = sim_callback->read (sim_callback, f, local, len); 362 if (res > 0) 363 for (i = 0; i < res; i++) 364 ARMul_SafeWriteByte (state, ptr + i, local[i]); 365 366 free (local); 367 state->Reg[0] = res == -1 ? -1 : len - res; 368 OSptr->ErrorNo = sim_callback->get_errno (sim_callback); 369} 370 371static void 372SWIwrite (ARMul_State * state, ARMword f, ARMword ptr, ARMword len) 373{ 374 struct OSblock *OSptr = (struct OSblock *) state->OSptr; 375 int res; 376 ARMword i; 377 char *local = malloc (len); 378 379 if (local == NULL) 380 { 381 sim_callback->printf_filtered 382 (sim_callback, 383 "sim: Unable to write 0x%lx bytes - out of memory\n", 384 (long) len); 385 return; 386 } 387 388 for (i = 0; i < len; i++) 389 local[i] = ARMul_SafeReadByte (state, ptr + i); 390 391 res = sim_callback->write (sim_callback, f, local, len); 392 state->Reg[0] = res == -1 ? -1 : len - res; 393 free (local); 394 395 OSptr->ErrorNo = sim_callback->get_errno (sim_callback); 396} 397 398static void 399SWIflen (ARMul_State * state, ARMword fh) 400{ 401 struct OSblock *OSptr = (struct OSblock *) state->OSptr; 402 ARMword addr; 403 404 if (fh > FOPEN_MAX) 405 { 406 OSptr->ErrorNo = EBADF; 407 state->Reg[0] = -1L; 408 return; 409 } 410 411 addr = sim_callback->lseek (sim_callback, fh, 0, SEEK_CUR); 412 413 state->Reg[0] = sim_callback->lseek (sim_callback, fh, 0L, SEEK_END); 414 (void) sim_callback->lseek (sim_callback, fh, addr, SEEK_SET); 415 416 OSptr->ErrorNo = sim_callback->get_errno (sim_callback); 417} 418 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 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). */ 448 449unsigned 450ARMul_OSHandleSWI (ARMul_State * state, ARMword number) 451{ 452 struct OSblock * OSptr = (struct OSblock *) state->OSptr; 453 int unhandled = FALSE; 454 455 switch (number) 456 { 457 case SWI_Read: 458 if (swi_mask & SWI_MASK_DEMON) 459 SWIread (state, state->Reg[0], state->Reg[1], state->Reg[2]); 460 else 461 unhandled = TRUE; 462 break; 463 464 case SWI_Write: 465 if (swi_mask & SWI_MASK_DEMON) 466 SWIwrite (state, state->Reg[0], state->Reg[1], state->Reg[2]); 467 else 468 unhandled = TRUE; 469 break; 470 471 case SWI_Open: 472 if (swi_mask & SWI_MASK_DEMON) 473 SWIopen (state, state->Reg[0], state->Reg[1]); 474 else 475 unhandled = TRUE; 476 break; 477 478 case SWI_Clock: 479 if (swi_mask & SWI_MASK_DEMON) 480 { 481 /* Return number of centi-seconds. */ 482 state->Reg[0] = 483#ifdef CLOCKS_PER_SEC 484 (CLOCKS_PER_SEC >= 100) 485 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100)) 486 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC); 487#else 488 /* Presume unix... clock() returns microseconds. */ 489 (ARMword) (clock () / 10000); 490#endif 491 OSptr->ErrorNo = errno; 492 } 493 else 494 unhandled = TRUE; 495 break; 496 497 case SWI_Time: 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; 505 break; 506 507 case SWI_Close: 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; 515 break; 516 517 case SWI_Flen: 518 if (swi_mask & SWI_MASK_DEMON) 519 SWIflen (state, state->Reg[0]); 520 else 521 unhandled = TRUE; 522 break; 523 524 case SWI_Exit: 525 if (swi_mask & SWI_MASK_DEMON) 526 state->Emulate = FALSE; 527 else 528 unhandled = TRUE; 529 break; 530 531 case SWI_Seek: 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; 540 break; 541 542 case SWI_WriteC: 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; 551 break; 552 553 case SWI_Write0: 554 if (swi_mask & SWI_MASK_DEMON) 555 SWIWrite0 (state, state->Reg[0]); 556 else 557 unhandled = TRUE; 558 break; 559 560 case SWI_GetErrno: 561 if (swi_mask & SWI_MASK_DEMON) 562 state->Reg[0] = OSptr->ErrorNo; 563 else 564 unhandled = TRUE; 565 break; 566 567 case SWI_GetEnv: 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; 575 576 WriteCommandLineTo (state, state->Reg[0]); 577 } 578 else 579 unhandled = TRUE; 580 break; 581 582 case SWI_Breakpoint: 583 state->EndCondition = RDIError_BreakpointReached; 584 state->Emulate = FALSE; 585 break; 586 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 611 /* Handle Angel SWIs as well as Demon ones. */ 612 case AngelSWI_ARM: 613 case AngelSWI_Thumb: 614 if (swi_mask & SWI_MASK_ANGEL) 615 { 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 { 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. */ 629 return TRUE; 630 631 /* Unimplemented reason codes. */ 632 case AngelSWI_Reason_ReadC: 633 case AngelSWI_Reason_TmpNam: 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] = 643#ifdef CLOCKS_PER_SEC 644 (CLOCKS_PER_SEC >= 100) 645 ? (ARMword) (clock () / (CLOCKS_PER_SEC / 100)) 646 : (ARMword) ((clock () * 100) / CLOCKS_PER_SEC); 647#else 648 /* Presume unix... clock() returns microseconds. */ 649 (ARMword) (clock () / 10000); 650#endif 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; 748 749 case AngelSWI_Reason_IsTTY: 750 state->Reg[0] = sim_callback->isatty (sim_callback, 751 ARMul_ReadWord (state, addr)); 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)); 763 } 764 } 765 else 766 unhandled = TRUE; 767 break; 768 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; 795 break; 796 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. */ 802 return TRUE; 803 804 case 0x180001: /* RedBoot's Syscall SWI in ARM mode. */ 805 if (swi_mask & SWI_MASK_REDBOOT) 806 { 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, 862 "sim: unhandled RedBoot syscall `%d' encountered - " 863 "returning ENOSYS\n", 864 state->Reg[0]); 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 } 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; 891 } 892 893 default: 894 unhandled = TRUE; 895 } 896 897 if (unhandled) 898 { 899 if (SWI_vector_installed) 900 { 901 ARMword cpsr; 902 ARMword i_size; 903 904 cpsr = ARMul_GetCPSR (state); 905 i_size = INSN_SIZE; 906 907 ARMul_SetSPSR (state, SVC32MODE, cpsr); 908 909 cpsr &= ~0xbf; 910 cpsr |= SVC32MODE | 0x80; 911 ARMul_SetCPSR (state, cpsr); 912 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 { 920 sim_callback->printf_filtered 921 (sim_callback, 922 "sim: unknown SWI encountered - %x - ignoring\n", 923 number); 924 return FALSE; 925 } 926 } 927 928 return TRUE; 929} 930 931#ifndef NOOS 932#ifndef ASIM 933 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!). */ 938 939unsigned 940ARMul_OSException (ARMul_State * state ATTRIBUTE_UNUSED, 941 ARMword vector ATTRIBUTE_UNUSED, 942 ARMword pc ATTRIBUTE_UNUSED) 943{ 944 return FALSE; 945} 946 947#endif 948#endif /* NOOS */ 949