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