1 /* This must come before any other includes. */
7 #include "sim-options.h"
11 #include "sim-assert.h"
12 #include "sim-signal.h"
23 /* simulation target board. NULL=default configuration */
24 static char* board = NULL;
26 static DECLARE_OPTION_HANDLER (mn10300_option_handler);
29 OPTION_BOARD = OPTION_START,
33 mn10300_option_handler (SIM_DESC sd,
46 board = zalloc(strlen(arg) + 1);
56 static const OPTION mn10300_options[] =
58 #define BOARD_AM32 "stdeval1"
59 { {"board", required_argument, NULL, OPTION_BOARD},
60 '\0', "none" /* rely on compile-time string concatenation for other options */
62 , "Customize simulation for a particular board.", mn10300_option_handler },
64 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
67 /* For compatibility */
71 mn10300_pc_get (sim_cpu *cpu)
77 mn10300_pc_set (sim_cpu *cpu, sim_cia pc)
82 static int mn10300_reg_fetch (SIM_CPU *, int, void *, int);
83 static int mn10300_reg_store (SIM_CPU *, int, const void *, int);
85 /* These default values correspond to expected usage for the chip. */
88 sim_open (SIM_OPEN_KIND kind,
94 SIM_DESC sd = sim_state_alloc (kind, cb);
96 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
98 /* Set default options before parsing user options. */
99 current_target_byte_order = BFD_ENDIAN_LITTLE;
101 /* The cpu data is kept in a separately allocated chunk of memory. */
102 if (sim_cpu_alloc_all (sd, 1) != SIM_RC_OK)
105 /* for compatibility */
108 /* FIXME: should be better way of setting up interrupts. For
109 moment, only support watchpoints causing a breakpoint (gdb
111 STATE_WATCHPOINTS (sd)->interrupt_handler = NULL;
112 STATE_WATCHPOINTS (sd)->interrupt_names = NULL;
114 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
116 sim_add_option_table (sd, NULL, mn10300_options);
118 /* Allocate core managed memory */
119 sim_do_command (sd, "memory region 0,0x100000");
120 sim_do_command (sd, "memory region 0x40000000,0x200000");
122 /* The parser will print an error message for us, so we silently return. */
123 if (sim_parse_args (sd, argv) != SIM_RC_OK)
125 /* Uninstall the modules to avoid memory leaks,
126 file descriptor leaks, etc. */
127 sim_module_uninstall (sd);
132 && (strcmp(board, BOARD_AM32) == 0 ) )
135 STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
137 sim_do_command (sd, "memory region 0x44000000,0x40000");
138 sim_do_command (sd, "memory region 0x48000000,0x400000");
140 /* device support for mn1030002 */
141 /* interrupt controller */
143 sim_hw_parse (sd, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
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");
151 /* DEBUG: ACK input */
152 sim_hw_parse (sd, "/glue@0x30002000/reg 0x30002000 4");
153 sim_hw_parse (sd, "/glue@0x30002000 > int ack /mn103int");
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");
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");
171 /* processor interrupt device */
174 sim_hw_parse (sd, "/mn103cpu@0x20000000");
175 sim_hw_parse (sd, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
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");
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");
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");
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");
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");
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");
217 /* 8 and 16 bit timers */
218 sim_hw_parse (sd, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16");
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");
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");
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");
244 sim_hw_parse (sd, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
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");
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");
263 sim_io_eprintf (sd, "Error: Board `%s' unknown.\n", board);
270 /* check for/establish the a reference program image */
271 if (sim_analyze_program (sd, STATE_PROG_FILE (sd), abfd) != SIM_RC_OK)
273 sim_module_uninstall (sd);
277 /* establish any remaining configuration options */
278 if (sim_config (sd) != SIM_RC_OK)
280 sim_module_uninstall (sd);
284 if (sim_post_argv_init (sd) != SIM_RC_OK)
286 /* Uninstall the modules to avoid memory leaks,
287 file descriptor leaks, etc. */
288 sim_module_uninstall (sd);
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); */
297 /* CPU specific initialization. */
298 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
300 SIM_CPU *cpu = STATE_CPU (sd, i);
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;
312 sim_create_inferior (SIM_DESC sd,
313 struct bfd *prog_bfd,
317 memset (&State, 0, sizeof (State));
318 if (prog_bfd != NULL) {
319 PC = bfd_get_start_address (prog_bfd);
323 CPU_PC_SET (STATE_CPU (sd, 0), (uint64_t) PC);
325 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_am33_2)
331 /* FIXME These would more efficient to use than load_mem/store_mem,
332 but need to be changed to use the memory map. */
335 mn10300_reg_fetch (SIM_CPU *cpu, int rn, void *memory, int length)
337 reg_t reg = State.regs[rn];
347 mn10300_reg_store (SIM_CPU *cpu, int rn, const void *memory, int length)
349 const uint8_t *a = memory;
350 State.regs[rn] = (a[3] << 24) + (a[2] << 16) + (a[1] << 8) + a[0];
355 mn10300_core_signal (SIM_DESC sd,
361 transfer_type transfer,
362 sim_core_signals sig)
364 const char *copy = (transfer == read_transfer ? "read" : "write");
365 address_word ip = CIA_ADDR (cia);
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",
372 (unsigned long) addr, (unsigned long) ip);
373 program_interrupt(sd, cpu, cia, SIM_SIGSEGV);
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",
379 (unsigned long) addr, (unsigned long) ip);
380 program_interrupt(sd, cpu, cia, SIM_SIGBUS);
384 sim_engine_abort (sd, cpu, cia,
385 "mn10300_core_signal - internal error - bad switch");
391 program_interrupt (SIM_DESC sd,
398 static int in_interrupt = 0;
400 #ifdef SIM_CPU_EXCEPTION_TRIGGER
401 SIM_CPU_EXCEPTION_TRIGGER(sd,cpu,cia);
404 /* avoid infinite recursion */
406 sim_io_printf (sd, "ERROR: recursion in program_interrupt during software exception dispatch.");
410 /* copy NMI handler code from dv-mn103cpu.c */
411 store_word (SP - 4, CPU_PC_GET (cpu));
412 store_half (SP - 8, PSW);
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
419 if ((NULL != board) && (strcmp(board, BOARD_AM32) == 0))
420 store_byte (0x34000103, 0x04);
425 CPU_PC_SET (cpu, 0x40000008);
428 sim_engine_halt(sd, cpu, NULL, cia, sim_stopped, sig);
433 mn10300_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia)
437 if(State.exc_suspended > 0)
438 sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", State.exc_suspended);
440 CPU_PC_SET (cpu, cia);
441 memcpy(State.exc_trigger_regs, State.regs, sizeof(State.exc_trigger_regs));
442 State.exc_suspended = 0;
446 mn10300_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception)
450 if(State.exc_suspended > 0)
451 sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n",
452 State.exc_suspended, exception);
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;
461 mn10300_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception)
465 if(exception == 0 && State.exc_suspended > 0)
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);
474 else if(exception != 0 && State.exc_suspended > 0)
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);
480 memcpy(State.regs, State.exc_suspend_regs, sizeof(State.regs));
481 CPU_PC_SET (cpu, PC); /* copy PC back from new State.regs */
483 else if(exception != 0 && State.exc_suspended == 0)
485 sim_io_eprintf(sd, "Warning, ignoring spontanous exception signal (%d)\n", exception);
487 State.exc_suspended = 0;
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
494 fpu_disabled_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
496 sim_io_eprintf(sd, "FPU disabled exception\n");
497 program_interrupt (sd, cpu, cia, SIM_SIGFPE);
500 /* This is called when the FP unit is enabled but one of the
501 unimplemented insns is issued. It raises interrupt code 0x1c8. */
503 fpu_unimp_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
505 sim_io_eprintf(sd, "Unimplemented FPU instruction exception\n");
506 program_interrupt (sd, cpu, cia, SIM_SIGFPE);
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. */
513 fpu_check_signal_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
515 if ((FPCR & EC_MASK) == 0)
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);
527 /* Convert a 32-bit single-precision FP value in the target platform
528 format to a sim_fpu value. */
530 reg2val_32 (const void *reg, sim_fpu *val)
532 FS2FPU (*(reg_t *)reg, *val);
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. */
539 round_32 (sim_fpu *val)
541 return sim_fpu_round_32 (val, sim_fpu_round_near, sim_fpu_denorm_zero);
544 /* Convert a sim_fpu value to the 32-bit single-precision target
547 val2reg_32 (const sim_fpu *val, void *reg)
549 FPU2FS (*val, *(reg_t *)reg);
552 /* Define the 32-bit single-precision conversion and rounding uniform
554 const struct fp_prec_t
556 reg2val_32, round_32, val2reg_32
559 /* Convert a 64-bit double-precision FP value in the target platform
560 format to a sim_fpu value. */
562 reg2val_64 (const void *reg, sim_fpu *val)
564 FD2FPU (*(dword *)reg, *val);
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. */
571 round_64 (sim_fpu *val)
573 return sim_fpu_round_64 (val, sim_fpu_round_near, sim_fpu_denorm_zero);
576 /* Convert a sim_fpu value to the 64-bit double-precision target
579 val2reg_64 (const sim_fpu *val, void *reg)
581 FPU2FD (*val, *(dword *)reg);
584 /* Define the 64-bit single-precision conversion and rounding uniform
586 const struct fp_prec_t
588 reg2val_64, round_64, val2reg_64
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)
596 /* Check whether overflow, underflow or inexact exceptions should be
599 fpu_status_ok (sim_fpu_status stat)
601 if ((stat & sim_fpu_status_overflow)
604 else if ((stat & (sim_fpu_status_underflow | sim_fpu_status_denorm))
607 else if ((stat & (sim_fpu_status_inexact | sim_fpu_status_rounded))
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))
621 /* Implement a 32/64 bit reciprocal square root, signaling FP
622 exceptions when appropriate. */
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)
627 sim_fpu in, med, out;
629 REG2VAL (reg_in, &in);
632 switch (sim_fpu_is (&in))
634 case SIM_FPU_IS_SNAN:
635 case SIM_FPU_IS_NNUMBER:
636 case SIM_FPU_IS_NINF:
640 VAL2REG (&sim_fpu_qnan, reg_out);
643 case SIM_FPU_IS_QNAN:
644 VAL2REG (&sim_fpu_qnan, reg_out);
647 case SIM_FPU_IS_PINF:
648 VAL2REG (&sim_fpu_zero, reg_out);
651 case SIM_FPU_IS_PNUMBER:
653 /* Since we don't have a function to compute rsqrt directly,
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);
664 case SIM_FPU_IS_NZERO:
665 case SIM_FPU_IS_PZERO:
670 /* Generate an INF with the same sign. */
671 sim_fpu_inv (&out, &in);
672 VAL2REG (&out, reg_out);
680 fpu_check_signal_exception (sd, cpu, cia);
688 case SIM_FPU_IS_SNAN:
689 case SIM_FPU_IS_QNAN:
692 case SIM_FPU_IS_NINF:
693 case SIM_FPU_IS_NNUMBER:
694 case SIM_FPU_IS_NDENORM:
697 case SIM_FPU_IS_PINF:
698 case SIM_FPU_IS_PNUMBER:
699 case SIM_FPU_IS_PDENORM:
702 case SIM_FPU_IS_NZERO:
703 case SIM_FPU_IS_PZERO:
711 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
712 exception bits as specified. */
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)
720 REG2VAL (reg_in1, &m);
721 REG2VAL (reg_in2, &n);
726 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n))
734 FPCR |= cmp2fcc (sim_fpu_cmp (&m, &n));
736 fpu_check_signal_exception (sd, cpu, cia);
739 /* Implement a 32/64 bit FP add, setting FP exception bits when
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)
748 REG2VAL (reg_in1, &m);
749 REG2VAL (reg_in2, &n);
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))
762 VAL2REG (&sim_fpu_qnan, reg_out);
766 sim_fpu_status stat = sim_fpu_add (&r, &m, &n);
768 if (fpu_status_ok (stat))
769 VAL2REG (&r, reg_out);
772 fpu_check_signal_exception (sd, cpu, cia);
775 /* Implement a 32/64 bit FP sub, setting FP exception bits when
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)
784 REG2VAL (reg_in1, &m);
785 REG2VAL (reg_in2, &n);
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))
798 VAL2REG (&sim_fpu_qnan, reg_out);
802 sim_fpu_status stat = sim_fpu_sub (&r, &m, &n);
804 if (fpu_status_ok (stat))
805 VAL2REG (&r, reg_out);
808 fpu_check_signal_exception (sd, cpu, cia);
811 /* Implement a 32/64 bit FP mul, setting FP exception bits when
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)
820 REG2VAL (reg_in1, &m);
821 REG2VAL (reg_in2, &n);
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)))
832 VAL2REG (&sim_fpu_qnan, reg_out);
836 sim_fpu_status stat = sim_fpu_mul (&r, &m, &n);
838 if (fpu_status_ok (stat))
839 VAL2REG (&r, reg_out);
842 fpu_check_signal_exception (sd, cpu, cia);
845 /* Implement a 32/64 bit FP div, setting FP exception bits when
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)
854 REG2VAL (reg_in1, &m);
855 REG2VAL (reg_in2, &n);
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)))
866 VAL2REG (&sim_fpu_qnan, reg_out);
868 else if (sim_fpu_is_number (&m) && sim_fpu_is_zero (&n)
873 sim_fpu_status stat = sim_fpu_div (&r, &m, &n);
875 if (fpu_status_ok (stat))
876 VAL2REG (&r, reg_out);
879 fpu_check_signal_exception (sd, cpu, cia);
882 /* Implement a 32/64 bit FP madd, setting FP exception bits when
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)
889 sim_fpu m1, m2, m, n, r;
891 REG2VAL (reg_in1, &m1);
892 REG2VAL (reg_in2, &m2);
893 REG2VAL (reg_in3, &n);
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)))
906 VAL2REG (&sim_fpu_qnan, reg_out);
910 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
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;
916 stat |= sim_fpu_add (&r, &m, &n);
918 if (fpu_status_ok (stat))
919 VAL2REG (&r, reg_out);
922 fpu_check_signal_exception (sd, cpu, cia);
925 /* Implement a 32/64 bit FP msub, setting FP exception bits when
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)
932 sim_fpu m1, m2, m, n, r;
934 REG2VAL (reg_in1, &m1);
935 REG2VAL (reg_in2, &m2);
936 REG2VAL (reg_in3, &n);
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)))
949 VAL2REG (&sim_fpu_qnan, reg_out);
953 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
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;
959 stat |= sim_fpu_sub (&r, &m, &n);
961 if (fpu_status_ok (stat))
962 VAL2REG (&r, reg_out);
965 fpu_check_signal_exception (sd, cpu, cia);
968 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
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)
975 sim_fpu m1, m2, m, mm, n, r;
977 REG2VAL (reg_in1, &m1);
978 REG2VAL (reg_in2, &m2);
979 REG2VAL (reg_in3, &n);
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)))
992 VAL2REG (&sim_fpu_qnan, reg_out);
996 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
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;
1002 stat |= sim_fpu_neg (&mm, &m);
1003 stat |= sim_fpu_add (&r, &mm, &n);
1005 if (fpu_status_ok (stat))
1006 VAL2REG (&r, reg_out);
1009 fpu_check_signal_exception (sd, cpu, cia);
1012 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
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)
1019 sim_fpu m1, m2, m, mm, n, r;
1021 REG2VAL (reg_in1, &m1);
1022 REG2VAL (reg_in2, &m2);
1023 REG2VAL (reg_in3, &n);
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)))
1036 VAL2REG (&sim_fpu_qnan, reg_out);
1040 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
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;
1046 stat |= sim_fpu_neg (&mm, &m);
1047 stat |= sim_fpu_sub (&r, &mm, &n);
1049 if (fpu_status_ok (stat))
1050 VAL2REG (&r, reg_out);
1053 fpu_check_signal_exception (sd, cpu, cia);