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, unsigned char *, int);
83 static int mn10300_reg_store (SIM_CPU
*, int, unsigned char *, 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
,
272 (STATE_PROG_ARGV (sd
) != NULL
273 ? *STATE_PROG_ARGV (sd
)
277 sim_module_uninstall (sd
);
281 /* establish any remaining configuration options */
282 if (sim_config (sd
) != SIM_RC_OK
)
284 sim_module_uninstall (sd
);
288 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
290 /* Uninstall the modules to avoid memory leaks,
291 file descriptor leaks, etc. */
292 sim_module_uninstall (sd
);
297 /* set machine specific configuration */
298 /* STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
299 /* | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
301 /* CPU specific initialization. */
302 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
304 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
306 CPU_REG_FETCH (cpu
) = mn10300_reg_fetch
;
307 CPU_REG_STORE (cpu
) = mn10300_reg_store
;
308 CPU_PC_FETCH (cpu
) = mn10300_pc_get
;
309 CPU_PC_STORE (cpu
) = mn10300_pc_set
;
316 sim_create_inferior (SIM_DESC sd
,
317 struct bfd
*prog_bfd
,
321 memset (&State
, 0, sizeof (State
));
322 if (prog_bfd
!= NULL
) {
323 PC
= bfd_get_start_address (prog_bfd
);
327 CPU_PC_SET (STATE_CPU (sd
, 0), (unsigned64
) PC
);
329 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_am33_2
)
335 /* FIXME These would more efficient to use than load_mem/store_mem,
336 but need to be changed to use the memory map. */
339 mn10300_reg_fetch (SIM_CPU
*cpu
, int rn
, unsigned char *memory
, int length
)
341 reg_t reg
= State
.regs
[rn
];
351 mn10300_reg_store (SIM_CPU
*cpu
, int rn
, unsigned char *memory
, int length
)
354 State
.regs
[rn
] = (a
[3] << 24) + (a
[2] << 16) + (a
[1] << 8) + a
[0];
359 mn10300_core_signal (SIM_DESC sd
,
365 transfer_type transfer
,
366 sim_core_signals sig
)
368 const char *copy
= (transfer
== read_transfer
? "read" : "write");
369 address_word ip
= CIA_ADDR (cia
);
373 case sim_core_unmapped_signal
:
374 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
376 (unsigned long) addr
, (unsigned long) ip
);
377 program_interrupt(sd
, cpu
, cia
, SIM_SIGSEGV
);
380 case sim_core_unaligned_signal
:
381 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
383 (unsigned long) addr
, (unsigned long) ip
);
384 program_interrupt(sd
, cpu
, cia
, SIM_SIGBUS
);
388 sim_engine_abort (sd
, cpu
, cia
,
389 "mn10300_core_signal - internal error - bad switch");
395 program_interrupt (SIM_DESC sd
,
402 static int in_interrupt
= 0;
404 #ifdef SIM_CPU_EXCEPTION_TRIGGER
405 SIM_CPU_EXCEPTION_TRIGGER(sd
,cpu
,cia
);
408 /* avoid infinite recursion */
410 sim_io_printf (sd
, "ERROR: recursion in program_interrupt during software exception dispatch.");
414 /* copy NMI handler code from dv-mn103cpu.c */
415 store_word (SP
- 4, CPU_PC_GET (cpu
));
416 store_half (SP
- 8, PSW
);
418 /* Set the SYSEF flag in NMICR by backdoor method. See
419 dv-mn103int.c:write_icr(). This is necessary because
420 software exceptions are not modelled by actually talking to
421 the interrupt controller, so it cannot set its own SYSEF
423 if ((NULL
!= board
) && (strcmp(board
, BOARD_AM32
) == 0))
424 store_byte (0x34000103, 0x04);
429 CPU_PC_SET (cpu
, 0x40000008);
432 sim_engine_halt(sd
, cpu
, NULL
, cia
, sim_stopped
, sig
);
437 mn10300_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
441 if(State
.exc_suspended
> 0)
442 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", State
.exc_suspended
);
444 CPU_PC_SET (cpu
, cia
);
445 memcpy(State
.exc_trigger_regs
, State
.regs
, sizeof(State
.exc_trigger_regs
));
446 State
.exc_suspended
= 0;
450 mn10300_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
454 if(State
.exc_suspended
> 0)
455 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
456 State
.exc_suspended
, exception
);
458 memcpy(State
.exc_suspend_regs
, State
.regs
, sizeof(State
.exc_suspend_regs
));
459 memcpy(State
.regs
, State
.exc_trigger_regs
, sizeof(State
.regs
));
460 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
461 State
.exc_suspended
= exception
;
465 mn10300_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
469 if(exception
== 0 && State
.exc_suspended
> 0)
474 if(State
.exc_suspended
!= SIGTRAP
) /* warn not for breakpoints */
475 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
476 State
.exc_suspended
);
478 else if(exception
!= 0 && State
.exc_suspended
> 0)
480 if(exception
!= State
.exc_suspended
)
481 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
482 State
.exc_suspended
, exception
);
484 memcpy(State
.regs
, State
.exc_suspend_regs
, sizeof(State
.regs
));
485 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
487 else if(exception
!= 0 && State
.exc_suspended
== 0)
489 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
491 State
.exc_suspended
= 0;
494 /* This is called when an FP instruction is issued when the FP unit is
495 disabled, i.e., the FE bit of PSW is zero. It raises interrupt
498 fpu_disabled_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
500 sim_io_eprintf(sd
, "FPU disabled exception\n");
501 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
504 /* This is called when the FP unit is enabled but one of the
505 unimplemented insns is issued. It raises interrupt code 0x1c8. */
507 fpu_unimp_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
509 sim_io_eprintf(sd
, "Unimplemented FPU instruction exception\n");
510 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
513 /* This is called at the end of any FP insns that may have triggered
514 FP exceptions. If no exception is enabled, it returns immediately.
515 Otherwise, it raises an exception code 0x1d0. */
517 fpu_check_signal_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
519 if ((FPCR
& EC_MASK
) == 0)
522 sim_io_eprintf(sd
, "FPU %s%s%s%s%s exception\n",
523 (FPCR
& EC_V
) ? "V" : "",
524 (FPCR
& EC_Z
) ? "Z" : "",
525 (FPCR
& EC_O
) ? "O" : "",
526 (FPCR
& EC_U
) ? "U" : "",
527 (FPCR
& EC_I
) ? "I" : "");
528 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
531 /* Convert a 32-bit single-precision FP value in the target platform
532 format to a sim_fpu value. */
534 reg2val_32 (const void *reg
, sim_fpu
*val
)
536 FS2FPU (*(reg_t
*)reg
, *val
);
539 /* Round the given sim_fpu value to single precision, following the
540 target platform rounding and denormalization conventions. On
541 AM33/2.0, round_near is the only rounding mode. */
543 round_32 (sim_fpu
*val
)
545 return sim_fpu_round_32 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
548 /* Convert a sim_fpu value to the 32-bit single-precision target
551 val2reg_32 (const sim_fpu
*val
, void *reg
)
553 FPU2FS (*val
, *(reg_t
*)reg
);
556 /* Define the 32-bit single-precision conversion and rounding uniform
558 const struct fp_prec_t
560 reg2val_32
, round_32
, val2reg_32
563 /* Convert a 64-bit double-precision FP value in the target platform
564 format to a sim_fpu value. */
566 reg2val_64 (const void *reg
, sim_fpu
*val
)
568 FD2FPU (*(dword
*)reg
, *val
);
571 /* Round the given sim_fpu value to double precision, following the
572 target platform rounding and denormalization conventions. On
573 AM33/2.0, round_near is the only rounding mode. */
575 round_64 (sim_fpu
*val
)
577 return sim_fpu_round_64 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
580 /* Convert a sim_fpu value to the 64-bit double-precision target
583 val2reg_64 (const sim_fpu
*val
, void *reg
)
585 FPU2FD (*val
, *(dword
*)reg
);
588 /* Define the 64-bit single-precision conversion and rounding uniform
590 const struct fp_prec_t
592 reg2val_64
, round_64
, val2reg_64
595 /* Define shortcuts to the uniform interface operations. */
596 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
597 #define ROUND(val) (*ops->round) (val)
598 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
600 /* Check whether overflow, underflow or inexact exceptions should be
603 fpu_status_ok (sim_fpu_status stat
)
605 if ((stat
& sim_fpu_status_overflow
)
608 else if ((stat
& (sim_fpu_status_underflow
| sim_fpu_status_denorm
))
611 else if ((stat
& (sim_fpu_status_inexact
| sim_fpu_status_rounded
))
614 else if (stat
& ~ (sim_fpu_status_overflow
615 | sim_fpu_status_underflow
616 | sim_fpu_status_denorm
617 | sim_fpu_status_inexact
618 | sim_fpu_status_rounded
))
625 /* Implement a 32/64 bit reciprocal square root, signaling FP
626 exceptions when appropriate. */
628 fpu_rsqrt (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
629 const void *reg_in
, void *reg_out
, const struct fp_prec_t
*ops
)
631 sim_fpu in
, med
, out
;
633 REG2VAL (reg_in
, &in
);
636 switch (sim_fpu_is (&in
))
638 case SIM_FPU_IS_SNAN
:
639 case SIM_FPU_IS_NNUMBER
:
640 case SIM_FPU_IS_NINF
:
644 VAL2REG (&sim_fpu_qnan
, reg_out
);
647 case SIM_FPU_IS_QNAN
:
648 VAL2REG (&sim_fpu_qnan
, reg_out
);
651 case SIM_FPU_IS_PINF
:
652 VAL2REG (&sim_fpu_zero
, reg_out
);
655 case SIM_FPU_IS_PNUMBER
:
657 /* Since we don't have a function to compute rsqrt directly,
659 sim_fpu_status stat
= 0;
660 stat
|= sim_fpu_sqrt (&med
, &in
);
661 stat
|= sim_fpu_inv (&out
, &med
);
662 stat
|= ROUND (&out
);
663 if (fpu_status_ok (stat
))
664 VAL2REG (&out
, reg_out
);
668 case SIM_FPU_IS_NZERO
:
669 case SIM_FPU_IS_PZERO
:
674 /* Generate an INF with the same sign. */
675 sim_fpu_inv (&out
, &in
);
676 VAL2REG (&out
, reg_out
);
684 fpu_check_signal_exception (sd
, cpu
, cia
);
692 case SIM_FPU_IS_SNAN
:
693 case SIM_FPU_IS_QNAN
:
696 case SIM_FPU_IS_NINF
:
697 case SIM_FPU_IS_NNUMBER
:
698 case SIM_FPU_IS_NDENORM
:
701 case SIM_FPU_IS_PINF
:
702 case SIM_FPU_IS_PNUMBER
:
703 case SIM_FPU_IS_PDENORM
:
706 case SIM_FPU_IS_NZERO
:
707 case SIM_FPU_IS_PZERO
:
715 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
716 exception bits as specified. */
718 fpu_cmp (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
719 const void *reg_in1
, const void *reg_in2
,
720 const struct fp_prec_t
*ops
)
724 REG2VAL (reg_in1
, &m
);
725 REG2VAL (reg_in2
, &n
);
730 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
))
738 FPCR
|= cmp2fcc (sim_fpu_cmp (&m
, &n
));
740 fpu_check_signal_exception (sd
, cpu
, cia
);
743 /* Implement a 32/64 bit FP add, setting FP exception bits when
746 fpu_add (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
747 const void *reg_in1
, const void *reg_in2
,
748 void *reg_out
, const struct fp_prec_t
*ops
)
752 REG2VAL (reg_in1
, &m
);
753 REG2VAL (reg_in2
, &n
);
757 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
758 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
759 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
)
760 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
761 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
))
766 VAL2REG (&sim_fpu_qnan
, reg_out
);
770 sim_fpu_status stat
= sim_fpu_add (&r
, &m
, &n
);
772 if (fpu_status_ok (stat
))
773 VAL2REG (&r
, reg_out
);
776 fpu_check_signal_exception (sd
, cpu
, cia
);
779 /* Implement a 32/64 bit FP sub, setting FP exception bits when
782 fpu_sub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
783 const void *reg_in1
, const void *reg_in2
,
784 void *reg_out
, const struct fp_prec_t
*ops
)
788 REG2VAL (reg_in1
, &m
);
789 REG2VAL (reg_in2
, &n
);
793 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
794 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
795 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
)
796 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
797 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
))
802 VAL2REG (&sim_fpu_qnan
, reg_out
);
806 sim_fpu_status stat
= sim_fpu_sub (&r
, &m
, &n
);
808 if (fpu_status_ok (stat
))
809 VAL2REG (&r
, reg_out
);
812 fpu_check_signal_exception (sd
, cpu
, cia
);
815 /* Implement a 32/64 bit FP mul, setting FP exception bits when
818 fpu_mul (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
819 const void *reg_in1
, const void *reg_in2
,
820 void *reg_out
, const struct fp_prec_t
*ops
)
824 REG2VAL (reg_in1
, &m
);
825 REG2VAL (reg_in2
, &n
);
829 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
830 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_zero (&n
))
831 || (sim_fpu_is_zero (&m
) && sim_fpu_is_infinity (&n
)))
836 VAL2REG (&sim_fpu_qnan
, reg_out
);
840 sim_fpu_status stat
= sim_fpu_mul (&r
, &m
, &n
);
842 if (fpu_status_ok (stat
))
843 VAL2REG (&r
, reg_out
);
846 fpu_check_signal_exception (sd
, cpu
, cia
);
849 /* Implement a 32/64 bit FP div, setting FP exception bits when
852 fpu_div (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
853 const void *reg_in1
, const void *reg_in2
,
854 void *reg_out
, const struct fp_prec_t
*ops
)
858 REG2VAL (reg_in1
, &m
);
859 REG2VAL (reg_in2
, &n
);
863 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
864 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
))
865 || (sim_fpu_is_zero (&m
) && sim_fpu_is_zero (&n
)))
870 VAL2REG (&sim_fpu_qnan
, reg_out
);
872 else if (sim_fpu_is_number (&m
) && sim_fpu_is_zero (&n
)
877 sim_fpu_status stat
= sim_fpu_div (&r
, &m
, &n
);
879 if (fpu_status_ok (stat
))
880 VAL2REG (&r
, reg_out
);
883 fpu_check_signal_exception (sd
, cpu
, cia
);
886 /* Implement a 32/64 bit FP madd, setting FP exception bits when
889 fpu_fmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
890 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
891 void *reg_out
, const struct fp_prec_t
*ops
)
893 sim_fpu m1
, m2
, m
, n
, r
;
895 REG2VAL (reg_in1
, &m1
);
896 REG2VAL (reg_in2
, &m2
);
897 REG2VAL (reg_in3
, &n
);
902 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
903 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
904 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
910 VAL2REG (&sim_fpu_qnan
, reg_out
);
914 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
916 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
917 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
918 goto invalid_operands
;
920 stat
|= sim_fpu_add (&r
, &m
, &n
);
922 if (fpu_status_ok (stat
))
923 VAL2REG (&r
, reg_out
);
926 fpu_check_signal_exception (sd
, cpu
, cia
);
929 /* Implement a 32/64 bit FP msub, setting FP exception bits when
932 fpu_fmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
933 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
934 void *reg_out
, const struct fp_prec_t
*ops
)
936 sim_fpu m1
, m2
, m
, n
, r
;
938 REG2VAL (reg_in1
, &m1
);
939 REG2VAL (reg_in2
, &m2
);
940 REG2VAL (reg_in3
, &n
);
945 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
946 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
947 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
953 VAL2REG (&sim_fpu_qnan
, reg_out
);
957 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
959 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
960 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
961 goto invalid_operands
;
963 stat
|= sim_fpu_sub (&r
, &m
, &n
);
965 if (fpu_status_ok (stat
))
966 VAL2REG (&r
, reg_out
);
969 fpu_check_signal_exception (sd
, cpu
, cia
);
972 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
975 fpu_fnmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
976 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
977 void *reg_out
, const struct fp_prec_t
*ops
)
979 sim_fpu m1
, m2
, m
, mm
, n
, r
;
981 REG2VAL (reg_in1
, &m1
);
982 REG2VAL (reg_in2
, &m2
);
983 REG2VAL (reg_in3
, &n
);
988 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
989 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
990 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
996 VAL2REG (&sim_fpu_qnan
, reg_out
);
1000 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1002 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1003 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
1004 goto invalid_operands
;
1006 stat
|= sim_fpu_neg (&mm
, &m
);
1007 stat
|= sim_fpu_add (&r
, &mm
, &n
);
1009 if (fpu_status_ok (stat
))
1010 VAL2REG (&r
, reg_out
);
1013 fpu_check_signal_exception (sd
, cpu
, cia
);
1016 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1019 fpu_fnmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1020 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1021 void *reg_out
, const struct fp_prec_t
*ops
)
1023 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1025 REG2VAL (reg_in1
, &m1
);
1026 REG2VAL (reg_in2
, &m2
);
1027 REG2VAL (reg_in3
, &n
);
1032 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1033 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1034 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1040 VAL2REG (&sim_fpu_qnan
, reg_out
);
1044 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1046 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1047 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
1048 goto invalid_operands
;
1050 stat
|= sim_fpu_neg (&mm
, &m
);
1051 stat
|= sim_fpu_sub (&r
, &mm
, &n
);
1053 if (fpu_status_ok (stat
))
1054 VAL2REG (&r
, reg_out
);
1057 fpu_check_signal_exception (sd
, cpu
, cia
);