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:
Alexandre Oliva 2004-06-26 22:18:18 +00:00
parent 489503ee33
commit c76b4bab30
7 changed files with 3727 additions and 1 deletions

View File

@ -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.

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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 *);