1 #include "config.h" 2 #include <signal.h> 3 4 #include "sim-main.h" 5 #include "sim-options.h" 6 #include "sim-hw.h" 7 8 #include "bfd.h" 9 #include "sim-assert.h" 10 11 12 #ifdef HAVE_STDLIB_H 13 #include <stdlib.h> 14 #endif 15 16 #ifdef HAVE_STRING_H 17 #include <string.h> 18 #else 19 #ifdef HAVE_STRINGS_H 20 #include <strings.h> 21 #endif 22 #endif 23 24 #include "bfd.h" 25 26 27 host_callback *mn10300_callback; 28 struct _state State; 29 30 31 /* simulation target board. NULL=default configuration */ 32 static char* board = NULL; 33 34 static DECLARE_OPTION_HANDLER (mn10300_option_handler); 35 36 enum { 37 OPTION_BOARD = OPTION_START, 38 }; 39 40 static SIM_RC 41 mn10300_option_handler (SIM_DESC sd, 42 sim_cpu *cpu, 43 int opt, 44 char *arg, 45 int is_command) 46 { 47 int cpu_nr; 48 switch (opt) 49 { 50 case OPTION_BOARD: 51 { 52 if (arg) 53 { 54 board = zalloc(strlen(arg) + 1); 55 strcpy(board, arg); 56 } 57 return SIM_RC_OK; 58 } 59 } 60 61 return SIM_RC_OK; 62 } 63 64 static const OPTION mn10300_options[] = 65 { 66 #define BOARD_AM32 "stdeval1" 67 { {"board", required_argument, NULL, OPTION_BOARD}, 68 '\0', "none" /* rely on compile-time string concatenation for other options */ 69 "|" BOARD_AM32 70 , "Customize simulation for a particular board.", mn10300_option_handler }, 71 72 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL } 73 }; 74 75 /* For compatibility */ 76 SIM_DESC simulator; 77 78 static sim_cia 79 mn10300_pc_get (sim_cpu *cpu) 80 { 81 return PC; 82 } 83 84 static void 85 mn10300_pc_set (sim_cpu *cpu, sim_cia pc) 86 { 87 PC = pc; 88 } 89 90 /* These default values correspond to expected usage for the chip. */ 91 92 SIM_DESC 93 sim_open (SIM_OPEN_KIND kind, 94 host_callback *cb, 95 struct bfd *abfd, 96 char **argv) 97 { 98 int i; 99 SIM_DESC sd = sim_state_alloc (kind, cb); 100 mn10300_callback = cb; 101 102 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER); 103 104 /* The cpu data is kept in a separately allocated chunk of memory. */ 105 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK) 106 return 0; 107 108 /* for compatibility */ 109 simulator = sd; 110 111 /* FIXME: should be better way of setting up interrupts. For 112 moment, only support watchpoints causing a breakpoint (gdb 113 halt). */ 114 STATE_WATCHPOINTS (sd)->pc = &(PC); 115 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC); 116 STATE_WATCHPOINTS (sd)->interrupt_handler = NULL; 117 STATE_WATCHPOINTS (sd)->interrupt_names = NULL; 118 119 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) 120 return 0; 121 sim_add_option_table (sd, NULL, mn10300_options); 122 123 /* Allocate core managed memory */ 124 sim_do_command (sd, "memory region 0,0x100000"); 125 sim_do_command (sd, "memory region 0x40000000,0x200000"); 126 127 /* getopt will print the error message so we just have to exit if this fails. 128 FIXME: Hmmm... in the case of gdb we need getopt to call 129 print_filtered. */ 130 if (sim_parse_args (sd, argv) != SIM_RC_OK) 131 { 132 /* Uninstall the modules to avoid memory leaks, 133 file descriptor leaks, etc. */ 134 sim_module_uninstall (sd); 135 return 0; 136 } 137 138 if ( NULL != board 139 && (strcmp(board, BOARD_AM32) == 0 ) ) 140 { 141 /* environment */ 142 STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT; 143 144 sim_do_command (sd, "memory region 0x44000000,0x40000"); 145 sim_do_command (sd, "memory region 0x48000000,0x400000"); 146 147 /* device support for mn1030002 */ 148 /* interrupt controller */ 149 150 sim_hw_parse (sd, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8"); 151 152 /* DEBUG: NMI input's */ 153 sim_hw_parse (sd, "/glue@0x30000000/reg 0x30000000 12"); 154 sim_hw_parse (sd, "/glue@0x30000000 > int0 nmirq /mn103int"); 155 sim_hw_parse (sd, "/glue@0x30000000 > int1 watchdog /mn103int"); 156 sim_hw_parse (sd, "/glue@0x30000000 > int2 syserr /mn103int"); 157 158 /* DEBUG: ACK input */ 159 sim_hw_parse (sd, "/glue@0x30002000/reg 0x30002000 4"); 160 sim_hw_parse (sd, "/glue@0x30002000 > int ack /mn103int"); 161 162 /* DEBUG: LEVEL output */ 163 sim_hw_parse (sd, "/glue@0x30004000/reg 0x30004000 8"); 164 sim_hw_parse (sd, "/mn103int > nmi int0 /glue@0x30004000"); 165 sim_hw_parse (sd, "/mn103int > level int1 /glue@0x30004000"); 166 167 /* DEBUG: A bunch of interrupt inputs */ 168 sim_hw_parse (sd, "/glue@0x30006000/reg 0x30006000 32"); 169 sim_hw_parse (sd, "/glue@0x30006000 > int0 irq-0 /mn103int"); 170 sim_hw_parse (sd, "/glue@0x30006000 > int1 irq-1 /mn103int"); 171 sim_hw_parse (sd, "/glue@0x30006000 > int2 irq-2 /mn103int"); 172 sim_hw_parse (sd, "/glue@0x30006000 > int3 irq-3 /mn103int"); 173 sim_hw_parse (sd, "/glue@0x30006000 > int4 irq-4 /mn103int"); 174 sim_hw_parse (sd, "/glue@0x30006000 > int5 irq-5 /mn103int"); 175 sim_hw_parse (sd, "/glue@0x30006000 > int6 irq-6 /mn103int"); 176 sim_hw_parse (sd, "/glue@0x30006000 > int7 irq-7 /mn103int"); 177 178 /* processor interrupt device */ 179 180 /* the device */ 181 sim_hw_parse (sd, "/mn103cpu@0x20000000"); 182 sim_hw_parse (sd, "/mn103cpu@0x20000000/reg 0x20000000 0x42"); 183 184 /* DEBUG: ACK output wired upto a glue device */ 185 sim_hw_parse (sd, "/glue@0x20002000"); 186 sim_hw_parse (sd, "/glue@0x20002000/reg 0x20002000 4"); 187 sim_hw_parse (sd, "/mn103cpu > ack int0 /glue@0x20002000"); 188 189 /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */ 190 sim_hw_parse (sd, "/glue@0x20004000"); 191 sim_hw_parse (sd, "/glue@0x20004000/reg 0x20004000 12"); 192 sim_hw_parse (sd, "/glue@0x20004000 > int0 reset /mn103cpu"); 193 sim_hw_parse (sd, "/glue@0x20004000 > int1 nmi /mn103cpu"); 194 sim_hw_parse (sd, "/glue@0x20004000 > int2 level /mn103cpu"); 195 196 /* REAL: The processor wired up to the real interrupt controller */ 197 sim_hw_parse (sd, "/mn103cpu > ack ack /mn103int"); 198 sim_hw_parse (sd, "/mn103int > level level /mn103cpu"); 199 sim_hw_parse (sd, "/mn103int > nmi nmi /mn103cpu"); 200 201 202 /* PAL */ 203 204 /* the device */ 205 sim_hw_parse (sd, "/pal@0x31000000"); 206 sim_hw_parse (sd, "/pal@0x31000000/reg 0x31000000 64"); 207 sim_hw_parse (sd, "/pal@0x31000000/poll? true"); 208 209 /* DEBUG: PAL wired up to a glue device */ 210 sim_hw_parse (sd, "/glue@0x31002000"); 211 sim_hw_parse (sd, "/glue@0x31002000/reg 0x31002000 16"); 212 sim_hw_parse (sd, "/pal@0x31000000 > countdown int0 /glue@0x31002000"); 213 sim_hw_parse (sd, "/pal@0x31000000 > timer int1 /glue@0x31002000"); 214 sim_hw_parse (sd, "/pal@0x31000000 > int int2 /glue@0x31002000"); 215 sim_hw_parse (sd, "/glue@0x31002000 > int0 int3 /glue@0x31002000"); 216 sim_hw_parse (sd, "/glue@0x31002000 > int1 int3 /glue@0x31002000"); 217 sim_hw_parse (sd, "/glue@0x31002000 > int2 int3 /glue@0x31002000"); 218 219 /* REAL: The PAL wired up to the real interrupt controller */ 220 sim_hw_parse (sd, "/pal@0x31000000 > countdown irq-0 /mn103int"); 221 sim_hw_parse (sd, "/pal@0x31000000 > timer irq-1 /mn103int"); 222 sim_hw_parse (sd, "/pal@0x31000000 > int irq-2 /mn103int"); 223 224 /* 8 and 16 bit timers */ 225 sim_hw_parse (sd, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16"); 226 227 /* Hook timer interrupts up to interrupt controller */ 228 sim_hw_parse (sd, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int"); 229 sim_hw_parse (sd, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int"); 230 sim_hw_parse (sd, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int"); 231 sim_hw_parse (sd, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int"); 232 sim_hw_parse (sd, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int"); 233 sim_hw_parse (sd, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int"); 234 sim_hw_parse (sd, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int"); 235 sim_hw_parse (sd, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int"); 236 sim_hw_parse (sd, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int"); 237 238 239 /* Serial devices 0,1,2 */ 240 sim_hw_parse (sd, "/mn103ser@0x34000800/reg 0x34000800 48"); 241 sim_hw_parse (sd, "/mn103ser@0x34000800/poll? true"); 242 243 /* Hook serial interrupts up to interrupt controller */ 244 sim_hw_parse (sd, "/mn103ser > serial-0-receive serial-0-receive /mn103int"); 245 sim_hw_parse (sd, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int"); 246 sim_hw_parse (sd, "/mn103ser > serial-1-receive serial-1-receive /mn103int"); 247 sim_hw_parse (sd, "/mn103ser > serial-1-transmit serial-1-transmit /mn103int"); 248 sim_hw_parse (sd, "/mn103ser > serial-2-receive serial-2-receive /mn103int"); 249 sim_hw_parse (sd, "/mn103ser > serial-2-transmit serial-2-transmit /mn103int"); 250 251 sim_hw_parse (sd, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8"); 252 253 /* Memory control registers */ 254 sim_do_command (sd, "memory region 0x32000020,0x30"); 255 /* Cache control register */ 256 sim_do_command (sd, "memory region 0x20000070,0x4"); 257 /* Cache purge regions */ 258 sim_do_command (sd, "memory region 0x28400000,0x800"); 259 sim_do_command (sd, "memory region 0x28401000,0x800"); 260 /* DMA registers */ 261 sim_do_command (sd, "memory region 0x32000100,0xF"); 262 sim_do_command (sd, "memory region 0x32000200,0xF"); 263 sim_do_command (sd, "memory region 0x32000400,0xF"); 264 sim_do_command (sd, "memory region 0x32000800,0xF"); 265 } 266 else 267 { 268 if (board != NULL) 269 { 270 sim_io_eprintf (sd, "Error: Board `%s' unknown.\n", board); 271 return 0; 272 } 273 } 274 275 276 277 /* check for/establish the a reference program image */ 278 if (sim_analyze_program (sd, 279 (STATE_PROG_ARGV (sd) != NULL 280 ? *STATE_PROG_ARGV (sd) 281 : NULL), 282 abfd) != SIM_RC_OK) 283 { 284 sim_module_uninstall (sd); 285 return 0; 286 } 287 288 /* establish any remaining configuration options */ 289 if (sim_config (sd) != SIM_RC_OK) 290 { 291 sim_module_uninstall (sd); 292 return 0; 293 } 294 295 if (sim_post_argv_init (sd) != SIM_RC_OK) 296 { 297 /* Uninstall the modules to avoid memory leaks, 298 file descriptor leaks, etc. */ 299 sim_module_uninstall (sd); 300 return 0; 301 } 302 303 304 /* set machine specific configuration */ 305 /* STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */ 306 /* | PSW_CY | PSW_OV | PSW_S | PSW_Z); */ 307 308 /* CPU specific initialization. */ 309 for (i = 0; i < MAX_NR_PROCESSORS; ++i) 310 { 311 SIM_CPU *cpu = STATE_CPU (sd, i); 312 313 CPU_PC_FETCH (cpu) = mn10300_pc_get; 314 CPU_PC_STORE (cpu) = mn10300_pc_set; 315 } 316 317 return sd; 318 } 319 320 321 void 322 sim_close (SIM_DESC sd, int quitting) 323 { 324 sim_module_uninstall (sd); 325 } 326 327 328 SIM_RC 329 sim_create_inferior (SIM_DESC sd, 330 struct bfd *prog_bfd, 331 char **argv, 332 char **env) 333 { 334 memset (&State, 0, sizeof (State)); 335 if (prog_bfd != NULL) { 336 PC = bfd_get_start_address (prog_bfd); 337 } else { 338 PC = 0; 339 } 340 CPU_PC_SET (STATE_CPU (sd, 0), (unsigned64) PC); 341 342 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_am33_2) 343 PSW |= PSW_FE; 344 345 return SIM_RC_OK; 346 } 347 348 /* FIXME These would more efficient to use than load_mem/store_mem, 349 but need to be changed to use the memory map. */ 350 351 int 352 sim_fetch_register (SIM_DESC sd, 353 int rn, 354 unsigned char *memory, 355 int length) 356 { 357 reg_t reg = State.regs[rn]; 358 uint8 *a = memory; 359 a[0] = reg; 360 a[1] = reg >> 8; 361 a[2] = reg >> 16; 362 a[3] = reg >> 24; 363 return length; 364 } 365 366 int 367 sim_store_register (SIM_DESC sd, 368 int rn, 369 unsigned char *memory, 370 int length) 371 { 372 uint8 *a = memory; 373 State.regs[rn] = (a[3] << 24) + (a[2] << 16) + (a[1] << 8) + a[0]; 374 return length; 375 } 376 377 void 378 mn10300_core_signal (SIM_DESC sd, 379 sim_cpu *cpu, 380 sim_cia cia, 381 unsigned map, 382 int nr_bytes, 383 address_word addr, 384 transfer_type transfer, 385 sim_core_signals sig) 386 { 387 const char *copy = (transfer == read_transfer ? "read" : "write"); 388 address_word ip = CIA_ADDR (cia); 389 390 switch (sig) 391 { 392 case sim_core_unmapped_signal: 393 sim_io_eprintf (sd, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n", 394 nr_bytes, copy, 395 (unsigned long) addr, (unsigned long) ip); 396 program_interrupt(sd, cpu, cia, SIM_SIGSEGV); 397 break; 398 399 case sim_core_unaligned_signal: 400 sim_io_eprintf (sd, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n", 401 nr_bytes, copy, 402 (unsigned long) addr, (unsigned long) ip); 403 program_interrupt(sd, cpu, cia, SIM_SIGBUS); 404 break; 405 406 default: 407 sim_engine_abort (sd, cpu, cia, 408 "mn10300_core_signal - internal error - bad switch"); 409 } 410 } 411 412 413 void 414 program_interrupt (SIM_DESC sd, 415 sim_cpu *cpu, 416 sim_cia cia, 417 SIM_SIGNAL sig) 418 { 419 int status; 420 struct hw *device; 421 static int in_interrupt = 0; 422 423 #ifdef SIM_CPU_EXCEPTION_TRIGGER 424 SIM_CPU_EXCEPTION_TRIGGER(sd,cpu,cia); 425 #endif 426 427 /* avoid infinite recursion */ 428 if (in_interrupt) 429 { 430 (*mn10300_callback->printf_filtered) (mn10300_callback, 431 "ERROR: recursion in program_interrupt during software exception dispatch."); 432 } 433 else 434 { 435 in_interrupt = 1; 436 /* copy NMI handler code from dv-mn103cpu.c */ 437 store_word (SP - 4, CPU_PC_GET (cpu)); 438 store_half (SP - 8, PSW); 439 440 /* Set the SYSEF flag in NMICR by backdoor method. See 441 dv-mn103int.c:write_icr(). This is necessary because 442 software exceptions are not modelled by actually talking to 443 the interrupt controller, so it cannot set its own SYSEF 444 flag. */ 445 if ((NULL != board) && (strcmp(board, BOARD_AM32) == 0)) 446 store_byte (0x34000103, 0x04); 447 } 448 449 PSW &= ~PSW_IE; 450 SP = SP - 8; 451 CPU_PC_SET (cpu, 0x40000008); 452 453 in_interrupt = 0; 454 sim_engine_halt(sd, cpu, NULL, cia, sim_stopped, sig); 455 } 456 457 458 void 459 mn10300_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia) 460 { 461 ASSERT(cpu != NULL); 462 463 if(State.exc_suspended > 0) 464 sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", State.exc_suspended); 465 466 CPU_PC_SET (cpu, cia); 467 memcpy(State.exc_trigger_regs, State.regs, sizeof(State.exc_trigger_regs)); 468 State.exc_suspended = 0; 469 } 470 471 void 472 mn10300_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception) 473 { 474 ASSERT(cpu != NULL); 475 476 if(State.exc_suspended > 0) 477 sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n", 478 State.exc_suspended, exception); 479 480 memcpy(State.exc_suspend_regs, State.regs, sizeof(State.exc_suspend_regs)); 481 memcpy(State.regs, State.exc_trigger_regs, sizeof(State.regs)); 482 CPU_PC_SET (cpu, PC); /* copy PC back from new State.regs */ 483 State.exc_suspended = exception; 484 } 485 486 void 487 mn10300_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception) 488 { 489 ASSERT(cpu != NULL); 490 491 if(exception == 0 && State.exc_suspended > 0) 492 { 493 if(State.exc_suspended != SIGTRAP) /* warn not for breakpoints */ 494 sim_io_eprintf(sd, "Warning, resuming but ignoring pending exception signal (%d)\n", 495 State.exc_suspended); 496 } 497 else if(exception != 0 && State.exc_suspended > 0) 498 { 499 if(exception != State.exc_suspended) 500 sim_io_eprintf(sd, "Warning, resuming with mismatched exception signal (%d vs %d)\n", 501 State.exc_suspended, exception); 502 503 memcpy(State.regs, State.exc_suspend_regs, sizeof(State.regs)); 504 CPU_PC_SET (cpu, PC); /* copy PC back from new State.regs */ 505 } 506 else if(exception != 0 && State.exc_suspended == 0) 507 { 508 sim_io_eprintf(sd, "Warning, ignoring spontanous exception signal (%d)\n", exception); 509 } 510 State.exc_suspended = 0; 511 } 512 513 /* This is called when an FP instruction is issued when the FP unit is 514 disabled, i.e., the FE bit of PSW is zero. It raises interrupt 515 code 0x1c0. */ 516 void 517 fpu_disabled_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia) 518 { 519 sim_io_eprintf(sd, "FPU disabled exception\n"); 520 program_interrupt (sd, cpu, cia, SIM_SIGFPE); 521 } 522 523 /* This is called when the FP unit is enabled but one of the 524 unimplemented insns is issued. It raises interrupt code 0x1c8. */ 525 void 526 fpu_unimp_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia) 527 { 528 sim_io_eprintf(sd, "Unimplemented FPU instruction exception\n"); 529 program_interrupt (sd, cpu, cia, SIM_SIGFPE); 530 } 531 532 /* This is called at the end of any FP insns that may have triggered 533 FP exceptions. If no exception is enabled, it returns immediately. 534 Otherwise, it raises an exception code 0x1d0. */ 535 void 536 fpu_check_signal_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia) 537 { 538 if ((FPCR & EC_MASK) == 0) 539 return; 540 541 sim_io_eprintf(sd, "FPU %s%s%s%s%s exception\n", 542 (FPCR & EC_V) ? "V" : "", 543 (FPCR & EC_Z) ? "Z" : "", 544 (FPCR & EC_O) ? "O" : "", 545 (FPCR & EC_U) ? "U" : "", 546 (FPCR & EC_I) ? "I" : ""); 547 program_interrupt (sd, cpu, cia, SIM_SIGFPE); 548 } 549 550 /* Convert a 32-bit single-precision FP value in the target platform 551 format to a sim_fpu value. */ 552 static void 553 reg2val_32 (const void *reg, sim_fpu *val) 554 { 555 FS2FPU (*(reg_t *)reg, *val); 556 } 557 558 /* Round the given sim_fpu value to single precision, following the 559 target platform rounding and denormalization conventions. On 560 AM33/2.0, round_near is the only rounding mode. */ 561 static int 562 round_32 (sim_fpu *val) 563 { 564 return sim_fpu_round_32 (val, sim_fpu_round_near, sim_fpu_denorm_zero); 565 } 566 567 /* Convert a sim_fpu value to the 32-bit single-precision target 568 representation. */ 569 static void 570 val2reg_32 (const sim_fpu *val, void *reg) 571 { 572 FPU2FS (*val, *(reg_t *)reg); 573 } 574 575 /* Define the 32-bit single-precision conversion and rounding uniform 576 interface. */ 577 const struct fp_prec_t 578 fp_single_prec = { 579 reg2val_32, round_32, val2reg_32 580 }; 581 582 /* Convert a 64-bit double-precision FP value in the target platform 583 format to a sim_fpu value. */ 584 static void 585 reg2val_64 (const void *reg, sim_fpu *val) 586 { 587 FD2FPU (*(dword *)reg, *val); 588 } 589 590 /* Round the given sim_fpu value to double precision, following the 591 target platform rounding and denormalization conventions. On 592 AM33/2.0, round_near is the only rounding mode. */ 593 static int 594 round_64 (sim_fpu *val) 595 { 596 return sim_fpu_round_64 (val, sim_fpu_round_near, sim_fpu_denorm_zero); 597 } 598 599 /* Convert a sim_fpu value to the 64-bit double-precision target 600 representation. */ 601 static void 602 val2reg_64 (const sim_fpu *val, void *reg) 603 { 604 FPU2FD (*val, *(dword *)reg); 605 } 606 607 /* Define the 64-bit single-precision conversion and rounding uniform 608 interface. */ 609 const struct fp_prec_t 610 fp_double_prec = { 611 reg2val_64, round_64, val2reg_64 612 }; 613 614 /* Define shortcuts to the uniform interface operations. */ 615 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val) 616 #define ROUND(val) (*ops->round) (val) 617 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg) 618 619 /* Check whether overflow, underflow or inexact exceptions should be 620 raised. */ 621 static int 622 fpu_status_ok (sim_fpu_status stat) 623 { 624 if ((stat & sim_fpu_status_overflow) 625 && (FPCR & EE_O)) 626 FPCR |= EC_O; 627 else if ((stat & (sim_fpu_status_underflow | sim_fpu_status_denorm)) 628 && (FPCR & EE_U)) 629 FPCR |= EC_U; 630 else if ((stat & (sim_fpu_status_inexact | sim_fpu_status_rounded)) 631 && (FPCR & EE_I)) 632 FPCR |= EC_I; 633 else if (stat & ~ (sim_fpu_status_overflow 634 | sim_fpu_status_underflow 635 | sim_fpu_status_denorm 636 | sim_fpu_status_inexact 637 | sim_fpu_status_rounded)) 638 abort (); 639 else 640 return 1; 641 return 0; 642 } 643 644 /* Implement a 32/64 bit reciprocal square root, signaling FP 645 exceptions when appropriate. */ 646 void 647 fpu_rsqrt (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, 648 const void *reg_in, void *reg_out, const struct fp_prec_t *ops) 649 { 650 sim_fpu in, med, out; 651 652 REG2VAL (reg_in, &in); 653 ROUND (&in); 654 FPCR &= ~ EC_MASK; 655 switch (sim_fpu_is (&in)) 656 { 657 case SIM_FPU_IS_SNAN: 658 case SIM_FPU_IS_NNUMBER: 659 case SIM_FPU_IS_NINF: 660 if (FPCR & EE_V) 661 FPCR |= EC_V; 662 else 663 VAL2REG (&sim_fpu_qnan, reg_out); 664 break; 665 666 case SIM_FPU_IS_QNAN: 667 VAL2REG (&sim_fpu_qnan, reg_out); 668 break; 669 670 case SIM_FPU_IS_PINF: 671 VAL2REG (&sim_fpu_zero, reg_out); 672 break; 673 674 case SIM_FPU_IS_PNUMBER: 675 { 676 /* Since we don't have a function to compute rsqrt directly, 677 use sqrt and inv. */ 678 sim_fpu_status stat = 0; 679 stat |= sim_fpu_sqrt (&med, &in); 680 stat |= sim_fpu_inv (&out, &med); 681 stat |= ROUND (&out); 682 if (fpu_status_ok (stat)) 683 VAL2REG (&out, reg_out); 684 } 685 break; 686 687 case SIM_FPU_IS_NZERO: 688 case SIM_FPU_IS_PZERO: 689 if (FPCR & EE_Z) 690 FPCR |= EC_Z; 691 else 692 { 693 /* Generate an INF with the same sign. */ 694 sim_fpu_inv (&out, &in); 695 VAL2REG (&out, reg_out); 696 } 697 break; 698 699 default: 700 abort (); 701 } 702 703 fpu_check_signal_exception (sd, cpu, cia); 704 } 705 706 static inline reg_t 707 cmp2fcc (int res) 708 { 709 switch (res) 710 { 711 case SIM_FPU_IS_SNAN: 712 case SIM_FPU_IS_QNAN: 713 return FCC_U; 714 715 case SIM_FPU_IS_NINF: 716 case SIM_FPU_IS_NNUMBER: 717 case SIM_FPU_IS_NDENORM: 718 return FCC_L; 719 720 case SIM_FPU_IS_PINF: 721 case SIM_FPU_IS_PNUMBER: 722 case SIM_FPU_IS_PDENORM: 723 return FCC_G; 724 725 case SIM_FPU_IS_NZERO: 726 case SIM_FPU_IS_PZERO: 727 return FCC_E; 728 729 default: 730 abort (); 731 } 732 } 733 734 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or 735 exception bits as specified. */ 736 void 737 fpu_cmp (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, 738 const void *reg_in1, const void *reg_in2, 739 const struct fp_prec_t *ops) 740 { 741 sim_fpu m, n; 742 743 REG2VAL (reg_in1, &m); 744 REG2VAL (reg_in2, &n); 745 FPCR &= ~ EC_MASK; 746 FPCR &= ~ FCC_MASK; 747 ROUND (&m); 748 ROUND (&n); 749 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)) 750 { 751 if (FPCR & EE_V) 752 FPCR |= EC_V; 753 else 754 FPCR |= FCC_U; 755 } 756 else 757 FPCR |= cmp2fcc (sim_fpu_cmp (&m, &n)); 758 759 fpu_check_signal_exception (sd, cpu, cia); 760 } 761 762 /* Implement a 32/64 bit FP add, setting FP exception bits when 763 appropriate. */ 764 void 765 fpu_add (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, 766 const void *reg_in1, const void *reg_in2, 767 void *reg_out, const struct fp_prec_t *ops) 768 { 769 sim_fpu m, n, r; 770 771 REG2VAL (reg_in1, &m); 772 REG2VAL (reg_in2, &n); 773 ROUND (&m); 774 ROUND (&n); 775 FPCR &= ~ EC_MASK; 776 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n) 777 || (sim_fpu_is (&m) == SIM_FPU_IS_PINF 778 && sim_fpu_is (&n) == SIM_FPU_IS_NINF) 779 || (sim_fpu_is (&m) == SIM_FPU_IS_NINF 780 && sim_fpu_is (&n) == SIM_FPU_IS_PINF)) 781 { 782 if (FPCR & EE_V) 783 FPCR |= EC_V; 784 else 785 VAL2REG (&sim_fpu_qnan, reg_out); 786 } 787 else 788 { 789 sim_fpu_status stat = sim_fpu_add (&r, &m, &n); 790 stat |= ROUND (&r); 791 if (fpu_status_ok (stat)) 792 VAL2REG (&r, reg_out); 793 } 794 795 fpu_check_signal_exception (sd, cpu, cia); 796 } 797 798 /* Implement a 32/64 bit FP sub, setting FP exception bits when 799 appropriate. */ 800 void 801 fpu_sub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, 802 const void *reg_in1, const void *reg_in2, 803 void *reg_out, const struct fp_prec_t *ops) 804 { 805 sim_fpu m, n, r; 806 807 REG2VAL (reg_in1, &m); 808 REG2VAL (reg_in2, &n); 809 ROUND (&m); 810 ROUND (&n); 811 FPCR &= ~ EC_MASK; 812 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n) 813 || (sim_fpu_is (&m) == SIM_FPU_IS_PINF 814 && sim_fpu_is (&n) == SIM_FPU_IS_PINF) 815 || (sim_fpu_is (&m) == SIM_FPU_IS_NINF 816 && sim_fpu_is (&n) == SIM_FPU_IS_NINF)) 817 { 818 if (FPCR & EE_V) 819 FPCR |= EC_V; 820 else 821 VAL2REG (&sim_fpu_qnan, reg_out); 822 } 823 else 824 { 825 sim_fpu_status stat = sim_fpu_sub (&r, &m, &n); 826 stat |= ROUND (&r); 827 if (fpu_status_ok (stat)) 828 VAL2REG (&r, reg_out); 829 } 830 831 fpu_check_signal_exception (sd, cpu, cia); 832 } 833 834 /* Implement a 32/64 bit FP mul, setting FP exception bits when 835 appropriate. */ 836 void 837 fpu_mul (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, 838 const void *reg_in1, const void *reg_in2, 839 void *reg_out, const struct fp_prec_t *ops) 840 { 841 sim_fpu m, n, r; 842 843 REG2VAL (reg_in1, &m); 844 REG2VAL (reg_in2, &n); 845 ROUND (&m); 846 ROUND (&n); 847 FPCR &= ~ EC_MASK; 848 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n) 849 || (sim_fpu_is_infinity (&m) && sim_fpu_is_zero (&n)) 850 || (sim_fpu_is_zero (&m) && sim_fpu_is_infinity (&n))) 851 { 852 if (FPCR & EE_V) 853 FPCR |= EC_V; 854 else 855 VAL2REG (&sim_fpu_qnan, reg_out); 856 } 857 else 858 { 859 sim_fpu_status stat = sim_fpu_mul (&r, &m, &n); 860 stat |= ROUND (&r); 861 if (fpu_status_ok (stat)) 862 VAL2REG (&r, reg_out); 863 } 864 865 fpu_check_signal_exception (sd, cpu, cia); 866 } 867 868 /* Implement a 32/64 bit FP div, setting FP exception bits when 869 appropriate. */ 870 void 871 fpu_div (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, 872 const void *reg_in1, const void *reg_in2, 873 void *reg_out, const struct fp_prec_t *ops) 874 { 875 sim_fpu m, n, r; 876 877 REG2VAL (reg_in1, &m); 878 REG2VAL (reg_in2, &n); 879 ROUND (&m); 880 ROUND (&n); 881 FPCR &= ~ EC_MASK; 882 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n) 883 || (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)) 884 || (sim_fpu_is_zero (&m) && sim_fpu_is_zero (&n))) 885 { 886 if (FPCR & EE_V) 887 FPCR |= EC_V; 888 else 889 VAL2REG (&sim_fpu_qnan, reg_out); 890 } 891 else if (sim_fpu_is_number (&m) && sim_fpu_is_zero (&n) 892 && (FPCR & EE_Z)) 893 FPCR |= EC_Z; 894 else 895 { 896 sim_fpu_status stat = sim_fpu_div (&r, &m, &n); 897 stat |= ROUND (&r); 898 if (fpu_status_ok (stat)) 899 VAL2REG (&r, reg_out); 900 } 901 902 fpu_check_signal_exception (sd, cpu, cia); 903 } 904 905 /* Implement a 32/64 bit FP madd, setting FP exception bits when 906 appropriate. */ 907 void 908 fpu_fmadd (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, 909 const void *reg_in1, const void *reg_in2, const void *reg_in3, 910 void *reg_out, const struct fp_prec_t *ops) 911 { 912 sim_fpu m1, m2, m, n, r; 913 914 REG2VAL (reg_in1, &m1); 915 REG2VAL (reg_in2, &m2); 916 REG2VAL (reg_in3, &n); 917 ROUND (&m1); 918 ROUND (&m2); 919 ROUND (&n); 920 FPCR &= ~ EC_MASK; 921 if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n) 922 || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2)) 923 || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2))) 924 { 925 invalid_operands: 926 if (FPCR & EE_V) 927 FPCR |= EC_V; 928 else 929 VAL2REG (&sim_fpu_qnan, reg_out); 930 } 931 else 932 { 933 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2); 934 935 if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n) 936 && sim_fpu_sign (&m) != sim_fpu_sign (&n)) 937 goto invalid_operands; 938 939 stat |= sim_fpu_add (&r, &m, &n); 940 stat |= ROUND (&r); 941 if (fpu_status_ok (stat)) 942 VAL2REG (&r, reg_out); 943 } 944 945 fpu_check_signal_exception (sd, cpu, cia); 946 } 947 948 /* Implement a 32/64 bit FP msub, setting FP exception bits when 949 appropriate. */ 950 void 951 fpu_fmsub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, 952 const void *reg_in1, const void *reg_in2, const void *reg_in3, 953 void *reg_out, const struct fp_prec_t *ops) 954 { 955 sim_fpu m1, m2, m, n, r; 956 957 REG2VAL (reg_in1, &m1); 958 REG2VAL (reg_in2, &m2); 959 REG2VAL (reg_in3, &n); 960 ROUND (&m1); 961 ROUND (&m2); 962 ROUND (&n); 963 FPCR &= ~ EC_MASK; 964 if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n) 965 || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2)) 966 || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2))) 967 { 968 invalid_operands: 969 if (FPCR & EE_V) 970 FPCR |= EC_V; 971 else 972 VAL2REG (&sim_fpu_qnan, reg_out); 973 } 974 else 975 { 976 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2); 977 978 if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n) 979 && sim_fpu_sign (&m) == sim_fpu_sign (&n)) 980 goto invalid_operands; 981 982 stat |= sim_fpu_sub (&r, &m, &n); 983 stat |= ROUND (&r); 984 if (fpu_status_ok (stat)) 985 VAL2REG (&r, reg_out); 986 } 987 988 fpu_check_signal_exception (sd, cpu, cia); 989 } 990 991 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when 992 appropriate. */ 993 void 994 fpu_fnmadd (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, 995 const void *reg_in1, const void *reg_in2, const void *reg_in3, 996 void *reg_out, const struct fp_prec_t *ops) 997 { 998 sim_fpu m1, m2, m, mm, n, r; 999 1000 REG2VAL (reg_in1, &m1); 1001 REG2VAL (reg_in2, &m2); 1002 REG2VAL (reg_in3, &n); 1003 ROUND (&m1); 1004 ROUND (&m2); 1005 ROUND (&n); 1006 FPCR &= ~ EC_MASK; 1007 if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n) 1008 || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2)) 1009 || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2))) 1010 { 1011 invalid_operands: 1012 if (FPCR & EE_V) 1013 FPCR |= EC_V; 1014 else 1015 VAL2REG (&sim_fpu_qnan, reg_out); 1016 } 1017 else 1018 { 1019 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2); 1020 1021 if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n) 1022 && sim_fpu_sign (&m) == sim_fpu_sign (&n)) 1023 goto invalid_operands; 1024 1025 stat |= sim_fpu_neg (&mm, &m); 1026 stat |= sim_fpu_add (&r, &mm, &n); 1027 stat |= ROUND (&r); 1028 if (fpu_status_ok (stat)) 1029 VAL2REG (&r, reg_out); 1030 } 1031 1032 fpu_check_signal_exception (sd, cpu, cia); 1033 } 1034 1035 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when 1036 appropriate. */ 1037 void 1038 fpu_fnmsub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, 1039 const void *reg_in1, const void *reg_in2, const void *reg_in3, 1040 void *reg_out, const struct fp_prec_t *ops) 1041 { 1042 sim_fpu m1, m2, m, mm, n, r; 1043 1044 REG2VAL (reg_in1, &m1); 1045 REG2VAL (reg_in2, &m2); 1046 REG2VAL (reg_in3, &n); 1047 ROUND (&m1); 1048 ROUND (&m2); 1049 ROUND (&n); 1050 FPCR &= ~ EC_MASK; 1051 if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n) 1052 || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2)) 1053 || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2))) 1054 { 1055 invalid_operands: 1056 if (FPCR & EE_V) 1057 FPCR |= EC_V; 1058 else 1059 VAL2REG (&sim_fpu_qnan, reg_out); 1060 } 1061 else 1062 { 1063 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2); 1064 1065 if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n) 1066 && sim_fpu_sign (&m) != sim_fpu_sign (&n)) 1067 goto invalid_operands; 1068 1069 stat |= sim_fpu_neg (&mm, &m); 1070 stat |= sim_fpu_sub (&r, &mm, &n); 1071 stat |= ROUND (&r); 1072 if (fpu_status_ok (stat)) 1073 VAL2REG (&r, reg_out); 1074 } 1075 1076 fpu_check_signal_exception (sd, cpu, cia); 1077 } 1078