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:
Chris Demetriou 2002-06-07 00:13:24 +00:00
parent feb2269354
commit cfe9ea23c7
5 changed files with 473 additions and 320 deletions

View File

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

View File

@ -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
View 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 */

View File

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

View File

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