2002-06-06 Chris Demetriou <cgd@broadcom.com>
Ed Satterthwaite <ehs@broadcom.com> * cp1.h: New file. * sim-main.h: Include cp1.h. (SETFCC, GETFCC, IR, UF, OF, DX, IO, UO, FP_FLAGS, FP_ENABLE) (FP_CAUSE, GETFS, FP_RM_NEAREST, FP_RM_TOZERO, FP_RM_TOPINF) (FP_RM_TOMINF, GETRM): Remove. Moved to cp1.h. (FP_FS, FP_MASK_RM, FP_SH_RM, Nan, Less, Equal): Remove. (value_fcr, store_fcr, test_fcsr, fp_cmp): New prototypes. (ValueFCR, StoreFCR, TestFCSR, Compare): New macros. * cp1.c: Don't include sim-fpu.h; already included by sim-main.h. Clean up formatting of some comments. (NaN, Equal, Less): Remove. (test_fcsr, value_fcr, store_fcr, update_fcsr, fp_test) (fp_cmp): New functions. * mips.igen (do_c_cond_fmt): Remove. (C.cond.fmta, C.cond.fmtb): Replace uses of do_c_cond_fmt_a with Compare. Add result tracing. (CxC1): Remove, replace with... (CFC1a, CFC1b, CFC1c, CTC1a, CTC1b, CTC1c): New instructions. (DMxC1): Remove, replace with... (DMFC1a, DMFC1b, DMTC1a, DMTC1b): New instructions. (MxC1): Remove, replace with... (MFC1a, MFC1b, MTC1a, MTC1b): New instructions.
This commit is contained in:
parent
feb2269354
commit
cfe9ea23c7
@ -1,3 +1,29 @@
|
||||
2002-06-06 Chris Demetriou <cgd@broadcom.com>
|
||||
Ed Satterthwaite <ehs@broadcom.com>
|
||||
|
||||
* cp1.h: New file.
|
||||
* sim-main.h: Include cp1.h.
|
||||
(SETFCC, GETFCC, IR, UF, OF, DX, IO, UO, FP_FLAGS, FP_ENABLE)
|
||||
(FP_CAUSE, GETFS, FP_RM_NEAREST, FP_RM_TOZERO, FP_RM_TOPINF)
|
||||
(FP_RM_TOMINF, GETRM): Remove. Moved to cp1.h.
|
||||
(FP_FS, FP_MASK_RM, FP_SH_RM, Nan, Less, Equal): Remove.
|
||||
(value_fcr, store_fcr, test_fcsr, fp_cmp): New prototypes.
|
||||
(ValueFCR, StoreFCR, TestFCSR, Compare): New macros.
|
||||
* cp1.c: Don't include sim-fpu.h; already included by
|
||||
sim-main.h. Clean up formatting of some comments.
|
||||
(NaN, Equal, Less): Remove.
|
||||
(test_fcsr, value_fcr, store_fcr, update_fcsr, fp_test)
|
||||
(fp_cmp): New functions.
|
||||
* mips.igen (do_c_cond_fmt): Remove.
|
||||
(C.cond.fmta, C.cond.fmtb): Replace uses of do_c_cond_fmt_a with
|
||||
Compare. Add result tracing.
|
||||
(CxC1): Remove, replace with...
|
||||
(CFC1a, CFC1b, CFC1c, CTC1a, CTC1b, CTC1c): New instructions.
|
||||
(DMxC1): Remove, replace with...
|
||||
(DMFC1a, DMFC1b, DMTC1a, DMTC1b): New instructions.
|
||||
(MxC1): Remove, replace with...
|
||||
(MFC1a, MFC1b, MTC1a, MTC1b): New instructions.
|
||||
|
||||
2002-06-04 Chris Demetriou <cgd@broadcom.com>
|
||||
|
||||
* sim-main.h (FGRIDX): Remove, replace all uses with...
|
||||
|
282
sim/mips/cp1.c
282
sim/mips/cp1.c
@ -40,7 +40,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
*/
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "sim-fpu.h"
|
||||
|
||||
/* Within cp1.c we refer to sim_cpu directly. */
|
||||
#define CPU cpu
|
||||
@ -313,126 +312,163 @@ store_fpr (sim_cpu *cpu,
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
NaN (op, fmt)
|
||||
uword64 op;
|
||||
FP_formats fmt;
|
||||
|
||||
/* CP1 control/status registers */
|
||||
|
||||
void
|
||||
test_fcsr (sim_cpu *cpu,
|
||||
address_word cia)
|
||||
{
|
||||
int boolean = 0;
|
||||
switch (fmt)
|
||||
unsigned int cause;
|
||||
|
||||
cause = (FCSR & fcsr_CAUSE_mask) >> fcsr_CAUSE_shift;
|
||||
if ((cause & ((FCSR & fcsr_ENABLES_mask) >> fcsr_ENABLES_shift)) != 0
|
||||
|| (cause & (1 << UO)))
|
||||
{
|
||||
case fmt_single:
|
||||
case fmt_word:
|
||||
{
|
||||
sim_fpu wop;
|
||||
sim_fpu_32to (&wop, op);
|
||||
boolean = sim_fpu_is_nan (&wop);
|
||||
break;
|
||||
}
|
||||
case fmt_double:
|
||||
case fmt_long:
|
||||
{
|
||||
sim_fpu wop;
|
||||
sim_fpu_64to (&wop, op);
|
||||
boolean = sim_fpu_is_nan (&wop);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf (stderr, "Bad switch\n");
|
||||
abort ();
|
||||
SignalExceptionFPE();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("DBG: NaN: returning %d for 0x%s (format = %s)\n",
|
||||
boolean, pr_addr (op), fpu_format_name (fmt));
|
||||
#endif /* DEBUG */
|
||||
|
||||
return (boolean);
|
||||
}
|
||||
|
||||
int
|
||||
Less (op1, op2, fmt)
|
||||
uword64 op1;
|
||||
uword64 op2;
|
||||
FP_formats fmt;
|
||||
unsigned_word
|
||||
value_fcr(sim_cpu *cpu,
|
||||
address_word cia,
|
||||
int fcr)
|
||||
{
|
||||
int boolean = 0;
|
||||
unsigned32 value = 0;
|
||||
|
||||
/* Argument checking already performed by the FPCOMPARE code */
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("DBG: Less: %s: op1 = 0x%s : op2 = 0x%s\n",
|
||||
fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* The format type should already have been checked: */
|
||||
switch (fmt)
|
||||
switch (fcr)
|
||||
{
|
||||
case fmt_single:
|
||||
{
|
||||
sim_fpu wop1;
|
||||
sim_fpu wop2;
|
||||
sim_fpu_32to (&wop1, op1);
|
||||
sim_fpu_32to (&wop2, op2);
|
||||
boolean = sim_fpu_is_lt (&wop1, &wop2);
|
||||
break;
|
||||
}
|
||||
case fmt_double:
|
||||
{
|
||||
sim_fpu wop1;
|
||||
sim_fpu wop2;
|
||||
sim_fpu_64to (&wop1, op1);
|
||||
sim_fpu_64to (&wop2, op2);
|
||||
boolean = sim_fpu_is_lt (&wop1, &wop2);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf (stderr, "Bad switch\n");
|
||||
abort ();
|
||||
case 0: /* FP Implementation and Revision Register */
|
||||
value = FCR0;
|
||||
break;
|
||||
case 25: /* FP Condition Codes Register */
|
||||
value = (FCR31 & fcsr_FCC_mask) >> fcsr_FCC_shift;
|
||||
value = (value & 0x1) | (value >> 1); /* close FCC gap */
|
||||
break;
|
||||
case 26: /* FP Exceptions Register */
|
||||
value = FCR31 & (fcsr_CAUSE_mask | fcsr_FLAGS_mask);
|
||||
break;
|
||||
case 28: /* FP Enables Register */
|
||||
value = FCR31 & (fcsr_ENABLES_mask | fcsr_RM_mask);
|
||||
if (FCR31 & fcsr_FS)
|
||||
value |= 0x4; /* nonstandard FS bit */
|
||||
break;
|
||||
case 31: /* FP Control/Status Register */
|
||||
value = FCR31 & ~fcsr_ZERO_mask;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("DBG: Less: returning %d (format = %s)\n",
|
||||
boolean, fpu_format_name (fmt));
|
||||
#endif /* DEBUG */
|
||||
|
||||
return (boolean);
|
||||
return (EXTEND32 (value));
|
||||
}
|
||||
|
||||
int
|
||||
Equal (op1, op2, fmt)
|
||||
uword64 op1;
|
||||
uword64 op2;
|
||||
FP_formats fmt;
|
||||
void
|
||||
store_fcr(sim_cpu *cpu,
|
||||
address_word cia,
|
||||
int fcr,
|
||||
unsigned_word value)
|
||||
{
|
||||
int boolean = 0;
|
||||
unsigned32 v;
|
||||
|
||||
/* Argument checking already performed by the FPCOMPARE code */
|
||||
v = VL4_8(value);
|
||||
switch (fcr)
|
||||
{
|
||||
case 25: /* FP Condition Codes Register */
|
||||
v = (v << 1) | (v & 0x1); /* adjust for FCC gap */
|
||||
FCR31 &= ~fcsr_FCC_mask;
|
||||
FCR31 |= ((v << fcsr_FCC_shift) & fcsr_FCC_mask);
|
||||
break;
|
||||
case 26: /* FP Exceptions Register */
|
||||
FCR31 &= ~(fcsr_CAUSE_mask | fcsr_FLAGS_mask);
|
||||
FCR31 |= (v & (fcsr_CAUSE_mask | fcsr_FLAGS_mask));
|
||||
test_fcsr(cpu, cia);
|
||||
break;
|
||||
case 28: /* FP Enables Register */
|
||||
if (v & 0x4) /* nonstandard FS bit */
|
||||
v |= fcsr_FS;
|
||||
else
|
||||
v &= ~fcsr_FS;
|
||||
FCR31 &= (fcsr_FCC_mask | fcsr_CAUSE_mask | fcsr_FLAGS_mask);
|
||||
FCR31 |= (v & (fcsr_FS | fcsr_ENABLES_mask | fcsr_RM_mask));
|
||||
test_fcsr(cpu, cia);
|
||||
break;
|
||||
case 31: /* FP Control/Status Register */
|
||||
FCR31 = v & ~fcsr_ZERO_mask;
|
||||
test_fcsr(cpu, cia);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("DBG: Equal: %s: op1 = 0x%s : op2 = 0x%s\n",
|
||||
fpu_format_name (fmt), pr_addr (op1), pr_addr (op2));
|
||||
#endif /* DEBUG */
|
||||
void
|
||||
update_fcsr (sim_cpu *cpu,
|
||||
address_word cia,
|
||||
sim_fpu_status status)
|
||||
{
|
||||
FCSR &= ~fcsr_CAUSE_mask;
|
||||
|
||||
/* The format type should already have been checked: */
|
||||
if (status != 0)
|
||||
{
|
||||
unsigned int cause = 0;
|
||||
|
||||
/* map between sim_fpu codes and MIPS FCSR */
|
||||
if (status & (sim_fpu_status_invalid_snan
|
||||
| sim_fpu_status_invalid_isi
|
||||
| sim_fpu_status_invalid_idi
|
||||
| sim_fpu_status_invalid_zdz
|
||||
| sim_fpu_status_invalid_imz
|
||||
| sim_fpu_status_invalid_cmp
|
||||
| sim_fpu_status_invalid_sqrt
|
||||
| sim_fpu_status_invalid_cvi))
|
||||
cause |= (1 << IO);
|
||||
if (status & sim_fpu_status_invalid_div0)
|
||||
cause |= (1 << DZ);
|
||||
if (status & sim_fpu_status_overflow)
|
||||
cause |= (1 << OF);
|
||||
if (status & sim_fpu_status_underflow)
|
||||
cause |= (1 << UF);
|
||||
if (status & sim_fpu_status_inexact)
|
||||
cause |= (1 << IR);
|
||||
#if 0 /* Not yet. */
|
||||
/* Implicit clearing of other bits by unimplemented done by callers. */
|
||||
if (status & sim_fpu_status_unimplemented)
|
||||
cause |= (1 << UO);
|
||||
#endif
|
||||
|
||||
FCSR |= (cause << fcsr_CAUSE_shift);
|
||||
test_fcsr (cpu, cia);
|
||||
FCSR |= ((cause & ~(1 << UO)) << fcsr_FLAGS_shift);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Comparison operations. */
|
||||
|
||||
static sim_fpu_status
|
||||
fp_test(unsigned64 op1,
|
||||
unsigned64 op2,
|
||||
FP_formats fmt,
|
||||
int abs,
|
||||
int cond,
|
||||
int *condition)
|
||||
{
|
||||
sim_fpu wop1;
|
||||
sim_fpu wop2;
|
||||
sim_fpu_status status = 0;
|
||||
int less, equal, unordered;
|
||||
|
||||
/* The format type has already been checked: */
|
||||
switch (fmt)
|
||||
{
|
||||
case fmt_single:
|
||||
{
|
||||
sim_fpu wop1;
|
||||
sim_fpu wop2;
|
||||
sim_fpu_32to (&wop1, op1);
|
||||
sim_fpu_32to (&wop2, op2);
|
||||
boolean = sim_fpu_is_eq (&wop1, &wop2);
|
||||
break;
|
||||
}
|
||||
case fmt_double:
|
||||
{
|
||||
sim_fpu wop1;
|
||||
sim_fpu wop2;
|
||||
sim_fpu_64to (&wop1, op1);
|
||||
sim_fpu_64to (&wop2, op2);
|
||||
boolean = sim_fpu_is_eq (&wop1, &wop2);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -440,12 +476,60 @@ Equal (op1, op2, fmt)
|
||||
abort ();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf ("DBG: Equal: returning %d (format = %s)\n",
|
||||
boolean, fpu_format_name (fmt));
|
||||
#endif /* DEBUG */
|
||||
if (sim_fpu_is_nan (&wop1) || sim_fpu_is_nan (&wop2))
|
||||
{
|
||||
if ((cond & (1 << 3)) ||
|
||||
sim_fpu_is_snan (&wop1) || sim_fpu_is_snan (&wop2))
|
||||
status = sim_fpu_status_invalid_snan;
|
||||
less = 0;
|
||||
equal = 0;
|
||||
unordered = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (abs)
|
||||
{
|
||||
status |= sim_fpu_abs (&wop1, &wop1);
|
||||
status |= sim_fpu_abs (&wop2, &wop2);
|
||||
}
|
||||
equal = sim_fpu_is_eq (&wop1, &wop2);
|
||||
less = !equal && sim_fpu_is_lt (&wop1, &wop2);
|
||||
unordered = 0;
|
||||
}
|
||||
*condition = (((cond & (1 << 2)) && less)
|
||||
|| ((cond & (1 << 1)) && equal)
|
||||
|| ((cond & (1 << 0)) && unordered));
|
||||
return status;
|
||||
}
|
||||
|
||||
return (boolean);
|
||||
void
|
||||
fp_cmp(sim_cpu *cpu,
|
||||
address_word cia,
|
||||
unsigned64 op1,
|
||||
unsigned64 op2,
|
||||
FP_formats fmt,
|
||||
int abs,
|
||||
int cond,
|
||||
int cc)
|
||||
{
|
||||
sim_fpu_status status = 0;
|
||||
|
||||
/* The format type should already have been checked: */
|
||||
switch (fmt)
|
||||
{
|
||||
case fmt_single:
|
||||
case fmt_double:
|
||||
{
|
||||
int result;
|
||||
status = fp_test(op1, op2, fmt, abs, cond, &result);
|
||||
update_fcsr (cpu, cia, status);
|
||||
SETFCC (cc, result);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sim_io_eprintf (SD, "Bad switch\n");
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -613,6 +697,8 @@ fp_sqrt(sim_cpu *cpu,
|
||||
}
|
||||
|
||||
|
||||
/* Conversion operations. */
|
||||
|
||||
uword64
|
||||
convert (sim_cpu *cpu,
|
||||
address_word cia,
|
||||
|
81
sim/mips/cp1.h
Normal file
81
sim/mips/cp1.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*> cp1.h <*/
|
||||
/* MIPS Simulator FPU (CoProcessor 1) definitions.
|
||||
Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc.
|
||||
Derived from sim-main.h contributed by Cygnus Solutions,
|
||||
modified substially by Broadcom Corporation (SiByte).
|
||||
|
||||
This file is part of GDB, the GNU debugger.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef CP1_H
|
||||
#define CP1_H
|
||||
|
||||
/* See sim-main.h for allocation of registers FCR0 and FCR31 (FCSR)
|
||||
in CPU state (struct sim_cpu), and for FPU functions. */
|
||||
|
||||
#define fcsr_FCC_mask (0xFE800000)
|
||||
#define fcsr_FCC_shift (23)
|
||||
#define fcsr_FCC_bit(cc) ((cc) == 0 ? 23 : (24 + (cc)))
|
||||
#define fcsr_FS (1 << 24) /* MIPS III onwards : Flush to Zero */
|
||||
#define fcsr_ZERO_mask (0x007C0000)
|
||||
#define fcsr_CAUSE_mask (0x0003F000)
|
||||
#define fcsr_CAUSE_shift (12)
|
||||
#define fcsr_ENABLES_mask (0x00000F80)
|
||||
#define fcsr_ENABLES_shift (7)
|
||||
#define fcsr_FLAGS_mask (0x0000007C)
|
||||
#define fcsr_FLAGS_shift (2)
|
||||
#define fcsr_RM_mask (0x00000003)
|
||||
#define fcsr_RM_shift (0)
|
||||
|
||||
|
||||
/* Macros to update and retrieve the FCSR condition-code bits. This
|
||||
is complicated by the fact that there is a hole in the index range
|
||||
of the bits within the FCSR register. (Note that the number of bits
|
||||
visible depends on the ISA in use, but that is handled elsewhere.) */
|
||||
#define SETFCC(cc,v) \
|
||||
do { \
|
||||
(FCSR = ((FCSR & ~(1 << fcsr_FCC_bit(cc))) | ((v) << fcsr_FCC_bit(cc)))); \
|
||||
} while (0)
|
||||
#define GETFCC(cc) ((FCSR & (1 << fcsr_FCC_bit(cc))) != 0 ? 1 : 0)
|
||||
|
||||
|
||||
/* Read flush-to-zero bit (not right-justified). */
|
||||
#define GETFS() ((int)(FCSR & fcsr_FS))
|
||||
|
||||
|
||||
/* FCSR flag bits definitions and access macros. */
|
||||
#define IR 0 /* I: Inexact Result */
|
||||
#define UF 1 /* U: UnderFlow */
|
||||
#define OF 2 /* O: OverFlow */
|
||||
#define DZ 3 /* Z: Division by Zero */
|
||||
#define IO 4 /* V: Invalid Operation */
|
||||
#define UO 5 /* E: Unimplemented Operation (CAUSE field only) */
|
||||
|
||||
#define FP_FLAGS(b) (1 << ((b) + fcsr_FLAGS_shift))
|
||||
#define FP_ENABLE(b) (1 << ((b) + fcsr_ENABLES_shift))
|
||||
#define FP_CAUSE(b) (1 << ((b) + fcsr_CAUSE_shift))
|
||||
|
||||
|
||||
/* Rounding mode bit definitions and access macros. */
|
||||
#define FP_RM_NEAREST 0 /* Round to nearest (Round). */
|
||||
#define FP_RM_TOZERO 1 /* Round to zero (Trunc). */
|
||||
#define FP_RM_TOPINF 2 /* Round to Plus infinity (Ceil). */
|
||||
#define FP_RM_TOMINF 3 /* Round to Minus infinity (Floor). */
|
||||
|
||||
#define GETRM() ((FCSR >> fcsr_RM_shift) & fcsr_RM_mask)
|
||||
|
||||
|
||||
#endif /* CP1_H */
|
@ -3747,45 +3747,6 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// C.EQ.S
|
||||
// C.EQ.D
|
||||
// ...
|
||||
|
||||
:function:::void:do_c_cond_fmt:int fmt, int ft, int fs, int cc, int cond, instruction_word insn
|
||||
{
|
||||
int less;
|
||||
int equal;
|
||||
int unordered;
|
||||
int condition;
|
||||
unsigned64 ofs = ValueFPR (fs, fmt);
|
||||
unsigned64 oft = ValueFPR (ft, fmt);
|
||||
if (NaN (ofs, fmt) || NaN (oft, fmt))
|
||||
{
|
||||
if (FCSR & FP_ENABLE (IO))
|
||||
{
|
||||
FCSR |= FP_CAUSE (IO);
|
||||
SignalExceptionFPE ();
|
||||
}
|
||||
less = 0;
|
||||
equal = 0;
|
||||
unordered = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
less = Less (ofs, oft, fmt);
|
||||
equal = Equal (ofs, oft, fmt);
|
||||
unordered = 0;
|
||||
}
|
||||
condition = (((cond & (1 << 2)) && less)
|
||||
|| ((cond & (1 << 1)) && equal)
|
||||
|| ((cond & (1 << 0)) && unordered));
|
||||
SETFCC (cc, condition);
|
||||
}
|
||||
|
||||
010001,10,3.FMT,5.FT,5.FS,3.0,00,11,4.COND:COP1:32,f::C.cond.fmta
|
||||
"c.%s<COND>.%s<FMT> f<FS>, f<FT>"
|
||||
*mipsI:
|
||||
@ -3795,7 +3756,8 @@
|
||||
int fmt = FMT;
|
||||
check_fpu (SD_);
|
||||
check_fmt_p (SD_, fmt, instruction_0);
|
||||
do_c_cond_fmt (SD_, fmt, FT, FS, 0, COND, instruction_0);
|
||||
Compare (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt, COND, 0);
|
||||
TRACE_ALU_RESULT (ValueFCR (31));
|
||||
}
|
||||
|
||||
010001,10,3.FMT,5.FT,5.FS,3.CC,00,11,4.COND:COP1:32,f::C.cond.fmtb
|
||||
@ -3812,7 +3774,8 @@
|
||||
int fmt = FMT;
|
||||
check_fpu (SD_);
|
||||
check_fmt_p (SD_, fmt, instruction_0);
|
||||
do_c_cond_fmt (SD_, fmt, FT, FS, CC, COND, instruction_0);
|
||||
Compare (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt, COND, CC);
|
||||
TRACE_ALU_RESULT (ValueFCR (31));
|
||||
}
|
||||
|
||||
|
||||
@ -3851,80 +3814,92 @@
|
||||
}
|
||||
|
||||
|
||||
// CFC1
|
||||
// CTC1
|
||||
010001,00,X,10,5.RT,5.FS,00000000000:COP1Sa:32,f::CxC1
|
||||
"c%s<X>c1 r<RT>, f<FS>"
|
||||
010001,00010,5.RT,5.FS,00000000000:COP1:32,f::CFC1a
|
||||
"cfc1 r<RT>, f<FS>"
|
||||
*mipsI:
|
||||
*mipsII:
|
||||
*mipsIII:
|
||||
{
|
||||
check_fpu (SD_);
|
||||
if (X)
|
||||
{
|
||||
if (FS == 0)
|
||||
PENDING_FILL(FCR0IDX,VL4_8(GPR[RT]));
|
||||
else if (FS == 31)
|
||||
PENDING_FILL(FCR31IDX,VL4_8(GPR[RT]));
|
||||
/* else NOP */
|
||||
PENDING_SCHED(FCSR, FCR31 & (1<<23), 1, 23);
|
||||
}
|
||||
else
|
||||
{ /* control from */
|
||||
if (FS == 0)
|
||||
PENDING_FILL(RT, EXTEND32 (FCR0));
|
||||
else if (FS == 31)
|
||||
PENDING_FILL(RT, EXTEND32 (FCR31));
|
||||
/* else NOP */
|
||||
}
|
||||
if (FS == 0)
|
||||
PENDING_FILL (RT, EXTEND32 (FCR0));
|
||||
else if (FS == 31)
|
||||
PENDING_FILL (RT, EXTEND32 (FCR31));
|
||||
/* else NOP */
|
||||
}
|
||||
010001,00,X,10,5.RT,5.FS,00000000000:COP1Sb:32,f::CxC1
|
||||
"c%s<X>c1 r<RT>, f<FS>"
|
||||
|
||||
010001,00010,5.RT,5.FS,00000000000:COP1:32,f::CFC1b
|
||||
"cfc1 r<RT>, f<FS>"
|
||||
*mipsIV:
|
||||
*mipsV:
|
||||
*mips32:
|
||||
*mips64:
|
||||
*vr4100:
|
||||
*vr5000:
|
||||
*r3900:
|
||||
{
|
||||
check_fpu (SD_);
|
||||
if (X)
|
||||
if (FS == 0 || FS == 31)
|
||||
{
|
||||
/* control to */
|
||||
TRACE_ALU_INPUT1 (GPR[RT]);
|
||||
if (FS == 0)
|
||||
{
|
||||
FCR0 = VL4_8(GPR[RT]);
|
||||
TRACE_ALU_RESULT (FCR0);
|
||||
}
|
||||
else if (FS == 31)
|
||||
{
|
||||
FCR31 = VL4_8(GPR[RT]);
|
||||
SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
|
||||
TRACE_ALU_RESULT (FCR31);
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_ALU_RESULT0 ();
|
||||
}
|
||||
/* else NOP */
|
||||
unsigned_word fcr = ValueFCR (FS);
|
||||
TRACE_ALU_INPUT1 (fcr);
|
||||
GPR[RT] = fcr;
|
||||
}
|
||||
else
|
||||
{ /* control from */
|
||||
if (FS == 0)
|
||||
{
|
||||
TRACE_ALU_INPUT1 (FCR0);
|
||||
GPR[RT] = EXTEND32 (FCR0);
|
||||
}
|
||||
else if (FS == 31)
|
||||
{
|
||||
TRACE_ALU_INPUT1 (FCR31);
|
||||
GPR[RT] = EXTEND32 (FCR31);
|
||||
}
|
||||
TRACE_ALU_RESULT (GPR[RT]);
|
||||
/* else NOP */
|
||||
/* else NOP */
|
||||
TRACE_ALU_RESULT (GPR[RT]);
|
||||
}
|
||||
|
||||
010001,00010,5.RT,5.FS,00000000000:COP1:32,f::CFC1c
|
||||
"cfc1 r<RT>, f<FS>"
|
||||
*mipsV:
|
||||
*mips32:
|
||||
*mips64:
|
||||
{
|
||||
check_fpu (SD_);
|
||||
if (FS == 0 || FS == 25 || FS == 26 || FS == 28 || FS == 31)
|
||||
{
|
||||
unsigned_word fcr = ValueFCR (FS);
|
||||
TRACE_ALU_INPUT1 (fcr);
|
||||
GPR[RT] = fcr;
|
||||
}
|
||||
/* else NOP */
|
||||
TRACE_ALU_RESULT (GPR[RT]);
|
||||
}
|
||||
|
||||
010001,00110,5.RT,5.FS,00000000000:COP1:32,f::CTC1a
|
||||
"ctc1 r<RT>, f<FS>"
|
||||
*mipsI:
|
||||
*mipsII:
|
||||
*mipsIII:
|
||||
{
|
||||
check_fpu (SD_);
|
||||
if (FS == 31)
|
||||
PENDING_FILL (FCRCS_REGNUM, VL4_8 (GPR[RT]));
|
||||
/* else NOP */
|
||||
}
|
||||
|
||||
010001,00110,5.RT,5.FS,00000000000:COP1:32,f::CTC1b
|
||||
"ctc1 r<RT>, f<FS>"
|
||||
*mipsIV:
|
||||
*vr4100:
|
||||
*vr5000:
|
||||
*r3900:
|
||||
{
|
||||
check_fpu (SD_);
|
||||
TRACE_ALU_INPUT1 (GPR[RT]);
|
||||
if (FS == 31)
|
||||
StoreFCR (FS, GPR[RT]);
|
||||
/* else NOP */
|
||||
}
|
||||
|
||||
010001,00110,5.RT,5.FS,00000000000:COP1:32,f::CTC1c
|
||||
"ctc1 r<RT>, f<FS>"
|
||||
*mipsV:
|
||||
*mips32:
|
||||
*mips64:
|
||||
{
|
||||
check_fpu (SD_);
|
||||
TRACE_ALU_INPUT1 (GPR[RT]);
|
||||
if (FS == 25 || FS == 26 || FS == 28 || FS == 31)
|
||||
StoreFCR (FS, GPR[RT]);
|
||||
/* else NOP */
|
||||
}
|
||||
|
||||
|
||||
@ -4047,42 +4022,25 @@
|
||||
}
|
||||
|
||||
|
||||
// DMFC1
|
||||
// DMTC1
|
||||
010001,00,X,01,5.RT,5.FS,00000000000:COP1Sa:64,f::DMxC1
|
||||
"dm%s<X>c1 r<RT>, f<FS>"
|
||||
010001,00001,5.RT,5.FS,00000000000:COP1:64,f::DMFC1a
|
||||
"dmfc1 r<RT>, f<FS>"
|
||||
*mipsIII:
|
||||
{
|
||||
unsigned64 v;
|
||||
check_fpu (SD_);
|
||||
check_u64 (SD_, instruction_0);
|
||||
if (X)
|
||||
{
|
||||
if (SizeFGR() == 64)
|
||||
PENDING_FILL((FS + FGR_BASE),GPR[RT]);
|
||||
else if ((FS & 0x1) == 0)
|
||||
{
|
||||
PENDING_FILL(((FS + 1) + FGR_BASE),VH4_8(GPR[RT]));
|
||||
PENDING_FILL((FS + FGR_BASE),VL4_8(GPR[RT]));
|
||||
}
|
||||
}
|
||||
if (SizeFGR () == 64)
|
||||
v = FGR[FS];
|
||||
else if ((FS & 0x1) == 0)
|
||||
v = SET64HI (FGR[FS+1]) | FGR[FS];
|
||||
else
|
||||
{
|
||||
if (SizeFGR() == 64)
|
||||
PENDING_FILL(RT,FGR[FS]);
|
||||
else if ((FS & 0x1) == 0)
|
||||
PENDING_FILL(RT,(SET64HI(FGR[FS+1]) | FGR[FS]));
|
||||
else
|
||||
{
|
||||
if (STATE_VERBOSE_P(SD))
|
||||
sim_io_eprintf (SD,
|
||||
"Warning: PC 0x%lx: semantic_DMxC1_COP1Sa 32-bit use of odd FPR number\n",
|
||||
(long) CIA);
|
||||
PENDING_FILL(RT,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);
|
||||
}
|
||||
}
|
||||
v = SET64HI (0xDEADC0DE) | 0xBAD0BAD0;
|
||||
PENDING_FILL (RT, v);
|
||||
TRACE_ALU_RESULT (v);
|
||||
}
|
||||
010001,00,X,01,5.RT,5.FS,00000000000:COP1Sb:64,f::DMxC1
|
||||
"dm%s<X>c1 r<RT>, f<FS>"
|
||||
|
||||
010001,00001,5.RT,5.FS,00000000000:COP1:64,f::DMFC1b
|
||||
"dmfc1 r<RT>, f<FS>"
|
||||
*mipsIV:
|
||||
*mipsV:
|
||||
*mips64:
|
||||
@ -4092,28 +4050,52 @@
|
||||
{
|
||||
check_fpu (SD_);
|
||||
check_u64 (SD_, instruction_0);
|
||||
if (X)
|
||||
if (SizeFGR () == 64)
|
||||
GPR[RT] = FGR[FS];
|
||||
else if ((FS & 0x1) == 0)
|
||||
GPR[RT] = SET64HI (FGR[FS+1]) | FGR[FS];
|
||||
else
|
||||
GPR[RT] = SET64HI (0xDEADC0DE) | 0xBAD0BAD0;
|
||||
TRACE_ALU_RESULT (GPR[RT]);
|
||||
}
|
||||
|
||||
|
||||
010001,00101,5.RT,5.FS,00000000000:COP1:64,f::DMTC1a
|
||||
"dmtc1 r<RT>, f<FS>"
|
||||
*mipsIII:
|
||||
{
|
||||
unsigned64 v;
|
||||
check_fpu (SD_);
|
||||
check_u64 (SD_, instruction_0);
|
||||
if (SizeFGR () == 64)
|
||||
PENDING_FILL ((FS + FGR_BASE), GPR[RT]);
|
||||
else if ((FS & 0x1) == 0)
|
||||
{
|
||||
if (SizeFGR() == 64)
|
||||
StoreFPR (FS, fmt_uninterpreted_64, GPR[RT]);
|
||||
else if ((FS & 0x1) == 0)
|
||||
StoreFPR (FS, fmt_uninterpreted_64, SET64HI (FGR[FS+1]) | FGR[FS]);
|
||||
PENDING_FILL (((FS + 1) + FGR_BASE), VH4_8 (GPR[RT]));
|
||||
PENDING_FILL ((FS + FGR_BASE), VL4_8 (GPR[RT]));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SizeFGR() == 64)
|
||||
GPR[RT] = FGR[FS];
|
||||
else if ((FS & 0x1) == 0)
|
||||
GPR[RT] = SET64HI (FGR[FS+1]) | FGR[FS];
|
||||
else
|
||||
{
|
||||
if (STATE_VERBOSE_P(SD))
|
||||
sim_io_eprintf (SD,
|
||||
"Warning: PC 0x%lx: DMxC1 32-bit use of odd FPR number\n",
|
||||
(long) CIA);
|
||||
GPR[RT] = SET64HI (0xDEADC0DE) | 0xBAD0BAD0;
|
||||
}
|
||||
}
|
||||
Unpredictable ();
|
||||
TRACE_FP_RESULT (GPR[RT]);
|
||||
}
|
||||
|
||||
010001,00101,5.RT,5.FS,00000000000:COP1:64,f::DMTC1b
|
||||
"dmtc1 r<RT>, f<FS>"
|
||||
*mipsIV:
|
||||
*mipsV:
|
||||
*mips64:
|
||||
*vr4100:
|
||||
*vr5000:
|
||||
*r3900:
|
||||
{
|
||||
check_fpu (SD_);
|
||||
check_u64 (SD_, instruction_0);
|
||||
if (SizeFGR () == 64)
|
||||
StoreFPR (FS, fmt_uninterpreted_64, GPR[RT]);
|
||||
else if ((FS & 0x1) == 0)
|
||||
StoreFPR (FS, fmt_uninterpreted_64, GPR[RT]);
|
||||
else
|
||||
Unpredictable ();
|
||||
}
|
||||
|
||||
|
||||
@ -4247,33 +4229,21 @@
|
||||
}
|
||||
|
||||
|
||||
// MFC1
|
||||
// MTC1
|
||||
010001,00,X,00,5.RT,5.FS,00000000000:COP1Sa:32,f::MxC1
|
||||
"m%s<X>c1 r<RT>, f<FS>"
|
||||
010001,00000,5.RT,5.FS,00000000000:COP1:32,f::MFC1a
|
||||
"mfc1 r<RT>, f<FS>"
|
||||
*mipsI:
|
||||
*mipsII:
|
||||
*mipsIII:
|
||||
{
|
||||
unsigned64 v;
|
||||
check_fpu (SD_);
|
||||
if (X)
|
||||
{ /*MTC1*/
|
||||
if (SizeFGR() == 64)
|
||||
{
|
||||
if (STATE_VERBOSE_P(SD))
|
||||
sim_io_eprintf (SD,
|
||||
"Warning: PC 0x%lx: MTC1 not DMTC1 with 64 bit regs\n",
|
||||
(long) CIA);
|
||||
PENDING_FILL ((FS + FGR_BASE), (SET64HI(0xDEADC0DE) | VL4_8(GPR[RT])));
|
||||
}
|
||||
else
|
||||
PENDING_FILL ((FS + FGR_BASE), VL4_8(GPR[RT]));
|
||||
}
|
||||
else /*MFC1*/
|
||||
PENDING_FILL (RT, EXTEND32 (FGR[FS]));
|
||||
v = EXTEND32 (FGR[FS]);
|
||||
PENDING_FILL (RT, v);
|
||||
TRACE_ALU_RESULT (v);
|
||||
}
|
||||
010001,00,X,00,5.RT,5.FS,00000000000:COP1Sb:32,f::MxC1
|
||||
"m%s<X>c1 r<RT>, f<FS>"
|
||||
|
||||
010001,00000,5.RT,5.FS,00000000000:COP1:32,f::MFC1b
|
||||
"mfc1 r<RT>, f<FS>"
|
||||
*mipsIV:
|
||||
*mipsV:
|
||||
*mips32:
|
||||
@ -4281,14 +4251,10 @@
|
||||
*vr4100:
|
||||
*vr5000:
|
||||
*r3900:
|
||||
{
|
||||
int fs = FS;
|
||||
{
|
||||
check_fpu (SD_);
|
||||
if (X)
|
||||
/*MTC1*/
|
||||
StoreFPR (FS, fmt_uninterpreted_32, VL4_8 (GPR[RT]));
|
||||
else /*MFC1*/
|
||||
GPR[RT] = EXTEND32 (FGR[FS]);
|
||||
GPR[RT] = EXTEND32 (FGR[FS]);
|
||||
TRACE_ALU_RESULT (GPR[RT]);
|
||||
}
|
||||
|
||||
|
||||
@ -4414,7 +4380,33 @@
|
||||
}
|
||||
|
||||
|
||||
// MTC1 see MxC1
|
||||
010001,00100,5.RT,5.FS,00000000000:COP1:32,f::MTC1a
|
||||
"mtc1 r<RT>, f<FS>"
|
||||
*mipsI:
|
||||
*mipsII:
|
||||
*mipsIII:
|
||||
{
|
||||
check_fpu (SD_);
|
||||
if (SizeFGR () == 64)
|
||||
PENDING_FILL ((FS + FGR_BASE), (SET64HI (0xDEADC0DE) | VL4_8 (GPR[RT])));
|
||||
else
|
||||
PENDING_FILL ((FS + FGR_BASE), VL4_8 (GPR[RT]));
|
||||
TRACE_FP_RESULT (GPR[RT]);
|
||||
}
|
||||
|
||||
010001,00100,5.RT,5.FS,00000000000:COP1:32,f::MTC1b
|
||||
"mtc1 r<RT>, f<FS>"
|
||||
*mipsIV:
|
||||
*mipsV:
|
||||
*mips32:
|
||||
*mips64:
|
||||
*vr4100:
|
||||
*vr5000:
|
||||
*r3900:
|
||||
{
|
||||
check_fpu (SD_);
|
||||
StoreFPR (FS, fmt_uninterpreted_32, VL4_8 (GPR[RT]));
|
||||
}
|
||||
|
||||
|
||||
010001,10,3.FMT,5.FT,5.FS,5.FD,000010:COP1:32,f::MUL.fmt
|
||||
|
@ -64,6 +64,7 @@ typedef unsigned64 uword64;
|
||||
/* Floating-point operations: */
|
||||
|
||||
#include "sim-fpu.h"
|
||||
#include "cp1.h"
|
||||
|
||||
/* FPU registers must be one of the following types. All other values
|
||||
are reserved (and undefined). */
|
||||
@ -80,17 +81,6 @@ typedef enum {
|
||||
fmt_uninterpreted_64 = 0x80000000U,
|
||||
} FP_formats;
|
||||
|
||||
/* Macro to update FPSR condition-code field. This is complicated by
|
||||
the fact that there is a hole in the index range of the bits within
|
||||
the FCSR register. Also, the number of bits visible depends on the
|
||||
MIPS ISA version being supported. */
|
||||
|
||||
#define SETFCC(cc,v) {\
|
||||
int bit = ((cc == 0) ? 23 : (24 + (cc)));\
|
||||
FCSR = ((FCSR & ~(1 << bit)) | ((v) << bit));\
|
||||
}
|
||||
#define GETFCC(cc) (((((cc) == 0) ? (FCSR & (1 << 23)) : (FCSR & (1 << (24 + (cc))))) != 0) ? 1U : 0)
|
||||
|
||||
/* This should be the COC1 value at the start of the preceding
|
||||
instruction: */
|
||||
#define PREVCOC1() ((STATE & simPCOC1) ? 1 : 0)
|
||||
@ -104,36 +94,6 @@ typedef enum {
|
||||
#define SizeFGR() (WITH_TARGET_FLOATING_POINT_BITSIZE)
|
||||
#endif
|
||||
|
||||
/* Standard FCRS bits: */
|
||||
#define IR (0) /* Inexact Result */
|
||||
#define UF (1) /* UnderFlow */
|
||||
#define OF (2) /* OverFlow */
|
||||
#define DZ (3) /* Division by Zero */
|
||||
#define IO (4) /* Invalid Operation */
|
||||
#define UO (5) /* Unimplemented Operation */
|
||||
|
||||
/* Get masks for individual flags: */
|
||||
#if 1 /* SAFE version */
|
||||
#define FP_FLAGS(b) (((unsigned)(b) < 5) ? (1 << ((b) + 2)) : 0)
|
||||
#define FP_ENABLE(b) (((unsigned)(b) < 5) ? (1 << ((b) + 7)) : 0)
|
||||
#define FP_CAUSE(b) (((unsigned)(b) < 6) ? (1 << ((b) + 12)) : 0)
|
||||
#else
|
||||
#define FP_FLAGS(b) (1 << ((b) + 2))
|
||||
#define FP_ENABLE(b) (1 << ((b) + 7))
|
||||
#define FP_CAUSE(b) (1 << ((b) + 12))
|
||||
#endif
|
||||
|
||||
#define FP_FS (1 << 24) /* MIPS III onwards : Flush to Zero */
|
||||
|
||||
#define FP_MASK_RM (0x3)
|
||||
#define FP_SH_RM (0)
|
||||
#define FP_RM_NEAREST (0) /* Round to nearest (Round) */
|
||||
#define FP_RM_TOZERO (1) /* Round to zero (Trunc) */
|
||||
#define FP_RM_TOPINF (2) /* Round to Plus infinity (Ceil) */
|
||||
#define FP_RM_TOMINF (3) /* Round to Minus infinity (Floor) */
|
||||
#define GETRM() (int)((FCSR >> FP_SH_RM) & FP_MASK_RM)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -716,10 +676,18 @@ void store_fpr (SIM_STATE, int fpr, FP_formats fmt, unsigned64 value);
|
||||
#define StoreFPR(FPR,FMT,VALUE) store_fpr (SIM_ARGS, (FPR), (FMT), (VALUE))
|
||||
|
||||
|
||||
/* FCR access. */
|
||||
unsigned_word value_fcr (SIM_STATE, int fcr);
|
||||
#define ValueFCR(FCR) value_fcr (SIM_ARGS, (FCR))
|
||||
void store_fcr (SIM_STATE, int fcr, unsigned_word value);
|
||||
#define StoreFCR(FCR,VALUE) store_fcr (SIM_ARGS, (FCR), (VALUE))
|
||||
void test_fcsr (SIM_STATE);
|
||||
#define TestFCSR() test_fcsr (SIM_ARGS)
|
||||
|
||||
|
||||
/* FPU operations. */
|
||||
int NaN (unsigned64 op, FP_formats fmt);
|
||||
int Less (unsigned64 op1, unsigned64 op2, FP_formats fmt);
|
||||
int Equal (unsigned64 op1, unsigned64 op2, FP_formats fmt);
|
||||
void fp_cmp (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt, int abs, int cond, int cc);
|
||||
#define Compare(op1,op2,fmt,cond,cc) fp_cmp(SIM_ARGS, op1, op2, fmt, 0, cond, cc)
|
||||
unsigned64 fp_abs (SIM_STATE, unsigned64 op, FP_formats fmt);
|
||||
#define AbsoluteValue(op,fmt) fp_abs(SIM_ARGS, op, fmt)
|
||||
unsigned64 fp_neg (SIM_STATE, unsigned64 op, FP_formats fmt);
|
||||
|
Loading…
Reference in New Issue
Block a user