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 */
87 /* These default values correspond to expected usage for the chip. */
90 sim_open (SIM_OPEN_KIND kind
,
95 SIM_DESC sd
= sim_state_alloc (kind
, cb
);
96 mn10300_callback
= cb
;
98 SIM_ASSERT (STATE_MAGIC (sd
) == SIM_MAGIC_NUMBER
);
100 /* for compatibility */
103 /* FIXME: should be better way of setting up interrupts. For
104 moment, only support watchpoints causing a breakpoint (gdb
106 STATE_WATCHPOINTS (sd
)->pc
= &(PC
);
107 STATE_WATCHPOINTS (sd
)->sizeof_pc
= sizeof (PC
);
108 STATE_WATCHPOINTS (sd
)->interrupt_handler
= NULL
;
109 STATE_WATCHPOINTS (sd
)->interrupt_names
= NULL
;
111 if (sim_pre_argv_init (sd
, argv
[0]) != SIM_RC_OK
)
113 sim_add_option_table (sd
, NULL
, mn10300_options
);
115 /* Allocate core managed memory */
116 sim_do_command (sd
, "memory region 0,0x100000");
117 sim_do_command (sd
, "memory region 0x40000000,0x200000");
119 /* getopt will print the error message so we just have to exit if this fails.
120 FIXME: Hmmm... in the case of gdb we need getopt to call
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
,
271 (STATE_PROG_ARGV (sd
) != NULL
272 ? *STATE_PROG_ARGV (sd
)
276 sim_module_uninstall (sd
);
280 /* establish any remaining configuration options */
281 if (sim_config (sd
) != SIM_RC_OK
)
283 sim_module_uninstall (sd
);
287 if (sim_post_argv_init (sd
) != SIM_RC_OK
)
289 /* Uninstall the modules to avoid memory leaks,
290 file descriptor leaks, etc. */
291 sim_module_uninstall (sd
);
296 /* set machine specific configuration */
297 /* STATE_CPU (sd, 0)->psw_mask = (PSW_NP | PSW_EP | PSW_ID | PSW_SAT */
298 /* | PSW_CY | PSW_OV | PSW_S | PSW_Z); */
305 sim_close (SIM_DESC sd
, int quitting
)
307 sim_module_uninstall (sd
);
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 CIA_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. */
344 return (a
[1] << 8) + (a
[0]);
351 return (a
[3]<<24) + (a
[2]<<16) + (a
[1]<<8) + (a
[0]);
355 put_byte (uint8
*addr
, uint8 data
)
362 put_half (uint8
*addr
, uint16 data
)
366 a
[1] = (data
>> 8) & 0xff;
370 put_word (uint8
*addr
, uint32 data
)
374 a
[1] = (data
>> 8) & 0xff;
375 a
[2] = (data
>> 16) & 0xff;
376 a
[3] = (data
>> 24) & 0xff;
380 sim_fetch_register (SIM_DESC sd
,
382 unsigned char *memory
,
385 put_word (memory
, State
.regs
[rn
]);
390 sim_store_register (SIM_DESC sd
,
392 unsigned char *memory
,
395 State
.regs
[rn
] = get_word (memory
);
401 mn10300_core_signal (SIM_DESC sd
,
407 transfer_type transfer
,
408 sim_core_signals sig
)
410 const char *copy
= (transfer
== read_transfer
? "read" : "write");
411 address_word ip
= CIA_ADDR (cia
);
415 case sim_core_unmapped_signal
:
416 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n",
418 (unsigned long) addr
, (unsigned long) ip
);
419 program_interrupt(sd
, cpu
, cia
, SIM_SIGSEGV
);
422 case sim_core_unaligned_signal
:
423 sim_io_eprintf (sd
, "mn10300-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n",
425 (unsigned long) addr
, (unsigned long) ip
);
426 program_interrupt(sd
, cpu
, cia
, SIM_SIGBUS
);
430 sim_engine_abort (sd
, cpu
, cia
,
431 "mn10300_core_signal - internal error - bad switch");
437 program_interrupt (SIM_DESC sd
,
444 static int in_interrupt
= 0;
446 #ifdef SIM_CPU_EXCEPTION_TRIGGER
447 SIM_CPU_EXCEPTION_TRIGGER(sd
,cpu
,cia
);
450 /* avoid infinite recursion */
453 (*mn10300_callback
->printf_filtered
) (mn10300_callback
,
454 "ERROR: recursion in program_interrupt during software exception dispatch.");
459 /* copy NMI handler code from dv-mn103cpu.c */
460 store_word (SP
- 4, CIA_GET (cpu
));
461 store_half (SP
- 8, PSW
);
463 /* Set the SYSEF flag in NMICR by backdoor method. See
464 dv-mn103int.c:write_icr(). This is necessary because
465 software exceptions are not modelled by actually talking to
466 the interrupt controller, so it cannot set its own SYSEF
468 if ((NULL
!= board
) && (strcmp(board
, BOARD_AM32
) == 0))
469 store_byte (0x34000103, 0x04);
474 CIA_SET (cpu
, 0x40000008);
477 sim_engine_halt(sd
, cpu
, NULL
, cia
, sim_stopped
, sig
);
482 mn10300_cpu_exception_trigger(SIM_DESC sd
, sim_cpu
* cpu
, address_word cia
)
486 if(State
.exc_suspended
> 0)
487 sim_io_eprintf(sd
, "Warning, nested exception triggered (%d)\n", State
.exc_suspended
);
490 memcpy(State
.exc_trigger_regs
, State
.regs
, sizeof(State
.exc_trigger_regs
));
491 State
.exc_suspended
= 0;
495 mn10300_cpu_exception_suspend(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
499 if(State
.exc_suspended
> 0)
500 sim_io_eprintf(sd
, "Warning, nested exception signal (%d then %d)\n",
501 State
.exc_suspended
, exception
);
503 memcpy(State
.exc_suspend_regs
, State
.regs
, sizeof(State
.exc_suspend_regs
));
504 memcpy(State
.regs
, State
.exc_trigger_regs
, sizeof(State
.regs
));
505 CIA_SET (cpu
, PC
); /* copy PC back from new State.regs */
506 State
.exc_suspended
= exception
;
510 mn10300_cpu_exception_resume(SIM_DESC sd
, sim_cpu
* cpu
, int exception
)
514 if(exception
== 0 && State
.exc_suspended
> 0)
516 if(State
.exc_suspended
!= SIGTRAP
) /* warn not for breakpoints */
517 sim_io_eprintf(sd
, "Warning, resuming but ignoring pending exception signal (%d)\n",
518 State
.exc_suspended
);
520 else if(exception
!= 0 && State
.exc_suspended
> 0)
522 if(exception
!= State
.exc_suspended
)
523 sim_io_eprintf(sd
, "Warning, resuming with mismatched exception signal (%d vs %d)\n",
524 State
.exc_suspended
, exception
);
526 memcpy(State
.regs
, State
.exc_suspend_regs
, sizeof(State
.regs
));
527 CIA_SET (cpu
, PC
); /* copy PC back from new State.regs */
529 else if(exception
!= 0 && State
.exc_suspended
== 0)
531 sim_io_eprintf(sd
, "Warning, ignoring spontanous exception signal (%d)\n", exception
);
533 State
.exc_suspended
= 0;
536 /* This is called when an FP instruction is issued when the FP unit is
537 disabled, i.e., the FE bit of PSW is zero. It raises interrupt
540 fpu_disabled_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
542 sim_io_eprintf(sd
, "FPU disabled exception\n");
543 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
546 /* This is called when the FP unit is enabled but one of the
547 unimplemented insns is issued. It raises interrupt code 0x1c8. */
549 fpu_unimp_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
551 sim_io_eprintf(sd
, "Unimplemented FPU instruction exception\n");
552 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
555 /* This is called at the end of any FP insns that may have triggered
556 FP exceptions. If no exception is enabled, it returns immediately.
557 Otherwise, it raises an exception code 0x1d0. */
559 fpu_check_signal_exception (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
)
561 if ((FPCR
& EC_MASK
) == 0)
564 sim_io_eprintf(sd
, "FPU %s%s%s%s%s exception\n",
565 (FPCR
& EC_V
) ? "V" : "",
566 (FPCR
& EC_Z
) ? "Z" : "",
567 (FPCR
& EC_O
) ? "O" : "",
568 (FPCR
& EC_U
) ? "U" : "",
569 (FPCR
& EC_I
) ? "I" : "");
570 program_interrupt (sd
, cpu
, cia
, SIM_SIGFPE
);
573 /* Convert a 32-bit single-precision FP value in the target platform
574 format to a sim_fpu value. */
576 reg2val_32 (const void *reg
, sim_fpu
*val
)
578 FS2FPU (*(reg_t
*)reg
, *val
);
581 /* Round the given sim_fpu value to single precision, following the
582 target platform rounding and denormalization conventions. On
583 AM33/2.0, round_near is the only rounding mode. */
585 round_32 (sim_fpu
*val
)
587 return sim_fpu_round_32 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
590 /* Convert a sim_fpu value to the 32-bit single-precision target
593 val2reg_32 (const sim_fpu
*val
, void *reg
)
595 FPU2FS (*val
, *(reg_t
*)reg
);
598 /* Define the 32-bit single-precision conversion and rounding uniform
600 const struct fp_prec_t
602 reg2val_32
, round_32
, val2reg_32
605 /* Convert a 64-bit double-precision FP value in the target platform
606 format to a sim_fpu value. */
608 reg2val_64 (const void *reg
, sim_fpu
*val
)
610 FD2FPU (*(dword
*)reg
, *val
);
613 /* Round the given sim_fpu value to double precision, following the
614 target platform rounding and denormalization conventions. On
615 AM33/2.0, round_near is the only rounding mode. */
617 round_64 (sim_fpu
*val
)
619 return sim_fpu_round_64 (val
, sim_fpu_round_near
, sim_fpu_denorm_zero
);
622 /* Convert a sim_fpu value to the 64-bit double-precision target
625 val2reg_64 (const sim_fpu
*val
, void *reg
)
627 FPU2FD (*val
, *(dword
*)reg
);
630 /* Define the 64-bit single-precision conversion and rounding uniform
632 const struct fp_prec_t
634 reg2val_64
, round_64
, val2reg_64
637 /* Define shortcuts to the uniform interface operations. */
638 #define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
639 #define ROUND(val) (*ops->round) (val)
640 #define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
642 /* Check whether overflow, underflow or inexact exceptions should be
645 fpu_status_ok (sim_fpu_status stat
)
647 if ((stat
& sim_fpu_status_overflow
)
650 else if ((stat
& (sim_fpu_status_underflow
| sim_fpu_status_denorm
))
653 else if ((stat
& (sim_fpu_status_inexact
| sim_fpu_status_rounded
))
656 else if (stat
& ~ (sim_fpu_status_overflow
657 | sim_fpu_status_underflow
658 | sim_fpu_status_denorm
659 | sim_fpu_status_inexact
660 | sim_fpu_status_rounded
))
667 /* Implement a 32/64 bit reciprocal square root, signaling FP
668 exceptions when appropriate. */
670 fpu_rsqrt (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
671 const void *reg_in
, void *reg_out
, const struct fp_prec_t
*ops
)
673 sim_fpu in
, med
, out
;
675 REG2VAL (reg_in
, &in
);
678 switch (sim_fpu_is (&in
))
680 case SIM_FPU_IS_SNAN
:
681 case SIM_FPU_IS_NNUMBER
:
682 case SIM_FPU_IS_NINF
:
686 VAL2REG (&sim_fpu_qnan
, reg_out
);
689 case SIM_FPU_IS_QNAN
:
690 VAL2REG (&sim_fpu_qnan
, reg_out
);
693 case SIM_FPU_IS_PINF
:
694 VAL2REG (&sim_fpu_zero
, reg_out
);
697 case SIM_FPU_IS_PNUMBER
:
699 /* Since we don't have a function to compute rsqrt directly,
701 sim_fpu_status stat
= 0;
702 stat
|= sim_fpu_sqrt (&med
, &in
);
703 stat
|= sim_fpu_inv (&out
, &med
);
704 stat
|= ROUND (&out
);
705 if (fpu_status_ok (stat
))
706 VAL2REG (&out
, reg_out
);
710 case SIM_FPU_IS_NZERO
:
711 case SIM_FPU_IS_PZERO
:
716 /* Generate an INF with the same sign. */
717 sim_fpu_inv (&out
, &in
);
718 VAL2REG (&out
, reg_out
);
726 fpu_check_signal_exception (sd
, cpu
, cia
);
734 case SIM_FPU_IS_SNAN
:
735 case SIM_FPU_IS_QNAN
:
738 case SIM_FPU_IS_NINF
:
739 case SIM_FPU_IS_NNUMBER
:
740 case SIM_FPU_IS_NDENORM
:
743 case SIM_FPU_IS_PINF
:
744 case SIM_FPU_IS_PNUMBER
:
745 case SIM_FPU_IS_PDENORM
:
748 case SIM_FPU_IS_NZERO
:
749 case SIM_FPU_IS_PZERO
:
757 /* Implement a 32/64 bit FP compare, setting the FPCR status and/or
758 exception bits as specified. */
760 fpu_cmp (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
761 const void *reg_in1
, const void *reg_in2
,
762 const struct fp_prec_t
*ops
)
766 REG2VAL (reg_in1
, &m
);
767 REG2VAL (reg_in2
, &n
);
772 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
))
780 FPCR
|= cmp2fcc (sim_fpu_cmp (&m
, &n
));
782 fpu_check_signal_exception (sd
, cpu
, cia
);
785 /* Implement a 32/64 bit FP add, setting FP exception bits when
788 fpu_add (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
789 const void *reg_in1
, const void *reg_in2
,
790 void *reg_out
, const struct fp_prec_t
*ops
)
794 REG2VAL (reg_in1
, &m
);
795 REG2VAL (reg_in2
, &n
);
799 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
800 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
801 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
)
802 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
803 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
))
808 VAL2REG (&sim_fpu_qnan
, reg_out
);
812 sim_fpu_status stat
= sim_fpu_add (&r
, &m
, &n
);
814 if (fpu_status_ok (stat
))
815 VAL2REG (&r
, reg_out
);
818 fpu_check_signal_exception (sd
, cpu
, cia
);
821 /* Implement a 32/64 bit FP sub, setting FP exception bits when
824 fpu_sub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
825 const void *reg_in1
, const void *reg_in2
,
826 void *reg_out
, const struct fp_prec_t
*ops
)
830 REG2VAL (reg_in1
, &m
);
831 REG2VAL (reg_in2
, &n
);
835 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
836 || (sim_fpu_is (&m
) == SIM_FPU_IS_PINF
837 && sim_fpu_is (&n
) == SIM_FPU_IS_PINF
)
838 || (sim_fpu_is (&m
) == SIM_FPU_IS_NINF
839 && sim_fpu_is (&n
) == SIM_FPU_IS_NINF
))
844 VAL2REG (&sim_fpu_qnan
, reg_out
);
848 sim_fpu_status stat
= sim_fpu_sub (&r
, &m
, &n
);
850 if (fpu_status_ok (stat
))
851 VAL2REG (&r
, reg_out
);
854 fpu_check_signal_exception (sd
, cpu
, cia
);
857 /* Implement a 32/64 bit FP mul, setting FP exception bits when
860 fpu_mul (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
861 const void *reg_in1
, const void *reg_in2
,
862 void *reg_out
, const struct fp_prec_t
*ops
)
866 REG2VAL (reg_in1
, &m
);
867 REG2VAL (reg_in2
, &n
);
871 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
872 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_zero (&n
))
873 || (sim_fpu_is_zero (&m
) && sim_fpu_is_infinity (&n
)))
878 VAL2REG (&sim_fpu_qnan
, reg_out
);
882 sim_fpu_status stat
= sim_fpu_mul (&r
, &m
, &n
);
884 if (fpu_status_ok (stat
))
885 VAL2REG (&r
, reg_out
);
888 fpu_check_signal_exception (sd
, cpu
, cia
);
891 /* Implement a 32/64 bit FP div, setting FP exception bits when
894 fpu_div (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
895 const void *reg_in1
, const void *reg_in2
,
896 void *reg_out
, const struct fp_prec_t
*ops
)
900 REG2VAL (reg_in1
, &m
);
901 REG2VAL (reg_in2
, &n
);
905 if (sim_fpu_is_snan (&m
) || sim_fpu_is_snan (&n
)
906 || (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
))
907 || (sim_fpu_is_zero (&m
) && sim_fpu_is_zero (&n
)))
912 VAL2REG (&sim_fpu_qnan
, reg_out
);
914 else if (sim_fpu_is_number (&m
) && sim_fpu_is_zero (&n
)
919 sim_fpu_status stat
= sim_fpu_div (&r
, &m
, &n
);
921 if (fpu_status_ok (stat
))
922 VAL2REG (&r
, reg_out
);
925 fpu_check_signal_exception (sd
, cpu
, cia
);
928 /* Implement a 32/64 bit FP madd, setting FP exception bits when
931 fpu_fmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
932 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
933 void *reg_out
, const struct fp_prec_t
*ops
)
935 sim_fpu m1
, m2
, m
, n
, r
;
937 REG2VAL (reg_in1
, &m1
);
938 REG2VAL (reg_in2
, &m2
);
939 REG2VAL (reg_in3
, &n
);
944 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
945 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
946 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
952 VAL2REG (&sim_fpu_qnan
, reg_out
);
956 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
958 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
959 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
960 goto invalid_operands
;
962 stat
|= sim_fpu_add (&r
, &m
, &n
);
964 if (fpu_status_ok (stat
))
965 VAL2REG (&r
, reg_out
);
968 fpu_check_signal_exception (sd
, cpu
, cia
);
971 /* Implement a 32/64 bit FP msub, setting FP exception bits when
974 fpu_fmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
975 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
976 void *reg_out
, const struct fp_prec_t
*ops
)
978 sim_fpu m1
, m2
, m
, n
, r
;
980 REG2VAL (reg_in1
, &m1
);
981 REG2VAL (reg_in2
, &m2
);
982 REG2VAL (reg_in3
, &n
);
987 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
988 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
989 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
995 VAL2REG (&sim_fpu_qnan
, reg_out
);
999 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1001 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1002 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
1003 goto invalid_operands
;
1005 stat
|= sim_fpu_sub (&r
, &m
, &n
);
1007 if (fpu_status_ok (stat
))
1008 VAL2REG (&r
, reg_out
);
1011 fpu_check_signal_exception (sd
, cpu
, cia
);
1014 /* Implement a 32/64 bit FP nmadd, setting FP exception bits when
1017 fpu_fnmadd (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1018 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1019 void *reg_out
, const struct fp_prec_t
*ops
)
1021 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1023 REG2VAL (reg_in1
, &m1
);
1024 REG2VAL (reg_in2
, &m2
);
1025 REG2VAL (reg_in3
, &n
);
1030 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1031 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1032 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1038 VAL2REG (&sim_fpu_qnan
, reg_out
);
1042 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1044 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1045 && sim_fpu_sign (&m
) == sim_fpu_sign (&n
))
1046 goto invalid_operands
;
1048 stat
|= sim_fpu_neg (&mm
, &m
);
1049 stat
|= sim_fpu_add (&r
, &mm
, &n
);
1051 if (fpu_status_ok (stat
))
1052 VAL2REG (&r
, reg_out
);
1055 fpu_check_signal_exception (sd
, cpu
, cia
);
1058 /* Implement a 32/64 bit FP nmsub, setting FP exception bits when
1061 fpu_fnmsub (SIM_DESC sd
, sim_cpu
*cpu
, sim_cia cia
,
1062 const void *reg_in1
, const void *reg_in2
, const void *reg_in3
,
1063 void *reg_out
, const struct fp_prec_t
*ops
)
1065 sim_fpu m1
, m2
, m
, mm
, n
, r
;
1067 REG2VAL (reg_in1
, &m1
);
1068 REG2VAL (reg_in2
, &m2
);
1069 REG2VAL (reg_in3
, &n
);
1074 if (sim_fpu_is_snan (&m1
) || sim_fpu_is_snan (&m2
) || sim_fpu_is_snan (&n
)
1075 || (sim_fpu_is_infinity (&m1
) && sim_fpu_is_zero (&m2
))
1076 || (sim_fpu_is_zero (&m1
) && sim_fpu_is_infinity (&m2
)))
1082 VAL2REG (&sim_fpu_qnan
, reg_out
);
1086 sim_fpu_status stat
= sim_fpu_mul (&m
, &m1
, &m2
);
1088 if (sim_fpu_is_infinity (&m
) && sim_fpu_is_infinity (&n
)
1089 && sim_fpu_sign (&m
) != sim_fpu_sign (&n
))
1090 goto invalid_operands
;
1092 stat
|= sim_fpu_neg (&mm
, &m
);
1093 stat
|= sim_fpu_sub (&r
, &mm
, &n
);
1095 if (fpu_status_ok (stat
))
1096 VAL2REG (&r
, reg_out
);
1099 fpu_check_signal_exception (sd
, cpu
, cia
);