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