diff options
-rw-r--r-- | sim/mips/ChangeLog | 20 | ||||
-rw-r--r-- | sim/mips/Makefile.in | 1 | ||||
-rwxr-xr-x | sim/mips/configure | 2 | ||||
-rw-r--r-- | sim/mips/configure.in | 2 | ||||
-rw-r--r-- | sim/mips/cp1.c | 253 | ||||
-rw-r--r-- | sim/mips/mips.igen | 4 | ||||
-rw-r--r-- | sim/mips/mips3d.igen | 176 | ||||
-rw-r--r-- | sim/mips/sim-main.h | 21 |
8 files changed, 475 insertions, 4 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index 1cb95e0..d08971d 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,3 +1,23 @@ +2002-06-14 Chris Demetriou <cgd@broadcom.com> + Ed Satterthwaite <ehs@broadcom.com> + + * mips3d.igen: New file which contains MIPS-3D ASE instructions. + * Makefile.in (IGEN_INCLUDE): Add mips3d.igen. + * mips.igen: Include mips3d.igen. + (mips3d): New model name for MIPS-3D ASE instructions. + (CVT.W.fmt): Don't use this instruction for word (source) format + instructions. + * cp1.c (fp_binary_r, fp_add_r, fp_mul_r, fpu_inv1, fpu_inv1_32) + (fpu_inv1_64, fp_recip1, fp_recip2, fpu_inv_sqrt1, fpu_inv_sqrt1_32) + (fpu_inv_sqrt1_64, fp_rsqrt1, fp_rsqrt2): New functions. + (NR_FRAC_GUARD, IMPLICIT_1): New macros. + * sim-main.h (fmt_pw, CompareAbs, AddR, MultiplyR, Recip1, Recip2) + (RSquareRoot1, RSquareRoot2): New macros. + (fp_add_r, fp_mul_r, fp_recip1, fp_recip2, fp_rsqrt1) + (fp_rsqrt2): New functions. + * configure.in: Add MIPS-3D support to mipsisa64 simulator. + * configure: Regenerate. + 2002-06-13 Chris Demetriou <cgd@broadcom.com> Ed Satterthwaite <ehs@broadcom.com> diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in index f4604c0..e0e9faf 100644 --- a/sim/mips/Makefile.in +++ b/sim/mips/Makefile.in @@ -84,6 +84,7 @@ M16_DC=$(srcdir)/m16.dc IGEN_INCLUDE=\ $(srcdir)/m16.igen \ $(srcdir)/mdmx.igen \ + $(srcdir)/mips3d.igen \ $(srcdir)/sb1.igen \ $(srcdir)/tx.igen \ $(srcdir)/vr.igen \ diff --git a/sim/mips/configure b/sim/mips/configure index 2a9d8b9..859757a 100755 --- a/sim/mips/configure +++ b/sim/mips/configure @@ -4028,7 +4028,7 @@ case "${target}" in sim_igen_filter="32,64,f" ;; mipsisa64*-*-*) sim_gen=IGEN - sim_igen_machine="-M mips64" + sim_igen_machine="-M mips64,mips3d" sim_igen_filter="32,64,f" ;; mips*lsi*) sim_gen=M16 diff --git a/sim/mips/configure.in b/sim/mips/configure.in index bb71308..3672b66 100644 --- a/sim/mips/configure.in +++ b/sim/mips/configure.in @@ -133,7 +133,7 @@ case "${target}" in sim_igen_filter="32,64,f" ;; mipsisa64*-*-*) sim_gen=IGEN - sim_igen_machine="-M mips64" + sim_igen_machine="-M mips64,mips3d" sim_igen_filter="32,64,f" ;; mips*lsi*) sim_gen=M16 diff --git a/sim/mips/cp1.c b/sim/mips/cp1.c index 24c0a21..26249f0 100644 --- a/sim/mips/cp1.c +++ b/sim/mips/cp1.c @@ -2,7 +2,8 @@ /* MIPS Simulator FPU (CoProcessor 1) support. Copyright (C) 2002 Free Software Foundation, Inc. Originally created by Cygnus Solutions, modified substially - by Broadcom Corporation (SiByte). + by Broadcom Corporation (SiByte). Paired-single operation support + and MIPS-3D support contributed by Broadcom Corporation (SiByte). This file is part of GDB, the GNU debugger. @@ -1098,6 +1099,256 @@ fp_nmsub(sim_cpu *cpu, } +/* MIPS-3D ASE operations. */ + +/* Variant of fp_binary for *r.ps MIPS-3D operations. */ +static unsigned64 +fp_binary_r(sim_cpu *cpu, + address_word cia, + int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *), + unsigned64 op1, + unsigned64 op2) +{ + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + sim_fpu_round round = rounding_mode (GETRM ()); + sim_fpu_denorm denorm = denorm_mode (cpu); + sim_fpu_status status_u, status_l; + unsigned64 result; + unsigned32 res_u, res_l; + + /* The format must be fmt_ps. */ + status_u = 0; + sim_fpu_32to (&wop1, FP_PS_upper (op1)); + sim_fpu_32to (&wop2, FP_PS_lower (op1)); + status_u |= (*sim_fpu_op) (&ans, &wop1, &wop2); + status_u |= sim_fpu_round_32 (&ans, round, denorm); + sim_fpu_to32 (&res_u, &ans); + status_l = 0; + sim_fpu_32to (&wop1, FP_PS_upper (op2)); + sim_fpu_32to (&wop2, FP_PS_lower (op2)); + status_l |= (*sim_fpu_op) (&ans, &wop1, &wop2); + status_l |= sim_fpu_round_32 (&ans, round, denorm); + sim_fpu_to32 (&res_l, &ans); + result = FP_PS_cat (res_u, res_l); + + update_fcsr (cpu, cia, status_u | status_l); + return result; +} + +unsigned64 +fp_add_r(sim_cpu *cpu, + address_word cia, + unsigned64 op1, + unsigned64 op2, + FP_formats fmt) +{ + return fp_binary_r (cpu, cia, &sim_fpu_add, op1, op2); +} + +unsigned64 +fp_mul_r(sim_cpu *cpu, + address_word cia, + unsigned64 op1, + unsigned64 op2, + FP_formats fmt) +{ + return fp_binary_r (cpu, cia, &sim_fpu_mul, op1, op2); +} + +#define NR_FRAC_GUARD (60) +#define IMPLICIT_1 LSBIT64 (NR_FRAC_GUARD) + +static int +fpu_inv1(sim_fpu *f, const sim_fpu *l) +{ + static const sim_fpu sim_fpu_one = { + sim_fpu_class_number, 0, IMPLICIT_1, 0 + }; + int status = 0; + sim_fpu t; + + if (sim_fpu_is_zero (l)) + { + *f = sim_fpu_maxfp; + f->sign = l->sign; + return sim_fpu_status_invalid_div0; + } + if (sim_fpu_is_infinity (l)) + { + *f = sim_fpu_zero; + f->sign = l->sign; + return status; + } + status |= sim_fpu_div (f, &sim_fpu_one, l); + return status; +} + +static int +fpu_inv1_32(sim_fpu *f, const sim_fpu *l) +{ + if (sim_fpu_is_zero (l)) + { + *f = sim_fpu_max32; + f->sign = l->sign; + return sim_fpu_status_invalid_div0; + } + return fpu_inv1 (f, l); +} + +static int +fpu_inv1_64(sim_fpu *f, const sim_fpu *l) +{ + if (sim_fpu_is_zero (l)) + { + *f = sim_fpu_max64; + f->sign = l->sign; + return sim_fpu_status_invalid_div0; + } + return fpu_inv1 (f, l); +} + +unsigned64 +fp_recip1(sim_cpu *cpu, + address_word cia, + unsigned64 op, + FP_formats fmt) +{ + switch (fmt) + { + case fmt_single: + case fmt_ps: + return fp_unary (cpu, cia, &fpu_inv1_32, op, fmt); + case fmt_double: + return fp_unary (cpu, cia, &fpu_inv1_64, op, fmt); + } + return 0; +} + +unsigned64 +fp_recip2(sim_cpu *cpu, + address_word cia, + unsigned64 op1, + unsigned64 op2, + FP_formats fmt) +{ + static const unsigned64 one_single = UNSIGNED64 (0x3F800000); + static const unsigned64 one_double = UNSIGNED64 (0x3FF0000000000000); + static const unsigned64 one_ps = (one_single << 32 | one_single); + unsigned64 one; + + /* Implemented as nmsub fd, 1, fs, ft. */ + switch (fmt) + { + case fmt_single: one = one_single; break; + case fmt_double: one = one_double; break; + case fmt_ps: one = one_ps; break; + default: one = 0; abort (); + } + return fp_mac (cpu, cia, &sim_fpu_sub, op1, op2, one, 0, 1, fmt); +} + +static int +fpu_inv_sqrt1(sim_fpu *f, const sim_fpu *l) +{ + static const sim_fpu sim_fpu_one = { + sim_fpu_class_number, 0, IMPLICIT_1, 0 + }; + int status = 0; + sim_fpu t; + + if (sim_fpu_is_zero (l)) + { + *f = sim_fpu_maxfp; + f->sign = l->sign; + return sim_fpu_status_invalid_div0; + } + if (sim_fpu_is_infinity (l)) + { + if (!l->sign) + { + f->class = sim_fpu_class_zero; + f->sign = 0; + } + else + { + *f = sim_fpu_qnan; + status = sim_fpu_status_invalid_sqrt; + } + return status; + } + status |= sim_fpu_sqrt (&t, l); + status |= sim_fpu_div (f, &sim_fpu_one, &t); + return status; +} + +static int +fpu_inv_sqrt1_32(sim_fpu *f, const sim_fpu *l) +{ + if (sim_fpu_is_zero (l)) + { + *f = sim_fpu_max32; + f->sign = l->sign; + return sim_fpu_status_invalid_div0; + } + return fpu_inv_sqrt1 (f, l); +} + +static int +fpu_inv_sqrt1_64(sim_fpu *f, const sim_fpu *l) +{ + if (sim_fpu_is_zero (l)) + { + *f = sim_fpu_max64; + f->sign = l->sign; + return sim_fpu_status_invalid_div0; + } + return fpu_inv_sqrt1 (f, l); +} + +unsigned64 +fp_rsqrt1(sim_cpu *cpu, + address_word cia, + unsigned64 op, + FP_formats fmt) +{ + switch (fmt) + { + case fmt_single: + case fmt_ps: + return fp_unary (cpu, cia, &fpu_inv_sqrt1_32, op, fmt); + case fmt_double: + return fp_unary (cpu, cia, &fpu_inv_sqrt1_64, op, fmt); + } + return 0; +} + +unsigned64 +fp_rsqrt2(sim_cpu *cpu, + address_word cia, + unsigned64 op1, + unsigned64 op2, + FP_formats fmt) +{ + static const unsigned64 half_single = UNSIGNED64 (0x3F000000); + static const unsigned64 half_double = UNSIGNED64 (0x3FE0000000000000); + static const unsigned64 half_ps = (half_single << 32 | half_single); + unsigned64 half; + + /* Implemented as (nmsub fd, 0.5, fs, ft)/2, where the divide is + done by scaling the exponent during multiply. */ + switch (fmt) + { + case fmt_single: half = half_single; break; + case fmt_double: half = half_double; break; + case fmt_ps: half = half_ps; break; + default: half = 0; abort (); + } + return fp_mac (cpu, cia, &sim_fpu_sub, op1, op2, half, -1, 1, fmt); +} + + /* Conversion operations. */ uword64 diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen index a264365..1e55825 100644 --- a/sim/mips/mips.igen +++ b/sim/mips/mips.igen @@ -63,6 +63,7 @@ // Instructions for the ASEs are in separate .igen files. // ASEs add instructions on to a base ISA. :model:::mips16:mips16: // m16.igen (and m16.dc) +:model:::mips3d:mips3d: // mips3d.igen :model:::mdmx:mdmx: // mdmx.igen // Vendor Extensions @@ -4028,7 +4029,7 @@ } -010001,10,3.FMT,00000,5.FS,5.FD,100100:COP1:32,f::CVT.W.fmt +010001,10,3.FMT!6,00000,5.FS,5.FD,100100:COP1:32,f::CVT.W.fmt "cvt.w.%s<FMT> f<FD>, f<FS>" *mipsI: *mipsII: @@ -5123,6 +5124,7 @@ :include:::m16.igen :include:::mdmx.igen +:include:::mips3d.igen :include:::sb1.igen :include:::tx.igen :include:::vr.igen diff --git a/sim/mips/mips3d.igen b/sim/mips/mips3d.igen new file mode 100644 index 0000000..f7043ef --- /dev/null +++ b/sim/mips/mips3d.igen @@ -0,0 +1,176 @@ +// -*- C -*- + +// Simulator definition for the MIPS MIPS-3D ASE. +// Copyright (C) 2002 Free Software Foundation, Inc. +// Contributed 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. + +// Reference: MIPS64 Architecture for Programmers Volume IV-c: +// The MIPS-3D Application-Specific Extension to the +// MIPS64 Architecture. (MIPS Document MD00099) + + +010001,10,110,5.FT,5.FS,5.FD,011000:COP1:64,f::ADDR.PS +"addr.ps f<FD>, f<FS>, f<FT>" +*mips3d: +{ + /* fd.PL = ft.PU + ft.PL; fd.PU = fs.PU + fs.PL; */ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (FD, fmt_ps, AddR (ValueFPR (FS, fmt_ps), + ValueFPR (FT, fmt_ps), fmt_ps)); +} + + +010001,01001,3.CC,0,1.TF,16.OFFSET:COP1:64,f::BC1ANY2tf +"bc1any2%s<TF> <CC>, %#lx<OFFSET>" +*mips3d: +{ + address_word offset; + int cc = CC; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + if ((cc & 0x1) != 0) + Unpredictable (); + if ((GETFCC (cc) == TF) || (GETFCC (cc + 1) == TF)) + { + offset = (EXTEND16 (OFFSET) << 2); + DELAY_SLOT (NIA + offset); + } +} + + +010001,01010,3.CC,0,1.TF,16.OFFSET:COP1:64,f::BC1ANY4tf +"bc1any4%s<TF> <CC>, %#lx<OFFSET>" +*mips3d: +{ + address_word offset; + int cc = CC; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + if ((cc & 0x3) != 0) + Unpredictable (); + if ((GETFCC (cc) == TF) + || (GETFCC (cc + 1) == TF) + || (GETFCC (cc + 2) == TF) + || (GETFCC (cc + 3) == TF)) + { + offset = (EXTEND16 (OFFSET) << 2); + DELAY_SLOT (NIA + offset); + } +} + + +010001,10,3.FMT,5.FT,5.FS,3.CC,01,11,4.COND:COP1:64,f::CABS.cond.fmt +"cabs.%s<COND>.%s<FMT> <CC>, f<FS>, f<FT>" +*mips3d: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + CompareAbs (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt, COND, CC); + TRACE_ALU_RESULT (ValueFCR (31)); +} + + +010001,10,110,00000,5.FS,5.FD,100100:COP1:64,f::CVT.PW.PS +"cvt.pw.ps f<FD>, f<FS>" +*mips3d: +{ + /* fd.pu = cvt_rnd (fs.pu); fd.pl = cvt_rnd (fs.pl); */ + /* fmt_pw is fmt_long for 64 bit transfers, but cvt encoding is fmt_word. */ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (FD, fmt_pw, ConvertPS (GETRM (), ValueFPR (FS, fmt_ps), + fmt_ps, fmt_word)); +} + + +010001,10,100,00000,5.FS,5.FD,100110:COP1:64,f::CVT.PS.PW +"cvt.ps.pw f<FD>, f<FS>" +*mips3d: +{ + /* fd.pl = cvt_rnd (fs.pl); fd.pu = cvt_rnd (fs.pu); */ + /* fmt_pw is fmt_long for 64 bit transfers, but cvt encoding is fmt_word. */ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (FD, fmt_ps, ConvertPS (GETRM (), ValueFPR (FS, fmt_pw), + fmt_word, fmt_ps)); +} + + +010001,10,110,5.FT,5.FS,5.FD,011010:COP1:64,f::MULR.PS +"mulr.ps f<FD>, f<FS>, f<FT>" +*mips3d: +{ + /* fd.PL = ft.PU * ft.PL; fd.PU = fs.PU * fs.PL; */ + check_fpu (SD_); + check_u64 (SD_, instruction_0); + StoreFPR (FD, fmt_ps, MultiplyR (ValueFPR (FS, fmt_ps), + ValueFPR (FT, fmt_ps), fmt_ps)); +} + + +010001,10,3.FMT,00000,5.FS,5.FD,011101:COP1:64,f::RECIP1.fmt +"recip1.%s<FMT> f<FD>, f<FS>" +*mips3d: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (FD, fmt, Recip1 (ValueFPR (FS, fmt), fmt)); +} + + +010001,10,3.FMT,5.FT,5.FS,5.FD,011100:COP1:64,f::RECIP2.fmt +"recip2.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips3d: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (FD, fmt, Recip2 (ValueFPR (FS, fmt), ValueFPR (FT, fmt), fmt)); +} + + +010001,10,3.FMT,00000,5.FS,5.FD,011110:COP1:64,f::RSQRT1.fmt +"rsqrt1.%s<FMT> f<FD>, f<FS>" +*mips3d: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (FD, fmt, RSquareRoot1 (ValueFPR (FS, fmt), fmt)); +} + + +010001,10,3.FMT,5.FT,5.FS,5.FD,011111:COP1:64,f::RSQRT2.fmt +"rsqrt2.%s<FMT> f<FD>, f<FS>, f<FT>" +*mips3d: +{ + int fmt = FMT; + check_fpu (SD_); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (FD, fmt, RSquareRoot2 (ValueFPR (FS, fmt), + ValueFPR (FT, fmt), fmt)); +} diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h index 833fd5f..fed625e 100644 --- a/sim/mips/sim-main.h +++ b/sim/mips/sim-main.h @@ -82,6 +82,10 @@ typedef enum { fmt_uninterpreted_64 = 0x80000000U, } FP_formats; +/* For paired word (pw) operations, the opcode representation is fmt_word, + but register transfers (StoreFPR, ValueFPR, etc.) are done as fmt_long. */ +#define fmt_pw fmt_long + /* This should be the COC1 value at the start of the preceding instruction: */ #define PREVCOC1() ((STATE & simPCOC1) ? 1 : 0) @@ -732,6 +736,23 @@ unsigned64 convert_ps (SIM_STATE, int rm, unsigned64 op, FP_formats from, #define ConvertPS(rm,op,from,to) convert_ps (SIM_ARGS, rm, op, from, to) +/* MIPS-3D ASE operations. */ +#define CompareAbs(op1,op2,fmt,cond,cc) \ +fp_cmp(SIM_ARGS, op1, op2, fmt, 1, cond, cc) +unsigned64 fp_add_r (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt); +#define AddR(op1,op2,fmt) fp_add_r(SIM_ARGS, op1, op2, fmt) +unsigned64 fp_mul_r (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt); +#define MultiplyR(op1,op2,fmt) fp_mul_r(SIM_ARGS, op1, op2, fmt) +unsigned64 fp_recip1 (SIM_STATE, unsigned64 op, FP_formats fmt); +#define Recip1(op,fmt) fp_recip1(SIM_ARGS, op, fmt) +unsigned64 fp_recip2 (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt); +#define Recip2(op1,op2,fmt) fp_recip2(SIM_ARGS, op1, op2, fmt) +unsigned64 fp_rsqrt1 (SIM_STATE, unsigned64 op, FP_formats fmt); +#define RSquareRoot1(op,fmt) fp_rsqrt1(SIM_ARGS, op, fmt) +unsigned64 fp_rsqrt2 (SIM_STATE, unsigned64 op1, unsigned64 op2, FP_formats fmt); +#define RSquareRoot2(op1,op2,fmt) fp_rsqrt2(SIM_ARGS, op1, op2, fmt) + + /* MDMX access. */ typedef unsigned int MX_fmtsel; /* MDMX format select field (5 bits). */ |