5 #include "sim-options.h"
9 #include "sim-assert.h"
30 /* simulation target board. NULL=default configuration */
31 static char* board
= NULL
;
33 static DECLARE_OPTION_HANDLER (mn10300_option_handler
);
36 OPTION_BOARD
= OPTION_START
,
40 mn10300_option_handler (SIM_DESC sd
,
53 board
= zalloc(strlen(arg
) + 1);
63 static const OPTION mn10300_options
[] =
65 #define BOARD_AM32 "stdeval1"
66 { {"board", required_argument
, NULL
, OPTION_BOARD
},
67 '\0', "none" /* rely on compile-time string concatenation for other options */
69 , "Customize simulation for a particular board.", mn10300_option_handler
},
71 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
74 /* For compatibility */
78 mn10300_pc_get (sim_cpu
*cpu
)
84 mn10300_pc_set (sim_cpu
*cpu
, sim_cia pc
)
89 /* These default values correspond to expected usage for the chip. */
92 sim_open (SIM_OPEN_KIND kind
,
98 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
100 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
102 /* The cpu data is kept in a separately allocated chunk of memory. */
103 if (sim_cpu_alloc_all (sd
, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK
)
106 /* for compatibility */
109 /* FIXME: should be better way of setting up interrupts. For
110 moment, only support watchpoints causing a breakpoint (gdb
112 STATE_WATCHPOINTS (sd
)->pc
= &(PC
);
113 STATE_WATCHPOINTS (sd
)->sizeof_pc
= sizeof (PC
);
114 STATE_WATCHPOINTS (sd
)->interrupt_handler
= NULL
;
115 STATE_WATCHPOINTS (sd
)->interrupt_names
= NULL
;
117 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
119 sim_add_option_table (sd
, NULL
, mn10300_options
);
121 /* Allocate core managed memory */
122 sim_do_command (sd
, "memory region 0,0x100000");
123 sim_do_command (sd
, "memory region 0x40000000,0x200000");
125 /* getopt will print the error message so we just have to exit if this fails.
126 FIXME: Hmmm... in the case of gdb we need getopt to call
128 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
130 /* Uninstall the modules to avoid memory leaks,
131 file descriptor leaks, etc. */
132 sim_module_uninstall (sd
);
137 && (strcmp(board
, BOARD_AM32
) == 0 ) )
140 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
142 sim_do_command (sd
, "memory region 0x44000000,0x40000");
143 sim_do_command (sd
, "memory region 0x48000000,0x400000");
145 /* device support for mn1030002 */
146 /* interrupt controller */
148 sim_hw_parse (sd
, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
150 /* DEBUG: NMI input's */
151 sim_hw_parse (sd
, "/glue@0x30000000/reg 0x30000000 12");
152 sim_hw_parse (sd
, "/glue@0x30000000 > int0 nmirq /mn103int");
153 sim_hw_parse (sd
, "/glue@0x30000000 > int1 watchdog /mn103int");
154 sim_hw_parse (sd
, "/glue@0x30000000 > int2 syserr /mn103int");
156 /* DEBUG: ACK input */
157 sim_hw_parse (sd
, "/glue@0x30002000/reg 0x30002000 4");
158 sim_hw_parse (sd
, "/glue@0x30002000 > int ack /mn103int");
160 /* DEBUG: LEVEL output */
161 sim_hw_parse (sd
, "/glue@0x30004000/reg 0x30004000 8");
162 sim_hw_parse (sd
, "/mn103int > nmi int0 /glue@0x30004000");
163 sim_hw_parse (sd
, "/mn103int > level int1 /glue@0x30004000");
165 /* DEBUG: A bunch of interrupt inputs */
166 sim_hw_parse (sd
, "/glue@0x30006000/reg 0x30006000 32");
167 sim_hw_parse (sd
, "/glue@0x30006000 > int0 irq-0 /mn103int");
168 sim_hw_parse (sd
, "/glue@0x30006000 > int1 irq-1 /mn103int");
169 sim_hw_parse (sd
, "/glue@0x30006000 > int2 irq-2 /mn103int");
170 sim_hw_parse (sd
, "/glue@0x30006000 > int3 irq-3 /mn103int");
171 sim_hw_parse (sd
, "/glue@0x30006000 > int4 irq-4 /mn103int");
172 sim_hw_parse (sd
, "/glue@0x30006000 > int5 irq-5 /mn103int");
173 sim_hw_parse (sd
, "/glue@0x30006000 > int6 irq-6 /mn103int");
174 sim_hw_parse (sd
, "/glue@0x30006000 > int7 irq-7 /mn103int");
176 /* processor interrupt device */
179 sim_hw_parse (sd
, "/mn103cpu@0x20000000");
180 sim_hw_parse (sd
, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
182 /* DEBUG: ACK output wired upto a glue device */
183 sim_hw_parse (sd
, "/glue@0x20002000");
184 sim_hw_parse (sd
, "/glue@0x20002000/reg 0x20002000 4");
185 sim_hw_parse (sd
, "/mn103cpu > ack int0 /glue@0x20002000");
187 /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
188 sim_hw_parse (sd
, "/glue@0x20004000");
189 sim_hw_parse (sd
, "/glue@0x20004000/reg 0x20004000 12");
190 sim_hw_parse (sd
, "/glue@0x20004000 > int0 reset /mn103cpu");
191 sim_hw_parse (sd
, "/glue@0x20004000 > int1 nmi /mn103cpu");
192 sim_hw_parse (sd
, "/glue@0x20004000 > int2 level /mn103cpu");
194 /* REAL: The processor wired up to the real interrupt controller */
195 sim_hw_parse (sd
, "/mn103cpu > ack ack /mn103int");
196 sim_hw_parse (sd
, "/mn103int > level level /mn103cpu");
197 sim_hw_parse (sd
, "/mn103int > nmi nmi /mn103cpu");
203 sim_hw_parse (sd
, "/pal@0x31000000");
204 sim_hw_parse (sd
, "/pal@0x31000000/reg 0x31000000 64");
205 sim_hw_parse (sd
, "/pal@0x31000000/poll? true");
207 /* DEBUG: PAL wired up to a glue device */
208 sim_hw_parse (sd
, "/glue@0x31002000");
209 sim_hw_parse (sd
, "/glue@0x31002000/reg 0x31002000 16");
210 sim_hw_parse (sd
, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
211 sim_hw_parse (sd
, "/pal@0x31000000 > timer int1 /glue@0x31002000");
212 sim_hw_parse (sd
, "/pal@0x31000000 > int int2 /glue@0x31002000");
213 sim_hw_parse (sd
, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
214 sim_hw_parse (sd
, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
215 sim_hw_parse (sd
, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
217 /* REAL: The PAL wired up to the real interrupt controller */
218 sim_hw_parse (sd
, "/pal@0x31000000 > countdown irq-0 /mn103int");
219 sim_hw_parse (sd
, "/pal@0x31000000 > timer irq-1 /mn103int");
220 sim_hw_parse (sd
, "/pal@0x31000000 > int irq-2 /mn103int");
222 /* 8 and 16 bit timers */
223 sim_hw_parse (sd
, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16");
225 /* Hook timer interrupts up to interrupt controller */
226 sim_hw_parse (sd
, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int");
227 sim_hw_parse (sd
, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int");
228 sim_hw_parse (sd
, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int");
229 sim_hw_parse (sd
, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int");
230 sim_hw_parse (sd
, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int");
231 sim_hw_parse (sd
, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int");
232 sim_hw_parse (sd
, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int");
233 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int");
234 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int");
237 /* Serial devices 0,1,2 */
238 sim_hw_parse (sd
, "/mn103ser@0x34000800/reg 0x34000800 48");
239 sim_hw_parse (sd
, "/mn103ser@0x34000800/poll? true");
241 /* Hook serial interrupts up to interrupt controller */
242 sim_hw_parse (sd
, "/mn103ser > serial-0-receive serial-0-receive /mn103int");
243 sim_hw_parse (sd
, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int");
244 sim_hw_parse (sd
, "/mn103ser > serial-1-receive serial-1-receive /mn103int");
245 sim_hw_parse (sd
, "/mn103ser > serial-1-transmit serial-1-transmit /mn103int");
246 sim_hw_parse (sd
, "/mn103ser > serial-2-receive serial-2-receive /mn103int");
247 sim_hw_parse (sd
, "/mn103ser > serial-2-transmit serial-2-transmit /mn103int");
249 sim_hw_parse (sd
, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
251 /* Memory control registers */
252 sim_do_command (sd
, "memory region 0x32000020,0x30");
253 /* Cache control register */
254 sim_do_command (sd
, "memory region 0x20000070,0x4");
255 /* Cache purge regions */
256 sim_do_command (sd
, "memory region 0x28400000,0x800");
257 sim_do_command (sd
, "memory region 0x28401000,0x800");
259 sim_do_command (sd
, "memory region 0x32000100,0xF");
260 sim_do_command (sd
, "memory region 0x32000200,0xF");
261 sim_do_command (sd
, "memory region 0x32000400,0xF");
262 sim_do_command (sd
, "memory region 0x32000800,0xF");
268 sim_io_eprintf (sd
, "Error: Board `%s' unknown.\n", board
);
275 /* check for/establish the a reference program image */
276 if (sim_analyze_program (sd
,
277 (STATE_PROG_ARGV (sd
) != NULL
278 ? *STATE_PROG_ARGV (sd
)
282 sim_module_uninstall (sd
);
286 /* establish any remaining configuration options */
287 if (sim_config (sd
) != SIM_RC_OK
)
289 sim_module_uninstall (sd
);
293 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
295 /* Uninstall the modules to avoid memory leaks,
296 file descriptor leaks, etc. */
297 sim_module_uninstall (sd
);
302 /* set machine specific configuration */
303 /* STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
304 /* | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
306 /* CPU specific initialization. */
307 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
309 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
311 CPU_PC_FETCH (cpu
) = mn10300_pc_get
;
312 CPU_PC_STORE (cpu
) = mn10300_pc_set
;
319 sim_create_inferior (SIM_DESC sd
,
320 struct bfd
*prog_bfd
,
324 memset (&State
, 0, sizeof (State
));
325 if (prog_bfd
!= NULL
) {
326 PC
= bfd_get_start_address (prog_bfd
);
330 CPU_PC_SET (STATE_CPU (sd
, 0), (unsigned64
) PC
);
332 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_am33_2
)
338 /* FIXME These would more efficient to use than load_mem/store_mem,
339 but need to be changed to use the memory map. */
342 sim_fetch_register (SIM_DESC sd
,
344 unsigned char *memory
,
347 reg_t reg
= State
.regs
[rn
];
357 sim_store_register (SIM_DESC sd
,
359 unsigned char *memory
,
363 State
.regs
[rn
] = (a
[3] << 24) + (a
[2] << 16) + (a
[1] << 8) + a
[0];
368 mn10300_core_signal (SIM_DESC sd
,
374 transfer_type transfer
,
375 sim_core_signals sig
)
377 const char *copy
= (transfer
== read_transfer
? "read" : "write");
378 address_word ip
= CIA_ADDR (cia
);
382 case sim_core_unmapped_signal
:
383 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
385 (unsigned long) addr
, (unsigned long) ip
);
386 program_interrupt(sd
, cpu
, cia
, SIM_SIGSEGV
);
389 case sim_core_unaligned_signal
:
390 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
392 (unsigned long) addr
, (unsigned long) ip
);
393 program_interrupt(sd
, cpu
, cia
, SIM_SIGBUS
);
397 sim_engine_abort (sd
, cpu
, cia
,
398 "mn10300_core_signal - internal error - bad switch");
404 program_interrupt (SIM_DESC sd
,
411 static int in_interrupt
= 0;
413 #ifdef SIM_CPU_EXCEPTION_TRIGGER
414 SIM_CPU_EXCEPTION_TRIGGER(sd
,cpu
,cia
);
417 /* avoid infinite recursion */
419 sim_io_printf (sd
, "ERROR: recursion in program_interrupt during software exception dispatch.");
423 /* copy NMI handler code from dv-mn103cpu.c */
424 store_word (SP
- 4, CPU_PC_GET (cpu
));
425 store_half (SP
- 8, PSW
);
427 /* Set the SYSEF flag in NMICR by backdoor method. See
428 dv-mn103int.c:write_icr(). This is necessary because
429 software exceptions are not modelled by actually talking to
430 the interrupt controller, so it cannot set its own SYSEF
432 if ((NULL
!= board
) && (strcmp(board
, BOARD_AM32
) == 0))
433 store_byte (0x34000103, 0x04);
438 CPU_PC_SET (cpu
, 0x40000008);
441 sim_engine_halt(sd
, cpu
, NULL
, cia
, sim_stopped
, sig
);
446 mn10300_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
450 if(State
.exc_suspended
> 0)
451 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", State
.exc_suspended
);
453 CPU_PC_SET (cpu
, cia
);
454 memcpy(State
.exc_trigger_regs
, State
.regs
, sizeof(State
.exc_trigger_regs
));
455 State
.exc_suspended
= 0;
459 mn10300_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
463 if(State
.exc_suspended
> 0)
464 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
465 State
.exc_suspended
, exception
);
467 memcpy(State
.exc_suspend_regs
, State
.regs
, sizeof(State
.exc_suspend_regs
));
468 memcpy(State
.regs
, State
.exc_trigger_regs
, sizeof(State
.regs
));
469 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
470 State
.exc_suspended
= exception
;
474 mn10300_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
478 if(exception
== 0 && State
.exc_suspended
> 0)
480 if(State
.exc_suspended
!= SIGTRAP
) /* warn not for breakpoints */
481 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
482 State
.exc_suspended
);
484 else if(exception
!= 0 && State
.exc_suspended
> 0)
486 if(exception
!= State
.exc_suspended
)
487 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
488 State
.exc_suspended
, exception
);
490 memcpy(State
.regs
, State
.exc_suspend_regs
, sizeof(State
.regs
));
491 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
493 else if(exception
!= 0 && State
.exc_suspended
== 0)
495 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
497 State
.exc_suspended
= 0;
500 /* This is called when an FP instruction is issued when the FP unit is
501 disabled, i.e., the FE bit of PSW is zero. It raises interrupt
504 fpu_disabled_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
506 sim_io_eprintf(sd
, "FPU disabled exception\n");
507 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
510 /* This is called when the FP unit is enabled but one of the
511 unimplemented insns is issued. It raises interrupt code 0x1c8. */
513 fpu_unimp_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
515 sim_io_eprintf(sd
, "Unimplemented FPU instruction exception\n");
516 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
519 /* This is called at the end of any FP insns that may have triggered
520 FP exceptions. If no exception is enabled, it returns immediately.
521 Otherwise, it raises an exception code 0x1d0. */
523 fpu_check_signal_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
525 if ((FPCR
& EC_MASK
) == 0)
528 sim_io_eprintf(sd
, "FPU %s%s%s%s%s exception\n",
529 (FPCR
& EC_V
) ? "V" : "",
530 (FPCR
& EC_Z
) ? "Z" : "",
531 (FPCR
& EC_O
) ? "O" : "",
532 (FPCR
& EC_U
) ? "U" : "",
533 (FPCR
& EC_I
) ? "I" : "");
534 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
537 /* Convert a 32-bit single-precision FP value in the target platform
538 format to a sim_fpu value. */
540 reg2val_32 (const void *reg
, sim_fpu
*val
)
542 FS2FPU (*(reg_t
*)reg
, *val
);
545 /* Round the given sim_fpu value to single precision, following the
546 target platform rounding and denormalization conventions. On
547 AM33/2.0, round_near is the only rounding mode. */
549 round_32 (sim_fpu
*val
)
551 return sim_fpu_round_32 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
554 /* Convert a sim_fpu value to the 32-bit single-precision target
557 val2reg_32 (const sim_fpu
*val
, void *reg
)
559 FPU2FS (*val
, *(reg_t
*)reg
);
562 /* Define the 32-bit single-precision conversion and rounding uniform
564 const struct fp_prec_t
566 reg2val_32
, round_32
, val2reg_32
569 /* Convert a 64-bit double-precision FP value in the target platform
570 format to a sim_fpu value. */
572 reg2val_64 (const void *reg
, sim_fpu
*val
)
574 FD2FPU (*(dword
*)reg
, *val
);
577 /* Round the given sim_fpu value to double precision, following the
578 target platform rounding and denormalization conventions. On
579 AM33/2.0, round_near is the only rounding mode. */
581 round_64 (sim_fpu
*val
)
583 return sim_fpu_round_64 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
586 /* Convert a sim_fpu value to the 64-bit double-precision target
589 val2reg_64 (const sim_fpu
*val
, void *reg
)
591 FPU2FD (*val
, *(dword
*)reg
);
594 /* Define the 64-bit single-precision conversion and rounding uniform
596 const struct fp_prec_t
598 reg2val_64
, round_64
, val2reg_64
601 /* Define shortcuts to the uniform interface operations. */
602 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
603 #define ROUND(val) (*ops->round) (val)
604 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
606 /* Check whether overflow, underflow or inexact exceptions should be
609 fpu_status_ok (sim_fpu_status stat
)
611 if ((stat
& sim_fpu_status_overflow
)
614 else if ((stat
& (sim_fpu_status_underflow
| sim_fpu_status_denorm
))
617 else if ((stat
& (sim_fpu_status_inexact
| sim_fpu_status_rounded
))
620 else if (stat
& ~ (sim_fpu_status_overflow
621 | sim_fpu_status_underflow
622 | sim_fpu_status_denorm
623 | sim_fpu_status_inexact
624 | sim_fpu_status_rounded
))
631 /* Implement a 32/64 bit reciprocal square root, signaling FP
632 exceptions when appropriate. */
634 fpu_rsqrt (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
635 const void *reg_in
, void *reg_out
, const struct fp_prec_t
*ops
)
637 sim_fpu in
, med
, out
;
639 REG2VAL (reg_in
, &in
);
642 switch (sim_fpu_is (&in
))
644 case SIM_FPU_IS_SNAN
:
645 case SIM_FPU_IS_NNUMBER
:
646 case SIM_FPU_IS_NINF
:
650 VAL2REG (&sim_fpu_qnan
, reg_out
);
653 case SIM_FPU_IS_QNAN
:
654 VAL2REG (&sim_fpu_qnan
, reg_out
);
657 case SIM_FPU_IS_PINF
:
658 VAL2REG (&sim_fpu_zero
, reg_out
);
661 case SIM_FPU_IS_PNUMBER
:
663 /* Since we don't have a function to compute rsqrt directly,
665 sim_fpu_status stat
= 0;
666 stat
|= sim_fpu_sqrt (&med
, &in
);
667 stat
|= sim_fpu_inv (&out
, &med
);
668 stat
|= ROUND (&out
);
669 if (fpu_status_ok (stat
))
670 VAL2REG (&out
, reg_out
);
674 case SIM_FPU_IS_NZERO
:
675 case SIM_FPU_IS_PZERO
:
680 /* Generate an INF with the same sign. */
681 sim_fpu_inv (&out
, &in
);
682 VAL2REG (&out
, reg_out
);
690 fpu_check_signal_exception (sd
, cpu
, cia
);
698 case SIM_FPU_IS_SNAN
:
699 case SIM_FPU_IS_QNAN
:
702 case SIM_FPU_IS_NINF
:
703 case SIM_FPU_IS_NNUMBER
:
704 case SIM_FPU_IS_NDENORM
:
707 case SIM_FPU_IS_PINF
:
708 case SIM_FPU_IS_PNUMBER
:
709 case SIM_FPU_IS_PDENORM
:
712 case SIM_FPU_IS_NZERO
:
713 case SIM_FPU_IS_PZERO
:
721 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
722 exception bits as specified. */
724 fpu_cmp (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
725 const void *reg_in1
, const void *reg_in2
,
726 const struct fp_prec_t
*ops
)
730 REG2VAL (reg_in1
, &m
);
731 REG2VAL (reg_in2
, &n
);
736 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
))
744 FPCR
|= cmp2fcc (sim_fpu_cmp (&m
, &n
));
746 fpu_check_signal_exception (sd
, cpu
, cia
);
749 /* Implement a 32/64 bit FP add, setting FP exception bits when
752 fpu_add (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
753 const void *reg_in1
, const void *reg_in2
,
754 void *reg_out
, const struct fp_prec_t
*ops
)
758 REG2VAL (reg_in1
, &m
);
759 REG2VAL (reg_in2
, &n
);
763 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
764 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
765 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
)
766 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
767 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
))
772 VAL2REG (&sim_fpu_qnan
, reg_out
);
776 sim_fpu_status stat
= sim_fpu_add (&r
, &m
, &n
);
778 if (fpu_status_ok (stat
))
779 VAL2REG (&r
, reg_out
);
782 fpu_check_signal_exception (sd
, cpu
, cia
);
785 /* Implement a 32/64 bit FP sub, setting FP exception bits when
788 fpu_sub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
789 const void *reg_in1
, const void *reg_in2
,
790 void *reg_out
, const struct fp_prec_t
*ops
)
794 REG2VAL (reg_in1
, &m
);
795 REG2VAL (reg_in2
, &n
);
799 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
800 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
801 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
)
802 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
803 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
))
808 VAL2REG (&sim_fpu_qnan
, reg_out
);
812 sim_fpu_status stat
= sim_fpu_sub (&r
, &m
, &n
);
814 if (fpu_status_ok (stat
))
815 VAL2REG (&r
, reg_out
);
818 fpu_check_signal_exception (sd
, cpu
, cia
);
821 /* Implement a 32/64 bit FP mul, setting FP exception bits when
824 fpu_mul (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
825 const void *reg_in1
, const void *reg_in2
,
826 void *reg_out
, const struct fp_prec_t
*ops
)
830 REG2VAL (reg_in1
, &m
);
831 REG2VAL (reg_in2
, &n
);
835 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
836 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_zero (&n
))
837 || (sim_fpu_is_zero (&m
) && sim_fpu_is_infinity (&n
)))
842 VAL2REG (&sim_fpu_qnan
, reg_out
);
846 sim_fpu_status stat
= sim_fpu_mul (&r
, &m
, &n
);
848 if (fpu_status_ok (stat
))
849 VAL2REG (&r
, reg_out
);
852 fpu_check_signal_exception (sd
, cpu
, cia
);
855 /* Implement a 32/64 bit FP div, setting FP exception bits when
858 fpu_div (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
859 const void *reg_in1
, const void *reg_in2
,
860 void *reg_out
, const struct fp_prec_t
*ops
)
864 REG2VAL (reg_in1
, &m
);
865 REG2VAL (reg_in2
, &n
);
869 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
870 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
))
871 || (sim_fpu_is_zero (&m
) && sim_fpu_is_zero (&n
)))
876 VAL2REG (&sim_fpu_qnan
, reg_out
);
878 else if (sim_fpu_is_number (&m
) && sim_fpu_is_zero (&n
)
883 sim_fpu_status stat
= sim_fpu_div (&r
, &m
, &n
);
885 if (fpu_status_ok (stat
))
886 VAL2REG (&r
, reg_out
);
889 fpu_check_signal_exception (sd
, cpu
, cia
);
892 /* Implement a 32/64 bit FP madd, setting FP exception bits when
895 fpu_fmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
896 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
897 void *reg_out
, const struct fp_prec_t
*ops
)
899 sim_fpu m1
, m2
, m
, n
, r
;
901 REG2VAL (reg_in1
, &m1
);
902 REG2VAL (reg_in2
, &m2
);
903 REG2VAL (reg_in3
, &n
);
908 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
909 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
910 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
916 VAL2REG (&sim_fpu_qnan
, reg_out
);
920 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
922 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
923 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
924 goto invalid_operands
;
926 stat
|= sim_fpu_add (&r
, &m
, &n
);
928 if (fpu_status_ok (stat
))
929 VAL2REG (&r
, reg_out
);
932 fpu_check_signal_exception (sd
, cpu
, cia
);
935 /* Implement a 32/64 bit FP msub, setting FP exception bits when
938 fpu_fmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
939 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
940 void *reg_out
, const struct fp_prec_t
*ops
)
942 sim_fpu m1
, m2
, m
, n
, r
;
944 REG2VAL (reg_in1
, &m1
);
945 REG2VAL (reg_in2
, &m2
);
946 REG2VAL (reg_in3
, &n
);
951 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
952 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
953 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
959 VAL2REG (&sim_fpu_qnan
, reg_out
);
963 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
965 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
966 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
967 goto invalid_operands
;
969 stat
|= sim_fpu_sub (&r
, &m
, &n
);
971 if (fpu_status_ok (stat
))
972 VAL2REG (&r
, reg_out
);
975 fpu_check_signal_exception (sd
, cpu
, cia
);
978 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
981 fpu_fnmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
982 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
983 void *reg_out
, const struct fp_prec_t
*ops
)
985 sim_fpu m1
, m2
, m
, mm
, n
, r
;
987 REG2VAL (reg_in1
, &m1
);
988 REG2VAL (reg_in2
, &m2
);
989 REG2VAL (reg_in3
, &n
);
994 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
995 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
996 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1002 VAL2REG (&sim_fpu_qnan
, reg_out
);
1006 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1008 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1009 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
1010 goto invalid_operands
;
1012 stat
|= sim_fpu_neg (&mm
, &m
);
1013 stat
|= sim_fpu_add (&r
, &mm
, &n
);
1015 if (fpu_status_ok (stat
))
1016 VAL2REG (&r
, reg_out
);
1019 fpu_check_signal_exception (sd
, cpu
, cia
);
1022 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1025 fpu_fnmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1026 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1027 void *reg_out
, const struct fp_prec_t
*ops
)
1029 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1031 REG2VAL (reg_in1
, &m1
);
1032 REG2VAL (reg_in2
, &m2
);
1033 REG2VAL (reg_in3
, &n
);
1038 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1039 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1040 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1046 VAL2REG (&sim_fpu_qnan
, reg_out
);
1050 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1052 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1053 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
1054 goto invalid_operands
;
1056 stat
|= sim_fpu_neg (&mm
, &m
);
1057 stat
|= sim_fpu_sub (&r
, &mm
, &n
);
1059 if (fpu_status_ok (stat
))
1060 VAL2REG (&r
, reg_out
);
1063 fpu_check_signal_exception (sd
, cpu
, cia
);