5 #include "sim-options.h"
9 #include "sim-assert.h"
27 host_callback
*mn10300_callback
;
31 /* simulation target board. NULL=default configuration */
32 static char* board
= NULL
;
34 static DECLARE_OPTION_HANDLER (mn10300_option_handler
);
37 OPTION_BOARD
= OPTION_START
,
41 mn10300_option_handler (SIM_DESC sd
,
54 board
= zalloc(strlen(arg
) + 1);
64 static const OPTION mn10300_options
[] =
66 #define BOARD_AM32 "stdeval1"
67 { {"board", required_argument
, NULL
, OPTION_BOARD
},
68 '\0', "none" /* rely on compile-time string concatenation for other options */
70 , "Customize simulation for a particular board.", mn10300_option_handler
},
72 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
75 /* For compatibility */
79 mn10300_pc_get (sim_cpu
*cpu
)
85 mn10300_pc_set (sim_cpu
*cpu
, sim_cia pc
)
90 /* These default values correspond to expected usage for the chip. */
93 sim_open (SIM_OPEN_KIND kind
,
99 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
100 mn10300_callback
= cb
;
102 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
104 /* The cpu data is kept in a separately allocated chunk of memory. */
105 if (sim_cpu_alloc_all (sd
, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK
)
108 /* for compatibility */
111 /* FIXME: should be better way of setting up interrupts. For
112 moment, only support watchpoints causing a breakpoint (gdb
114 STATE_WATCHPOINTS (sd
)->pc
= &(PC
);
115 STATE_WATCHPOINTS (sd
)->sizeof_pc
= sizeof (PC
);
116 STATE_WATCHPOINTS (sd
)->interrupt_handler
= NULL
;
117 STATE_WATCHPOINTS (sd
)->interrupt_names
= NULL
;
119 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
121 sim_add_option_table (sd
, NULL
, mn10300_options
);
123 /* Allocate core managed memory */
124 sim_do_command (sd
, "memory region 0,0x100000");
125 sim_do_command (sd
, "memory region 0x40000000,0x200000");
127 /* getopt will print the error message so we just have to exit if this fails.
128 FIXME: Hmmm... in the case of gdb we need getopt to call
130 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
132 /* Uninstall the modules to avoid memory leaks,
133 file descriptor leaks, etc. */
134 sim_module_uninstall (sd
);
139 && (strcmp(board
, BOARD_AM32
) == 0 ) )
142 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
144 sim_do_command (sd
, "memory region 0x44000000,0x40000");
145 sim_do_command (sd
, "memory region 0x48000000,0x400000");
147 /* device support for mn1030002 */
148 /* interrupt controller */
150 sim_hw_parse (sd
, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
152 /* DEBUG: NMI input's */
153 sim_hw_parse (sd
, "/glue@0x30000000/reg 0x30000000 12");
154 sim_hw_parse (sd
, "/glue@0x30000000 > int0 nmirq /mn103int");
155 sim_hw_parse (sd
, "/glue@0x30000000 > int1 watchdog /mn103int");
156 sim_hw_parse (sd
, "/glue@0x30000000 > int2 syserr /mn103int");
158 /* DEBUG: ACK input */
159 sim_hw_parse (sd
, "/glue@0x30002000/reg 0x30002000 4");
160 sim_hw_parse (sd
, "/glue@0x30002000 > int ack /mn103int");
162 /* DEBUG: LEVEL output */
163 sim_hw_parse (sd
, "/glue@0x30004000/reg 0x30004000 8");
164 sim_hw_parse (sd
, "/mn103int > nmi int0 /glue@0x30004000");
165 sim_hw_parse (sd
, "/mn103int > level int1 /glue@0x30004000");
167 /* DEBUG: A bunch of interrupt inputs */
168 sim_hw_parse (sd
, "/glue@0x30006000/reg 0x30006000 32");
169 sim_hw_parse (sd
, "/glue@0x30006000 > int0 irq-0 /mn103int");
170 sim_hw_parse (sd
, "/glue@0x30006000 > int1 irq-1 /mn103int");
171 sim_hw_parse (sd
, "/glue@0x30006000 > int2 irq-2 /mn103int");
172 sim_hw_parse (sd
, "/glue@0x30006000 > int3 irq-3 /mn103int");
173 sim_hw_parse (sd
, "/glue@0x30006000 > int4 irq-4 /mn103int");
174 sim_hw_parse (sd
, "/glue@0x30006000 > int5 irq-5 /mn103int");
175 sim_hw_parse (sd
, "/glue@0x30006000 > int6 irq-6 /mn103int");
176 sim_hw_parse (sd
, "/glue@0x30006000 > int7 irq-7 /mn103int");
178 /* processor interrupt device */
181 sim_hw_parse (sd
, "/mn103cpu@0x20000000");
182 sim_hw_parse (sd
, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
184 /* DEBUG: ACK output wired upto a glue device */
185 sim_hw_parse (sd
, "/glue@0x20002000");
186 sim_hw_parse (sd
, "/glue@0x20002000/reg 0x20002000 4");
187 sim_hw_parse (sd
, "/mn103cpu > ack int0 /glue@0x20002000");
189 /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
190 sim_hw_parse (sd
, "/glue@0x20004000");
191 sim_hw_parse (sd
, "/glue@0x20004000/reg 0x20004000 12");
192 sim_hw_parse (sd
, "/glue@0x20004000 > int0 reset /mn103cpu");
193 sim_hw_parse (sd
, "/glue@0x20004000 > int1 nmi /mn103cpu");
194 sim_hw_parse (sd
, "/glue@0x20004000 > int2 level /mn103cpu");
196 /* REAL: The processor wired up to the real interrupt controller */
197 sim_hw_parse (sd
, "/mn103cpu > ack ack /mn103int");
198 sim_hw_parse (sd
, "/mn103int > level level /mn103cpu");
199 sim_hw_parse (sd
, "/mn103int > nmi nmi /mn103cpu");
205 sim_hw_parse (sd
, "/pal@0x31000000");
206 sim_hw_parse (sd
, "/pal@0x31000000/reg 0x31000000 64");
207 sim_hw_parse (sd
, "/pal@0x31000000/poll? true");
209 /* DEBUG: PAL wired up to a glue device */
210 sim_hw_parse (sd
, "/glue@0x31002000");
211 sim_hw_parse (sd
, "/glue@0x31002000/reg 0x31002000 16");
212 sim_hw_parse (sd
, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
213 sim_hw_parse (sd
, "/pal@0x31000000 > timer int1 /glue@0x31002000");
214 sim_hw_parse (sd
, "/pal@0x31000000 > int int2 /glue@0x31002000");
215 sim_hw_parse (sd
, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
216 sim_hw_parse (sd
, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
217 sim_hw_parse (sd
, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
219 /* REAL: The PAL wired up to the real interrupt controller */
220 sim_hw_parse (sd
, "/pal@0x31000000 > countdown irq-0 /mn103int");
221 sim_hw_parse (sd
, "/pal@0x31000000 > timer irq-1 /mn103int");
222 sim_hw_parse (sd
, "/pal@0x31000000 > int irq-2 /mn103int");
224 /* 8 and 16 bit timers */
225 sim_hw_parse (sd
, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16");
227 /* Hook timer interrupts up to interrupt controller */
228 sim_hw_parse (sd
, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int");
229 sim_hw_parse (sd
, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int");
230 sim_hw_parse (sd
, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int");
231 sim_hw_parse (sd
, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int");
232 sim_hw_parse (sd
, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int");
233 sim_hw_parse (sd
, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int");
234 sim_hw_parse (sd
, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int");
235 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int");
236 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int");
239 /* Serial devices 0,1,2 */
240 sim_hw_parse (sd
, "/mn103ser@0x34000800/reg 0x34000800 48");
241 sim_hw_parse (sd
, "/mn103ser@0x34000800/poll? true");
243 /* Hook serial interrupts up to interrupt controller */
244 sim_hw_parse (sd
, "/mn103ser > serial-0-receive serial-0-receive /mn103int");
245 sim_hw_parse (sd
, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int");
246 sim_hw_parse (sd
, "/mn103ser > serial-1-receive serial-1-receive /mn103int");
247 sim_hw_parse (sd
, "/mn103ser > serial-1-transmit serial-1-transmit /mn103int");
248 sim_hw_parse (sd
, "/mn103ser > serial-2-receive serial-2-receive /mn103int");
249 sim_hw_parse (sd
, "/mn103ser > serial-2-transmit serial-2-transmit /mn103int");
251 sim_hw_parse (sd
, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
253 /* Memory control registers */
254 sim_do_command (sd
, "memory region 0x32000020,0x30");
255 /* Cache control register */
256 sim_do_command (sd
, "memory region 0x20000070,0x4");
257 /* Cache purge regions */
258 sim_do_command (sd
, "memory region 0x28400000,0x800");
259 sim_do_command (sd
, "memory region 0x28401000,0x800");
261 sim_do_command (sd
, "memory region 0x32000100,0xF");
262 sim_do_command (sd
, "memory region 0x32000200,0xF");
263 sim_do_command (sd
, "memory region 0x32000400,0xF");
264 sim_do_command (sd
, "memory region 0x32000800,0xF");
270 sim_io_eprintf (sd
, "Error: Board `%s' unknown.\n", board
);
277 /* check for/establish the a reference program image */
278 if (sim_analyze_program (sd
,
279 (STATE_PROG_ARGV (sd
) != NULL
280 ? *STATE_PROG_ARGV (sd
)
284 sim_module_uninstall (sd
);
288 /* establish any remaining configuration options */
289 if (sim_config (sd
) != SIM_RC_OK
)
291 sim_module_uninstall (sd
);
295 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
297 /* Uninstall the modules to avoid memory leaks,
298 file descriptor leaks, etc. */
299 sim_module_uninstall (sd
);
304 /* set machine specific configuration */
305 /* STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
306 /* | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
308 /* CPU specific initialization. */
309 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
311 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
313 CPU_PC_FETCH (cpu
) = mn10300_pc_get
;
314 CPU_PC_STORE (cpu
) = mn10300_pc_set
;
322 sim_close (SIM_DESC sd
, int quitting
)
324 sim_module_uninstall (sd
);
329 sim_create_inferior (SIM_DESC sd
,
330 struct bfd
*prog_bfd
,
334 memset (&State
, 0, sizeof (State
));
335 if (prog_bfd
!= NULL
) {
336 PC
= bfd_get_start_address (prog_bfd
);
340 CPU_PC_SET (STATE_CPU (sd
, 0), (unsigned64
) PC
);
342 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_am33_2
)
348 /* FIXME These would more efficient to use than load_mem/store_mem,
349 but need to be changed to use the memory map. */
352 sim_fetch_register (SIM_DESC sd
,
354 unsigned char *memory
,
357 reg_t reg
= State
.regs
[rn
];
367 sim_store_register (SIM_DESC sd
,
369 unsigned char *memory
,
373 State
.regs
[rn
] = (a
[3] << 24) + (a
[2] << 16) + (a
[1] << 8) + a
[0];
378 mn10300_core_signal (SIM_DESC sd
,
384 transfer_type transfer
,
385 sim_core_signals sig
)
387 const char *copy
= (transfer
== read_transfer
? "read" : "write");
388 address_word ip
= CIA_ADDR (cia
);
392 case sim_core_unmapped_signal
:
393 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
395 (unsigned long) addr
, (unsigned long) ip
);
396 program_interrupt(sd
, cpu
, cia
, SIM_SIGSEGV
);
399 case sim_core_unaligned_signal
:
400 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
402 (unsigned long) addr
, (unsigned long) ip
);
403 program_interrupt(sd
, cpu
, cia
, SIM_SIGBUS
);
407 sim_engine_abort (sd
, cpu
, cia
,
408 "mn10300_core_signal - internal error - bad switch");
414 program_interrupt (SIM_DESC sd
,
421 static int in_interrupt
= 0;
423 #ifdef SIM_CPU_EXCEPTION_TRIGGER
424 SIM_CPU_EXCEPTION_TRIGGER(sd
,cpu
,cia
);
427 /* avoid infinite recursion */
430 (*mn10300_callback
->printf_filtered
) (mn10300_callback
,
431 "ERROR: recursion in program_interrupt during software exception dispatch.");
436 /* copy NMI handler code from dv-mn103cpu.c */
437 store_word (SP
- 4, CPU_PC_GET (cpu
));
438 store_half (SP
- 8, PSW
);
440 /* Set the SYSEF flag in NMICR by backdoor method. See
441 dv-mn103int.c:write_icr(). This is necessary because
442 software exceptions are not modelled by actually talking to
443 the interrupt controller, so it cannot set its own SYSEF
445 if ((NULL
!= board
) && (strcmp(board
, BOARD_AM32
) == 0))
446 store_byte (0x34000103, 0x04);
451 CPU_PC_SET (cpu
, 0x40000008);
454 sim_engine_halt(sd
, cpu
, NULL
, cia
, sim_stopped
, sig
);
459 mn10300_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
463 if(State
.exc_suspended
> 0)
464 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", State
.exc_suspended
);
466 CPU_PC_SET (cpu
, cia
);
467 memcpy(State
.exc_trigger_regs
, State
.regs
, sizeof(State
.exc_trigger_regs
));
468 State
.exc_suspended
= 0;
472 mn10300_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
476 if(State
.exc_suspended
> 0)
477 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
478 State
.exc_suspended
, exception
);
480 memcpy(State
.exc_suspend_regs
, State
.regs
, sizeof(State
.exc_suspend_regs
));
481 memcpy(State
.regs
, State
.exc_trigger_regs
, sizeof(State
.regs
));
482 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
483 State
.exc_suspended
= exception
;
487 mn10300_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
491 if(exception
== 0 && State
.exc_suspended
> 0)
493 if(State
.exc_suspended
!= SIGTRAP
) /* warn not for breakpoints */
494 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
495 State
.exc_suspended
);
497 else if(exception
!= 0 && State
.exc_suspended
> 0)
499 if(exception
!= State
.exc_suspended
)
500 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
501 State
.exc_suspended
, exception
);
503 memcpy(State
.regs
, State
.exc_suspend_regs
, sizeof(State
.regs
));
504 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
506 else if(exception
!= 0 && State
.exc_suspended
== 0)
508 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
510 State
.exc_suspended
= 0;
513 /* This is called when an FP instruction is issued when the FP unit is
514 disabled, i.e., the FE bit of PSW is zero. It raises interrupt
517 fpu_disabled_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
519 sim_io_eprintf(sd
, "FPU disabled exception\n");
520 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
523 /* This is called when the FP unit is enabled but one of the
524 unimplemented insns is issued. It raises interrupt code 0x1c8. */
526 fpu_unimp_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
528 sim_io_eprintf(sd
, "Unimplemented FPU instruction exception\n");
529 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
532 /* This is called at the end of any FP insns that may have triggered
533 FP exceptions. If no exception is enabled, it returns immediately.
534 Otherwise, it raises an exception code 0x1d0. */
536 fpu_check_signal_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
538 if ((FPCR
& EC_MASK
) == 0)
541 sim_io_eprintf(sd
, "FPU %s%s%s%s%s exception\n",
542 (FPCR
& EC_V
) ? "V" : "",
543 (FPCR
& EC_Z
) ? "Z" : "",
544 (FPCR
& EC_O
) ? "O" : "",
545 (FPCR
& EC_U
) ? "U" : "",
546 (FPCR
& EC_I
) ? "I" : "");
547 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
550 /* Convert a 32-bit single-precision FP value in the target platform
551 format to a sim_fpu value. */
553 reg2val_32 (const void *reg
, sim_fpu
*val
)
555 FS2FPU (*(reg_t
*)reg
, *val
);
558 /* Round the given sim_fpu value to single precision, following the
559 target platform rounding and denormalization conventions. On
560 AM33/2.0, round_near is the only rounding mode. */
562 round_32 (sim_fpu
*val
)
564 return sim_fpu_round_32 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
567 /* Convert a sim_fpu value to the 32-bit single-precision target
570 val2reg_32 (const sim_fpu
*val
, void *reg
)
572 FPU2FS (*val
, *(reg_t
*)reg
);
575 /* Define the 32-bit single-precision conversion and rounding uniform
577 const struct fp_prec_t
579 reg2val_32
, round_32
, val2reg_32
582 /* Convert a 64-bit double-precision FP value in the target platform
583 format to a sim_fpu value. */
585 reg2val_64 (const void *reg
, sim_fpu
*val
)
587 FD2FPU (*(dword
*)reg
, *val
);
590 /* Round the given sim_fpu value to double precision, following the
591 target platform rounding and denormalization conventions. On
592 AM33/2.0, round_near is the only rounding mode. */
594 round_64 (sim_fpu
*val
)
596 return sim_fpu_round_64 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
599 /* Convert a sim_fpu value to the 64-bit double-precision target
602 val2reg_64 (const sim_fpu
*val
, void *reg
)
604 FPU2FD (*val
, *(dword
*)reg
);
607 /* Define the 64-bit single-precision conversion and rounding uniform
609 const struct fp_prec_t
611 reg2val_64
, round_64
, val2reg_64
614 /* Define shortcuts to the uniform interface operations. */
615 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
616 #define ROUND(val) (*ops->round) (val)
617 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
619 /* Check whether overflow, underflow or inexact exceptions should be
622 fpu_status_ok (sim_fpu_status stat
)
624 if ((stat
& sim_fpu_status_overflow
)
627 else if ((stat
& (sim_fpu_status_underflow
| sim_fpu_status_denorm
))
630 else if ((stat
& (sim_fpu_status_inexact
| sim_fpu_status_rounded
))
633 else if (stat
& ~ (sim_fpu_status_overflow
634 | sim_fpu_status_underflow
635 | sim_fpu_status_denorm
636 | sim_fpu_status_inexact
637 | sim_fpu_status_rounded
))
644 /* Implement a 32/64 bit reciprocal square root, signaling FP
645 exceptions when appropriate. */
647 fpu_rsqrt (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
648 const void *reg_in
, void *reg_out
, const struct fp_prec_t
*ops
)
650 sim_fpu in
, med
, out
;
652 REG2VAL (reg_in
, &in
);
655 switch (sim_fpu_is (&in
))
657 case SIM_FPU_IS_SNAN
:
658 case SIM_FPU_IS_NNUMBER
:
659 case SIM_FPU_IS_NINF
:
663 VAL2REG (&sim_fpu_qnan
, reg_out
);
666 case SIM_FPU_IS_QNAN
:
667 VAL2REG (&sim_fpu_qnan
, reg_out
);
670 case SIM_FPU_IS_PINF
:
671 VAL2REG (&sim_fpu_zero
, reg_out
);
674 case SIM_FPU_IS_PNUMBER
:
676 /* Since we don't have a function to compute rsqrt directly,
678 sim_fpu_status stat
= 0;
679 stat
|= sim_fpu_sqrt (&med
, &in
);
680 stat
|= sim_fpu_inv (&out
, &med
);
681 stat
|= ROUND (&out
);
682 if (fpu_status_ok (stat
))
683 VAL2REG (&out
, reg_out
);
687 case SIM_FPU_IS_NZERO
:
688 case SIM_FPU_IS_PZERO
:
693 /* Generate an INF with the same sign. */
694 sim_fpu_inv (&out
, &in
);
695 VAL2REG (&out
, reg_out
);
703 fpu_check_signal_exception (sd
, cpu
, cia
);
711 case SIM_FPU_IS_SNAN
:
712 case SIM_FPU_IS_QNAN
:
715 case SIM_FPU_IS_NINF
:
716 case SIM_FPU_IS_NNUMBER
:
717 case SIM_FPU_IS_NDENORM
:
720 case SIM_FPU_IS_PINF
:
721 case SIM_FPU_IS_PNUMBER
:
722 case SIM_FPU_IS_PDENORM
:
725 case SIM_FPU_IS_NZERO
:
726 case SIM_FPU_IS_PZERO
:
734 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
735 exception bits as specified. */
737 fpu_cmp (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
738 const void *reg_in1
, const void *reg_in2
,
739 const struct fp_prec_t
*ops
)
743 REG2VAL (reg_in1
, &m
);
744 REG2VAL (reg_in2
, &n
);
749 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
))
757 FPCR
|= cmp2fcc (sim_fpu_cmp (&m
, &n
));
759 fpu_check_signal_exception (sd
, cpu
, cia
);
762 /* Implement a 32/64 bit FP add, setting FP exception bits when
765 fpu_add (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
766 const void *reg_in1
, const void *reg_in2
,
767 void *reg_out
, const struct fp_prec_t
*ops
)
771 REG2VAL (reg_in1
, &m
);
772 REG2VAL (reg_in2
, &n
);
776 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
777 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
778 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
)
779 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
780 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
))
785 VAL2REG (&sim_fpu_qnan
, reg_out
);
789 sim_fpu_status stat
= sim_fpu_add (&r
, &m
, &n
);
791 if (fpu_status_ok (stat
))
792 VAL2REG (&r
, reg_out
);
795 fpu_check_signal_exception (sd
, cpu
, cia
);
798 /* Implement a 32/64 bit FP sub, setting FP exception bits when
801 fpu_sub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
802 const void *reg_in1
, const void *reg_in2
,
803 void *reg_out
, const struct fp_prec_t
*ops
)
807 REG2VAL (reg_in1
, &m
);
808 REG2VAL (reg_in2
, &n
);
812 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
813 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
814 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
)
815 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
816 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
))
821 VAL2REG (&sim_fpu_qnan
, reg_out
);
825 sim_fpu_status stat
= sim_fpu_sub (&r
, &m
, &n
);
827 if (fpu_status_ok (stat
))
828 VAL2REG (&r
, reg_out
);
831 fpu_check_signal_exception (sd
, cpu
, cia
);
834 /* Implement a 32/64 bit FP mul, setting FP exception bits when
837 fpu_mul (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
838 const void *reg_in1
, const void *reg_in2
,
839 void *reg_out
, const struct fp_prec_t
*ops
)
843 REG2VAL (reg_in1
, &m
);
844 REG2VAL (reg_in2
, &n
);
848 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
849 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_zero (&n
))
850 || (sim_fpu_is_zero (&m
) && sim_fpu_is_infinity (&n
)))
855 VAL2REG (&sim_fpu_qnan
, reg_out
);
859 sim_fpu_status stat
= sim_fpu_mul (&r
, &m
, &n
);
861 if (fpu_status_ok (stat
))
862 VAL2REG (&r
, reg_out
);
865 fpu_check_signal_exception (sd
, cpu
, cia
);
868 /* Implement a 32/64 bit FP div, setting FP exception bits when
871 fpu_div (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
872 const void *reg_in1
, const void *reg_in2
,
873 void *reg_out
, const struct fp_prec_t
*ops
)
877 REG2VAL (reg_in1
, &m
);
878 REG2VAL (reg_in2
, &n
);
882 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
883 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
))
884 || (sim_fpu_is_zero (&m
) && sim_fpu_is_zero (&n
)))
889 VAL2REG (&sim_fpu_qnan
, reg_out
);
891 else if (sim_fpu_is_number (&m
) && sim_fpu_is_zero (&n
)
896 sim_fpu_status stat
= sim_fpu_div (&r
, &m
, &n
);
898 if (fpu_status_ok (stat
))
899 VAL2REG (&r
, reg_out
);
902 fpu_check_signal_exception (sd
, cpu
, cia
);
905 /* Implement a 32/64 bit FP madd, setting FP exception bits when
908 fpu_fmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
909 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
910 void *reg_out
, const struct fp_prec_t
*ops
)
912 sim_fpu m1
, m2
, m
, n
, r
;
914 REG2VAL (reg_in1
, &m1
);
915 REG2VAL (reg_in2
, &m2
);
916 REG2VAL (reg_in3
, &n
);
921 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
922 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
923 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
929 VAL2REG (&sim_fpu_qnan
, reg_out
);
933 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
935 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
936 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
937 goto invalid_operands
;
939 stat
|= sim_fpu_add (&r
, &m
, &n
);
941 if (fpu_status_ok (stat
))
942 VAL2REG (&r
, reg_out
);
945 fpu_check_signal_exception (sd
, cpu
, cia
);
948 /* Implement a 32/64 bit FP msub, setting FP exception bits when
951 fpu_fmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
952 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
953 void *reg_out
, const struct fp_prec_t
*ops
)
955 sim_fpu m1
, m2
, m
, n
, r
;
957 REG2VAL (reg_in1
, &m1
);
958 REG2VAL (reg_in2
, &m2
);
959 REG2VAL (reg_in3
, &n
);
964 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
965 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
966 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
972 VAL2REG (&sim_fpu_qnan
, reg_out
);
976 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
978 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
979 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
980 goto invalid_operands
;
982 stat
|= sim_fpu_sub (&r
, &m
, &n
);
984 if (fpu_status_ok (stat
))
985 VAL2REG (&r
, reg_out
);
988 fpu_check_signal_exception (sd
, cpu
, cia
);
991 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
994 fpu_fnmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
995 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
996 void *reg_out
, const struct fp_prec_t
*ops
)
998 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1000 REG2VAL (reg_in1
, &m1
);
1001 REG2VAL (reg_in2
, &m2
);
1002 REG2VAL (reg_in3
, &n
);
1007 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1008 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1009 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1015 VAL2REG (&sim_fpu_qnan
, reg_out
);
1019 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1021 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1022 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
1023 goto invalid_operands
;
1025 stat
|= sim_fpu_neg (&mm
, &m
);
1026 stat
|= sim_fpu_add (&r
, &mm
, &n
);
1028 if (fpu_status_ok (stat
))
1029 VAL2REG (&r
, reg_out
);
1032 fpu_check_signal_exception (sd
, cpu
, cia
);
1035 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1038 fpu_fnmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1039 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1040 void *reg_out
, const struct fp_prec_t
*ops
)
1042 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1044 REG2VAL (reg_in1
, &m1
);
1045 REG2VAL (reg_in2
, &m2
);
1046 REG2VAL (reg_in3
, &n
);
1051 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1052 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1053 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1059 VAL2REG (&sim_fpu_qnan
, reg_out
);
1063 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1065 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1066 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
1067 goto invalid_operands
;
1069 stat
|= sim_fpu_neg (&mm
, &m
);
1070 stat
|= sim_fpu_sub (&r
, &mm
, &n
);
1072 if (fpu_status_ok (stat
))
1073 VAL2REG (&r
, reg_out
);
1076 fpu_check_signal_exception (sd
, cpu
, cia
);