1 /* This must come before any other includes. */
5 #include "sim-options.h"
9 #include "sim-assert.h"
11 #include "sim-signal.h"
13 #include "mn10300-sim.h"
22 /* simulation target board. NULL=default configuration */
23 static char* board
= NULL
;
25 static DECLARE_OPTION_HANDLER (mn10300_option_handler
);
28 OPTION_BOARD
= OPTION_START
,
32 mn10300_option_handler (SIM_DESC sd
,
45 board
= zalloc(strlen(arg
) + 1);
55 static const OPTION mn10300_options
[] =
57 #define BOARD_AM32 "stdeval1"
58 { {"board", required_argument
, NULL
, OPTION_BOARD
},
59 '\0', "none" /* rely on compile-time string concatenation for other options */
61 , "Customize simulation for a particular board.", mn10300_option_handler
},
63 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
66 /* For compatibility */
70 mn10300_pc_get (sim_cpu
*cpu
)
76 mn10300_pc_set (sim_cpu
*cpu
, sim_cia pc
)
81 static int mn10300_reg_fetch (SIM_CPU
*, int, void *, int);
82 static int mn10300_reg_store (SIM_CPU
*, int, const void *, int);
84 /* These default values correspond to expected usage for the chip. */
87 sim_open (SIM_OPEN_KIND kind
,
93 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
95 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
97 /* Set default options before parsing user options. */
98 current_target_byte_order
= BFD_ENDIAN_LITTLE
;
100 /* The cpu data is kept in a separately allocated chunk of memory. */
101 if (sim_cpu_alloc_all (sd
, 0) != SIM_RC_OK
)
104 /* for compatibility */
107 /* FIXME: should be better way of setting up interrupts. For
108 moment, only support watchpoints causing a breakpoint (gdb
110 STATE_WATCHPOINTS (sd
)->interrupt_handler
= NULL
;
111 STATE_WATCHPOINTS (sd
)->interrupt_names
= NULL
;
113 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
115 sim_add_option_table (sd
, NULL
, mn10300_options
);
117 /* Allocate core managed memory */
118 sim_do_command (sd
, "memory region 0,0x100000");
119 sim_do_command (sd
, "memory region 0x40000000,0x200000");
121 /* The parser will print an error message for us, so we silently return. */
122 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
124 /* Uninstall the modules to avoid memory leaks,
125 file descriptor leaks, etc. */
126 sim_module_uninstall (sd
);
131 && (strcmp(board
, BOARD_AM32
) == 0 ) )
134 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
136 sim_do_command (sd
, "memory region 0x44000000,0x40000");
137 sim_do_command (sd
, "memory region 0x48000000,0x400000");
139 /* device support for mn1030002 */
140 /* interrupt controller */
142 sim_hw_parse (sd
, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
144 /* DEBUG: NMI input's */
145 sim_hw_parse (sd
, "/glue@0x30000000/reg 0x30000000 12");
146 sim_hw_parse (sd
, "/glue@0x30000000 > int0 nmirq /mn103int");
147 sim_hw_parse (sd
, "/glue@0x30000000 > int1 watchdog /mn103int");
148 sim_hw_parse (sd
, "/glue@0x30000000 > int2 syserr /mn103int");
150 /* DEBUG: ACK input */
151 sim_hw_parse (sd
, "/glue@0x30002000/reg 0x30002000 4");
152 sim_hw_parse (sd
, "/glue@0x30002000 > int ack /mn103int");
154 /* DEBUG: LEVEL output */
155 sim_hw_parse (sd
, "/glue@0x30004000/reg 0x30004000 8");
156 sim_hw_parse (sd
, "/mn103int > nmi int0 /glue@0x30004000");
157 sim_hw_parse (sd
, "/mn103int > level int1 /glue@0x30004000");
159 /* DEBUG: A bunch of interrupt inputs */
160 sim_hw_parse (sd
, "/glue@0x30006000/reg 0x30006000 32");
161 sim_hw_parse (sd
, "/glue@0x30006000 > int0 irq-0 /mn103int");
162 sim_hw_parse (sd
, "/glue@0x30006000 > int1 irq-1 /mn103int");
163 sim_hw_parse (sd
, "/glue@0x30006000 > int2 irq-2 /mn103int");
164 sim_hw_parse (sd
, "/glue@0x30006000 > int3 irq-3 /mn103int");
165 sim_hw_parse (sd
, "/glue@0x30006000 > int4 irq-4 /mn103int");
166 sim_hw_parse (sd
, "/glue@0x30006000 > int5 irq-5 /mn103int");
167 sim_hw_parse (sd
, "/glue@0x30006000 > int6 irq-6 /mn103int");
168 sim_hw_parse (sd
, "/glue@0x30006000 > int7 irq-7 /mn103int");
170 /* processor interrupt device */
173 sim_hw_parse (sd
, "/mn103cpu@0x20000000");
174 sim_hw_parse (sd
, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
176 /* DEBUG: ACK output wired upto a glue device */
177 sim_hw_parse (sd
, "/glue@0x20002000");
178 sim_hw_parse (sd
, "/glue@0x20002000/reg 0x20002000 4");
179 sim_hw_parse (sd
, "/mn103cpu > ack int0 /glue@0x20002000");
181 /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
182 sim_hw_parse (sd
, "/glue@0x20004000");
183 sim_hw_parse (sd
, "/glue@0x20004000/reg 0x20004000 12");
184 sim_hw_parse (sd
, "/glue@0x20004000 > int0 reset /mn103cpu");
185 sim_hw_parse (sd
, "/glue@0x20004000 > int1 nmi /mn103cpu");
186 sim_hw_parse (sd
, "/glue@0x20004000 > int2 level /mn103cpu");
188 /* REAL: The processor wired up to the real interrupt controller */
189 sim_hw_parse (sd
, "/mn103cpu > ack ack /mn103int");
190 sim_hw_parse (sd
, "/mn103int > level level /mn103cpu");
191 sim_hw_parse (sd
, "/mn103int > nmi nmi /mn103cpu");
197 sim_hw_parse (sd
, "/pal@0x31000000");
198 sim_hw_parse (sd
, "/pal@0x31000000/reg 0x31000000 64");
199 sim_hw_parse (sd
, "/pal@0x31000000/poll? true");
201 /* DEBUG: PAL wired up to a glue device */
202 sim_hw_parse (sd
, "/glue@0x31002000");
203 sim_hw_parse (sd
, "/glue@0x31002000/reg 0x31002000 16");
204 sim_hw_parse (sd
, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
205 sim_hw_parse (sd
, "/pal@0x31000000 > timer int1 /glue@0x31002000");
206 sim_hw_parse (sd
, "/pal@0x31000000 > int int2 /glue@0x31002000");
207 sim_hw_parse (sd
, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
208 sim_hw_parse (sd
, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
209 sim_hw_parse (sd
, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
211 /* REAL: The PAL wired up to the real interrupt controller */
212 sim_hw_parse (sd
, "/pal@0x31000000 > countdown irq-0 /mn103int");
213 sim_hw_parse (sd
, "/pal@0x31000000 > timer irq-1 /mn103int");
214 sim_hw_parse (sd
, "/pal@0x31000000 > int irq-2 /mn103int");
216 /* 8 and 16 bit timers */
217 sim_hw_parse (sd
, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16");
219 /* Hook timer interrupts up to interrupt controller */
220 sim_hw_parse (sd
, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int");
221 sim_hw_parse (sd
, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int");
222 sim_hw_parse (sd
, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int");
223 sim_hw_parse (sd
, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int");
224 sim_hw_parse (sd
, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int");
225 sim_hw_parse (sd
, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int");
226 sim_hw_parse (sd
, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int");
227 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int");
228 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int");
231 /* Serial devices 0,1,2 */
232 sim_hw_parse (sd
, "/mn103ser@0x34000800/reg 0x34000800 48");
233 sim_hw_parse (sd
, "/mn103ser@0x34000800/poll? true");
235 /* Hook serial interrupts up to interrupt controller */
236 sim_hw_parse (sd
, "/mn103ser > serial-0-receive serial-0-receive /mn103int");
237 sim_hw_parse (sd
, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int");
238 sim_hw_parse (sd
, "/mn103ser > serial-1-receive serial-1-receive /mn103int");
239 sim_hw_parse (sd
, "/mn103ser > serial-1-transmit serial-1-transmit /mn103int");
240 sim_hw_parse (sd
, "/mn103ser > serial-2-receive serial-2-receive /mn103int");
241 sim_hw_parse (sd
, "/mn103ser > serial-2-transmit serial-2-transmit /mn103int");
243 sim_hw_parse (sd
, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
245 /* Memory control registers */
246 sim_do_command (sd
, "memory region 0x32000020,0x30");
247 /* Cache control register */
248 sim_do_command (sd
, "memory region 0x20000070,0x4");
249 /* Cache purge regions */
250 sim_do_command (sd
, "memory region 0x28400000,0x800");
251 sim_do_command (sd
, "memory region 0x28401000,0x800");
253 sim_do_command (sd
, "memory region 0x32000100,0xF");
254 sim_do_command (sd
, "memory region 0x32000200,0xF");
255 sim_do_command (sd
, "memory region 0x32000400,0xF");
256 sim_do_command (sd
, "memory region 0x32000800,0xF");
262 sim_io_eprintf (sd
, "Error: Board `%s' unknown.\n", board
);
269 /* check for/establish the a reference program image */
270 if (sim_analyze_program (sd
, STATE_PROG_FILE (sd
), abfd
) != SIM_RC_OK
)
272 sim_module_uninstall (sd
);
276 /* establish any remaining configuration options */
277 if (sim_config (sd
) != SIM_RC_OK
)
279 sim_module_uninstall (sd
);
283 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
285 /* Uninstall the modules to avoid memory leaks,
286 file descriptor leaks, etc. */
287 sim_module_uninstall (sd
);
292 /* set machine specific configuration */
293 /* STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
294 /* | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
296 /* CPU specific initialization. */
297 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
299 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
301 CPU_REG_FETCH (cpu
) = mn10300_reg_fetch
;
302 CPU_REG_STORE (cpu
) = mn10300_reg_store
;
303 CPU_PC_FETCH (cpu
) = mn10300_pc_get
;
304 CPU_PC_STORE (cpu
) = mn10300_pc_set
;
311 sim_create_inferior (SIM_DESC sd
,
312 struct bfd
*prog_bfd
,
316 memset (&State
, 0, sizeof (State
));
317 if (prog_bfd
!= NULL
) {
318 PC
= bfd_get_start_address (prog_bfd
);
322 CPU_PC_SET (STATE_CPU (sd
, 0), (uint64_t) PC
);
324 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_am33_2
)
330 /* FIXME These would more efficient to use than load_mem/store_mem,
331 but need to be changed to use the memory map. */
334 mn10300_reg_fetch (SIM_CPU
*cpu
, int rn
, void *memory
, int length
)
336 reg_t reg
= State
.regs
[rn
];
346 mn10300_reg_store (SIM_CPU
*cpu
, int rn
, const void *memory
, int length
)
348 const uint8_t *a
= memory
;
349 State
.regs
[rn
] = (a
[3] << 24) + (a
[2] << 16) + (a
[1] << 8) + a
[0];
354 mn10300_core_signal (SIM_DESC sd
,
360 transfer_type transfer
,
361 sim_core_signals sig
)
363 const char *copy
= (transfer
== read_transfer
? "read" : "write");
364 address_word ip
= CIA_ADDR (cia
);
368 case sim_core_unmapped_signal
:
369 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
371 (unsigned long) addr
, (unsigned long) ip
);
372 program_interrupt(sd
, cpu
, cia
, SIM_SIGSEGV
);
375 case sim_core_unaligned_signal
:
376 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
378 (unsigned long) addr
, (unsigned long) ip
);
379 program_interrupt(sd
, cpu
, cia
, SIM_SIGBUS
);
383 sim_engine_abort (sd
, cpu
, cia
,
384 "mn10300_core_signal - internal error - bad switch");
390 program_interrupt (SIM_DESC sd
,
397 static int in_interrupt
= 0;
399 #ifdef SIM_CPU_EXCEPTION_TRIGGER
400 SIM_CPU_EXCEPTION_TRIGGER(sd
,cpu
,cia
);
403 /* avoid infinite recursion */
405 sim_io_printf (sd
, "ERROR: recursion in program_interrupt during software exception dispatch.");
409 /* copy NMI handler code from dv-mn103cpu.c */
410 store_word (SP
- 4, CPU_PC_GET (cpu
));
411 store_half (SP
- 8, PSW
);
413 /* Set the SYSEF flag in NMICR by backdoor method. See
414 dv-mn103int.c:write_icr(). This is necessary because
415 software exceptions are not modelled by actually talking to
416 the interrupt controller, so it cannot set its own SYSEF
418 if ((NULL
!= board
) && (strcmp(board
, BOARD_AM32
) == 0))
419 store_byte (0x34000103, 0x04);
424 CPU_PC_SET (cpu
, 0x40000008);
427 sim_engine_halt(sd
, cpu
, NULL
, cia
, sim_stopped
, sig
);
432 mn10300_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
436 if(State
.exc_suspended
> 0)
437 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", State
.exc_suspended
);
439 CPU_PC_SET (cpu
, cia
);
440 memcpy(State
.exc_trigger_regs
, State
.regs
, sizeof(State
.exc_trigger_regs
));
441 State
.exc_suspended
= 0;
445 mn10300_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
449 if(State
.exc_suspended
> 0)
450 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
451 State
.exc_suspended
, exception
);
453 memcpy(State
.exc_suspend_regs
, State
.regs
, sizeof(State
.exc_suspend_regs
));
454 memcpy(State
.regs
, State
.exc_trigger_regs
, sizeof(State
.regs
));
455 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
456 State
.exc_suspended
= exception
;
460 mn10300_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
464 if(exception
== 0 && State
.exc_suspended
> 0)
469 if(State
.exc_suspended
!= SIGTRAP
) /* warn not for breakpoints */
470 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
471 State
.exc_suspended
);
473 else if(exception
!= 0 && State
.exc_suspended
> 0)
475 if(exception
!= State
.exc_suspended
)
476 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
477 State
.exc_suspended
, exception
);
479 memcpy(State
.regs
, State
.exc_suspend_regs
, sizeof(State
.regs
));
480 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
482 else if(exception
!= 0 && State
.exc_suspended
== 0)
484 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
486 State
.exc_suspended
= 0;
489 /* This is called when an FP instruction is issued when the FP unit is
490 disabled, i.e., the FE bit of PSW is zero. It raises interrupt
493 fpu_disabled_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
495 sim_io_eprintf(sd
, "FPU disabled exception\n");
496 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
499 /* This is called when the FP unit is enabled but one of the
500 unimplemented insns is issued. It raises interrupt code 0x1c8. */
502 fpu_unimp_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
504 sim_io_eprintf(sd
, "Unimplemented FPU instruction exception\n");
505 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
508 /* This is called at the end of any FP insns that may have triggered
509 FP exceptions. If no exception is enabled, it returns immediately.
510 Otherwise, it raises an exception code 0x1d0. */
512 fpu_check_signal_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
514 if ((FPCR
& EC_MASK
) == 0)
517 sim_io_eprintf(sd
, "FPU %s%s%s%s%s exception\n",
518 (FPCR
& EC_V
) ? "V" : "",
519 (FPCR
& EC_Z
) ? "Z" : "",
520 (FPCR
& EC_O
) ? "O" : "",
521 (FPCR
& EC_U
) ? "U" : "",
522 (FPCR
& EC_I
) ? "I" : "");
523 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
526 /* Convert a 32-bit single-precision FP value in the target platform
527 format to a sim_fpu value. */
529 reg2val_32 (const void *reg
, sim_fpu
*val
)
531 FS2FPU (*(reg_t
*)reg
, *val
);
534 /* Round the given sim_fpu value to single precision, following the
535 target platform rounding and denormalization conventions. On
536 AM33/2.0, round_near is the only rounding mode. */
538 round_32 (sim_fpu
*val
)
540 return sim_fpu_round_32 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
543 /* Convert a sim_fpu value to the 32-bit single-precision target
546 val2reg_32 (const sim_fpu
*val
, void *reg
)
548 FPU2FS (*val
, *(reg_t
*)reg
);
551 /* Define the 32-bit single-precision conversion and rounding uniform
553 const struct fp_prec_t
555 reg2val_32
, round_32
, val2reg_32
558 /* Convert a 64-bit double-precision FP value in the target platform
559 format to a sim_fpu value. */
561 reg2val_64 (const void *reg
, sim_fpu
*val
)
563 FD2FPU (*(dword
*)reg
, *val
);
566 /* Round the given sim_fpu value to double precision, following the
567 target platform rounding and denormalization conventions. On
568 AM33/2.0, round_near is the only rounding mode. */
570 round_64 (sim_fpu
*val
)
572 return sim_fpu_round_64 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
575 /* Convert a sim_fpu value to the 64-bit double-precision target
578 val2reg_64 (const sim_fpu
*val
, void *reg
)
580 FPU2FD (*val
, *(dword
*)reg
);
583 /* Define the 64-bit single-precision conversion and rounding uniform
585 const struct fp_prec_t
587 reg2val_64
, round_64
, val2reg_64
590 /* Define shortcuts to the uniform interface operations. */
591 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
592 #define ROUND(val) (*ops->round) (val)
593 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
595 /* Check whether overflow, underflow or inexact exceptions should be
598 fpu_status_ok (sim_fpu_status stat
)
600 if ((stat
& sim_fpu_status_overflow
)
603 else if ((stat
& (sim_fpu_status_underflow
| sim_fpu_status_denorm
))
606 else if ((stat
& (sim_fpu_status_inexact
| sim_fpu_status_rounded
))
609 else if (stat
& ~ (sim_fpu_status_overflow
610 | sim_fpu_status_underflow
611 | sim_fpu_status_denorm
612 | sim_fpu_status_inexact
613 | sim_fpu_status_rounded
))
620 /* Implement a 32/64 bit reciprocal square root, signaling FP
621 exceptions when appropriate. */
623 fpu_rsqrt (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
624 const void *reg_in
, void *reg_out
, const struct fp_prec_t
*ops
)
626 sim_fpu in
, med
, out
;
628 REG2VAL (reg_in
, &in
);
631 switch (sim_fpu_is (&in
))
633 case SIM_FPU_IS_SNAN
:
634 case SIM_FPU_IS_NNUMBER
:
635 case SIM_FPU_IS_NINF
:
639 VAL2REG (&sim_fpu_qnan
, reg_out
);
642 case SIM_FPU_IS_QNAN
:
643 VAL2REG (&sim_fpu_qnan
, reg_out
);
646 case SIM_FPU_IS_PINF
:
647 VAL2REG (&sim_fpu_zero
, reg_out
);
650 case SIM_FPU_IS_PNUMBER
:
652 /* Since we don't have a function to compute rsqrt directly,
654 sim_fpu_status stat
= 0;
655 stat
|= sim_fpu_sqrt (&med
, &in
);
656 stat
|= sim_fpu_inv (&out
, &med
);
657 stat
|= ROUND (&out
);
658 if (fpu_status_ok (stat
))
659 VAL2REG (&out
, reg_out
);
663 case SIM_FPU_IS_NZERO
:
664 case SIM_FPU_IS_PZERO
:
669 /* Generate an INF with the same sign. */
670 sim_fpu_inv (&out
, &in
);
671 VAL2REG (&out
, reg_out
);
679 fpu_check_signal_exception (sd
, cpu
, cia
);
687 case SIM_FPU_IS_SNAN
:
688 case SIM_FPU_IS_QNAN
:
691 case SIM_FPU_IS_NINF
:
692 case SIM_FPU_IS_NNUMBER
:
693 case SIM_FPU_IS_NDENORM
:
696 case SIM_FPU_IS_PINF
:
697 case SIM_FPU_IS_PNUMBER
:
698 case SIM_FPU_IS_PDENORM
:
701 case SIM_FPU_IS_NZERO
:
702 case SIM_FPU_IS_PZERO
:
710 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
711 exception bits as specified. */
713 fpu_cmp (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
714 const void *reg_in1
, const void *reg_in2
,
715 const struct fp_prec_t
*ops
)
719 REG2VAL (reg_in1
, &m
);
720 REG2VAL (reg_in2
, &n
);
725 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
))
733 FPCR
|= cmp2fcc (sim_fpu_cmp (&m
, &n
));
735 fpu_check_signal_exception (sd
, cpu
, cia
);
738 /* Implement a 32/64 bit FP add, setting FP exception bits when
741 fpu_add (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
742 const void *reg_in1
, const void *reg_in2
,
743 void *reg_out
, const struct fp_prec_t
*ops
)
747 REG2VAL (reg_in1
, &m
);
748 REG2VAL (reg_in2
, &n
);
752 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
753 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
754 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
)
755 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
756 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
))
761 VAL2REG (&sim_fpu_qnan
, reg_out
);
765 sim_fpu_status stat
= sim_fpu_add (&r
, &m
, &n
);
767 if (fpu_status_ok (stat
))
768 VAL2REG (&r
, reg_out
);
771 fpu_check_signal_exception (sd
, cpu
, cia
);
774 /* Implement a 32/64 bit FP sub, setting FP exception bits when
777 fpu_sub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
778 const void *reg_in1
, const void *reg_in2
,
779 void *reg_out
, const struct fp_prec_t
*ops
)
783 REG2VAL (reg_in1
, &m
);
784 REG2VAL (reg_in2
, &n
);
788 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
789 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
790 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
)
791 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
792 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
))
797 VAL2REG (&sim_fpu_qnan
, reg_out
);
801 sim_fpu_status stat
= sim_fpu_sub (&r
, &m
, &n
);
803 if (fpu_status_ok (stat
))
804 VAL2REG (&r
, reg_out
);
807 fpu_check_signal_exception (sd
, cpu
, cia
);
810 /* Implement a 32/64 bit FP mul, setting FP exception bits when
813 fpu_mul (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
814 const void *reg_in1
, const void *reg_in2
,
815 void *reg_out
, const struct fp_prec_t
*ops
)
819 REG2VAL (reg_in1
, &m
);
820 REG2VAL (reg_in2
, &n
);
824 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
825 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_zero (&n
))
826 || (sim_fpu_is_zero (&m
) && sim_fpu_is_infinity (&n
)))
831 VAL2REG (&sim_fpu_qnan
, reg_out
);
835 sim_fpu_status stat
= sim_fpu_mul (&r
, &m
, &n
);
837 if (fpu_status_ok (stat
))
838 VAL2REG (&r
, reg_out
);
841 fpu_check_signal_exception (sd
, cpu
, cia
);
844 /* Implement a 32/64 bit FP div, setting FP exception bits when
847 fpu_div (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
848 const void *reg_in1
, const void *reg_in2
,
849 void *reg_out
, const struct fp_prec_t
*ops
)
853 REG2VAL (reg_in1
, &m
);
854 REG2VAL (reg_in2
, &n
);
858 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
859 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
))
860 || (sim_fpu_is_zero (&m
) && sim_fpu_is_zero (&n
)))
865 VAL2REG (&sim_fpu_qnan
, reg_out
);
867 else if (sim_fpu_is_number (&m
) && sim_fpu_is_zero (&n
)
872 sim_fpu_status stat
= sim_fpu_div (&r
, &m
, &n
);
874 if (fpu_status_ok (stat
))
875 VAL2REG (&r
, reg_out
);
878 fpu_check_signal_exception (sd
, cpu
, cia
);
881 /* Implement a 32/64 bit FP madd, setting FP exception bits when
884 fpu_fmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
885 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
886 void *reg_out
, const struct fp_prec_t
*ops
)
888 sim_fpu m1
, m2
, m
, n
, r
;
890 REG2VAL (reg_in1
, &m1
);
891 REG2VAL (reg_in2
, &m2
);
892 REG2VAL (reg_in3
, &n
);
897 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
898 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
899 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
905 VAL2REG (&sim_fpu_qnan
, reg_out
);
909 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
911 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
912 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
913 goto invalid_operands
;
915 stat
|= sim_fpu_add (&r
, &m
, &n
);
917 if (fpu_status_ok (stat
))
918 VAL2REG (&r
, reg_out
);
921 fpu_check_signal_exception (sd
, cpu
, cia
);
924 /* Implement a 32/64 bit FP msub, setting FP exception bits when
927 fpu_fmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
928 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
929 void *reg_out
, const struct fp_prec_t
*ops
)
931 sim_fpu m1
, m2
, m
, n
, r
;
933 REG2VAL (reg_in1
, &m1
);
934 REG2VAL (reg_in2
, &m2
);
935 REG2VAL (reg_in3
, &n
);
940 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
941 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
942 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
948 VAL2REG (&sim_fpu_qnan
, reg_out
);
952 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
954 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
955 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
956 goto invalid_operands
;
958 stat
|= sim_fpu_sub (&r
, &m
, &n
);
960 if (fpu_status_ok (stat
))
961 VAL2REG (&r
, reg_out
);
964 fpu_check_signal_exception (sd
, cpu
, cia
);
967 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
970 fpu_fnmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
971 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
972 void *reg_out
, const struct fp_prec_t
*ops
)
974 sim_fpu m1
, m2
, m
, mm
, n
, r
;
976 REG2VAL (reg_in1
, &m1
);
977 REG2VAL (reg_in2
, &m2
);
978 REG2VAL (reg_in3
, &n
);
983 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
984 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
985 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
991 VAL2REG (&sim_fpu_qnan
, reg_out
);
995 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
997 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
998 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
999 goto invalid_operands
;
1001 stat
|= sim_fpu_neg (&mm
, &m
);
1002 stat
|= sim_fpu_add (&r
, &mm
, &n
);
1004 if (fpu_status_ok (stat
))
1005 VAL2REG (&r
, reg_out
);
1008 fpu_check_signal_exception (sd
, cpu
, cia
);
1011 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1014 fpu_fnmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1015 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1016 void *reg_out
, const struct fp_prec_t
*ops
)
1018 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1020 REG2VAL (reg_in1
, &m1
);
1021 REG2VAL (reg_in2
, &m2
);
1022 REG2VAL (reg_in3
, &n
);
1027 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1028 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1029 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1035 VAL2REG (&sim_fpu_qnan
, reg_out
);
1039 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1041 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1042 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
1043 goto invalid_operands
;
1045 stat
|= sim_fpu_neg (&mm
, &m
);
1046 stat
|= sim_fpu_sub (&r
, &mm
, &n
);
1048 if (fpu_status_ok (stat
))
1049 VAL2REG (&r
, reg_out
);
1052 fpu_check_signal_exception (sd
, cpu
, cia
);