5 #include "sim-options.h"
9 #include "sim-assert.h"
20 /* simulation target board. NULL=default configuration */
21 static char* board
= NULL
;
23 static DECLARE_OPTION_HANDLER (mn10300_option_handler
);
26 OPTION_BOARD
= OPTION_START
,
30 mn10300_option_handler (SIM_DESC sd
,
43 board
= zalloc(strlen(arg
) + 1);
53 static const OPTION mn10300_options
[] =
55 #define BOARD_AM32 "stdeval1"
56 { {"board", required_argument
, NULL
, OPTION_BOARD
},
57 '\0', "none" /* rely on compile-time string concatenation for other options */
59 , "Customize simulation for a particular board.", mn10300_option_handler
},
61 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
64 /* For compatibility */
68 mn10300_pc_get (sim_cpu
*cpu
)
74 mn10300_pc_set (sim_cpu
*cpu
, sim_cia pc
)
79 static int mn10300_reg_fetch (SIM_CPU
*, int, unsigned char *, int);
80 static int mn10300_reg_store (SIM_CPU
*, int, unsigned char *, int);
82 /* These default values correspond to expected usage for the chip. */
85 sim_open (SIM_OPEN_KIND kind
,
91 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
93 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
95 /* The cpu data is kept in a separately allocated chunk of memory. */
96 if (sim_cpu_alloc_all (sd
, 1, /*cgen_cpu_max_extra_bytes ()*/0) != SIM_RC_OK
)
99 /* for compatibility */
102 /* FIXME: should be better way of setting up interrupts. For
103 moment, only support watchpoints causing a breakpoint (gdb
105 STATE_WATCHPOINTS (sd
)->pc
= &(PC
);
106 STATE_WATCHPOINTS (sd
)->sizeof_pc
= sizeof (PC
);
107 STATE_WATCHPOINTS (sd
)->interrupt_handler
= NULL
;
108 STATE_WATCHPOINTS (sd
)->interrupt_names
= NULL
;
110 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
112 sim_add_option_table (sd
, NULL
, mn10300_options
);
114 /* Allocate core managed memory */
115 sim_do_command (sd
, "memory region 0,0x100000");
116 sim_do_command (sd
, "memory region 0x40000000,0x200000");
118 /* The parser will print an error message for us, so we silently return. */
119 if (sim_parse_args (sd
, argv
) != SIM_RC_OK
)
121 /* Uninstall the modules to avoid memory leaks,
122 file descriptor leaks, etc. */
123 sim_module_uninstall (sd
);
128 && (strcmp(board
, BOARD_AM32
) == 0 ) )
131 STATE_ENVIRONMENT (sd
) = OPERATING_ENVIRONMENT
;
133 sim_do_command (sd
, "memory region 0x44000000,0x40000");
134 sim_do_command (sd
, "memory region 0x48000000,0x400000");
136 /* device support for mn1030002 */
137 /* interrupt controller */
139 sim_hw_parse (sd
, "/mn103int@0x34000100/reg 0x34000100 0x7C 0x34000200 0x8 0x34000280 0x8");
141 /* DEBUG: NMI input's */
142 sim_hw_parse (sd
, "/glue@0x30000000/reg 0x30000000 12");
143 sim_hw_parse (sd
, "/glue@0x30000000 > int0 nmirq /mn103int");
144 sim_hw_parse (sd
, "/glue@0x30000000 > int1 watchdog /mn103int");
145 sim_hw_parse (sd
, "/glue@0x30000000 > int2 syserr /mn103int");
147 /* DEBUG: ACK input */
148 sim_hw_parse (sd
, "/glue@0x30002000/reg 0x30002000 4");
149 sim_hw_parse (sd
, "/glue@0x30002000 > int ack /mn103int");
151 /* DEBUG: LEVEL output */
152 sim_hw_parse (sd
, "/glue@0x30004000/reg 0x30004000 8");
153 sim_hw_parse (sd
, "/mn103int > nmi int0 /glue@0x30004000");
154 sim_hw_parse (sd
, "/mn103int > level int1 /glue@0x30004000");
156 /* DEBUG: A bunch of interrupt inputs */
157 sim_hw_parse (sd
, "/glue@0x30006000/reg 0x30006000 32");
158 sim_hw_parse (sd
, "/glue@0x30006000 > int0 irq-0 /mn103int");
159 sim_hw_parse (sd
, "/glue@0x30006000 > int1 irq-1 /mn103int");
160 sim_hw_parse (sd
, "/glue@0x30006000 > int2 irq-2 /mn103int");
161 sim_hw_parse (sd
, "/glue@0x30006000 > int3 irq-3 /mn103int");
162 sim_hw_parse (sd
, "/glue@0x30006000 > int4 irq-4 /mn103int");
163 sim_hw_parse (sd
, "/glue@0x30006000 > int5 irq-5 /mn103int");
164 sim_hw_parse (sd
, "/glue@0x30006000 > int6 irq-6 /mn103int");
165 sim_hw_parse (sd
, "/glue@0x30006000 > int7 irq-7 /mn103int");
167 /* processor interrupt device */
170 sim_hw_parse (sd
, "/mn103cpu@0x20000000");
171 sim_hw_parse (sd
, "/mn103cpu@0x20000000/reg 0x20000000 0x42");
173 /* DEBUG: ACK output wired upto a glue device */
174 sim_hw_parse (sd
, "/glue@0x20002000");
175 sim_hw_parse (sd
, "/glue@0x20002000/reg 0x20002000 4");
176 sim_hw_parse (sd
, "/mn103cpu > ack int0 /glue@0x20002000");
178 /* DEBUG: RESET/NMI/LEVEL wired up to a glue device */
179 sim_hw_parse (sd
, "/glue@0x20004000");
180 sim_hw_parse (sd
, "/glue@0x20004000/reg 0x20004000 12");
181 sim_hw_parse (sd
, "/glue@0x20004000 > int0 reset /mn103cpu");
182 sim_hw_parse (sd
, "/glue@0x20004000 > int1 nmi /mn103cpu");
183 sim_hw_parse (sd
, "/glue@0x20004000 > int2 level /mn103cpu");
185 /* REAL: The processor wired up to the real interrupt controller */
186 sim_hw_parse (sd
, "/mn103cpu > ack ack /mn103int");
187 sim_hw_parse (sd
, "/mn103int > level level /mn103cpu");
188 sim_hw_parse (sd
, "/mn103int > nmi nmi /mn103cpu");
194 sim_hw_parse (sd
, "/pal@0x31000000");
195 sim_hw_parse (sd
, "/pal@0x31000000/reg 0x31000000 64");
196 sim_hw_parse (sd
, "/pal@0x31000000/poll? true");
198 /* DEBUG: PAL wired up to a glue device */
199 sim_hw_parse (sd
, "/glue@0x31002000");
200 sim_hw_parse (sd
, "/glue@0x31002000/reg 0x31002000 16");
201 sim_hw_parse (sd
, "/pal@0x31000000 > countdown int0 /glue@0x31002000");
202 sim_hw_parse (sd
, "/pal@0x31000000 > timer int1 /glue@0x31002000");
203 sim_hw_parse (sd
, "/pal@0x31000000 > int int2 /glue@0x31002000");
204 sim_hw_parse (sd
, "/glue@0x31002000 > int0 int3 /glue@0x31002000");
205 sim_hw_parse (sd
, "/glue@0x31002000 > int1 int3 /glue@0x31002000");
206 sim_hw_parse (sd
, "/glue@0x31002000 > int2 int3 /glue@0x31002000");
208 /* REAL: The PAL wired up to the real interrupt controller */
209 sim_hw_parse (sd
, "/pal@0x31000000 > countdown irq-0 /mn103int");
210 sim_hw_parse (sd
, "/pal@0x31000000 > timer irq-1 /mn103int");
211 sim_hw_parse (sd
, "/pal@0x31000000 > int irq-2 /mn103int");
213 /* 8 and 16 bit timers */
214 sim_hw_parse (sd
, "/mn103tim@0x34001000/reg 0x34001000 36 0x34001080 100 0x34004000 16");
216 /* Hook timer interrupts up to interrupt controller */
217 sim_hw_parse (sd
, "/mn103tim > timer-0-underflow timer-0-underflow /mn103int");
218 sim_hw_parse (sd
, "/mn103tim > timer-1-underflow timer-1-underflow /mn103int");
219 sim_hw_parse (sd
, "/mn103tim > timer-2-underflow timer-2-underflow /mn103int");
220 sim_hw_parse (sd
, "/mn103tim > timer-3-underflow timer-3-underflow /mn103int");
221 sim_hw_parse (sd
, "/mn103tim > timer-4-underflow timer-4-underflow /mn103int");
222 sim_hw_parse (sd
, "/mn103tim > timer-5-underflow timer-5-underflow /mn103int");
223 sim_hw_parse (sd
, "/mn103tim > timer-6-underflow timer-6-underflow /mn103int");
224 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-a timer-6-compare-a /mn103int");
225 sim_hw_parse (sd
, "/mn103tim > timer-6-compare-b timer-6-compare-b /mn103int");
228 /* Serial devices 0,1,2 */
229 sim_hw_parse (sd
, "/mn103ser@0x34000800/reg 0x34000800 48");
230 sim_hw_parse (sd
, "/mn103ser@0x34000800/poll? true");
232 /* Hook serial interrupts up to interrupt controller */
233 sim_hw_parse (sd
, "/mn103ser > serial-0-receive serial-0-receive /mn103int");
234 sim_hw_parse (sd
, "/mn103ser > serial-0-transmit serial-0-transmit /mn103int");
235 sim_hw_parse (sd
, "/mn103ser > serial-1-receive serial-1-receive /mn103int");
236 sim_hw_parse (sd
, "/mn103ser > serial-1-transmit serial-1-transmit /mn103int");
237 sim_hw_parse (sd
, "/mn103ser > serial-2-receive serial-2-receive /mn103int");
238 sim_hw_parse (sd
, "/mn103ser > serial-2-transmit serial-2-transmit /mn103int");
240 sim_hw_parse (sd
, "/mn103iop@0x36008000/reg 0x36008000 8 0x36008020 8 0x36008040 0xc 0x36008060 8 0x36008080 8");
242 /* Memory control registers */
243 sim_do_command (sd
, "memory region 0x32000020,0x30");
244 /* Cache control register */
245 sim_do_command (sd
, "memory region 0x20000070,0x4");
246 /* Cache purge regions */
247 sim_do_command (sd
, "memory region 0x28400000,0x800");
248 sim_do_command (sd
, "memory region 0x28401000,0x800");
250 sim_do_command (sd
, "memory region 0x32000100,0xF");
251 sim_do_command (sd
, "memory region 0x32000200,0xF");
252 sim_do_command (sd
, "memory region 0x32000400,0xF");
253 sim_do_command (sd
, "memory region 0x32000800,0xF");
259 sim_io_eprintf (sd
, "Error: Board `%s' unknown.\n", board
);
266 /* check for/establish the a reference program image */
267 if (sim_analyze_program (sd
,
268 (STATE_PROG_ARGV (sd
) != NULL
269 ? *STATE_PROG_ARGV (sd
)
273 sim_module_uninstall (sd
);
277 /* establish any remaining configuration options */
278 if (sim_config (sd
) != SIM_RC_OK
)
280 sim_module_uninstall (sd
);
284 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
286 /* Uninstall the modules to avoid memory leaks,
287 file descriptor leaks, etc. */
288 sim_module_uninstall (sd
);
293 /* set machine specific configuration */
294 /* STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
295 /* | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
297 /* CPU specific initialization. */
298 for (i
= 0; i
< MAX_NR_PROCESSORS
; ++i
)
300 SIM_CPU
*cpu
= STATE_CPU (sd
, i
);
302 CPU_REG_FETCH (cpu
) = mn10300_reg_fetch
;
303 CPU_REG_STORE (cpu
) = mn10300_reg_store
;
304 CPU_PC_FETCH (cpu
) = mn10300_pc_get
;
305 CPU_PC_STORE (cpu
) = mn10300_pc_set
;
312 sim_create_inferior (SIM_DESC sd
,
313 struct bfd
*prog_bfd
,
317 memset (&State
, 0, sizeof (State
));
318 if (prog_bfd
!= NULL
) {
319 PC
= bfd_get_start_address (prog_bfd
);
323 CPU_PC_SET (STATE_CPU (sd
, 0), (unsigned64
) PC
);
325 if (STATE_ARCHITECTURE (sd
)->mach
== bfd_mach_am33_2
)
331 /* FIXME These would more efficient to use than load_mem/store_mem,
332 but need to be changed to use the memory map. */
335 mn10300_reg_fetch (SIM_CPU
*cpu
, int rn
, unsigned char *memory
, int length
)
337 reg_t reg
= State
.regs
[rn
];
347 mn10300_reg_store (SIM_CPU
*cpu
, int rn
, unsigned char *memory
, int length
)
350 State
.regs
[rn
] = (a
[3] << 24) + (a
[2] << 16) + (a
[1] << 8) + a
[0];
355 mn10300_core_signal (SIM_DESC sd
,
361 transfer_type transfer
,
362 sim_core_signals sig
)
364 const char *copy
= (transfer
== read_transfer
? "read" : "write");
365 address_word ip
= CIA_ADDR (cia
);
369 case sim_core_unmapped_signal
:
370 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
372 (unsigned long) addr
, (unsigned long) ip
);
373 program_interrupt(sd
, cpu
, cia
, SIM_SIGSEGV
);
376 case sim_core_unaligned_signal
:
377 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
379 (unsigned long) addr
, (unsigned long) ip
);
380 program_interrupt(sd
, cpu
, cia
, SIM_SIGBUS
);
384 sim_engine_abort (sd
, cpu
, cia
,
385 "mn10300_core_signal - internal error - bad switch");
391 program_interrupt (SIM_DESC sd
,
398 static int in_interrupt
= 0;
400 #ifdef SIM_CPU_EXCEPTION_TRIGGER
401 SIM_CPU_EXCEPTION_TRIGGER(sd
,cpu
,cia
);
404 /* avoid infinite recursion */
406 sim_io_printf (sd
, "ERROR: recursion in program_interrupt during software exception dispatch.");
410 /* copy NMI handler code from dv-mn103cpu.c */
411 store_word (SP
- 4, CPU_PC_GET (cpu
));
412 store_half (SP
- 8, PSW
);
414 /* Set the SYSEF flag in NMICR by backdoor method. See
415 dv-mn103int.c:write_icr(). This is necessary because
416 software exceptions are not modelled by actually talking to
417 the interrupt controller, so it cannot set its own SYSEF
419 if ((NULL
!= board
) && (strcmp(board
, BOARD_AM32
) == 0))
420 store_byte (0x34000103, 0x04);
425 CPU_PC_SET (cpu
, 0x40000008);
428 sim_engine_halt(sd
, cpu
, NULL
, cia
, sim_stopped
, sig
);
433 mn10300_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
437 if(State
.exc_suspended
> 0)
438 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", State
.exc_suspended
);
440 CPU_PC_SET (cpu
, cia
);
441 memcpy(State
.exc_trigger_regs
, State
.regs
, sizeof(State
.exc_trigger_regs
));
442 State
.exc_suspended
= 0;
446 mn10300_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
450 if(State
.exc_suspended
> 0)
451 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
452 State
.exc_suspended
, exception
);
454 memcpy(State
.exc_suspend_regs
, State
.regs
, sizeof(State
.exc_suspend_regs
));
455 memcpy(State
.regs
, State
.exc_trigger_regs
, sizeof(State
.regs
));
456 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
457 State
.exc_suspended
= exception
;
461 mn10300_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
465 if(exception
== 0 && State
.exc_suspended
> 0)
467 if(State
.exc_suspended
!= SIGTRAP
) /* warn not for breakpoints */
468 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
469 State
.exc_suspended
);
471 else if(exception
!= 0 && State
.exc_suspended
> 0)
473 if(exception
!= State
.exc_suspended
)
474 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
475 State
.exc_suspended
, exception
);
477 memcpy(State
.regs
, State
.exc_suspend_regs
, sizeof(State
.regs
));
478 CPU_PC_SET (cpu
, PC
); /* copy PC back from new State.regs */
480 else if(exception
!= 0 && State
.exc_suspended
== 0)
482 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
484 State
.exc_suspended
= 0;
487 /* This is called when an FP instruction is issued when the FP unit is
488 disabled, i.e., the FE bit of PSW is zero. It raises interrupt
491 fpu_disabled_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
493 sim_io_eprintf(sd
, "FPU disabled exception\n");
494 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
497 /* This is called when the FP unit is enabled but one of the
498 unimplemented insns is issued. It raises interrupt code 0x1c8. */
500 fpu_unimp_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
502 sim_io_eprintf(sd
, "Unimplemented FPU instruction exception\n");
503 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
506 /* This is called at the end of any FP insns that may have triggered
507 FP exceptions. If no exception is enabled, it returns immediately.
508 Otherwise, it raises an exception code 0x1d0. */
510 fpu_check_signal_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
512 if ((FPCR
& EC_MASK
) == 0)
515 sim_io_eprintf(sd
, "FPU %s%s%s%s%s exception\n",
516 (FPCR
& EC_V
) ? "V" : "",
517 (FPCR
& EC_Z
) ? "Z" : "",
518 (FPCR
& EC_O
) ? "O" : "",
519 (FPCR
& EC_U
) ? "U" : "",
520 (FPCR
& EC_I
) ? "I" : "");
521 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
524 /* Convert a 32-bit single-precision FP value in the target platform
525 format to a sim_fpu value. */
527 reg2val_32 (const void *reg
, sim_fpu
*val
)
529 FS2FPU (*(reg_t
*)reg
, *val
);
532 /* Round the given sim_fpu value to single precision, following the
533 target platform rounding and denormalization conventions. On
534 AM33/2.0, round_near is the only rounding mode. */
536 round_32 (sim_fpu
*val
)
538 return sim_fpu_round_32 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
541 /* Convert a sim_fpu value to the 32-bit single-precision target
544 val2reg_32 (const sim_fpu
*val
, void *reg
)
546 FPU2FS (*val
, *(reg_t
*)reg
);
549 /* Define the 32-bit single-precision conversion and rounding uniform
551 const struct fp_prec_t
553 reg2val_32
, round_32
, val2reg_32
556 /* Convert a 64-bit double-precision FP value in the target platform
557 format to a sim_fpu value. */
559 reg2val_64 (const void *reg
, sim_fpu
*val
)
561 FD2FPU (*(dword
*)reg
, *val
);
564 /* Round the given sim_fpu value to double precision, following the
565 target platform rounding and denormalization conventions. On
566 AM33/2.0, round_near is the only rounding mode. */
568 round_64 (sim_fpu
*val
)
570 return sim_fpu_round_64 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
573 /* Convert a sim_fpu value to the 64-bit double-precision target
576 val2reg_64 (const sim_fpu
*val
, void *reg
)
578 FPU2FD (*val
, *(dword
*)reg
);
581 /* Define the 64-bit single-precision conversion and rounding uniform
583 const struct fp_prec_t
585 reg2val_64
, round_64
, val2reg_64
588 /* Define shortcuts to the uniform interface operations. */
589 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
590 #define ROUND(val) (*ops->round) (val)
591 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
593 /* Check whether overflow, underflow or inexact exceptions should be
596 fpu_status_ok (sim_fpu_status stat
)
598 if ((stat
& sim_fpu_status_overflow
)
601 else if ((stat
& (sim_fpu_status_underflow
| sim_fpu_status_denorm
))
604 else if ((stat
& (sim_fpu_status_inexact
| sim_fpu_status_rounded
))
607 else if (stat
& ~ (sim_fpu_status_overflow
608 | sim_fpu_status_underflow
609 | sim_fpu_status_denorm
610 | sim_fpu_status_inexact
611 | sim_fpu_status_rounded
))
618 /* Implement a 32/64 bit reciprocal square root, signaling FP
619 exceptions when appropriate. */
621 fpu_rsqrt (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
622 const void *reg_in
, void *reg_out
, const struct fp_prec_t
*ops
)
624 sim_fpu in
, med
, out
;
626 REG2VAL (reg_in
, &in
);
629 switch (sim_fpu_is (&in
))
631 case SIM_FPU_IS_SNAN
:
632 case SIM_FPU_IS_NNUMBER
:
633 case SIM_FPU_IS_NINF
:
637 VAL2REG (&sim_fpu_qnan
, reg_out
);
640 case SIM_FPU_IS_QNAN
:
641 VAL2REG (&sim_fpu_qnan
, reg_out
);
644 case SIM_FPU_IS_PINF
:
645 VAL2REG (&sim_fpu_zero
, reg_out
);
648 case SIM_FPU_IS_PNUMBER
:
650 /* Since we don't have a function to compute rsqrt directly,
652 sim_fpu_status stat
= 0;
653 stat
|= sim_fpu_sqrt (&med
, &in
);
654 stat
|= sim_fpu_inv (&out
, &med
);
655 stat
|= ROUND (&out
);
656 if (fpu_status_ok (stat
))
657 VAL2REG (&out
, reg_out
);
661 case SIM_FPU_IS_NZERO
:
662 case SIM_FPU_IS_PZERO
:
667 /* Generate an INF with the same sign. */
668 sim_fpu_inv (&out
, &in
);
669 VAL2REG (&out
, reg_out
);
677 fpu_check_signal_exception (sd
, cpu
, cia
);
685 case SIM_FPU_IS_SNAN
:
686 case SIM_FPU_IS_QNAN
:
689 case SIM_FPU_IS_NINF
:
690 case SIM_FPU_IS_NNUMBER
:
691 case SIM_FPU_IS_NDENORM
:
694 case SIM_FPU_IS_PINF
:
695 case SIM_FPU_IS_PNUMBER
:
696 case SIM_FPU_IS_PDENORM
:
699 case SIM_FPU_IS_NZERO
:
700 case SIM_FPU_IS_PZERO
:
708 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
709 exception bits as specified. */
711 fpu_cmp (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
712 const void *reg_in1
, const void *reg_in2
,
713 const struct fp_prec_t
*ops
)
717 REG2VAL (reg_in1
, &m
);
718 REG2VAL (reg_in2
, &n
);
723 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
))
731 FPCR
|= cmp2fcc (sim_fpu_cmp (&m
, &n
));
733 fpu_check_signal_exception (sd
, cpu
, cia
);
736 /* Implement a 32/64 bit FP add, setting FP exception bits when
739 fpu_add (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
740 const void *reg_in1
, const void *reg_in2
,
741 void *reg_out
, const struct fp_prec_t
*ops
)
745 REG2VAL (reg_in1
, &m
);
746 REG2VAL (reg_in2
, &n
);
750 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
751 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
752 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
)
753 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
754 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
))
759 VAL2REG (&sim_fpu_qnan
, reg_out
);
763 sim_fpu_status stat
= sim_fpu_add (&r
, &m
, &n
);
765 if (fpu_status_ok (stat
))
766 VAL2REG (&r
, reg_out
);
769 fpu_check_signal_exception (sd
, cpu
, cia
);
772 /* Implement a 32/64 bit FP sub, setting FP exception bits when
775 fpu_sub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
776 const void *reg_in1
, const void *reg_in2
,
777 void *reg_out
, const struct fp_prec_t
*ops
)
781 REG2VAL (reg_in1
, &m
);
782 REG2VAL (reg_in2
, &n
);
786 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
787 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
788 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
)
789 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
790 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
))
795 VAL2REG (&sim_fpu_qnan
, reg_out
);
799 sim_fpu_status stat
= sim_fpu_sub (&r
, &m
, &n
);
801 if (fpu_status_ok (stat
))
802 VAL2REG (&r
, reg_out
);
805 fpu_check_signal_exception (sd
, cpu
, cia
);
808 /* Implement a 32/64 bit FP mul, setting FP exception bits when
811 fpu_mul (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
812 const void *reg_in1
, const void *reg_in2
,
813 void *reg_out
, const struct fp_prec_t
*ops
)
817 REG2VAL (reg_in1
, &m
);
818 REG2VAL (reg_in2
, &n
);
822 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
823 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_zero (&n
))
824 || (sim_fpu_is_zero (&m
) && sim_fpu_is_infinity (&n
)))
829 VAL2REG (&sim_fpu_qnan
, reg_out
);
833 sim_fpu_status stat
= sim_fpu_mul (&r
, &m
, &n
);
835 if (fpu_status_ok (stat
))
836 VAL2REG (&r
, reg_out
);
839 fpu_check_signal_exception (sd
, cpu
, cia
);
842 /* Implement a 32/64 bit FP div, setting FP exception bits when
845 fpu_div (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
846 const void *reg_in1
, const void *reg_in2
,
847 void *reg_out
, const struct fp_prec_t
*ops
)
851 REG2VAL (reg_in1
, &m
);
852 REG2VAL (reg_in2
, &n
);
856 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
857 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
))
858 || (sim_fpu_is_zero (&m
) && sim_fpu_is_zero (&n
)))
863 VAL2REG (&sim_fpu_qnan
, reg_out
);
865 else if (sim_fpu_is_number (&m
) && sim_fpu_is_zero (&n
)
870 sim_fpu_status stat
= sim_fpu_div (&r
, &m
, &n
);
872 if (fpu_status_ok (stat
))
873 VAL2REG (&r
, reg_out
);
876 fpu_check_signal_exception (sd
, cpu
, cia
);
879 /* Implement a 32/64 bit FP madd, setting FP exception bits when
882 fpu_fmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
883 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
884 void *reg_out
, const struct fp_prec_t
*ops
)
886 sim_fpu m1
, m2
, m
, n
, r
;
888 REG2VAL (reg_in1
, &m1
);
889 REG2VAL (reg_in2
, &m2
);
890 REG2VAL (reg_in3
, &n
);
895 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
896 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
897 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
903 VAL2REG (&sim_fpu_qnan
, reg_out
);
907 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
909 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
910 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
911 goto invalid_operands
;
913 stat
|= sim_fpu_add (&r
, &m
, &n
);
915 if (fpu_status_ok (stat
))
916 VAL2REG (&r
, reg_out
);
919 fpu_check_signal_exception (sd
, cpu
, cia
);
922 /* Implement a 32/64 bit FP msub, setting FP exception bits when
925 fpu_fmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
926 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
927 void *reg_out
, const struct fp_prec_t
*ops
)
929 sim_fpu m1
, m2
, m
, n
, r
;
931 REG2VAL (reg_in1
, &m1
);
932 REG2VAL (reg_in2
, &m2
);
933 REG2VAL (reg_in3
, &n
);
938 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
939 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
940 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
946 VAL2REG (&sim_fpu_qnan
, reg_out
);
950 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
952 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
953 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
954 goto invalid_operands
;
956 stat
|= sim_fpu_sub (&r
, &m
, &n
);
958 if (fpu_status_ok (stat
))
959 VAL2REG (&r
, reg_out
);
962 fpu_check_signal_exception (sd
, cpu
, cia
);
965 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
968 fpu_fnmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
969 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
970 void *reg_out
, const struct fp_prec_t
*ops
)
972 sim_fpu m1
, m2
, m
, mm
, n
, r
;
974 REG2VAL (reg_in1
, &m1
);
975 REG2VAL (reg_in2
, &m2
);
976 REG2VAL (reg_in3
, &n
);
981 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
982 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
983 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
989 VAL2REG (&sim_fpu_qnan
, reg_out
);
993 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
995 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
996 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
997 goto invalid_operands
;
999 stat
|= sim_fpu_neg (&mm
, &m
);
1000 stat
|= sim_fpu_add (&r
, &mm
, &n
);
1002 if (fpu_status_ok (stat
))
1003 VAL2REG (&r
, reg_out
);
1006 fpu_check_signal_exception (sd
, cpu
, cia
);
1009 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1012 fpu_fnmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1013 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1014 void *reg_out
, const struct fp_prec_t
*ops
)
1016 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1018 REG2VAL (reg_in1
, &m1
);
1019 REG2VAL (reg_in2
, &m2
);
1020 REG2VAL (reg_in3
, &n
);
1025 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1026 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1027 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1033 VAL2REG (&sim_fpu_qnan
, reg_out
);
1037 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1039 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1040 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
1041 goto invalid_operands
;
1043 stat
|= sim_fpu_neg (&mm
, &m
);
1044 stat
|= sim_fpu_sub (&r
, &mm
, &n
);
1046 if (fpu_status_ok (stat
))
1047 VAL2REG (&r
, reg_out
);
1050 fpu_check_signal_exception (sd
, cpu
, cia
);