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