From cfe9ea23c76110bc8aa48c77904e5a802f06a367 Mon Sep 17 00:00:00 2001 From: Chris Demetriou Date: Fri, 7 Jun 2002 00:13:24 +0000 Subject: [PATCH] 2002-06-06 Chris Demetriou Ed Satterthwaite * 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. --- sim/mips/ChangeLog | 26 ++++ sim/mips/cp1.c | 266 ++++++++++++++++++++++------------ sim/mips/cp1.h | 81 +++++++++++ sim/mips/mips.igen | 346 ++++++++++++++++++++++---------------------- sim/mips/sim-main.h | 56 ++----- 5 files changed, 464 insertions(+), 311 deletions(-) create mode 100644 sim/mips/cp1.h diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index 771edae002..dff7b80707 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,3 +1,29 @@ +2002-06-06 Chris Demetriou + Ed Satterthwaite + + * 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 * sim-main.h (FGRIDX): Remove, replace all uses with... diff --git a/sim/mips/cp1.c b/sim/mips/cp1.c index 442c31184e..3641df7fc9 100644 --- a/sim/mips/cp1.c +++ b/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,77 +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 */ +unsigned_word +value_fcr(sim_cpu *cpu, + address_word cia, + int fcr) +{ + unsigned32 value = 0; + + switch (fcr) + { + 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; + } - return (boolean); + return (EXTEND32 (value)); } -int -Less (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: Less: %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_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: @@ -391,61 +476,60 @@ Less (op1, op2, fmt) abort (); } -#ifdef DEBUG - printf ("DBG: Less: returning %d (format = %s)\n", - boolean, fpu_format_name (fmt)); -#endif /* DEBUG */ - - return (boolean); + 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; } -int -Equal (op1, op2, fmt) - uword64 op1; - uword64 op2; - FP_formats fmt; +void +fp_cmp(sim_cpu *cpu, + address_word cia, + unsigned64 op1, + unsigned64 op2, + FP_formats fmt, + int abs, + int cond, + int cc) { - int boolean = 0; - - /* Argument checking already performed by the FPCOMPARE code */ + sim_fpu_status status = 0; -#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 */ - - /* The format type should already have been checked: */ + /* The format type should already have 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); + int result; + status = fp_test(op1, op2, fmt, abs, cond, &result); + update_fcsr (cpu, cia, status); + SETFCC (cc, result); break; } default: - fprintf (stderr, "Bad switch\n"); + sim_io_eprintf (SD, "Bad switch\n"); abort (); } - -#ifdef DEBUG - printf ("DBG: Equal: returning %d (format = %s)\n", - boolean, fpu_format_name (fmt)); -#endif /* DEBUG */ - - return (boolean); } @@ -613,6 +697,8 @@ fp_sqrt(sim_cpu *cpu, } +/* Conversion operations. */ + uword64 convert (sim_cpu *cpu, address_word cia, diff --git a/sim/mips/cp1.h b/sim/mips/cp1.h new file mode 100644 index 0000000000..90919e3b2d --- /dev/null +++ b/sim/mips/cp1.h @@ -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 */ diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen index 874b685aa7..f374a54d57 100644 --- a/sim/mips/mips.igen +++ b/sim/mips/mips.igen @@ -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.%s f, f" *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%sc1 r, f" +010001,00010,5.RT,5.FS,00000000000:COP1:32,f::CFC1a +"cfc1 r, f" *mipsI: *mipsII: *mipsIII: { check_fpu (SD_); - if (X) + if (FS == 0) + PENDING_FILL (RT, EXTEND32 (FCR0)); + else if (FS == 31) + PENDING_FILL (RT, EXTEND32 (FCR31)); + /* else NOP */ +} + +010001,00010,5.RT,5.FS,00000000000:COP1:32,f::CFC1b +"cfc1 r, f" +*mipsIV: +*vr4100: +*vr5000: +*r3900: +{ + check_fpu (SD_); + if (FS == 0 || FS == 31) { - 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 */ + unsigned_word fcr = ValueFCR (FS); + TRACE_ALU_INPUT1 (fcr); + GPR[RT] = fcr; } + /* else NOP */ + TRACE_ALU_RESULT (GPR[RT]); } -010001,00,X,10,5.RT,5.FS,00000000000:COP1Sb:32,f::CxC1 -"c%sc1 r, f" -*mipsIV: + +010001,00010,5.RT,5.FS,00000000000:COP1:32,f::CFC1c +"cfc1 r, f" *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, f" +*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, f" +*mipsIV: *vr4100: *vr5000: *r3900: { check_fpu (SD_); - if (X) - { - /* 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 */ - } - 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 */ - } + 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, f" +*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%sc1 r, f" +010001,00001,5.RT,5.FS,00000000000:COP1:64,f::DMFC1a +"dmfc1 r, f" *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%sc1 r, f" + +010001,00001,5.RT,5.FS,00000000000:COP1:64,f::DMFC1b +"dmfc1 r, f" *mipsIV: *mipsV: *mips64: @@ -4092,28 +4050,52 @@ { check_fpu (SD_); check_u64 (SD_, instruction_0); - if (X) - { - 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]); - } + 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, f" +*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) - 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; - } + PENDING_FILL (((FS + 1) + FGR_BASE), VH4_8 (GPR[RT])); + PENDING_FILL ((FS + FGR_BASE), VL4_8 (GPR[RT])); } + else + Unpredictable (); + TRACE_FP_RESULT (GPR[RT]); +} + +010001,00101,5.RT,5.FS,00000000000:COP1:64,f::DMTC1b +"dmtc1 r, f" +*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%sc1 r, f" +010001,00000,5.RT,5.FS,00000000000:COP1:32,f::MFC1a +"mfc1 r, f" *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%sc1 r, f" + +010001,00000,5.RT,5.FS,00000000000:COP1:32,f::MFC1b +"mfc1 r, f" *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, f" +*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, f" +*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 diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h index 0c3d17b48d..efbf98ab86 100644 --- a/sim/mips/sim-main.h +++ b/sim/mips/sim-main.h @@ -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); -- 2.34.1