5 #include "sim-options.h"
9 #include "sim-assert.h"
20 /* simulation target board. NULL=default configuration */
21 static char* board
= NULL
;
23 static DECLARE_OPTION_HANDLER (mn10300_option_handler
);
26 OPTION_BOARD
= OPTION_START
,
30 mn10300_option_handler (SIM_DESC sd
,
43 board
= zalloc(strlen(arg
) + 1);
53 static const OPTION mn10300_options
[] =
55 #define BOARD_AM32 "stdeval1"
56 { {"board", required_argument
, NULL
, OPTION_BOARD
},
57 '\0', "none" /* rely on compile-time string concatenation for other options */
59 , "Customize simulation for a particular board.", mn10300_option_handler
},
61 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
64 /* For compatibility */
68 mn10300_pc_get (sim_cpu
*cpu
)
74 mn10300_pc_set (sim_cpu
*cpu
, sim_cia pc
)
79 static int mn10300_reg_fetch (SIM_CPU
*, int, unsigned char *, int);
80 static int mn10300_reg_store (SIM_CPU
*, int, unsigned char *, int);
82 /* These default values correspond to expected usage for the chip. */
85 sim_open (SIM_OPEN_KIND kind
,
91 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
93 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
95 /* The cpu data is kept in a separately allocated chunk of memory. */
96 if (sim_cpu_alloc_all (sd
, 1) != SIM_RC_OK
)
99 /* for compatibility */
102 /* FIXME: should be better way of setting up interrupts. For
103 moment, only support watchpoints causing a breakpoint (gdb
105 STATE_WATCHPOINTS (sd
)->interrupt_handler
= NULL
;
106 STATE_WATCHPOINTS (sd
)->interrupt_names
= NULL
;
108 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
110 sim_add_option_table (sd
, NULL
, mn10300_options
);
112 /* Allocate core managed memory */
113 sim_do_command (sd
, "memory region 0,0x100000");
114 sim_do_command (sd
, "memory region 0x40000000,0x200000");
116 /* The parser will print an error message for us, so we silently return. */
117 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
119 /* Uninstall the modules to avoid memory leaks,
120 file descriptor leaks, etc. */
121 sim_module_uninstall (sd
);
126 && (strcmp(board
, BOARD_AM32
) == 0 ) )
129 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
131 sim_do_command (sd
, "memory region 0x44000000,0x40000");
132 sim_do_command (sd
, "memory region 0x48000000,0x400000");
134 /* device support for mn1030002 */
135 /* interrupt controller */
137 sim_hw_parse (sd
, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
139 /* DEBUG: NMI input's */
140 sim_hw_parse (sd
, "/glue@0x30000000/reg 0x30000000 12");
141 sim_hw_parse (sd
, "/glue@0x30000000 > int0 nmirq /mn103int");
142 sim_hw_parse (sd
, "/glue@0x30000000 > int1 watchdog /mn103int");
143 sim_hw_parse (sd
, "/glue@0x30000000 > int2 syserr /mn103int");
145 /* DEBUG: ACK input */
146 sim_hw_parse (sd
, "/glue@0x30002000/reg 0x30002000 4");
147 sim_hw_parse (sd
, "/glue@0x30002000 > int ack /mn103int");
149 /* DEBUG: LEVEL output */
150 sim_hw_parse (sd
, "/glue@0x30004000/reg 0x30004000 8");
151 sim_hw_parse (sd
, "/mn103int > nmi int0 /glue@0x30004000");
152 sim_hw_parse (sd
, "/mn103int > level int1 /glue@0x30004000");
154 /* DEBUG: A bunch of interrupt inputs */
155 sim_hw_parse (sd
, "/glue@0x30006000/reg 0x30006000 32");
156 sim_hw_parse (sd
, "/glue@0x30006000 > int0 irq-0 /mn103int");
157 sim_hw_parse (sd
, "/glue@0x30006000 > int1 irq-1 /mn103int");
158 sim_hw_parse (sd
, "/glue@0x30006000 > int2 irq-2 /mn103int");
159 sim_hw_parse (sd
, "/glue@0x30006000 > int3 irq-3 /mn103int");
160 sim_hw_parse (sd
, "/glue@0x30006000 > int4 irq-4 /mn103int");
161 sim_hw_parse (sd
, "/glue@0x30006000 > int5 irq-5 /mn103int");
162 sim_hw_parse (sd
, "/glue@0x30006000 > int6 irq-6 /mn103int");
163 sim_hw_parse (sd
, "/glue@0x30006000 > int7 irq-7 /mn103int");
165 /* processor interrupt device */
168 sim_hw_parse (sd
, "/mn103cpu@0x20000000");
169 sim_hw_parse (sd
, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
171 /* DEBUG: ACK output wired upto a glue device */
172 sim_hw_parse (sd
, "/glue@0x20002000");
173 sim_hw_parse (sd
, "/glue@0x20002000/reg 0x20002000 4");
174 sim_hw_parse (sd
, "/mn103cpu > ack int0 /glue@0x20002000");
176 /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
177 sim_hw_parse (sd
, "/glue@0x20004000");
178 sim_hw_parse (sd
, "/glue@0x20004000/reg 0x20004000 12");
179 sim_hw_parse (sd
, "/glue@0x20004000 > int0 reset /mn103cpu");
180 sim_hw_parse (sd
, "/glue@0x20004000 > int1 nmi /mn103cpu");
181 sim_hw_parse (sd
, "/glue@0x20004000 > int2 level /mn103cpu");
183 /* REAL: The processor wired up to the real interrupt controller */
184 sim_hw_parse (sd
, "/mn103cpu > ack ack /mn103int");
185 sim_hw_parse (sd
, "/mn103int > level level /mn103cpu");
186 sim_hw_parse (sd
, "/mn103int > nmi nmi /mn103cpu");
192 sim_hw_parse (sd
, "/pal@0x31000000");
193 sim_hw_parse (sd
, "/pal@0x31000000/reg 0x31000000 64");
194 sim_hw_parse (sd
, "/pal@0x31000000/poll? true");
196 /* DEBUG: PAL wired up to a glue device */
197 sim_hw_parse (sd
, "/glue@0x31002000");
198 sim_hw_parse (sd
, "/glue@0x31002000/reg 0x31002000 16");
199 sim_hw_parse (sd
, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
200 sim_hw_parse (sd
, "/pal@0x31000000 > timer int1 /glue@0x31002000");
201 sim_hw_parse (sd
, "/pal@0x31000000 > int int2 /glue@0x31002000");
202 sim_hw_parse (sd
, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
203 sim_hw_parse (sd
, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
204 sim_hw_parse (sd
, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
206 /* REAL: The PAL wired up to the real interrupt controller */
207 sim_hw_parse (sd
, "/pal@0x31000000 > countdown irq-0 /mn103int");
208 sim_hw_parse (sd
, "/pal@0x31000000 > timer irq-1 /mn103int");
209 sim_hw_parse (sd
, "/pal@0x31000000 > int irq-2 /mn103int");
211 /* 8 and 16 bit timers */
212 sim_hw_parse (sd
, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16");
214 /* Hook timer interrupts up to interrupt controller */
215 sim_hw_parse (sd
, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int");
216 sim_hw_parse (sd
, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int");
217 sim_hw_parse (sd
, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int");
218 sim_hw_parse (sd
, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int");
219 sim_hw_parse (sd
, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int");
220 sim_hw_parse (sd
, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int");
221 sim_hw_parse (sd
, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int");
222 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int");
223 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int");
226 /* Serial devices 0,1,2 */
227 sim_hw_parse (sd
, "/mn103ser@0x34000800/reg 0x34000800 48");
228 sim_hw_parse (sd
, "/mn103ser@0x34000800/poll? true");
230 /* Hook serial interrupts up to interrupt controller */
231 sim_hw_parse (sd
, "/mn103ser > serial-0-receive serial-0-receive /mn103int");
232 sim_hw_parse (sd
, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int");
233 sim_hw_parse (sd
, "/mn103ser > serial-1-receive serial-1-receive /mn103int");
234 sim_hw_parse (sd
, "/mn103ser > serial-1-transmit serial-1-transmit /mn103int");
235 sim_hw_parse (sd
, "/mn103ser > serial-2-receive serial-2-receive /mn103int");
236 sim_hw_parse (sd
, "/mn103ser > serial-2-transmit serial-2-transmit /mn103int");
238 sim_hw_parse (sd
, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
240 /* Memory control registers */
241 sim_do_command (sd
, "memory region 0x32000020,0x30");
242 /* Cache control register */
243 sim_do_command (sd
, "memory region 0x20000070,0x4");
244 /* Cache purge regions */
245 sim_do_command (sd
, "memory region 0x28400000,0x800");
246 sim_do_command (sd
, "memory region 0x28401000,0x800");
248 sim_do_command (sd
, "memory region 0x32000100,0xF");
249 sim_do_command (sd
, "memory region 0x32000200,0xF");
250 sim_do_command (sd
, "memory region 0x32000400,0xF");
251 sim_do_command (sd
, "memory region 0x32000800,0xF");
257 sim_io_eprintf (sd
, "Error: Board `%s' unknown.\n", board
);
264 /* check for/establish the a reference program image */
265 if (sim_analyze_program (sd
,
266 (STATE_PROG_ARGV (sd
) != NULL
267 ? *STATE_PROG_ARGV (sd
)
271 sim_module_uninstall (sd
);
275 /* establish any remaining configuration options */
276 if (sim_config (sd
) != SIM_RC_OK
)
278 sim_module_uninstall (sd
);
282 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
284 /* Uninstall the modules to avoid memory leaks,
285 file descriptor leaks, etc. */
286 sim_module_uninstall (sd
);
291 /* set machine specific configuration */
292 /* STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
293 /* | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
295 /* CPU specific initialization. */
296 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
298 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
300 CPU_REG_FETCH (cpu
) = mn10300_reg_fetch
;
301 CPU_REG_STORE (cpu
) = mn10300_reg_store
;
302 CPU_PC_FETCH (cpu
) = mn10300_pc_get
;
303 CPU_PC_STORE (cpu
) = mn10300_pc_set
;
310 sim_create_inferior (SIM_DESC sd
,
311 struct bfd
*prog_bfd
,
315 memset (&State
, 0, sizeof (State
));
316 if (prog_bfd
!= NULL
) {
317 PC
= bfd_get_start_address (prog_bfd
);
321 CPU_PC_SET (STATE_CPU (sd
, 0), (unsigned64
) PC
);
323 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_am33_2
)
329 /* FIXME These would more efficient to use than load_mem/store_mem,
330 but need to be changed to use the memory map. */
333 mn10300_reg_fetch (SIM_CPU
*cpu
, int rn
, unsigned char *memory
, int length
)
335 reg_t reg
= State
.regs
[rn
];
345 mn10300_reg_store (SIM_CPU
*cpu
, int rn
, unsigned char *memory
, int length
)
348 State
.regs
[rn
] = (a
[3] << 24) + (a
[2] << 16) + (a
[1] << 8) + a
[0];
353 mn10300_core_signal (SIM_DESC sd
,
359 transfer_type transfer
,
360 sim_core_signals sig
)
362 const char *copy
= (transfer
== read_transfer
? "read" : "write");
363 address_word ip
= CIA_ADDR (cia
);
367 case sim_core_unmapped_signal
:
368 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
370 (unsigned long) addr
, (unsigned long) ip
);
371 program_interrupt(sd
, cpu
, cia
, SIM_SIGSEGV
);
374 case sim_core_unaligned_signal
:
375 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
377 (unsigned long) addr
, (unsigned long) ip
);
378 program_interrupt(sd
, cpu
, cia
, SIM_SIGBUS
);
382 sim_engine_abort (sd
, cpu
, cia
,
383 "mn10300_core_signal - internal error - bad switch");
389 program_interrupt (SIM_DESC sd
,
396 static int in_interrupt
= 0;
398 #ifdef SIM_CPU_EXCEPTION_TRIGGER
399 SIM_CPU_EXCEPTION_TRIGGER(sd
,cpu
,cia
);
402 /* avoid infinite recursion */
404 sim_io_printf (sd
, "ERROR: recursion in program_interrupt during software exception dispatch.");
408 /* copy NMI handler code from dv-mn103cpu.c */
409 store_word (SP
- 4, CPU_PC_GET (cpu
));
410 store_half (SP
- 8, PSW
);
412 /* Set the SYSEF flag in NMICR by backdoor method. See
413 dv-mn103int.c:write_icr(). This is necessary because
414 software exceptions are not modelled by actually talking to
415 the interrupt controller, so it cannot set its own SYSEF
417 if ((NULL
!= board
) && (strcmp(board
, BOARD_AM32
) == 0))
418 store_byte (0x34000103, 0x04);
423 CPU_PC_SET (cpu
, 0x40000008);
426 sim_engine_halt(sd
, cpu
, NULL
, cia
, sim_stopped
, sig
);
431 mn10300_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
435 if(State
.exc_suspended
> 0)
436 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", State
.exc_suspended
);
438 CPU_PC_SET (cpu
, cia
);
439 memcpy(State
.exc_trigger_regs
, State
.regs
, sizeof(State
.exc_trigger_regs
));
440 State
.exc_suspended
= 0;
444 mn10300_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
448 if(State
.exc_suspended
> 0)
449 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
450 State
.exc_suspended
, exception
);
452 memcpy(State
.exc_suspend_regs
, State
.regs
, sizeof(State
.exc_suspend_regs
));
453 memcpy(State
.regs
, State
.exc_trigger_regs
, sizeof(State
.regs
));
454 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
455 State
.exc_suspended
= exception
;
459 mn10300_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
463 if(exception
== 0 && State
.exc_suspended
> 0)
465 if(State
.exc_suspended
!= SIGTRAP
) /* warn not for breakpoints */
466 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
467 State
.exc_suspended
);
469 else if(exception
!= 0 && State
.exc_suspended
> 0)
471 if(exception
!= State
.exc_suspended
)
472 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
473 State
.exc_suspended
, exception
);
475 memcpy(State
.regs
, State
.exc_suspend_regs
, sizeof(State
.regs
));
476 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
478 else if(exception
!= 0 && State
.exc_suspended
== 0)
480 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
482 State
.exc_suspended
= 0;
485 /* This is called when an FP instruction is issued when the FP unit is
486 disabled, i.e., the FE bit of PSW is zero. It raises interrupt
489 fpu_disabled_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
491 sim_io_eprintf(sd
, "FPU disabled exception\n");
492 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
495 /* This is called when the FP unit is enabled but one of the
496 unimplemented insns is issued. It raises interrupt code 0x1c8. */
498 fpu_unimp_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
500 sim_io_eprintf(sd
, "Unimplemented FPU instruction exception\n");
501 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
504 /* This is called at the end of any FP insns that may have triggered
505 FP exceptions. If no exception is enabled, it returns immediately.
506 Otherwise, it raises an exception code 0x1d0. */
508 fpu_check_signal_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
510 if ((FPCR
& EC_MASK
) == 0)
513 sim_io_eprintf(sd
, "FPU %s%s%s%s%s exception\n",
514 (FPCR
& EC_V
) ? "V" : "",
515 (FPCR
& EC_Z
) ? "Z" : "",
516 (FPCR
& EC_O
) ? "O" : "",
517 (FPCR
& EC_U
) ? "U" : "",
518 (FPCR
& EC_I
) ? "I" : "");
519 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
522 /* Convert a 32-bit single-precision FP value in the target platform
523 format to a sim_fpu value. */
525 reg2val_32 (const void *reg
, sim_fpu
*val
)
527 FS2FPU (*(reg_t
*)reg
, *val
);
530 /* Round the given sim_fpu value to single precision, following the
531 target platform rounding and denormalization conventions. On
532 AM33/2.0, round_near is the only rounding mode. */
534 round_32 (sim_fpu
*val
)
536 return sim_fpu_round_32 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
539 /* Convert a sim_fpu value to the 32-bit single-precision target
542 val2reg_32 (const sim_fpu
*val
, void *reg
)
544 FPU2FS (*val
, *(reg_t
*)reg
);
547 /* Define the 32-bit single-precision conversion and rounding uniform
549 const struct fp_prec_t
551 reg2val_32
, round_32
, val2reg_32
554 /* Convert a 64-bit double-precision FP value in the target platform
555 format to a sim_fpu value. */
557 reg2val_64 (const void *reg
, sim_fpu
*val
)
559 FD2FPU (*(dword
*)reg
, *val
);
562 /* Round the given sim_fpu value to double precision, following the
563 target platform rounding and denormalization conventions. On
564 AM33/2.0, round_near is the only rounding mode. */
566 round_64 (sim_fpu
*val
)
568 return sim_fpu_round_64 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
571 /* Convert a sim_fpu value to the 64-bit double-precision target
574 val2reg_64 (const sim_fpu
*val
, void *reg
)
576 FPU2FD (*val
, *(dword
*)reg
);
579 /* Define the 64-bit single-precision conversion and rounding uniform
581 const struct fp_prec_t
583 reg2val_64
, round_64
, val2reg_64
586 /* Define shortcuts to the uniform interface operations. */
587 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
588 #define ROUND(val) (*ops->round) (val)
589 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
591 /* Check whether overflow, underflow or inexact exceptions should be
594 fpu_status_ok (sim_fpu_status stat
)
596 if ((stat
& sim_fpu_status_overflow
)
599 else if ((stat
& (sim_fpu_status_underflow
| sim_fpu_status_denorm
))
602 else if ((stat
& (sim_fpu_status_inexact
| sim_fpu_status_rounded
))
605 else if (stat
& ~ (sim_fpu_status_overflow
606 | sim_fpu_status_underflow
607 | sim_fpu_status_denorm
608 | sim_fpu_status_inexact
609 | sim_fpu_status_rounded
))
616 /* Implement a 32/64 bit reciprocal square root, signaling FP
617 exceptions when appropriate. */
619 fpu_rsqrt (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
620 const void *reg_in
, void *reg_out
, const struct fp_prec_t
*ops
)
622 sim_fpu in
, med
, out
;
624 REG2VAL (reg_in
, &in
);
627 switch (sim_fpu_is (&in
))
629 case SIM_FPU_IS_SNAN
:
630 case SIM_FPU_IS_NNUMBER
:
631 case SIM_FPU_IS_NINF
:
635 VAL2REG (&sim_fpu_qnan
, reg_out
);
638 case SIM_FPU_IS_QNAN
:
639 VAL2REG (&sim_fpu_qnan
, reg_out
);
642 case SIM_FPU_IS_PINF
:
643 VAL2REG (&sim_fpu_zero
, reg_out
);
646 case SIM_FPU_IS_PNUMBER
:
648 /* Since we don't have a function to compute rsqrt directly,
650 sim_fpu_status stat
= 0;
651 stat
|= sim_fpu_sqrt (&med
, &in
);
652 stat
|= sim_fpu_inv (&out
, &med
);
653 stat
|= ROUND (&out
);
654 if (fpu_status_ok (stat
))
655 VAL2REG (&out
, reg_out
);
659 case SIM_FPU_IS_NZERO
:
660 case SIM_FPU_IS_PZERO
:
665 /* Generate an INF with the same sign. */
666 sim_fpu_inv (&out
, &in
);
667 VAL2REG (&out
, reg_out
);
675 fpu_check_signal_exception (sd
, cpu
, cia
);
683 case SIM_FPU_IS_SNAN
:
684 case SIM_FPU_IS_QNAN
:
687 case SIM_FPU_IS_NINF
:
688 case SIM_FPU_IS_NNUMBER
:
689 case SIM_FPU_IS_NDENORM
:
692 case SIM_FPU_IS_PINF
:
693 case SIM_FPU_IS_PNUMBER
:
694 case SIM_FPU_IS_PDENORM
:
697 case SIM_FPU_IS_NZERO
:
698 case SIM_FPU_IS_PZERO
:
706 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
707 exception bits as specified. */
709 fpu_cmp (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
710 const void *reg_in1
, const void *reg_in2
,
711 const struct fp_prec_t
*ops
)
715 REG2VAL (reg_in1
, &m
);
716 REG2VAL (reg_in2
, &n
);
721 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
))
729 FPCR
|= cmp2fcc (sim_fpu_cmp (&m
, &n
));
731 fpu_check_signal_exception (sd
, cpu
, cia
);
734 /* Implement a 32/64 bit FP add, setting FP exception bits when
737 fpu_add (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
738 const void *reg_in1
, const void *reg_in2
,
739 void *reg_out
, const struct fp_prec_t
*ops
)
743 REG2VAL (reg_in1
, &m
);
744 REG2VAL (reg_in2
, &n
);
748 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
749 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
750 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
)
751 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
752 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
))
757 VAL2REG (&sim_fpu_qnan
, reg_out
);
761 sim_fpu_status stat
= sim_fpu_add (&r
, &m
, &n
);
763 if (fpu_status_ok (stat
))
764 VAL2REG (&r
, reg_out
);
767 fpu_check_signal_exception (sd
, cpu
, cia
);
770 /* Implement a 32/64 bit FP sub, setting FP exception bits when
773 fpu_sub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
774 const void *reg_in1
, const void *reg_in2
,
775 void *reg_out
, const struct fp_prec_t
*ops
)
779 REG2VAL (reg_in1
, &m
);
780 REG2VAL (reg_in2
, &n
);
784 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
785 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
786 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
)
787 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
788 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
))
793 VAL2REG (&sim_fpu_qnan
, reg_out
);
797 sim_fpu_status stat
= sim_fpu_sub (&r
, &m
, &n
);
799 if (fpu_status_ok (stat
))
800 VAL2REG (&r
, reg_out
);
803 fpu_check_signal_exception (sd
, cpu
, cia
);
806 /* Implement a 32/64 bit FP mul, setting FP exception bits when
809 fpu_mul (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
810 const void *reg_in1
, const void *reg_in2
,
811 void *reg_out
, const struct fp_prec_t
*ops
)
815 REG2VAL (reg_in1
, &m
);
816 REG2VAL (reg_in2
, &n
);
820 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
821 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_zero (&n
))
822 || (sim_fpu_is_zero (&m
) && sim_fpu_is_infinity (&n
)))
827 VAL2REG (&sim_fpu_qnan
, reg_out
);
831 sim_fpu_status stat
= sim_fpu_mul (&r
, &m
, &n
);
833 if (fpu_status_ok (stat
))
834 VAL2REG (&r
, reg_out
);
837 fpu_check_signal_exception (sd
, cpu
, cia
);
840 /* Implement a 32/64 bit FP div, setting FP exception bits when
843 fpu_div (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
844 const void *reg_in1
, const void *reg_in2
,
845 void *reg_out
, const struct fp_prec_t
*ops
)
849 REG2VAL (reg_in1
, &m
);
850 REG2VAL (reg_in2
, &n
);
854 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
855 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
))
856 || (sim_fpu_is_zero (&m
) && sim_fpu_is_zero (&n
)))
861 VAL2REG (&sim_fpu_qnan
, reg_out
);
863 else if (sim_fpu_is_number (&m
) && sim_fpu_is_zero (&n
)
868 sim_fpu_status stat
= sim_fpu_div (&r
, &m
, &n
);
870 if (fpu_status_ok (stat
))
871 VAL2REG (&r
, reg_out
);
874 fpu_check_signal_exception (sd
, cpu
, cia
);
877 /* Implement a 32/64 bit FP madd, setting FP exception bits when
880 fpu_fmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
881 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
882 void *reg_out
, const struct fp_prec_t
*ops
)
884 sim_fpu m1
, m2
, m
, n
, r
;
886 REG2VAL (reg_in1
, &m1
);
887 REG2VAL (reg_in2
, &m2
);
888 REG2VAL (reg_in3
, &n
);
893 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
894 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
895 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
901 VAL2REG (&sim_fpu_qnan
, reg_out
);
905 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
907 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
908 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
909 goto invalid_operands
;
911 stat
|= sim_fpu_add (&r
, &m
, &n
);
913 if (fpu_status_ok (stat
))
914 VAL2REG (&r
, reg_out
);
917 fpu_check_signal_exception (sd
, cpu
, cia
);
920 /* Implement a 32/64 bit FP msub, setting FP exception bits when
923 fpu_fmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
924 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
925 void *reg_out
, const struct fp_prec_t
*ops
)
927 sim_fpu m1
, m2
, m
, n
, r
;
929 REG2VAL (reg_in1
, &m1
);
930 REG2VAL (reg_in2
, &m2
);
931 REG2VAL (reg_in3
, &n
);
936 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
937 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
938 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
944 VAL2REG (&sim_fpu_qnan
, reg_out
);
948 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
950 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
951 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
952 goto invalid_operands
;
954 stat
|= sim_fpu_sub (&r
, &m
, &n
);
956 if (fpu_status_ok (stat
))
957 VAL2REG (&r
, reg_out
);
960 fpu_check_signal_exception (sd
, cpu
, cia
);
963 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
966 fpu_fnmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
967 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
968 void *reg_out
, const struct fp_prec_t
*ops
)
970 sim_fpu m1
, m2
, m
, mm
, n
, r
;
972 REG2VAL (reg_in1
, &m1
);
973 REG2VAL (reg_in2
, &m2
);
974 REG2VAL (reg_in3
, &n
);
979 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
980 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
981 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
987 VAL2REG (&sim_fpu_qnan
, reg_out
);
991 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
993 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
994 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
995 goto invalid_operands
;
997 stat
|= sim_fpu_neg (&mm
, &m
);
998 stat
|= sim_fpu_add (&r
, &mm
, &n
);
1000 if (fpu_status_ok (stat
))
1001 VAL2REG (&r
, reg_out
);
1004 fpu_check_signal_exception (sd
, cpu
, cia
);
1007 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1010 fpu_fnmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1011 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1012 void *reg_out
, const struct fp_prec_t
*ops
)
1014 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1016 REG2VAL (reg_in1
, &m1
);
1017 REG2VAL (reg_in2
, &m2
);
1018 REG2VAL (reg_in3
, &n
);
1023 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1024 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1025 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1031 VAL2REG (&sim_fpu_qnan
, reg_out
);
1035 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1037 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1038 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
1039 goto invalid_operands
;
1041 stat
|= sim_fpu_neg (&mm
, &m
);
1042 stat
|= sim_fpu_sub (&r
, &mm
, &n
);
1044 if (fpu_status_ok (stat
))
1045 VAL2REG (&r
, reg_out
);
1048 fpu_check_signal_exception (sd
, cpu
, cia
);