5 #include "sim-options.h"
9 #include "sim-assert.h"
27 host_callback *mn10300_callback;
31 /* simulation target board. NULL=default configuration */
32 static char* board = NULL;
34 static DECLARE_OPTION_HANDLER (mn10300_option_handler);
37 OPTION_BOARD = OPTION_START,
41 mn10300_option_handler (SIM_DESC sd,
54 board = zalloc(strlen(arg) + 1);
64 static const OPTION mn10300_options[] =
66 #define BOARD_AM32 "stdeval1"
67 { {"board", required_argument, NULL, OPTION_BOARD},
68 '\0', "none" /* rely on compile-time string concatenation for other options */
70 , "Customize simulation for a particular board.", mn10300_option_handler },
72 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
75 /* For compatibility */
79 mn10300_pc_get (sim_cpu *cpu)
85 mn10300_pc_set (sim_cpu *cpu, sim_cia pc)
90 /* These default values correspond to expected usage for the chip. */
93 sim_open (SIM_OPEN_KIND kind,
99 SIM_DESC sd = sim_state_alloc (kind, cb);
100 mn10300_callback = cb;
102 SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
104 /* The cpu data is kept in a separately allocated chunk of memory. */
105 if (sim_cpu_alloc_all (sd, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK)
108 /* for compatibility */
111 /* FIXME: should be better way of setting up interrupts. For
112 moment, only support watchpoints causing a breakpoint (gdb
114 STATE_WATCHPOINTS (sd)->pc = &(PC);
115 STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC);
116 STATE_WATCHPOINTS (sd)->interrupt_handler = NULL;
117 STATE_WATCHPOINTS (sd)->interrupt_names = NULL;
119 if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
121 sim_add_option_table (sd, NULL, mn10300_options);
123 /* Allocate core managed memory */
124 sim_do_command (sd, "memory region 0,0x100000");
125 sim_do_command (sd, "memory region 0x40000000,0x200000");
127 /* getopt will print the error message so we just have to exit if this fails.
128 FIXME: Hmmm... in the case of gdb we need getopt to call
130 if (sim_parse_args (sd, argv) != SIM_RC_OK)
132 /* Uninstall the modules to avoid memory leaks,
133 file descriptor leaks, etc. */
134 sim_module_uninstall (sd);
139 && (strcmp(board, BOARD_AM32) == 0 ) )
142 STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT;
144 sim_do_command (sd, "memory region 0x44000000,0x40000");
145 sim_do_command (sd, "memory region 0x48000000,0x400000");
147 /* device support for mn1030002 */
148 /* interrupt controller */
150 sim_hw_parse (sd, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
152 /* DEBUG: NMI input's */
153 sim_hw_parse (sd, "/glue@0x30000000/reg 0x30000000 12");
154 sim_hw_parse (sd, "/glue@0x30000000 > int0 nmirq /mn103int");
155 sim_hw_parse (sd, "/glue@0x30000000 > int1 watchdog /mn103int");
156 sim_hw_parse (sd, "/glue@0x30000000 > int2 syserr /mn103int");
158 /* DEBUG: ACK input */
159 sim_hw_parse (sd, "/glue@0x30002000/reg 0x30002000 4");
160 sim_hw_parse (sd, "/glue@0x30002000 > int ack /mn103int");
162 /* DEBUG: LEVEL output */
163 sim_hw_parse (sd, "/glue@0x30004000/reg 0x30004000 8");
164 sim_hw_parse (sd, "/mn103int > nmi int0 /glue@0x30004000");
165 sim_hw_parse (sd, "/mn103int > level int1 /glue@0x30004000");
167 /* DEBUG: A bunch of interrupt inputs */
168 sim_hw_parse (sd, "/glue@0x30006000/reg 0x30006000 32");
169 sim_hw_parse (sd, "/glue@0x30006000 > int0 irq-0 /mn103int");
170 sim_hw_parse (sd, "/glue@0x30006000 > int1 irq-1 /mn103int");
171 sim_hw_parse (sd, "/glue@0x30006000 > int2 irq-2 /mn103int");
172 sim_hw_parse (sd, "/glue@0x30006000 > int3 irq-3 /mn103int");
173 sim_hw_parse (sd, "/glue@0x30006000 > int4 irq-4 /mn103int");
174 sim_hw_parse (sd, "/glue@0x30006000 > int5 irq-5 /mn103int");
175 sim_hw_parse (sd, "/glue@0x30006000 > int6 irq-6 /mn103int");
176 sim_hw_parse (sd, "/glue@0x30006000 > int7 irq-7 /mn103int");
178 /* processor interrupt device */
181 sim_hw_parse (sd, "/mn103cpu@0x20000000");
182 sim_hw_parse (sd, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
184 /* DEBUG: ACK output wired upto a glue device */
185 sim_hw_parse (sd, "/glue@0x20002000");
186 sim_hw_parse (sd, "/glue@0x20002000/reg 0x20002000 4");
187 sim_hw_parse (sd, "/mn103cpu > ack int0 /glue@0x20002000");
189 /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
190 sim_hw_parse (sd, "/glue@0x20004000");
191 sim_hw_parse (sd, "/glue@0x20004000/reg 0x20004000 12");
192 sim_hw_parse (sd, "/glue@0x20004000 > int0 reset /mn103cpu");
193 sim_hw_parse (sd, "/glue@0x20004000 > int1 nmi /mn103cpu");
194 sim_hw_parse (sd, "/glue@0x20004000 > int2 level /mn103cpu");
196 /* REAL: The processor wired up to the real interrupt controller */
197 sim_hw_parse (sd, "/mn103cpu > ack ack /mn103int");
198 sim_hw_parse (sd, "/mn103int > level level /mn103cpu");
199 sim_hw_parse (sd, "/mn103int > nmi nmi /mn103cpu");
205 sim_hw_parse (sd, "/pal@0x31000000");
206 sim_hw_parse (sd, "/pal@0x31000000/reg 0x31000000 64");
207 sim_hw_parse (sd, "/pal@0x31000000/poll? true");
209 /* DEBUG: PAL wired up to a glue device */
210 sim_hw_parse (sd, "/glue@0x31002000");
211 sim_hw_parse (sd, "/glue@0x31002000/reg 0x31002000 16");
212 sim_hw_parse (sd, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
213 sim_hw_parse (sd, "/pal@0x31000000 > timer int1 /glue@0x31002000");
214 sim_hw_parse (sd, "/pal@0x31000000 > int int2 /glue@0x31002000");
215 sim_hw_parse (sd, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
216 sim_hw_parse (sd, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
217 sim_hw_parse (sd, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
219 /* REAL: The PAL wired up to the real interrupt controller */
220 sim_hw_parse (sd, "/pal@0x31000000 > countdown irq-0 /mn103int");
221 sim_hw_parse (sd, "/pal@0x31000000 > timer irq-1 /mn103int");
222 sim_hw_parse (sd, "/pal@0x31000000 > int irq-2 /mn103int");
224 /* 8 and 16 bit timers */
225 sim_hw_parse (sd, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16");
227 /* Hook timer interrupts up to interrupt controller */
228 sim_hw_parse (sd, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int");
229 sim_hw_parse (sd, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int");
230 sim_hw_parse (sd, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int");
231 sim_hw_parse (sd, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int");
232 sim_hw_parse (sd, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int");
233 sim_hw_parse (sd, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int");
234 sim_hw_parse (sd, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int");
235 sim_hw_parse (sd, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int");
236 sim_hw_parse (sd, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int");
239 /* Serial devices 0,1,2 */
240 sim_hw_parse (sd, "/mn103ser@0x34000800/reg 0x34000800 48");
241 sim_hw_parse (sd, "/mn103ser@0x34000800/poll? true");
243 /* Hook serial interrupts up to interrupt controller */
244 sim_hw_parse (sd, "/mn103ser > serial-0-receive serial-0-receive /mn103int");
245 sim_hw_parse (sd, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int");
246 sim_hw_parse (sd, "/mn103ser > serial-1-receive serial-1-receive /mn103int");
247 sim_hw_parse (sd, "/mn103ser > serial-1-transmit serial-1-transmit /mn103int");
248 sim_hw_parse (sd, "/mn103ser > serial-2-receive serial-2-receive /mn103int");
249 sim_hw_parse (sd, "/mn103ser > serial-2-transmit serial-2-transmit /mn103int");
251 sim_hw_parse (sd, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
253 /* Memory control registers */
254 sim_do_command (sd, "memory region 0x32000020,0x30");
255 /* Cache control register */
256 sim_do_command (sd, "memory region 0x20000070,0x4");
257 /* Cache purge regions */
258 sim_do_command (sd, "memory region 0x28400000,0x800");
259 sim_do_command (sd, "memory region 0x28401000,0x800");
261 sim_do_command (sd, "memory region 0x32000100,0xF");
262 sim_do_command (sd, "memory region 0x32000200,0xF");
263 sim_do_command (sd, "memory region 0x32000400,0xF");
264 sim_do_command (sd, "memory region 0x32000800,0xF");
270 sim_io_eprintf (sd, "Error: Board `%s' unknown.\n", board);
277 /* check for/establish the a reference program image */
278 if (sim_analyze_program (sd,
279 (STATE_PROG_ARGV (sd) != NULL
280 ? *STATE_PROG_ARGV (sd)
284 sim_module_uninstall (sd);
288 /* establish any remaining configuration options */
289 if (sim_config (sd) != SIM_RC_OK)
291 sim_module_uninstall (sd);
295 if (sim_post_argv_init (sd) != SIM_RC_OK)
297 /* Uninstall the modules to avoid memory leaks,
298 file descriptor leaks, etc. */
299 sim_module_uninstall (sd);
304 /* set machine specific configuration */
305 /* STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
306 /* | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
308 /* CPU specific initialization. */
309 for (i = 0; i < MAX_NR_PROCESSORS; ++i)
311 SIM_CPU *cpu = STATE_CPU (sd, i);
313 CPU_PC_FETCH (cpu) = mn10300_pc_get;
314 CPU_PC_STORE (cpu) = mn10300_pc_set;
321 sim_create_inferior (SIM_DESC sd,
322 struct bfd *prog_bfd,
326 memset (&State, 0, sizeof (State));
327 if (prog_bfd != NULL) {
328 PC = bfd_get_start_address (prog_bfd);
332 CPU_PC_SET (STATE_CPU (sd, 0), (unsigned64) PC);
334 if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_am33_2)
340 /* FIXME These would more efficient to use than load_mem/store_mem,
341 but need to be changed to use the memory map. */
344 sim_fetch_register (SIM_DESC sd,
346 unsigned char *memory,
349 reg_t reg = State.regs[rn];
359 sim_store_register (SIM_DESC sd,
361 unsigned char *memory,
365 State.regs[rn] = (a[3] << 24) + (a[2] << 16) + (a[1] << 8) + a[0];
370 mn10300_core_signal (SIM_DESC sd,
376 transfer_type transfer,
377 sim_core_signals sig)
379 const char *copy = (transfer == read_transfer ? "read" : "write");
380 address_word ip = CIA_ADDR (cia);
384 case sim_core_unmapped_signal:
385 sim_io_eprintf (sd, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
387 (unsigned long) addr, (unsigned long) ip);
388 program_interrupt(sd, cpu, cia, SIM_SIGSEGV);
391 case sim_core_unaligned_signal:
392 sim_io_eprintf (sd, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
394 (unsigned long) addr, (unsigned long) ip);
395 program_interrupt(sd, cpu, cia, SIM_SIGBUS);
399 sim_engine_abort (sd, cpu, cia,
400 "mn10300_core_signal - internal error - bad switch");
406 program_interrupt (SIM_DESC sd,
413 static int in_interrupt = 0;
415 #ifdef SIM_CPU_EXCEPTION_TRIGGER
416 SIM_CPU_EXCEPTION_TRIGGER(sd,cpu,cia);
419 /* avoid infinite recursion */
422 (*mn10300_callback->printf_filtered) (mn10300_callback,
423 "ERROR: recursion in program_interrupt during software exception dispatch.");
428 /* copy NMI handler code from dv-mn103cpu.c */
429 store_word (SP - 4, CPU_PC_GET (cpu));
430 store_half (SP - 8, PSW);
432 /* Set the SYSEF flag in NMICR by backdoor method. See
433 dv-mn103int.c:write_icr(). This is necessary because
434 software exceptions are not modelled by actually talking to
435 the interrupt controller, so it cannot set its own SYSEF
437 if ((NULL != board) && (strcmp(board, BOARD_AM32) == 0))
438 store_byte (0x34000103, 0x04);
443 CPU_PC_SET (cpu, 0x40000008);
446 sim_engine_halt(sd, cpu, NULL, cia, sim_stopped, sig);
451 mn10300_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia)
455 if(State.exc_suspended > 0)
456 sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", State.exc_suspended);
458 CPU_PC_SET (cpu, cia);
459 memcpy(State.exc_trigger_regs, State.regs, sizeof(State.exc_trigger_regs));
460 State.exc_suspended = 0;
464 mn10300_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception)
468 if(State.exc_suspended > 0)
469 sim_io_eprintf(sd, "Warning, nested exception signal (%d then %d)\n",
470 State.exc_suspended, exception);
472 memcpy(State.exc_suspend_regs, State.regs, sizeof(State.exc_suspend_regs));
473 memcpy(State.regs, State.exc_trigger_regs, sizeof(State.regs));
474 CPU_PC_SET (cpu, PC); /* copy PC back from new State.regs */
475 State.exc_suspended = exception;
479 mn10300_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception)
483 if(exception == 0 && State.exc_suspended > 0)
485 if(State.exc_suspended != SIGTRAP) /* warn not for breakpoints */
486 sim_io_eprintf(sd, "Warning, resuming but ignoring pending exception signal (%d)\n",
487 State.exc_suspended);
489 else if(exception != 0 && State.exc_suspended > 0)
491 if(exception != State.exc_suspended)
492 sim_io_eprintf(sd, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
493 State.exc_suspended, exception);
495 memcpy(State.regs, State.exc_suspend_regs, sizeof(State.regs));
496 CPU_PC_SET (cpu, PC); /* copy PC back from new State.regs */
498 else if(exception != 0 && State.exc_suspended == 0)
500 sim_io_eprintf(sd, "Warning, ignoring spontanous exception signal (%d)\n", exception);
502 State.exc_suspended = 0;
505 /* This is called when an FP instruction is issued when the FP unit is
506 disabled, i.e., the FE bit of PSW is zero. It raises interrupt
509 fpu_disabled_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
511 sim_io_eprintf(sd, "FPU disabled exception\n");
512 program_interrupt (sd, cpu, cia, SIM_SIGFPE);
515 /* This is called when the FP unit is enabled but one of the
516 unimplemented insns is issued. It raises interrupt code 0x1c8. */
518 fpu_unimp_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
520 sim_io_eprintf(sd, "Unimplemented FPU instruction exception\n");
521 program_interrupt (sd, cpu, cia, SIM_SIGFPE);
524 /* This is called at the end of any FP insns that may have triggered
525 FP exceptions. If no exception is enabled, it returns immediately.
526 Otherwise, it raises an exception code 0x1d0. */
528 fpu_check_signal_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
530 if ((FPCR & EC_MASK) == 0)
533 sim_io_eprintf(sd, "FPU %s%s%s%s%s exception\n",
534 (FPCR & EC_V) ? "V" : "",
535 (FPCR & EC_Z) ? "Z" : "",
536 (FPCR & EC_O) ? "O" : "",
537 (FPCR & EC_U) ? "U" : "",
538 (FPCR & EC_I) ? "I" : "");
539 program_interrupt (sd, cpu, cia, SIM_SIGFPE);
542 /* Convert a 32-bit single-precision FP value in the target platform
543 format to a sim_fpu value. */
545 reg2val_32 (const void *reg, sim_fpu *val)
547 FS2FPU (*(reg_t *)reg, *val);
550 /* Round the given sim_fpu value to single precision, following the
551 target platform rounding and denormalization conventions. On
552 AM33/2.0, round_near is the only rounding mode. */
554 round_32 (sim_fpu *val)
556 return sim_fpu_round_32 (val, sim_fpu_round_near, sim_fpu_denorm_zero);
559 /* Convert a sim_fpu value to the 32-bit single-precision target
562 val2reg_32 (const sim_fpu *val, void *reg)
564 FPU2FS (*val, *(reg_t *)reg);
567 /* Define the 32-bit single-precision conversion and rounding uniform
569 const struct fp_prec_t
571 reg2val_32, round_32, val2reg_32
574 /* Convert a 64-bit double-precision FP value in the target platform
575 format to a sim_fpu value. */
577 reg2val_64 (const void *reg, sim_fpu *val)
579 FD2FPU (*(dword *)reg, *val);
582 /* Round the given sim_fpu value to double precision, following the
583 target platform rounding and denormalization conventions. On
584 AM33/2.0, round_near is the only rounding mode. */
586 round_64 (sim_fpu *val)
588 return sim_fpu_round_64 (val, sim_fpu_round_near, sim_fpu_denorm_zero);
591 /* Convert a sim_fpu value to the 64-bit double-precision target
594 val2reg_64 (const sim_fpu *val, void *reg)
596 FPU2FD (*val, *(dword *)reg);
599 /* Define the 64-bit single-precision conversion and rounding uniform
601 const struct fp_prec_t
603 reg2val_64, round_64, val2reg_64
606 /* Define shortcuts to the uniform interface operations. */
607 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
608 #define ROUND(val) (*ops->round) (val)
609 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
611 /* Check whether overflow, underflow or inexact exceptions should be
614 fpu_status_ok (sim_fpu_status stat)
616 if ((stat & sim_fpu_status_overflow)
619 else if ((stat & (sim_fpu_status_underflow | sim_fpu_status_denorm))
622 else if ((stat & (sim_fpu_status_inexact | sim_fpu_status_rounded))
625 else if (stat & ~ (sim_fpu_status_overflow
626 | sim_fpu_status_underflow
627 | sim_fpu_status_denorm
628 | sim_fpu_status_inexact
629 | sim_fpu_status_rounded))
636 /* Implement a 32/64 bit reciprocal square root, signaling FP
637 exceptions when appropriate. */
639 fpu_rsqrt (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
640 const void *reg_in, void *reg_out, const struct fp_prec_t *ops)
642 sim_fpu in, med, out;
644 REG2VAL (reg_in, &in);
647 switch (sim_fpu_is (&in))
649 case SIM_FPU_IS_SNAN:
650 case SIM_FPU_IS_NNUMBER:
651 case SIM_FPU_IS_NINF:
655 VAL2REG (&sim_fpu_qnan, reg_out);
658 case SIM_FPU_IS_QNAN:
659 VAL2REG (&sim_fpu_qnan, reg_out);
662 case SIM_FPU_IS_PINF:
663 VAL2REG (&sim_fpu_zero, reg_out);
666 case SIM_FPU_IS_PNUMBER:
668 /* Since we don't have a function to compute rsqrt directly,
670 sim_fpu_status stat = 0;
671 stat |= sim_fpu_sqrt (&med, &in);
672 stat |= sim_fpu_inv (&out, &med);
673 stat |= ROUND (&out);
674 if (fpu_status_ok (stat))
675 VAL2REG (&out, reg_out);
679 case SIM_FPU_IS_NZERO:
680 case SIM_FPU_IS_PZERO:
685 /* Generate an INF with the same sign. */
686 sim_fpu_inv (&out, &in);
687 VAL2REG (&out, reg_out);
695 fpu_check_signal_exception (sd, cpu, cia);
703 case SIM_FPU_IS_SNAN:
704 case SIM_FPU_IS_QNAN:
707 case SIM_FPU_IS_NINF:
708 case SIM_FPU_IS_NNUMBER:
709 case SIM_FPU_IS_NDENORM:
712 case SIM_FPU_IS_PINF:
713 case SIM_FPU_IS_PNUMBER:
714 case SIM_FPU_IS_PDENORM:
717 case SIM_FPU_IS_NZERO:
718 case SIM_FPU_IS_PZERO:
726 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
727 exception bits as specified. */
729 fpu_cmp (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
730 const void *reg_in1, const void *reg_in2,
731 const struct fp_prec_t *ops)
735 REG2VAL (reg_in1, &m);
736 REG2VAL (reg_in2, &n);
741 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n))
749 FPCR |= cmp2fcc (sim_fpu_cmp (&m, &n));
751 fpu_check_signal_exception (sd, cpu, cia);
754 /* Implement a 32/64 bit FP add, setting FP exception bits when
757 fpu_add (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
758 const void *reg_in1, const void *reg_in2,
759 void *reg_out, const struct fp_prec_t *ops)
763 REG2VAL (reg_in1, &m);
764 REG2VAL (reg_in2, &n);
768 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
769 || (sim_fpu_is (&m) == SIM_FPU_IS_PINF
770 && sim_fpu_is (&n) == SIM_FPU_IS_NINF)
771 || (sim_fpu_is (&m) == SIM_FPU_IS_NINF
772 && sim_fpu_is (&n) == SIM_FPU_IS_PINF))
777 VAL2REG (&sim_fpu_qnan, reg_out);
781 sim_fpu_status stat = sim_fpu_add (&r, &m, &n);
783 if (fpu_status_ok (stat))
784 VAL2REG (&r, reg_out);
787 fpu_check_signal_exception (sd, cpu, cia);
790 /* Implement a 32/64 bit FP sub, setting FP exception bits when
793 fpu_sub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
794 const void *reg_in1, const void *reg_in2,
795 void *reg_out, const struct fp_prec_t *ops)
799 REG2VAL (reg_in1, &m);
800 REG2VAL (reg_in2, &n);
804 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
805 || (sim_fpu_is (&m) == SIM_FPU_IS_PINF
806 && sim_fpu_is (&n) == SIM_FPU_IS_PINF)
807 || (sim_fpu_is (&m) == SIM_FPU_IS_NINF
808 && sim_fpu_is (&n) == SIM_FPU_IS_NINF))
813 VAL2REG (&sim_fpu_qnan, reg_out);
817 sim_fpu_status stat = sim_fpu_sub (&r, &m, &n);
819 if (fpu_status_ok (stat))
820 VAL2REG (&r, reg_out);
823 fpu_check_signal_exception (sd, cpu, cia);
826 /* Implement a 32/64 bit FP mul, setting FP exception bits when
829 fpu_mul (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
830 const void *reg_in1, const void *reg_in2,
831 void *reg_out, const struct fp_prec_t *ops)
835 REG2VAL (reg_in1, &m);
836 REG2VAL (reg_in2, &n);
840 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
841 || (sim_fpu_is_infinity (&m) && sim_fpu_is_zero (&n))
842 || (sim_fpu_is_zero (&m) && sim_fpu_is_infinity (&n)))
847 VAL2REG (&sim_fpu_qnan, reg_out);
851 sim_fpu_status stat = sim_fpu_mul (&r, &m, &n);
853 if (fpu_status_ok (stat))
854 VAL2REG (&r, reg_out);
857 fpu_check_signal_exception (sd, cpu, cia);
860 /* Implement a 32/64 bit FP div, setting FP exception bits when
863 fpu_div (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
864 const void *reg_in1, const void *reg_in2,
865 void *reg_out, const struct fp_prec_t *ops)
869 REG2VAL (reg_in1, &m);
870 REG2VAL (reg_in2, &n);
874 if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
875 || (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n))
876 || (sim_fpu_is_zero (&m) && sim_fpu_is_zero (&n)))
881 VAL2REG (&sim_fpu_qnan, reg_out);
883 else if (sim_fpu_is_number (&m) && sim_fpu_is_zero (&n)
888 sim_fpu_status stat = sim_fpu_div (&r, &m, &n);
890 if (fpu_status_ok (stat))
891 VAL2REG (&r, reg_out);
894 fpu_check_signal_exception (sd, cpu, cia);
897 /* Implement a 32/64 bit FP madd, setting FP exception bits when
900 fpu_fmadd (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
901 const void *reg_in1, const void *reg_in2, const void *reg_in3,
902 void *reg_out, const struct fp_prec_t *ops)
904 sim_fpu m1, m2, m, n, r;
906 REG2VAL (reg_in1, &m1);
907 REG2VAL (reg_in2, &m2);
908 REG2VAL (reg_in3, &n);
913 if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
914 || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
915 || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
921 VAL2REG (&sim_fpu_qnan, reg_out);
925 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
927 if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
928 && sim_fpu_sign (&m) != sim_fpu_sign (&n))
929 goto invalid_operands;
931 stat |= sim_fpu_add (&r, &m, &n);
933 if (fpu_status_ok (stat))
934 VAL2REG (&r, reg_out);
937 fpu_check_signal_exception (sd, cpu, cia);
940 /* Implement a 32/64 bit FP msub, setting FP exception bits when
943 fpu_fmsub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
944 const void *reg_in1, const void *reg_in2, const void *reg_in3,
945 void *reg_out, const struct fp_prec_t *ops)
947 sim_fpu m1, m2, m, n, r;
949 REG2VAL (reg_in1, &m1);
950 REG2VAL (reg_in2, &m2);
951 REG2VAL (reg_in3, &n);
956 if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
957 || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
958 || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
964 VAL2REG (&sim_fpu_qnan, reg_out);
968 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
970 if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
971 && sim_fpu_sign (&m) == sim_fpu_sign (&n))
972 goto invalid_operands;
974 stat |= sim_fpu_sub (&r, &m, &n);
976 if (fpu_status_ok (stat))
977 VAL2REG (&r, reg_out);
980 fpu_check_signal_exception (sd, cpu, cia);
983 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
986 fpu_fnmadd (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
987 const void *reg_in1, const void *reg_in2, const void *reg_in3,
988 void *reg_out, const struct fp_prec_t *ops)
990 sim_fpu m1, m2, m, mm, n, r;
992 REG2VAL (reg_in1, &m1);
993 REG2VAL (reg_in2, &m2);
994 REG2VAL (reg_in3, &n);
999 if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
1000 || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
1001 || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
1007 VAL2REG (&sim_fpu_qnan, reg_out);
1011 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
1013 if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
1014 && sim_fpu_sign (&m) == sim_fpu_sign (&n))
1015 goto invalid_operands;
1017 stat |= sim_fpu_neg (&mm, &m);
1018 stat |= sim_fpu_add (&r, &mm, &n);
1020 if (fpu_status_ok (stat))
1021 VAL2REG (&r, reg_out);
1024 fpu_check_signal_exception (sd, cpu, cia);
1027 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1030 fpu_fnmsub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
1031 const void *reg_in1, const void *reg_in2, const void *reg_in3,
1032 void *reg_out, const struct fp_prec_t *ops)
1034 sim_fpu m1, m2, m, mm, n, r;
1036 REG2VAL (reg_in1, &m1);
1037 REG2VAL (reg_in2, &m2);
1038 REG2VAL (reg_in3, &n);
1043 if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
1044 || (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
1045 || (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
1051 VAL2REG (&sim_fpu_qnan, reg_out);
1055 sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
1057 if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
1058 && sim_fpu_sign (&m) != sim_fpu_sign (&n))
1059 goto invalid_operands;
1061 stat |= sim_fpu_neg (&mm, &m);
1062 stat |= sim_fpu_sub (&r, &mm, &n);
1064 if (fpu_status_ok (stat))
1065 VAL2REG (&r, reg_out);
1068 fpu_check_signal_exception (sd, cpu, cia);