2000-08-07 Graham Stott <grahams@cygnus.co.uk>
* am33-2.igen (fmadd, fmsub, fmnadd, fmnsub): Correct typo. 2000-05-29 Alexandre Oliva <aoliva@cygnus.com> * interp.c (fpu_disabled_exception, fpu_unimp_exception, fpu_check_signal_exception): Take additional state arguments. Print exception type and call program_interrupt. Adjust callers. (fpu_rsqrt, fpu_cmp, fpu_add, fpu_sub, fpu_mul, fpu_div, fpu_fmadd, fpu_fmsub, fpu_fnmadd, fpu_fnmsub): Take additional arguments. * mn10300_sim.h (fpu_disabled_exception, fpu_unimp_exception, fpu_check_signal_exception): Adjust prototypes. (fpu_rsqrt, fpu_cmp, fpu_add, fpu_sub, fpu_mul, fpu_div, fpu_fmadd, fpu_fmsub, fpu_fnmadd, fpu_fnmsub): Likewise. * am33-2.igen: Adjust calls. 2000-05-19 Alexandre Oliva <aoliva@cygnus.com> * op_utils.c (cmp2fcc): Moved... * interp.c: ... here. 2000-05-18 Alexandre Oliva <aoliva@cygnus.com> * am33-2.igen: Use `unsigned32', `signed32', `unsigned64' or `signed64' where type width is relevant. 2000-05-15 Alexandre Oliva <aoliva@cygnus.com> * mn10300_sim.h: Include sim-fpu.h. (FD2FPU, FPU2FD): Enclose the FD argument in parentheses. (fpu_check_signal_exception): Declare. (struct fp_prec_t, fp_single_prec, fp_double_prec): Likewise. (FP_SINGLE, FP_DOUBLE): Shorthands for fp_*_prec. (fpu_rsqrt, fpu_cmp, fpu_add, fpu_sub, fpu_mul, fpu_div, fpu_fmadd, fpu_fmsub, fpu_fnmadd, fpu_fnmsub): Declare. * interp.c (fpu_disabled_exception): Document. (fpu_unimp_exception): Likewise. (fpu_check_signal_exception): Define. (reg2val_32, round_32, val2reg_32, fp_single_prec): Likewise. (reg2val_64, round_64, val2reg_64, fp_double_prec): Likewise. (REG2VAL, ROUND, VAL2REG): Define shorthands. (fpu_status_ok): Define. (fpu_rsqrt, fpu_cmp, fpu_add, fpu_sub, fpu_mul, fpu_div, fpu_fmadd, fpu_fmsub, fpu_fnmadd, fpu_fnmsub): Define. * am33-2.igen (frsqrt, fcmp, fadd, fsub, fmul, fdiv, fmadd, fmsub, fnmadd, fnmsub): Use new functions. 2000-04-27 Alexandre Oliva <aoliva@cygnus.com> * interp.c (sim_create_inferior): Set PSW bit to enable FP insns if architecture is AM33/2.0. * am33.igen: Include am33-2.igen. 2000-04-23 Alexandre Oliva <aoliva@cygnus.com> * mn10300.igen (movm, call, ret, retf): Check for am33_2 too. * am33.igen (movm): Likewise. 2000-04-19 Alexandre Oliva <aoliva@cygnus.com> * am33.igen: Added `*am33_2' to some instructions that were missing it. 2000-04-07 Alexandre Oliva <aoliva@cygnus.com> * am33-2.igen: New file. All insns implemented, but FP flags are only set for fcmp, exceptional conditions are not handled yet. * Makefile.in (IGEN_INSN): Added am33-2.igen. (tmp-igen): Added -M am33_2. * mn10300.igen, am33.igen: Added `*am33_2' to all insns. * gencode.c: Support FMT_D3. * mn10300_sim.h (dword): New type. (struct _state): Added fpregs. (REG_FPCR, FPCR): New define. All assorted bitmaps. (XS2FS, AS2FS, Xf2FD): New macros. (FS2FPU, FD2FPU, FPU2FS, FPU2FD): Likewise. (load_dword, store_dword): New functions or macros. (u642dw, dw2u64): New functions. (fpu_disabled_exception, fpu_unimp_exception): Declared. * interp.c (fpu_disabled_exception): Defined; no actual implementation. (fpu_unimp_exception): Likewise. * op_utils.c (cmp2fcc): New function.
This commit is contained in:
parent
489503ee33
commit
c76b4bab30
@ -1,5 +1,74 @@
|
||||
2004-06-26 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
2000-08-07 Graham Stott <grahams@cygnus.co.uk>
|
||||
* am33-2.igen (fmadd, fmsub, fmnadd, fmnsub): Correct typo.
|
||||
2000-05-29 Alexandre Oliva <aoliva@cygnus.com>
|
||||
* interp.c (fpu_disabled_exception, fpu_unimp_exception,
|
||||
fpu_check_signal_exception): Take additional state arguments.
|
||||
Print exception type and call program_interrupt. Adjust callers.
|
||||
(fpu_rsqrt, fpu_cmp, fpu_add, fpu_sub, fpu_mul, fpu_div,
|
||||
fpu_fmadd, fpu_fmsub, fpu_fnmadd, fpu_fnmsub): Take additional
|
||||
arguments.
|
||||
* mn10300_sim.h (fpu_disabled_exception, fpu_unimp_exception,
|
||||
fpu_check_signal_exception): Adjust prototypes.
|
||||
(fpu_rsqrt, fpu_cmp, fpu_add, fpu_sub, fpu_mul, fpu_div,
|
||||
fpu_fmadd, fpu_fmsub, fpu_fnmadd, fpu_fnmsub): Likewise.
|
||||
* am33-2.igen: Adjust calls.
|
||||
2000-05-19 Alexandre Oliva <aoliva@cygnus.com>
|
||||
* op_utils.c (cmp2fcc): Moved...
|
||||
* interp.c: ... here.
|
||||
2000-05-18 Alexandre Oliva <aoliva@cygnus.com>
|
||||
* am33-2.igen: Use `unsigned32', `signed32', `unsigned64' or
|
||||
`signed64' where type width is relevant.
|
||||
2000-05-15 Alexandre Oliva <aoliva@cygnus.com>
|
||||
* mn10300_sim.h: Include sim-fpu.h.
|
||||
(FD2FPU, FPU2FD): Enclose the FD argument in parentheses.
|
||||
(fpu_check_signal_exception): Declare.
|
||||
(struct fp_prec_t, fp_single_prec, fp_double_prec): Likewise.
|
||||
(FP_SINGLE, FP_DOUBLE): Shorthands for fp_*_prec.
|
||||
(fpu_rsqrt, fpu_cmp, fpu_add, fpu_sub, fpu_mul, fpu_div,
|
||||
fpu_fmadd, fpu_fmsub, fpu_fnmadd, fpu_fnmsub): Declare.
|
||||
* interp.c (fpu_disabled_exception): Document.
|
||||
(fpu_unimp_exception): Likewise.
|
||||
(fpu_check_signal_exception): Define.
|
||||
(reg2val_32, round_32, val2reg_32, fp_single_prec): Likewise.
|
||||
(reg2val_64, round_64, val2reg_64, fp_double_prec): Likewise.
|
||||
(REG2VAL, ROUND, VAL2REG): Define shorthands.
|
||||
(fpu_status_ok): Define.
|
||||
(fpu_rsqrt, fpu_cmp, fpu_add, fpu_sub, fpu_mul, fpu_div,
|
||||
fpu_fmadd, fpu_fmsub, fpu_fnmadd, fpu_fnmsub): Define.
|
||||
* am33-2.igen (frsqrt, fcmp, fadd, fsub, fmul, fdiv,
|
||||
fmadd, fmsub, fnmadd, fnmsub): Use new functions.
|
||||
2000-04-27 Alexandre Oliva <aoliva@cygnus.com>
|
||||
* interp.c (sim_create_inferior): Set PSW bit to enable FP insns
|
||||
if architecture is AM33/2.0.
|
||||
* am33.igen: Include am33-2.igen.
|
||||
2000-04-23 Alexandre Oliva <aoliva@cygnus.com>
|
||||
* mn10300.igen (movm, call, ret, retf): Check for am33_2 too.
|
||||
* am33.igen (movm): Likewise.
|
||||
2000-04-19 Alexandre Oliva <aoliva@cygnus.com>
|
||||
* am33.igen: Added `*am33_2' to some instructions that were
|
||||
missing it.
|
||||
2000-04-07 Alexandre Oliva <aoliva@cygnus.com>
|
||||
* am33-2.igen: New file. All insns implemented, but FP flags are
|
||||
only set for fcmp, exceptional conditions are not handled yet.
|
||||
* Makefile.in (IGEN_INSN): Added am33-2.igen.
|
||||
(tmp-igen): Added -M am33_2.
|
||||
* mn10300.igen, am33.igen: Added `*am33_2' to all insns.
|
||||
* gencode.c: Support FMT_D3.
|
||||
* mn10300_sim.h (dword): New type.
|
||||
(struct _state): Added fpregs.
|
||||
(REG_FPCR, FPCR): New define. All assorted bitmaps.
|
||||
(XS2FS, AS2FS, Xf2FD): New macros.
|
||||
(FS2FPU, FD2FPU, FPU2FS, FPU2FD): Likewise.
|
||||
(load_dword, store_dword): New functions or macros.
|
||||
(u642dw, dw2u64): New functions.
|
||||
(fpu_disabled_exception, fpu_unimp_exception): Declared.
|
||||
* interp.c (fpu_disabled_exception): Defined; no actual
|
||||
implementation.
|
||||
(fpu_unimp_exception): Likewise.
|
||||
* op_utils.c (cmp2fcc): New function.
|
||||
|
||||
* interp.c, mn10300_sim.h, op_utils.c: Convert function prototypes
|
||||
and definitions to ISO C.
|
||||
|
||||
|
@ -79,7 +79,7 @@ clean-igen:
|
||||
cd ../igen && $(MAKE)
|
||||
|
||||
IGEN_TRACE= # -G omit-line-numbers # -G trace-rule-selection -G trace-rule-rejection -G trace-entries
|
||||
IGEN_INSN=$(srcdir)/mn10300.igen $(srcdir)/am33.igen
|
||||
IGEN_INSN=$(srcdir)/mn10300.igen $(srcdir)/am33.igen $(srcdir)/am33-2.igen
|
||||
IGEN_DC=$(srcdir)/mn10300.dc
|
||||
tmp-igen: $(IGEN_INSN) $(IGEN_DC) ../igen/igen
|
||||
cd ../igen && $(MAKE)
|
||||
@ -87,6 +87,7 @@ tmp-igen: $(IGEN_INSN) $(IGEN_DC) ../igen/igen
|
||||
$(IGEN_TRACE) \
|
||||
-G gen-direct-access \
|
||||
-M mn10300,am33 -G gen-multi-sim=am33 \
|
||||
-M am33_2 \
|
||||
-I $(srcdir) \
|
||||
-i $(IGEN_INSN) \
|
||||
-o $(IGEN_DC) \
|
||||
|
2285
sim/mn10300/am33-2.igen
Normal file
2285
sim/mn10300/am33-2.igen
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -322,6 +322,9 @@ sim_create_inferior (SIM_DESC sd,
|
||||
}
|
||||
CIA_SET (STATE_CPU (sd, 0), (unsigned64) PC);
|
||||
|
||||
if (STATE_ARCHITECTURE (sd)->mach == bfd_mach_am33_2)
|
||||
PSW |= PSW_FE;
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
@ -546,3 +549,569 @@ mn10300_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception)
|
||||
}
|
||||
State.exc_suspended = 0;
|
||||
}
|
||||
|
||||
/* This is called when an FP instruction is issued when the FP unit is
|
||||
disabled, i.e., the FE bit of PSW is zero. It raises interrupt
|
||||
code 0x1c0. */
|
||||
void
|
||||
fpu_disabled_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
|
||||
{
|
||||
sim_io_eprintf(sd, "FPU disabled exception\n");
|
||||
program_interrupt (sd, cpu, cia, SIM_SIGFPE);
|
||||
}
|
||||
|
||||
/* This is called when the FP unit is enabled but one of the
|
||||
unimplemented insns is issued. It raises interrupt code 0x1c8. */
|
||||
void
|
||||
fpu_unimp_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
|
||||
{
|
||||
sim_io_eprintf(sd, "Unimplemented FPU instruction exception\n");
|
||||
program_interrupt (sd, cpu, cia, SIM_SIGFPE);
|
||||
}
|
||||
|
||||
/* This is called at the end of any FP insns that may have triggered
|
||||
FP exceptions. If no exception is enabled, it returns immediately.
|
||||
Otherwise, it raises an exception code 0x1d0. */
|
||||
void
|
||||
fpu_check_signal_exception (SIM_DESC sd, sim_cpu *cpu, sim_cia cia)
|
||||
{
|
||||
if ((FPCR & EC_MASK) == 0)
|
||||
return;
|
||||
|
||||
sim_io_eprintf(sd, "FPU %s%s%s%s%s exception\n",
|
||||
(FPCR & EC_V) ? "V" : "",
|
||||
(FPCR & EC_Z) ? "Z" : "",
|
||||
(FPCR & EC_O) ? "O" : "",
|
||||
(FPCR & EC_U) ? "U" : "",
|
||||
(FPCR & EC_I) ? "I" : "");
|
||||
program_interrupt (sd, cpu, cia, SIM_SIGFPE);
|
||||
}
|
||||
|
||||
/* Convert a 32-bit single-precision FP value in the target platform
|
||||
format to a sim_fpu value. */
|
||||
static void
|
||||
reg2val_32 (const void *reg, sim_fpu *val)
|
||||
{
|
||||
FS2FPU (*(reg_t *)reg, *val);
|
||||
}
|
||||
|
||||
/* Round the given sim_fpu value to single precision, following the
|
||||
target platform rounding and denormalization conventions. On
|
||||
AM33/2.0, round_near is the only rounding mode. */
|
||||
static int
|
||||
round_32 (sim_fpu *val)
|
||||
{
|
||||
return sim_fpu_round_32 (val, sim_fpu_round_near, sim_fpu_denorm_zero);
|
||||
}
|
||||
|
||||
/* Convert a sim_fpu value to the 32-bit single-precision target
|
||||
representation. */
|
||||
static void
|
||||
val2reg_32 (const sim_fpu *val, void *reg)
|
||||
{
|
||||
FPU2FS (*val, *(reg_t *)reg);
|
||||
}
|
||||
|
||||
/* Define the 32-bit single-precision conversion and rounding uniform
|
||||
interface. */
|
||||
const struct fp_prec_t
|
||||
fp_single_prec = {
|
||||
reg2val_32, round_32, val2reg_32
|
||||
};
|
||||
|
||||
/* Convert a 64-bit double-precision FP value in the target platform
|
||||
format to a sim_fpu value. */
|
||||
static void
|
||||
reg2val_64 (const void *reg, sim_fpu *val)
|
||||
{
|
||||
FD2FPU (*(dword *)reg, *val);
|
||||
}
|
||||
|
||||
/* Round the given sim_fpu value to double precision, following the
|
||||
target platform rounding and denormalization conventions. On
|
||||
AM33/2.0, round_near is the only rounding mode. */
|
||||
int
|
||||
round_64 (sim_fpu *val)
|
||||
{
|
||||
return sim_fpu_round_64 (val, sim_fpu_round_near, sim_fpu_denorm_zero);
|
||||
}
|
||||
|
||||
/* Convert a sim_fpu value to the 64-bit double-precision target
|
||||
representation. */
|
||||
static void
|
||||
val2reg_64 (const sim_fpu *val, void *reg)
|
||||
{
|
||||
FPU2FD (*val, *(dword *)reg);
|
||||
}
|
||||
|
||||
/* Define the 64-bit single-precision conversion and rounding uniform
|
||||
interface. */
|
||||
const struct fp_prec_t
|
||||
fp_double_prec = {
|
||||
reg2val_64, round_64, val2reg_64
|
||||
};
|
||||
|
||||
/* Define shortcuts to the uniform interface operations. */
|
||||
#define REG2VAL(reg,val) (*ops->reg2val) (reg,val)
|
||||
#define ROUND(val) (*ops->round) (val)
|
||||
#define VAL2REG(val,reg) (*ops->val2reg) (val,reg)
|
||||
|
||||
/* Check whether overflow, underflow or inexact exceptions should be
|
||||
raised. */
|
||||
int
|
||||
fpu_status_ok (sim_fpu_status stat)
|
||||
{
|
||||
if ((stat & sim_fpu_status_overflow)
|
||||
&& (FPCR & EE_O))
|
||||
FPCR |= EC_O;
|
||||
else if ((stat & (sim_fpu_status_underflow | sim_fpu_status_denorm))
|
||||
&& (FPCR & EE_U))
|
||||
FPCR |= EC_U;
|
||||
else if ((stat & (sim_fpu_status_inexact | sim_fpu_status_rounded))
|
||||
&& (FPCR & EE_I))
|
||||
FPCR |= EC_I;
|
||||
else if (stat & ~ (sim_fpu_status_overflow
|
||||
| sim_fpu_status_underflow
|
||||
| sim_fpu_status_denorm
|
||||
| sim_fpu_status_inexact
|
||||
| sim_fpu_status_rounded))
|
||||
abort ();
|
||||
else
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Implement a 32/64 bit reciprocal square root, signaling FP
|
||||
exceptions when appropriate. */
|
||||
void
|
||||
fpu_rsqrt (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
|
||||
const void *reg_in, void *reg_out, const struct fp_prec_t *ops)
|
||||
{
|
||||
sim_fpu in, med, out;
|
||||
|
||||
REG2VAL (reg_in, &in);
|
||||
ROUND (&in);
|
||||
FPCR &= ~ EC_MASK;
|
||||
switch (sim_fpu_is (&in))
|
||||
{
|
||||
case SIM_FPU_IS_SNAN:
|
||||
case SIM_FPU_IS_NNUMBER:
|
||||
case SIM_FPU_IS_NINF:
|
||||
if (FPCR & EE_V)
|
||||
FPCR |= EC_V;
|
||||
else
|
||||
VAL2REG (&sim_fpu_qnan, reg_out);
|
||||
break;
|
||||
|
||||
case SIM_FPU_IS_QNAN:
|
||||
VAL2REG (&sim_fpu_qnan, reg_out);
|
||||
break;
|
||||
|
||||
case SIM_FPU_IS_PINF:
|
||||
VAL2REG (&sim_fpu_zero, reg_out);
|
||||
break;
|
||||
|
||||
case SIM_FPU_IS_PNUMBER:
|
||||
{
|
||||
/* Since we don't have a function to compute rsqrt directly,
|
||||
use sqrt and inv. */
|
||||
sim_fpu_status stat = 0;
|
||||
stat |= sim_fpu_sqrt (&med, &in);
|
||||
stat |= sim_fpu_inv (&out, &med);
|
||||
stat |= ROUND (&out);
|
||||
if (fpu_status_ok (stat))
|
||||
VAL2REG (&out, reg_out);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIM_FPU_IS_NZERO:
|
||||
case SIM_FPU_IS_PZERO:
|
||||
if (FPCR & EE_Z)
|
||||
FPCR |= EC_Z;
|
||||
else
|
||||
{
|
||||
/* Generate an INF with the same sign. */
|
||||
sim_fpu_inv (&out, &in);
|
||||
VAL2REG (&out, reg_out);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
fpu_check_signal_exception (sd, cpu, cia);
|
||||
}
|
||||
|
||||
static inline reg_t
|
||||
cmp2fcc (int res)
|
||||
{
|
||||
switch (res)
|
||||
{
|
||||
case SIM_FPU_IS_SNAN:
|
||||
case SIM_FPU_IS_QNAN:
|
||||
return FCC_U;
|
||||
|
||||
case SIM_FPU_IS_NINF:
|
||||
case SIM_FPU_IS_NNUMBER:
|
||||
case SIM_FPU_IS_NDENORM:
|
||||
return FCC_L;
|
||||
|
||||
case SIM_FPU_IS_PINF:
|
||||
case SIM_FPU_IS_PNUMBER:
|
||||
case SIM_FPU_IS_PDENORM:
|
||||
return FCC_G;
|
||||
|
||||
case SIM_FPU_IS_NZERO:
|
||||
case SIM_FPU_IS_PZERO:
|
||||
return FCC_E;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement a 32/64 bit FP compare, setting the FPCR status and/or
|
||||
exception bits as specified. */
|
||||
void
|
||||
fpu_cmp (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
|
||||
const void *reg_in1, const void *reg_in2,
|
||||
const struct fp_prec_t *ops)
|
||||
{
|
||||
sim_fpu m, n;
|
||||
|
||||
REG2VAL (reg_in1, &m);
|
||||
REG2VAL (reg_in2, &n);
|
||||
FPCR &= ~ EC_MASK;
|
||||
FPCR &= ~ FCC_MASK;
|
||||
ROUND (&m);
|
||||
ROUND (&n);
|
||||
if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n))
|
||||
{
|
||||
if (FPCR & EE_V)
|
||||
FPCR |= EC_V;
|
||||
else
|
||||
FPCR |= FCC_U;
|
||||
}
|
||||
else
|
||||
FPCR |= cmp2fcc (sim_fpu_cmp (&m, &n));
|
||||
|
||||
fpu_check_signal_exception (sd, cpu, cia);
|
||||
}
|
||||
|
||||
/* Implement a 32/64 bit FP add, setting FP exception bits when
|
||||
appropriate. */
|
||||
void
|
||||
fpu_add (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
|
||||
const void *reg_in1, const void *reg_in2,
|
||||
void *reg_out, const struct fp_prec_t *ops)
|
||||
{
|
||||
sim_fpu m, n, r;
|
||||
|
||||
REG2VAL (reg_in1, &m);
|
||||
REG2VAL (reg_in2, &n);
|
||||
ROUND (&m);
|
||||
ROUND (&n);
|
||||
FPCR &= ~ EC_MASK;
|
||||
if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
|
||||
|| (sim_fpu_is (&m) == SIM_FPU_IS_PINF
|
||||
&& sim_fpu_is (&n) == SIM_FPU_IS_NINF)
|
||||
|| (sim_fpu_is (&m) == SIM_FPU_IS_NINF
|
||||
&& sim_fpu_is (&n) == SIM_FPU_IS_PINF))
|
||||
{
|
||||
if (FPCR & EE_V)
|
||||
FPCR |= EC_V;
|
||||
else
|
||||
VAL2REG (&sim_fpu_qnan, reg_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
sim_fpu_status stat = sim_fpu_add (&r, &m, &n);
|
||||
stat |= ROUND (&r);
|
||||
if (fpu_status_ok (stat))
|
||||
VAL2REG (&r, reg_out);
|
||||
}
|
||||
|
||||
fpu_check_signal_exception (sd, cpu, cia);
|
||||
}
|
||||
|
||||
/* Implement a 32/64 bit FP sub, setting FP exception bits when
|
||||
appropriate. */
|
||||
void
|
||||
fpu_sub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
|
||||
const void *reg_in1, const void *reg_in2,
|
||||
void *reg_out, const struct fp_prec_t *ops)
|
||||
{
|
||||
sim_fpu m, n, r;
|
||||
|
||||
REG2VAL (reg_in1, &m);
|
||||
REG2VAL (reg_in2, &n);
|
||||
ROUND (&m);
|
||||
ROUND (&n);
|
||||
FPCR &= ~ EC_MASK;
|
||||
if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
|
||||
|| (sim_fpu_is (&m) == SIM_FPU_IS_PINF
|
||||
&& sim_fpu_is (&n) == SIM_FPU_IS_PINF)
|
||||
|| (sim_fpu_is (&m) == SIM_FPU_IS_NINF
|
||||
&& sim_fpu_is (&n) == SIM_FPU_IS_NINF))
|
||||
{
|
||||
if (FPCR & EE_V)
|
||||
FPCR |= EC_V;
|
||||
else
|
||||
VAL2REG (&sim_fpu_qnan, reg_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
sim_fpu_status stat = sim_fpu_sub (&r, &m, &n);
|
||||
stat |= ROUND (&r);
|
||||
if (fpu_status_ok (stat))
|
||||
VAL2REG (&r, reg_out);
|
||||
}
|
||||
|
||||
fpu_check_signal_exception (sd, cpu, cia);
|
||||
}
|
||||
|
||||
/* Implement a 32/64 bit FP mul, setting FP exception bits when
|
||||
appropriate. */
|
||||
void
|
||||
fpu_mul (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
|
||||
const void *reg_in1, const void *reg_in2,
|
||||
void *reg_out, const struct fp_prec_t *ops)
|
||||
{
|
||||
sim_fpu m, n, r;
|
||||
|
||||
REG2VAL (reg_in1, &m);
|
||||
REG2VAL (reg_in2, &n);
|
||||
ROUND (&m);
|
||||
ROUND (&n);
|
||||
FPCR &= ~ EC_MASK;
|
||||
if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
|
||||
|| (sim_fpu_is_infinity (&m) && sim_fpu_is_zero (&n))
|
||||
|| (sim_fpu_is_zero (&m) && sim_fpu_is_infinity (&n)))
|
||||
{
|
||||
if (FPCR & EE_V)
|
||||
FPCR |= EC_V;
|
||||
else
|
||||
VAL2REG (&sim_fpu_qnan, reg_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
sim_fpu_status stat = sim_fpu_mul (&r, &m, &n);
|
||||
stat |= ROUND (&r);
|
||||
if (fpu_status_ok (stat))
|
||||
VAL2REG (&r, reg_out);
|
||||
}
|
||||
|
||||
fpu_check_signal_exception (sd, cpu, cia);
|
||||
}
|
||||
|
||||
/* Implement a 32/64 bit FP div, setting FP exception bits when
|
||||
appropriate. */
|
||||
void
|
||||
fpu_div (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
|
||||
const void *reg_in1, const void *reg_in2,
|
||||
void *reg_out, const struct fp_prec_t *ops)
|
||||
{
|
||||
sim_fpu m, n, r;
|
||||
|
||||
REG2VAL (reg_in1, &m);
|
||||
REG2VAL (reg_in2, &n);
|
||||
ROUND (&m);
|
||||
ROUND (&n);
|
||||
FPCR &= ~ EC_MASK;
|
||||
if (sim_fpu_is_snan (&m) || sim_fpu_is_snan (&n)
|
||||
|| (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n))
|
||||
|| (sim_fpu_is_zero (&m) && sim_fpu_is_zero (&n)))
|
||||
{
|
||||
if (FPCR & EE_V)
|
||||
FPCR |= EC_V;
|
||||
else
|
||||
VAL2REG (&sim_fpu_qnan, reg_out);
|
||||
}
|
||||
else if (sim_fpu_is_number (&m) && sim_fpu_is_zero (&n)
|
||||
&& (FPCR & EE_Z))
|
||||
FPCR |= EC_Z;
|
||||
else
|
||||
{
|
||||
sim_fpu_status stat = sim_fpu_div (&r, &m, &n);
|
||||
stat |= ROUND (&r);
|
||||
if (fpu_status_ok (stat))
|
||||
VAL2REG (&r, reg_out);
|
||||
}
|
||||
|
||||
fpu_check_signal_exception (sd, cpu, cia);
|
||||
}
|
||||
|
||||
/* Implement a 32/64 bit FP madd, setting FP exception bits when
|
||||
appropriate. */
|
||||
void
|
||||
fpu_fmadd (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
|
||||
const void *reg_in1, const void *reg_in2, const void *reg_in3,
|
||||
void *reg_out, const struct fp_prec_t *ops)
|
||||
{
|
||||
sim_fpu m1, m2, m, n, r;
|
||||
|
||||
REG2VAL (reg_in1, &m1);
|
||||
REG2VAL (reg_in2, &m2);
|
||||
REG2VAL (reg_in3, &n);
|
||||
ROUND (&m1);
|
||||
ROUND (&m2);
|
||||
ROUND (&n);
|
||||
FPCR &= ~ EC_MASK;
|
||||
if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
|
||||
|| (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
|
||||
|| (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
|
||||
{
|
||||
invalid_operands:
|
||||
if (FPCR & EE_V)
|
||||
FPCR |= EC_V;
|
||||
else
|
||||
VAL2REG (&sim_fpu_qnan, reg_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
|
||||
|
||||
if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
|
||||
&& sim_fpu_sign (&m) != sim_fpu_sign (&n))
|
||||
goto invalid_operands;
|
||||
|
||||
stat |= sim_fpu_add (&r, &m, &n);
|
||||
stat |= ROUND (&r);
|
||||
if (fpu_status_ok (stat))
|
||||
VAL2REG (&r, reg_out);
|
||||
}
|
||||
|
||||
fpu_check_signal_exception (sd, cpu, cia);
|
||||
}
|
||||
|
||||
/* Implement a 32/64 bit FP msub, setting FP exception bits when
|
||||
appropriate. */
|
||||
void
|
||||
fpu_fmsub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
|
||||
const void *reg_in1, const void *reg_in2, const void *reg_in3,
|
||||
void *reg_out, const struct fp_prec_t *ops)
|
||||
{
|
||||
sim_fpu m1, m2, m, n, r;
|
||||
|
||||
REG2VAL (reg_in1, &m1);
|
||||
REG2VAL (reg_in2, &m2);
|
||||
REG2VAL (reg_in3, &n);
|
||||
ROUND (&m1);
|
||||
ROUND (&m2);
|
||||
ROUND (&n);
|
||||
FPCR &= ~ EC_MASK;
|
||||
if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
|
||||
|| (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
|
||||
|| (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
|
||||
{
|
||||
invalid_operands:
|
||||
if (FPCR & EE_V)
|
||||
FPCR |= EC_V;
|
||||
else
|
||||
VAL2REG (&sim_fpu_qnan, reg_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
|
||||
|
||||
if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
|
||||
&& sim_fpu_sign (&m) == sim_fpu_sign (&n))
|
||||
goto invalid_operands;
|
||||
|
||||
stat |= sim_fpu_sub (&r, &m, &n);
|
||||
stat |= ROUND (&r);
|
||||
if (fpu_status_ok (stat))
|
||||
VAL2REG (&r, reg_out);
|
||||
}
|
||||
|
||||
fpu_check_signal_exception (sd, cpu, cia);
|
||||
}
|
||||
|
||||
/* Implement a 32/64 bit FP nmadd, setting FP exception bits when
|
||||
appropriate. */
|
||||
void
|
||||
fpu_fnmadd (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
|
||||
const void *reg_in1, const void *reg_in2, const void *reg_in3,
|
||||
void *reg_out, const struct fp_prec_t *ops)
|
||||
{
|
||||
sim_fpu m1, m2, m, mm, n, r;
|
||||
|
||||
REG2VAL (reg_in1, &m1);
|
||||
REG2VAL (reg_in2, &m2);
|
||||
REG2VAL (reg_in3, &n);
|
||||
ROUND (&m1);
|
||||
ROUND (&m2);
|
||||
ROUND (&n);
|
||||
FPCR &= ~ EC_MASK;
|
||||
if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
|
||||
|| (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
|
||||
|| (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
|
||||
{
|
||||
invalid_operands:
|
||||
if (FPCR & EE_V)
|
||||
FPCR |= EC_V;
|
||||
else
|
||||
VAL2REG (&sim_fpu_qnan, reg_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
|
||||
|
||||
if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
|
||||
&& sim_fpu_sign (&m) == sim_fpu_sign (&n))
|
||||
goto invalid_operands;
|
||||
|
||||
stat |= sim_fpu_neg (&mm, &m);
|
||||
stat |= sim_fpu_add (&r, &mm, &n);
|
||||
stat |= ROUND (&r);
|
||||
if (fpu_status_ok (stat))
|
||||
VAL2REG (&r, reg_out);
|
||||
}
|
||||
|
||||
fpu_check_signal_exception (sd, cpu, cia);
|
||||
}
|
||||
|
||||
/* Implement a 32/64 bit FP nmsub, setting FP exception bits when
|
||||
appropriate. */
|
||||
void
|
||||
fpu_fnmsub (SIM_DESC sd, sim_cpu *cpu, sim_cia cia,
|
||||
const void *reg_in1, const void *reg_in2, const void *reg_in3,
|
||||
void *reg_out, const struct fp_prec_t *ops)
|
||||
{
|
||||
sim_fpu m1, m2, m, mm, n, r;
|
||||
|
||||
REG2VAL (reg_in1, &m1);
|
||||
REG2VAL (reg_in2, &m2);
|
||||
REG2VAL (reg_in3, &n);
|
||||
ROUND (&m1);
|
||||
ROUND (&m2);
|
||||
ROUND (&n);
|
||||
FPCR &= ~ EC_MASK;
|
||||
if (sim_fpu_is_snan (&m1) || sim_fpu_is_snan (&m2) || sim_fpu_is_snan (&n)
|
||||
|| (sim_fpu_is_infinity (&m1) && sim_fpu_is_zero (&m2))
|
||||
|| (sim_fpu_is_zero (&m1) && sim_fpu_is_infinity (&m2)))
|
||||
{
|
||||
invalid_operands:
|
||||
if (FPCR & EE_V)
|
||||
FPCR |= EC_V;
|
||||
else
|
||||
VAL2REG (&sim_fpu_qnan, reg_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
sim_fpu_status stat = sim_fpu_mul (&m, &m1, &m2);
|
||||
|
||||
if (sim_fpu_is_infinity (&m) && sim_fpu_is_infinity (&n)
|
||||
&& sim_fpu_sign (&m) != sim_fpu_sign (&n))
|
||||
goto invalid_operands;
|
||||
|
||||
stat |= sim_fpu_neg (&mm, &m);
|
||||
stat |= sim_fpu_sub (&r, &mm, &n);
|
||||
stat |= ROUND (&r);
|
||||
if (fpu_status_ok (stat))
|
||||
VAL2REG (&r, reg_out);
|
||||
}
|
||||
|
||||
fpu_check_signal_exception (sd, cpu, cia);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@
|
||||
#include <limits.h>
|
||||
#include "gdb/remote-sim.h"
|
||||
#include "bfd.h"
|
||||
#include "sim-fpu.h"
|
||||
|
||||
#ifndef INLINE
|
||||
#ifdef __GNUC__
|
||||
@ -53,6 +54,10 @@ typedef signed long int32;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 low, high;
|
||||
} dword;
|
||||
typedef uint32 reg_t;
|
||||
|
||||
struct simops
|
||||
@ -73,6 +78,11 @@ struct _state
|
||||
reg_t regs[32]; /* registers, d0-d3, a0-a3, sp, pc, mdr, psw,
|
||||
lir, lar, mdrq, plus some room for processor
|
||||
specific regs. */
|
||||
union
|
||||
{
|
||||
reg_t fs[32]; /* FS0-31 */
|
||||
dword fd[16]; /* FD0,2,...,30 */
|
||||
} fpregs;
|
||||
uint8 *mem; /* main memory */
|
||||
int exception;
|
||||
int exited;
|
||||
@ -123,6 +133,52 @@ extern struct simops Simops[];
|
||||
#define REG_MCRL 27
|
||||
#define REG_MCVF 28
|
||||
|
||||
#define REG_FPCR 29
|
||||
|
||||
#define FPCR (State.regs[REG_FPCR])
|
||||
|
||||
#define FCC_MASK LSMASK (21, 18)
|
||||
#define RM_MASK LSMASK (17, 16) /* Must always be zero. */
|
||||
#define EC_MASK LSMASK (14, 10)
|
||||
#define EE_MASK LSMASK ( 9, 5)
|
||||
#define EF_MASK LSMASK ( 4, 0)
|
||||
#define FPCR_MASK (FCC_MASK | EC_MASK | EE_MASK | EF_MASK)
|
||||
|
||||
#define FCC_L LSBIT (21)
|
||||
#define FCC_G LSBIT (20)
|
||||
#define FCC_E LSBIT (19)
|
||||
#define FCC_U LSBIT (18)
|
||||
|
||||
#define EC_V LSBIT (14)
|
||||
#define EC_Z LSBIT (13)
|
||||
#define EC_O LSBIT (12)
|
||||
#define EC_U LSBIT (11)
|
||||
#define EC_I LSBIT (10)
|
||||
|
||||
#define EE_V LSBIT (9)
|
||||
#define EE_Z LSBIT (8)
|
||||
#define EE_O LSBIT (7)
|
||||
#define EE_U LSBIT (6)
|
||||
#define EE_I LSBIT (5)
|
||||
|
||||
#define EF_V LSBIT (4)
|
||||
#define EF_Z LSBIT (3)
|
||||
#define EF_O LSBIT (2)
|
||||
#define EF_U LSBIT (1)
|
||||
#define EF_I LSBIT (0)
|
||||
|
||||
#define PSW_FE LSBIT(20)
|
||||
#define FPU_DISABLED !(PSW & PSW_FE)
|
||||
|
||||
#define XS2FS(X,S) State.fpregs.fs[((X<<4)|(S))]
|
||||
#define AS2FS(A,S) State.fpregs.fs[((A<<2)|(S))]
|
||||
#define Xf2FD(X,f) State.fpregs.fd[((X<<3)|(f))]
|
||||
|
||||
#define FS2FPU(FS,F) sim_fpu_32to (&(F), (FS))
|
||||
#define FD2FPU(FD,F) sim_fpu_232to (&(F), ((FD).high), ((FD).low))
|
||||
#define FPU2FS(F,FS) sim_fpu_to32 (&(FS), &(F))
|
||||
#define FPU2FD(F,FD) sim_fpu_to232 (&((FD).high), &((FD).low), &(F))
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SIGTRAP 5
|
||||
#define SIGQUIT 3
|
||||
@ -145,6 +201,20 @@ sim_core_read_unaligned_2 (STATE_CPU (simulator, 0), PC, read_map, (ADDR))
|
||||
#define load_word(ADDR) \
|
||||
sim_core_read_unaligned_4 (STATE_CPU (simulator, 0), PC, read_map, (ADDR))
|
||||
|
||||
#define load_dword(ADDR) \
|
||||
u642dw (sim_core_read_unaligned_8 (STATE_CPU (simulator, 0), \
|
||||
PC, read_map, (ADDR)))
|
||||
|
||||
static INLINE dword
|
||||
u642dw (unsigned64 dw)
|
||||
{
|
||||
dword r;
|
||||
|
||||
r.low = (unsigned32)dw;
|
||||
r.high = (unsigned32)(dw >> 32);
|
||||
return r;
|
||||
}
|
||||
|
||||
#define store_byte(ADDR, DATA) \
|
||||
sim_core_write_unaligned_1 (STATE_CPU (simulator, 0), \
|
||||
PC, write_map, (ADDR), (DATA))
|
||||
@ -158,6 +228,15 @@ sim_core_write_unaligned_2 (STATE_CPU (simulator, 0), \
|
||||
#define store_word(ADDR, DATA) \
|
||||
sim_core_write_unaligned_4 (STATE_CPU (simulator, 0), \
|
||||
PC, write_map, (ADDR), (DATA))
|
||||
#define store_dword(ADDR, DATA) \
|
||||
sim_core_write_unaligned_8 (STATE_CPU (simulator, 0), \
|
||||
PC, write_map, (ADDR), dw2u64 (DATA))
|
||||
|
||||
static INLINE unsigned64
|
||||
dw2u64 (dword data)
|
||||
{
|
||||
return data.low | (((unsigned64)data.high) << 32);
|
||||
}
|
||||
|
||||
/* Function declarations. */
|
||||
|
||||
@ -192,3 +271,29 @@ void program_interrupt (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, SIM_SIGNAL sig);
|
||||
void mn10300_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word pc);
|
||||
void mn10300_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception);
|
||||
void mn10300_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception);
|
||||
|
||||
void fpu_disabled_exception (SIM_DESC, sim_cpu *, address_word);
|
||||
void fpu_unimp_exception (SIM_DESC, sim_cpu *, address_word);
|
||||
void fpu_check_signal_exception (SIM_DESC, sim_cpu *, address_word);
|
||||
|
||||
extern const struct fp_prec_t
|
||||
{
|
||||
void (* reg2val) (const void *, sim_fpu *);
|
||||
int (* round) (sim_fpu *);
|
||||
void (* val2reg) (const sim_fpu *, void *);
|
||||
} fp_single_prec, fp_double_prec;
|
||||
|
||||
#define FP_SINGLE (&fp_single_prec)
|
||||
#define FP_DOUBLE (&fp_double_prec)
|
||||
|
||||
void fpu_rsqrt (SIM_DESC, sim_cpu *, address_word, const void *, void *, const struct fp_prec_t *);
|
||||
void fpu_sqrt (SIM_DESC, sim_cpu *, address_word, const void *, void *, const struct fp_prec_t *);
|
||||
void fpu_cmp (SIM_DESC, sim_cpu *, address_word, const void *, const void *, const struct fp_prec_t *);
|
||||
void fpu_add (SIM_DESC, sim_cpu *, address_word, const void *, const void *, void *, const struct fp_prec_t *);
|
||||
void fpu_sub (SIM_DESC, sim_cpu *, address_word, const void *, const void *, void *, const struct fp_prec_t *);
|
||||
void fpu_mul (SIM_DESC, sim_cpu *, address_word, const void *, const void *, void *, const struct fp_prec_t *);
|
||||
void fpu_div (SIM_DESC, sim_cpu *, address_word, const void *, const void *, void *, const struct fp_prec_t *);
|
||||
void fpu_fmadd (SIM_DESC, sim_cpu *, address_word, const void *, const void *, const void *, void *, const struct fp_prec_t *);
|
||||
void fpu_fmsub (SIM_DESC, sim_cpu *, address_word, const void *, const void *, const void *, void *, const struct fp_prec_t *);
|
||||
void fpu_fnmadd (SIM_DESC, sim_cpu *, address_word, const void *, const void *, const void *, void *, const struct fp_prec_t *);
|
||||
void fpu_fnmsub (SIM_DESC, sim_cpu *, address_word, const void *, const void *, const void *, void *, const struct fp_prec_t *);
|
||||
|
Loading…
Reference in New Issue
Block a user