5 #include "sim-options.h"
9 #include "sim-assert.h"
35 host_callback
*mn10300_callback
;
40 /* simulation target board. NULL=default configuration */
41 static char* board
= NULL
;
43 static DECLARE_OPTION_HANDLER (mn10300_option_handler
);
46 OPTION_BOARD
= OPTION_START
,
50 mn10300_option_handler (SIM_DESC sd
,
63 board
= zalloc(strlen(arg
) + 1);
73 static const OPTION mn10300_options
[] =
75 #define BOARD_AM32 "stdeval1"
76 { {"board", required_argument
, NULL
, OPTION_BOARD
},
77 '\0', "none" /* rely on compile-time string concatenation for other options */
79 , "Customize simulation for a particular board.", mn10300_option_handler
},
81 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
84 /* For compatibility */
88 mn10300_pc_get (sim_cpu
*cpu
)
94 mn10300_pc_set (sim_cpu
*cpu
, sim_cia pc
)
99 /* These default values correspond to expected usage for the chip. */
102 sim_open (SIM_OPEN_KIND kind
,
108 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
109 mn10300_callback
= cb
;
111 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
113 /* The cpu data is kept in a separately allocated chunk of memory. */
114 if (sim_cpu_alloc_all (sd
, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK
)
117 /* for compatibility */
120 /* FIXME: should be better way of setting up interrupts. For
121 moment, only support watchpoints causing a breakpoint (gdb
123 STATE_WATCHPOINTS (sd
)->pc
= &(PC
);
124 STATE_WATCHPOINTS (sd
)->sizeof_pc
= sizeof (PC
);
125 STATE_WATCHPOINTS (sd
)->interrupt_handler
= NULL
;
126 STATE_WATCHPOINTS (sd
)->interrupt_names
= NULL
;
128 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
130 sim_add_option_table (sd
, NULL
, mn10300_options
);
132 /* Allocate core managed memory */
133 sim_do_command (sd
, "memory region 0,0x100000");
134 sim_do_command (sd
, "memory region 0x40000000,0x200000");
136 /* getopt will print the error message so we just have to exit if this fails.
137 FIXME: Hmmm... in the case of gdb we need getopt to call
139 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
141 /* Uninstall the modules to avoid memory leaks,
142 file descriptor leaks, etc. */
143 sim_module_uninstall (sd
);
148 && (strcmp(board
, BOARD_AM32
) == 0 ) )
151 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
153 sim_do_command (sd
, "memory region 0x44000000,0x40000");
154 sim_do_command (sd
, "memory region 0x48000000,0x400000");
156 /* device support for mn1030002 */
157 /* interrupt controller */
159 sim_hw_parse (sd
, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
161 /* DEBUG: NMI input's */
162 sim_hw_parse (sd
, "/glue@0x30000000/reg 0x30000000 12");
163 sim_hw_parse (sd
, "/glue@0x30000000 > int0 nmirq /mn103int");
164 sim_hw_parse (sd
, "/glue@0x30000000 > int1 watchdog /mn103int");
165 sim_hw_parse (sd
, "/glue@0x30000000 > int2 syserr /mn103int");
167 /* DEBUG: ACK input */
168 sim_hw_parse (sd
, "/glue@0x30002000/reg 0x30002000 4");
169 sim_hw_parse (sd
, "/glue@0x30002000 > int ack /mn103int");
171 /* DEBUG: LEVEL output */
172 sim_hw_parse (sd
, "/glue@0x30004000/reg 0x30004000 8");
173 sim_hw_parse (sd
, "/mn103int > nmi int0 /glue@0x30004000");
174 sim_hw_parse (sd
, "/mn103int > level int1 /glue@0x30004000");
176 /* DEBUG: A bunch of interrupt inputs */
177 sim_hw_parse (sd
, "/glue@0x30006000/reg 0x30006000 32");
178 sim_hw_parse (sd
, "/glue@0x30006000 > int0 irq-0 /mn103int");
179 sim_hw_parse (sd
, "/glue@0x30006000 > int1 irq-1 /mn103int");
180 sim_hw_parse (sd
, "/glue@0x30006000 > int2 irq-2 /mn103int");
181 sim_hw_parse (sd
, "/glue@0x30006000 > int3 irq-3 /mn103int");
182 sim_hw_parse (sd
, "/glue@0x30006000 > int4 irq-4 /mn103int");
183 sim_hw_parse (sd
, "/glue@0x30006000 > int5 irq-5 /mn103int");
184 sim_hw_parse (sd
, "/glue@0x30006000 > int6 irq-6 /mn103int");
185 sim_hw_parse (sd
, "/glue@0x30006000 > int7 irq-7 /mn103int");
187 /* processor interrupt device */
190 sim_hw_parse (sd
, "/mn103cpu@0x20000000");
191 sim_hw_parse (sd
, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
193 /* DEBUG: ACK output wired upto a glue device */
194 sim_hw_parse (sd
, "/glue@0x20002000");
195 sim_hw_parse (sd
, "/glue@0x20002000/reg 0x20002000 4");
196 sim_hw_parse (sd
, "/mn103cpu > ack int0 /glue@0x20002000");
198 /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
199 sim_hw_parse (sd
, "/glue@0x20004000");
200 sim_hw_parse (sd
, "/glue@0x20004000/reg 0x20004000 12");
201 sim_hw_parse (sd
, "/glue@0x20004000 > int0 reset /mn103cpu");
202 sim_hw_parse (sd
, "/glue@0x20004000 > int1 nmi /mn103cpu");
203 sim_hw_parse (sd
, "/glue@0x20004000 > int2 level /mn103cpu");
205 /* REAL: The processor wired up to the real interrupt controller */
206 sim_hw_parse (sd
, "/mn103cpu > ack ack /mn103int");
207 sim_hw_parse (sd
, "/mn103int > level level /mn103cpu");
208 sim_hw_parse (sd
, "/mn103int > nmi nmi /mn103cpu");
214 sim_hw_parse (sd
, "/pal@0x31000000");
215 sim_hw_parse (sd
, "/pal@0x31000000/reg 0x31000000 64");
216 sim_hw_parse (sd
, "/pal@0x31000000/poll? true");
218 /* DEBUG: PAL wired up to a glue device */
219 sim_hw_parse (sd
, "/glue@0x31002000");
220 sim_hw_parse (sd
, "/glue@0x31002000/reg 0x31002000 16");
221 sim_hw_parse (sd
, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
222 sim_hw_parse (sd
, "/pal@0x31000000 > timer int1 /glue@0x31002000");
223 sim_hw_parse (sd
, "/pal@0x31000000 > int int2 /glue@0x31002000");
224 sim_hw_parse (sd
, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
225 sim_hw_parse (sd
, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
226 sim_hw_parse (sd
, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
228 /* REAL: The PAL wired up to the real interrupt controller */
229 sim_hw_parse (sd
, "/pal@0x31000000 > countdown irq-0 /mn103int");
230 sim_hw_parse (sd
, "/pal@0x31000000 > timer irq-1 /mn103int");
231 sim_hw_parse (sd
, "/pal@0x31000000 > int irq-2 /mn103int");
233 /* 8 and 16 bit timers */
234 sim_hw_parse (sd
, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16");
236 /* Hook timer interrupts up to interrupt controller */
237 sim_hw_parse (sd
, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int");
238 sim_hw_parse (sd
, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int");
239 sim_hw_parse (sd
, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int");
240 sim_hw_parse (sd
, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int");
241 sim_hw_parse (sd
, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int");
242 sim_hw_parse (sd
, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int");
243 sim_hw_parse (sd
, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int");
244 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int");
245 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int");
248 /* Serial devices 0,1,2 */
249 sim_hw_parse (sd
, "/mn103ser@0x34000800/reg 0x34000800 48");
250 sim_hw_parse (sd
, "/mn103ser@0x34000800/poll? true");
252 /* Hook serial interrupts up to interrupt controller */
253 sim_hw_parse (sd
, "/mn103ser > serial-0-receive serial-0-receive /mn103int");
254 sim_hw_parse (sd
, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int");
255 sim_hw_parse (sd
, "/mn103ser > serial-1-receive serial-1-receive /mn103int");
256 sim_hw_parse (sd
, "/mn103ser > serial-1-transmit serial-1-transmit /mn103int");
257 sim_hw_parse (sd
, "/mn103ser > serial-2-receive serial-2-receive /mn103int");
258 sim_hw_parse (sd
, "/mn103ser > serial-2-transmit serial-2-transmit /mn103int");
260 sim_hw_parse (sd
, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
262 /* Memory control registers */
263 sim_do_command (sd
, "memory region 0x32000020,0x30");
264 /* Cache control register */
265 sim_do_command (sd
, "memory region 0x20000070,0x4");
266 /* Cache purge regions */
267 sim_do_command (sd
, "memory region 0x28400000,0x800");
268 sim_do_command (sd
, "memory region 0x28401000,0x800");
270 sim_do_command (sd
, "memory region 0x32000100,0xF");
271 sim_do_command (sd
, "memory region 0x32000200,0xF");
272 sim_do_command (sd
, "memory region 0x32000400,0xF");
273 sim_do_command (sd
, "memory region 0x32000800,0xF");
279 sim_io_eprintf (sd
, "Error: Board `%s' unknown.\n", board
);
286 /* check for/establish the a reference program image */
287 if (sim_analyze_program (sd
,
288 (STATE_PROG_ARGV (sd
) != NULL
289 ? *STATE_PROG_ARGV (sd
)
293 sim_module_uninstall (sd
);
297 /* establish any remaining configuration options */
298 if (sim_config (sd
) != SIM_RC_OK
)
300 sim_module_uninstall (sd
);
304 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
306 /* Uninstall the modules to avoid memory leaks,
307 file descriptor leaks, etc. */
308 sim_module_uninstall (sd
);
313 /* set machine specific configuration */
314 /* STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
315 /* | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
317 /* CPU specific initialization. */
318 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
320 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
322 CPU_PC_FETCH (cpu
) = mn10300_pc_get
;
323 CPU_PC_STORE (cpu
) = mn10300_pc_set
;
331 sim_close (SIM_DESC sd
, int quitting
)
333 sim_module_uninstall (sd
);
338 sim_create_inferior (SIM_DESC sd
,
339 struct bfd
*prog_bfd
,
343 memset (&State
, 0, sizeof (State
));
344 if (prog_bfd
!= NULL
) {
345 PC
= bfd_get_start_address (prog_bfd
);
349 CPU_PC_SET (STATE_CPU (sd
, 0), (unsigned64
) PC
);
351 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_am33_2
)
357 /* FIXME These would more efficient to use than load_mem/store_mem,
358 but need to be changed to use the memory map. */
370 return (a
[1] << 8) + (a
[0]);
377 return (a
[3]<<24) + (a
[2]<<16) + (a
[1]<<8) + (a
[0]);
381 put_byte (uint8
*addr
, uint8 data
)
388 put_half (uint8
*addr
, uint16 data
)
392 a
[1] = (data
>> 8) & 0xff;
396 put_word (uint8
*addr
, uint32 data
)
400 a
[1] = (data
>> 8) & 0xff;
401 a
[2] = (data
>> 16) & 0xff;
402 a
[3] = (data
>> 24) & 0xff;
406 sim_fetch_register (SIM_DESC sd
,
408 unsigned char *memory
,
411 put_word (memory
, State
.regs
[rn
]);
416 sim_store_register (SIM_DESC sd
,
418 unsigned char *memory
,
421 State
.regs
[rn
] = get_word (memory
);
426 mn10300_core_signal (SIM_DESC sd
,
432 transfer_type transfer
,
433 sim_core_signals sig
)
435 const char *copy
= (transfer
== read_transfer
? "read" : "write");
436 address_word ip
= CIA_ADDR (cia
);
440 case sim_core_unmapped_signal
:
441 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
443 (unsigned long) addr
, (unsigned long) ip
);
444 program_interrupt(sd
, cpu
, cia
, SIM_SIGSEGV
);
447 case sim_core_unaligned_signal
:
448 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
450 (unsigned long) addr
, (unsigned long) ip
);
451 program_interrupt(sd
, cpu
, cia
, SIM_SIGBUS
);
455 sim_engine_abort (sd
, cpu
, cia
,
456 "mn10300_core_signal - internal error - bad switch");
462 program_interrupt (SIM_DESC sd
,
469 static int in_interrupt
= 0;
471 #ifdef SIM_CPU_EXCEPTION_TRIGGER
472 SIM_CPU_EXCEPTION_TRIGGER(sd
,cpu
,cia
);
475 /* avoid infinite recursion */
478 (*mn10300_callback
->printf_filtered
) (mn10300_callback
,
479 "ERROR: recursion in program_interrupt during software exception dispatch.");
484 /* copy NMI handler code from dv-mn103cpu.c */
485 store_word (SP
- 4, CPU_PC_GET (cpu
));
486 store_half (SP
- 8, PSW
);
488 /* Set the SYSEF flag in NMICR by backdoor method. See
489 dv-mn103int.c:write_icr(). This is necessary because
490 software exceptions are not modelled by actually talking to
491 the interrupt controller, so it cannot set its own SYSEF
493 if ((NULL
!= board
) && (strcmp(board
, BOARD_AM32
) == 0))
494 store_byte (0x34000103, 0x04);
499 CPU_PC_SET (cpu
, 0x40000008);
502 sim_engine_halt(sd
, cpu
, NULL
, cia
, sim_stopped
, sig
);
507 mn10300_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
511 if(State
.exc_suspended
> 0)
512 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", State
.exc_suspended
);
514 CPU_PC_SET (cpu
, cia
);
515 memcpy(State
.exc_trigger_regs
, State
.regs
, sizeof(State
.exc_trigger_regs
));
516 State
.exc_suspended
= 0;
520 mn10300_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
524 if(State
.exc_suspended
> 0)
525 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
526 State
.exc_suspended
, exception
);
528 memcpy(State
.exc_suspend_regs
, State
.regs
, sizeof(State
.exc_suspend_regs
));
529 memcpy(State
.regs
, State
.exc_trigger_regs
, sizeof(State
.regs
));
530 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
531 State
.exc_suspended
= exception
;
535 mn10300_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
539 if(exception
== 0 && State
.exc_suspended
> 0)
541 if(State
.exc_suspended
!= SIGTRAP
) /* warn not for breakpoints */
542 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
543 State
.exc_suspended
);
545 else if(exception
!= 0 && State
.exc_suspended
> 0)
547 if(exception
!= State
.exc_suspended
)
548 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
549 State
.exc_suspended
, exception
);
551 memcpy(State
.regs
, State
.exc_suspend_regs
, sizeof(State
.regs
));
552 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
554 else if(exception
!= 0 && State
.exc_suspended
== 0)
556 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
558 State
.exc_suspended
= 0;
561 /* This is called when an FP instruction is issued when the FP unit is
562 disabled, i.e., the FE bit of PSW is zero. It raises interrupt
565 fpu_disabled_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
567 sim_io_eprintf(sd
, "FPU disabled exception\n");
568 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
571 /* This is called when the FP unit is enabled but one of the
572 unimplemented insns is issued. It raises interrupt code 0x1c8. */
574 fpu_unimp_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
576 sim_io_eprintf(sd
, "Unimplemented FPU instruction exception\n");
577 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
580 /* This is called at the end of any FP insns that may have triggered
581 FP exceptions. If no exception is enabled, it returns immediately.
582 Otherwise, it raises an exception code 0x1d0. */
584 fpu_check_signal_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
586 if ((FPCR
& EC_MASK
) == 0)
589 sim_io_eprintf(sd
, "FPU %s%s%s%s%s exception\n",
590 (FPCR
& EC_V
) ? "V" : "",
591 (FPCR
& EC_Z
) ? "Z" : "",
592 (FPCR
& EC_O
) ? "O" : "",
593 (FPCR
& EC_U
) ? "U" : "",
594 (FPCR
& EC_I
) ? "I" : "");
595 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
598 /* Convert a 32-bit single-precision FP value in the target platform
599 format to a sim_fpu value. */
601 reg2val_32 (const void *reg
, sim_fpu
*val
)
603 FS2FPU (*(reg_t
*)reg
, *val
);
606 /* Round the given sim_fpu value to single precision, following the
607 target platform rounding and denormalization conventions. On
608 AM33/2.0, round_near is the only rounding mode. */
610 round_32 (sim_fpu
*val
)
612 return sim_fpu_round_32 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
615 /* Convert a sim_fpu value to the 32-bit single-precision target
618 val2reg_32 (const sim_fpu
*val
, void *reg
)
620 FPU2FS (*val
, *(reg_t
*)reg
);
623 /* Define the 32-bit single-precision conversion and rounding uniform
625 const struct fp_prec_t
627 reg2val_32
, round_32
, val2reg_32
630 /* Convert a 64-bit double-precision FP value in the target platform
631 format to a sim_fpu value. */
633 reg2val_64 (const void *reg
, sim_fpu
*val
)
635 FD2FPU (*(dword
*)reg
, *val
);
638 /* Round the given sim_fpu value to double precision, following the
639 target platform rounding and denormalization conventions. On
640 AM33/2.0, round_near is the only rounding mode. */
642 round_64 (sim_fpu
*val
)
644 return sim_fpu_round_64 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
647 /* Convert a sim_fpu value to the 64-bit double-precision target
650 val2reg_64 (const sim_fpu
*val
, void *reg
)
652 FPU2FD (*val
, *(dword
*)reg
);
655 /* Define the 64-bit single-precision conversion and rounding uniform
657 const struct fp_prec_t
659 reg2val_64
, round_64
, val2reg_64
662 /* Define shortcuts to the uniform interface operations. */
663 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
664 #define ROUND(val) (*ops->round) (val)
665 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
667 /* Check whether overflow, underflow or inexact exceptions should be
670 fpu_status_ok (sim_fpu_status stat
)
672 if ((stat
& sim_fpu_status_overflow
)
675 else if ((stat
& (sim_fpu_status_underflow
| sim_fpu_status_denorm
))
678 else if ((stat
& (sim_fpu_status_inexact
| sim_fpu_status_rounded
))
681 else if (stat
& ~ (sim_fpu_status_overflow
682 | sim_fpu_status_underflow
683 | sim_fpu_status_denorm
684 | sim_fpu_status_inexact
685 | sim_fpu_status_rounded
))
692 /* Implement a 32/64 bit reciprocal square root, signaling FP
693 exceptions when appropriate. */
695 fpu_rsqrt (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
696 const void *reg_in
, void *reg_out
, const struct fp_prec_t
*ops
)
698 sim_fpu in
, med
, out
;
700 REG2VAL (reg_in
, &in
);
703 switch (sim_fpu_is (&in
))
705 case SIM_FPU_IS_SNAN
:
706 case SIM_FPU_IS_NNUMBER
:
707 case SIM_FPU_IS_NINF
:
711 VAL2REG (&sim_fpu_qnan
, reg_out
);
714 case SIM_FPU_IS_QNAN
:
715 VAL2REG (&sim_fpu_qnan
, reg_out
);
718 case SIM_FPU_IS_PINF
:
719 VAL2REG (&sim_fpu_zero
, reg_out
);
722 case SIM_FPU_IS_PNUMBER
:
724 /* Since we don't have a function to compute rsqrt directly,
726 sim_fpu_status stat
= 0;
727 stat
|= sim_fpu_sqrt (&med
, &in
);
728 stat
|= sim_fpu_inv (&out
, &med
);
729 stat
|= ROUND (&out
);
730 if (fpu_status_ok (stat
))
731 VAL2REG (&out
, reg_out
);
735 case SIM_FPU_IS_NZERO
:
736 case SIM_FPU_IS_PZERO
:
741 /* Generate an INF with the same sign. */
742 sim_fpu_inv (&out
, &in
);
743 VAL2REG (&out
, reg_out
);
751 fpu_check_signal_exception (sd
, cpu
, cia
);
759 case SIM_FPU_IS_SNAN
:
760 case SIM_FPU_IS_QNAN
:
763 case SIM_FPU_IS_NINF
:
764 case SIM_FPU_IS_NNUMBER
:
765 case SIM_FPU_IS_NDENORM
:
768 case SIM_FPU_IS_PINF
:
769 case SIM_FPU_IS_PNUMBER
:
770 case SIM_FPU_IS_PDENORM
:
773 case SIM_FPU_IS_NZERO
:
774 case SIM_FPU_IS_PZERO
:
782 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
783 exception bits as specified. */
785 fpu_cmp (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
786 const void *reg_in1
, const void *reg_in2
,
787 const struct fp_prec_t
*ops
)
791 REG2VAL (reg_in1
, &m
);
792 REG2VAL (reg_in2
, &n
);
797 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
))
805 FPCR
|= cmp2fcc (sim_fpu_cmp (&m
, &n
));
807 fpu_check_signal_exception (sd
, cpu
, cia
);
810 /* Implement a 32/64 bit FP add, setting FP exception bits when
813 fpu_add (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 (&m
) == SIM_FPU_IS_PINF
826 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
)
827 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
828 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
))
833 VAL2REG (&sim_fpu_qnan
, reg_out
);
837 sim_fpu_status stat
= sim_fpu_add (&r
, &m
, &n
);
839 if (fpu_status_ok (stat
))
840 VAL2REG (&r
, reg_out
);
843 fpu_check_signal_exception (sd
, cpu
, cia
);
846 /* Implement a 32/64 bit FP sub, setting FP exception bits when
849 fpu_sub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
850 const void *reg_in1
, const void *reg_in2
,
851 void *reg_out
, const struct fp_prec_t
*ops
)
855 REG2VAL (reg_in1
, &m
);
856 REG2VAL (reg_in2
, &n
);
860 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
861 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
862 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
)
863 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
864 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
))
869 VAL2REG (&sim_fpu_qnan
, reg_out
);
873 sim_fpu_status stat
= sim_fpu_sub (&r
, &m
, &n
);
875 if (fpu_status_ok (stat
))
876 VAL2REG (&r
, reg_out
);
879 fpu_check_signal_exception (sd
, cpu
, cia
);
882 /* Implement a 32/64 bit FP mul, setting FP exception bits when
885 fpu_mul (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
886 const void *reg_in1
, const void *reg_in2
,
887 void *reg_out
, const struct fp_prec_t
*ops
)
891 REG2VAL (reg_in1
, &m
);
892 REG2VAL (reg_in2
, &n
);
896 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
897 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_zero (&n
))
898 || (sim_fpu_is_zero (&m
) && sim_fpu_is_infinity (&n
)))
903 VAL2REG (&sim_fpu_qnan
, reg_out
);
907 sim_fpu_status stat
= sim_fpu_mul (&r
, &m
, &n
);
909 if (fpu_status_ok (stat
))
910 VAL2REG (&r
, reg_out
);
913 fpu_check_signal_exception (sd
, cpu
, cia
);
916 /* Implement a 32/64 bit FP div, setting FP exception bits when
919 fpu_div (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
920 const void *reg_in1
, const void *reg_in2
,
921 void *reg_out
, const struct fp_prec_t
*ops
)
925 REG2VAL (reg_in1
, &m
);
926 REG2VAL (reg_in2
, &n
);
930 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
931 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
))
932 || (sim_fpu_is_zero (&m
) && sim_fpu_is_zero (&n
)))
937 VAL2REG (&sim_fpu_qnan
, reg_out
);
939 else if (sim_fpu_is_number (&m
) && sim_fpu_is_zero (&n
)
944 sim_fpu_status stat
= sim_fpu_div (&r
, &m
, &n
);
946 if (fpu_status_ok (stat
))
947 VAL2REG (&r
, reg_out
);
950 fpu_check_signal_exception (sd
, cpu
, cia
);
953 /* Implement a 32/64 bit FP madd, setting FP exception bits when
956 fpu_fmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
957 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
958 void *reg_out
, const struct fp_prec_t
*ops
)
960 sim_fpu m1
, m2
, m
, n
, r
;
962 REG2VAL (reg_in1
, &m1
);
963 REG2VAL (reg_in2
, &m2
);
964 REG2VAL (reg_in3
, &n
);
969 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
970 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
971 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
977 VAL2REG (&sim_fpu_qnan
, reg_out
);
981 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
983 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
984 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
985 goto invalid_operands
;
987 stat
|= sim_fpu_add (&r
, &m
, &n
);
989 if (fpu_status_ok (stat
))
990 VAL2REG (&r
, reg_out
);
993 fpu_check_signal_exception (sd
, cpu
, cia
);
996 /* Implement a 32/64 bit FP msub, setting FP exception bits when
999 fpu_fmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1000 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1001 void *reg_out
, const struct fp_prec_t
*ops
)
1003 sim_fpu m1
, m2
, m
, n
, r
;
1005 REG2VAL (reg_in1
, &m1
);
1006 REG2VAL (reg_in2
, &m2
);
1007 REG2VAL (reg_in3
, &n
);
1012 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1013 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1014 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1020 VAL2REG (&sim_fpu_qnan
, reg_out
);
1024 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1026 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1027 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
1028 goto invalid_operands
;
1030 stat
|= sim_fpu_sub (&r
, &m
, &n
);
1032 if (fpu_status_ok (stat
))
1033 VAL2REG (&r
, reg_out
);
1036 fpu_check_signal_exception (sd
, cpu
, cia
);
1039 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
1042 fpu_fnmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1043 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1044 void *reg_out
, const struct fp_prec_t
*ops
)
1046 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1048 REG2VAL (reg_in1
, &m1
);
1049 REG2VAL (reg_in2
, &m2
);
1050 REG2VAL (reg_in3
, &n
);
1055 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1056 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1057 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1063 VAL2REG (&sim_fpu_qnan
, reg_out
);
1067 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1069 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1070 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
1071 goto invalid_operands
;
1073 stat
|= sim_fpu_neg (&mm
, &m
);
1074 stat
|= sim_fpu_add (&r
, &mm
, &n
);
1076 if (fpu_status_ok (stat
))
1077 VAL2REG (&r
, reg_out
);
1080 fpu_check_signal_exception (sd
, cpu
, cia
);
1083 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1086 fpu_fnmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1087 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1088 void *reg_out
, const struct fp_prec_t
*ops
)
1090 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1092 REG2VAL (reg_in1
, &m1
);
1093 REG2VAL (reg_in2
, &m2
);
1094 REG2VAL (reg_in3
, &n
);
1099 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1100 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1101 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1107 VAL2REG (&sim_fpu_qnan
, reg_out
);
1111 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1113 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1114 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
1115 goto invalid_operands
;
1117 stat
|= sim_fpu_neg (&mm
, &m
);
1118 stat
|= sim_fpu_sub (&r
, &mm
, &n
);
1120 if (fpu_status_ok (stat
))
1121 VAL2REG (&r
, reg_out
);
1124 fpu_check_signal_exception (sd
, cpu
, cia
);