From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22236 invoked by alias); 8 Jun 2002 03:07:03 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 22229 invoked from network); 8 Jun 2002 03:07:01 -0000 Received: from unknown (HELO mms1.broadcom.com) (63.70.210.58) by sources.redhat.com with SMTP; 8 Jun 2002 03:07:01 -0000 Received: from 63.70.210.1 by mms1.broadcom.com with ESMTP (Broadcom MMS-1 SMTP Relay (MMS v4.7)); Fri, 07 Jun 2002 20:06:34 -0700 X-Server-Uuid: 1e1caf3a-b686-11d4-a6a3-00508bfc9ae5 Received: from dt-sj3-118.sj.broadcom.com (dt-sj3-118 [10.21.64.118]) by mail-sj1-5.sj.broadcom.com (8.12.2/8.12.2) with ESMTP id g583701S020508; Fri, 7 Jun 2002 20:07:00 -0700 (PDT) Received: (from cgd@localhost) by dt-sj3-118.sj.broadcom.com ( 8.9.1/SJ8.9.1) id UAA26237; Fri, 7 Jun 2002 20:06:59 -0700 (PDT) Date: Fri, 07 Jun 2002 20:07:00 -0000 Message-ID: <200206080306.UAA26237@dt-sj3-118.sj.broadcom.com> From: cgd@broadcom.com To: gdb-patches@sources.redhat.com Subject: [applied mips sim patch] better implementations of mul-acc ops. cc: cgd@broadcom.com MIME-Version: 1.0 X-WSS-ID: 111FAB301436499-01-01 Content-Type: text/plain Content-Transfer-Encoding: 7bit X-SW-Source: 2002-06/txt/msg00120.txt.bz2 [ tested in the same way as described in http://sources.redhat.com/ml/gdb-patches/2002-06/msg00103.html, but with a mipsisa64-elf target hacked to use the -mips64 multilib. ] 2002-06-07 Chris Demetriou Ed Satterthwaite * cp1.c (inner_mac, fp_mac, inner_rsqrt, fp_inv_sqrt) (fp_rsqrt, fp_madd, fp_msub, fp_nmadd, fp_nmsub): New functions. * sim-main.h (fp_rsqrt, fp_madd, fp_msub, fp_nmadd) (fp_nmsub): New prototypes. (RSquareRoot, MultiplyAdd, MultiplySub, NegMultiplyAdd) (NegMultiplySub): New defines. * mips.igen (RSQRT.fmt): Use RSquareRoot(). (MADD.D, MADD.S): Replace with... (MADD.fmt): New instruction. (MSUB.D, MSUB.S): Replace with... (MSUB.fmt): New instruction. (NMADD.D, NMADD.S): Replace with... (NMADD.fmt): New instruction. (NMSUB.D, MSUB.S): Replace with... (NMSUB.fmt): New instruction. Index: cp1.c =================================================================== RCS file: /cvs/src/src/sim/mips/cp1.c,v retrieving revision 1.15 diff -u -p -r1.15 cp1.c --- cp1.c 7 Jun 2002 22:55:49 -0000 1.15 +++ cp1.c 7 Jun 2002 23:12:24 -0000 @@ -672,6 +672,206 @@ fp_binary(sim_cpu *cpu, return result; } +/* Common MAC code for single operands (.s or .d), defers setting FCSR. */ +static sim_fpu_status +inner_mac(int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *), + unsigned64 op1, + unsigned64 op2, + unsigned64 op3, + int scale, + int negate, + FP_formats fmt, + sim_fpu_round round, + sim_fpu_denorm denorm, + unsigned64 *result) +{ + sim_fpu wop1; + sim_fpu wop2; + sim_fpu ans; + sim_fpu_status status = 0; + sim_fpu_status op_status; + unsigned64 temp = 0; + + switch (fmt) + { + case fmt_single: + { + unsigned32 res; + sim_fpu_32to (&wop1, op1); + sim_fpu_32to (&wop2, op2); + status |= sim_fpu_mul (&ans, &wop1, &wop2); + if (scale != 0 && sim_fpu_is_number (&ans)) /* number or denorm */ + ans.normal_exp += scale; + status |= sim_fpu_round_32 (&ans, round, denorm); + wop1 = ans; + op_status = 0; + sim_fpu_32to (&wop2, op3); + op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2); + op_status |= sim_fpu_round_32 (&ans, round, denorm); + status |= op_status; + if (negate) + { + wop1 = ans; + op_status = sim_fpu_neg (&ans, &wop1); + op_status |= sim_fpu_round_32 (&ans, round, denorm); + status |= op_status; + } + sim_fpu_to32 (&res, &ans); + temp = res; + break; + } + case fmt_double: + { + unsigned64 res; + sim_fpu_64to (&wop1, op1); + sim_fpu_64to (&wop2, op2); + status |= sim_fpu_mul (&ans, &wop1, &wop2); + if (scale != 0 && sim_fpu_is_number (&ans)) /* number or denorm */ + ans.normal_exp += scale; + status |= sim_fpu_round_64 (&ans, round, denorm); + wop1 = ans; + op_status = 0; + sim_fpu_64to (&wop2, op3); + op_status |= (*sim_fpu_op) (&ans, &wop1, &wop2); + op_status |= sim_fpu_round_64 (&ans, round, denorm); + status |= op_status; + if (negate) + { + wop1 = ans; + op_status = sim_fpu_neg (&ans, &wop1); + op_status |= sim_fpu_round_64 (&ans, round, denorm); + status |= op_status; + } + sim_fpu_to64 (&res, &ans); + temp = res; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + *result = temp; + return status; +} + +/* Common implementation of madd, nmadd, msub, nmsub that does + intermediate rounding per spec. Also used for recip2 and rsqrt2, + which are transformed into equivalent nmsub operations. The scale + argument is an adjustment to the exponent of the intermediate + product op1*op2. It is currently non-zero for rsqrt2 (-1), which + requires an effective division by 2. */ +static unsigned64 +fp_mac(sim_cpu *cpu, + address_word cia, + int (*sim_fpu_op)(sim_fpu *, const sim_fpu *, const sim_fpu *), + unsigned64 op1, + unsigned64 op2, + unsigned64 op3, + int scale, + int negate, + FP_formats fmt) +{ + sim_fpu_round round = rounding_mode (GETRM()); + sim_fpu_denorm denorm = denorm_mode (cpu); + sim_fpu_status status = 0; + unsigned64 result = 0; + + /* The format type has already been checked: */ + switch (fmt) + { + case fmt_single: + case fmt_double: + status = inner_mac(sim_fpu_op, op1, op2, op3, scale, + negate, fmt, round, denorm, &result); + break; + default: + sim_io_eprintf (SD, "Bad switch\n"); + abort (); + } + + update_fcsr (cpu, cia, status); + return result; +} + +/* Common rsqrt code for single operands (.s or .d), intermediate rounding. */ +static sim_fpu_status +inner_rsqrt(unsigned64 op1, + FP_formats fmt, + sim_fpu_round round, + sim_fpu_denorm denorm, + unsigned64 *result) +{ + sim_fpu wop1; + sim_fpu ans; + sim_fpu_status status = 0; + sim_fpu_status op_status; + unsigned64 temp = 0; + + switch (fmt) + { + case fmt_single: + { + unsigned32 res; + sim_fpu_32to (&wop1, op1); + status |= sim_fpu_sqrt (&ans, &wop1); + status |= sim_fpu_round_32 (&ans, status, round); + wop1 = ans; + op_status = sim_fpu_inv (&ans, &wop1); + op_status |= sim_fpu_round_32 (&ans, round, denorm); + sim_fpu_to32 (&res, &ans); + temp = res; + status |= op_status; + break; + } + case fmt_double: + { + unsigned64 res; + sim_fpu_64to (&wop1, op1); + status |= sim_fpu_sqrt (&ans, &wop1); + status |= sim_fpu_round_64 (&ans, round, denorm); + wop1 = ans; + op_status = sim_fpu_inv (&ans, &wop1); + op_status |= sim_fpu_round_64 (&ans, round, denorm); + sim_fpu_to64 (&res, &ans); + temp = res; + status |= op_status; + break; + } + default: + fprintf (stderr, "Bad switch\n"); + abort (); + } + *result = temp; + return status; +} + +static unsigned64 +fp_inv_sqrt(sim_cpu *cpu, + address_word cia, + unsigned64 op1, + FP_formats fmt) +{ + sim_fpu_round round = rounding_mode (GETRM()); + sim_fpu_round denorm = denorm_mode (cpu); + sim_fpu_status status = 0; + unsigned64 result = 0; + + /* The format type has already been checked: */ + switch (fmt) + { + case fmt_single: + case fmt_double: + status = inner_rsqrt (op1, fmt, round, denorm, &result); + break; + default: + sim_io_eprintf (SD, "Bad switch\n"); + abort (); + } + + update_fcsr (cpu, cia, status); + return result; +} + unsigned64 fp_abs(sim_cpu *cpu, @@ -747,6 +947,59 @@ fp_sqrt(sim_cpu *cpu, FP_formats fmt) { return fp_unary(cpu, cia, &sim_fpu_sqrt, op, fmt); +} + +unsigned64 +fp_rsqrt(sim_cpu *cpu, + address_word cia, + unsigned64 op, + FP_formats fmt) +{ + return fp_inv_sqrt(cpu, cia, op, fmt); +} + +unsigned64 +fp_madd(sim_cpu *cpu, + address_word cia, + unsigned64 op1, + unsigned64 op2, + unsigned64 op3, + FP_formats fmt) +{ + return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 0, fmt); +} + +unsigned64 +fp_msub(sim_cpu *cpu, + address_word cia, + unsigned64 op1, + unsigned64 op2, + unsigned64 op3, + FP_formats fmt) +{ + return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 0, fmt); +} + +unsigned64 +fp_nmadd(sim_cpu *cpu, + address_word cia, + unsigned64 op1, + unsigned64 op2, + unsigned64 op3, + FP_formats fmt) +{ + return fp_mac(cpu, cia, &sim_fpu_add, op1, op2, op3, 0, 1, fmt); +} + +unsigned64 +fp_nmsub(sim_cpu *cpu, + address_word cia, + unsigned64 op1, + unsigned64 op2, + unsigned64 op3, + FP_formats fmt) +{ + return fp_mac(cpu, cia, &sim_fpu_sub, op1, op2, op3, 0, 1, fmt); } Index: mips.igen =================================================================== RCS file: /cvs/src/src/sim/mips/mips.igen,v retrieving revision 1.42 diff -u -p -r1.42 mips.igen --- mips.igen 7 Jun 2002 00:13:24 -0000 1.42 +++ mips.igen 7 Jun 2002 23:12:24 -0000 @@ -4198,34 +4198,19 @@ -// -// FIXME: Not correct for mips* -// -010011,5.FR,5.FT,5.FS,5.FD,100,001:COP1X:32,f::MADD.D -"madd.d f, f, f, f" -*mipsIV: -*mipsV: -*mips64: -*vr5000: -{ - check_fpu (SD_); - { - StoreFPR(FD,fmt_double,Add(Multiply(ValueFPR(FS,fmt_double),ValueFPR(FT,fmt_double),fmt_double),ValueFPR(FR,fmt_double),fmt_double)); - } -} - - -010011,5.FR,5.FT,5.FS,5.FD,100,000:COP1X:32,f::MADD.S -"madd.s f, f, f, f" +010011,5.FR,5.FT,5.FS,5.FD,100,3.FMT:COP1X:64,f::MADD.fmt +"madd.%s f, f, f, f" *mipsIV: *mipsV: *mips64: *vr5000: { + int fmt = FMT; check_fpu (SD_); - { - StoreFPR(FD,fmt_single,Add(Multiply(ValueFPR(FS,fmt_single),ValueFPR(FT,fmt_single),fmt_single),ValueFPR(FR,fmt_single),fmt_single)); - } + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (FD, fmt, MultiplyAdd (ValueFPR (FS, fmt), ValueFPR (FT, fmt), + ValueFPR (FR, fmt), fmt)); } @@ -4354,29 +4339,19 @@ } -// MSUB.fmt -010011,5.FR,5.FT,5.FS,5.FD,101,001:COP1X:32,f::MSUB.D -"msub.d f, f, f, f" -*mipsIV: -*mipsV: -*mips64: -*vr5000: -{ - check_fpu (SD_); - StoreFPR(FD,fmt_double,Sub(Multiply(ValueFPR(FS,fmt_double),ValueFPR(FT,fmt_double),fmt_double),ValueFPR(FR,fmt_double),fmt_double)); -} - - -// MSUB.fmt -010011,5.FR,5.FT,5.FS,5.FD,101000:COP1X:32,f::MSUB.S -"msub.s f, f, f, f" +010011,5.FR,5.FT,5.FS,5.FD,101,3.FMT:COP1X:64,f::MSUB.fmt +"msub.%s f, f, f, f" *mipsIV: *mipsV: *mips64: *vr5000: { + int fmt = FMT; check_fpu (SD_); - StoreFPR(FD,fmt_single,Sub(Multiply(ValueFPR(FS,fmt_single),ValueFPR(FT,fmt_single),fmt_single),ValueFPR(FR,fmt_single),fmt_single)); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (FD, fmt, MultiplySub (ValueFPR (FS, fmt), ValueFPR (FT, fmt), + ValueFPR (FR, fmt), fmt)); } @@ -4449,55 +4424,35 @@ } -// NMADD.fmt -010011,5.FR,5.FT,5.FS,5.FD,110001:COP1X:32,f::NMADD.D -"nmadd.d f, f, f, f" -*mipsIV: -*mipsV: -*mips64: -*vr5000: -{ - check_fpu (SD_); - StoreFPR(FD,fmt_double,Negate(Add(Multiply(ValueFPR(FS,fmt_double),ValueFPR(FT,fmt_double),fmt_double),ValueFPR(FR,fmt_double),fmt_double),fmt_double)); -} - - -// NMADD.fmt -010011,5.FR,5.FT,5.FS,5.FD,110000:COP1X:32,f::NMADD.S -"nmadd.s f, f, f, f" -*mipsIV: -*mipsV: -*mips64: -*vr5000: -{ - check_fpu (SD_); - StoreFPR(FD,fmt_single,Negate(Add(Multiply(ValueFPR(FS,fmt_single),ValueFPR(FT,fmt_single),fmt_single),ValueFPR(FR,fmt_single),fmt_single),fmt_single)); -} - - -// NMSUB.fmt -010011,5.FR,5.FT,5.FS,5.FD,111001:COP1X:32,f::NMSUB.D -"nmsub.d f, f, f, f" +010011,5.FR,5.FT,5.FS,5.FD,110,3.FMT:COP1X:64,f::NMADD.fmt +"nmadd.%s f, f, f, f" *mipsIV: *mipsV: *mips64: *vr5000: { + int fmt = FMT; check_fpu (SD_); - StoreFPR(FD,fmt_double,Negate(Sub(Multiply(ValueFPR(FS,fmt_double),ValueFPR(FT,fmt_double),fmt_double),ValueFPR(FR,fmt_double),fmt_double),fmt_double)); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (FD, fmt, NegMultiplyAdd (ValueFPR (FS, fmt), ValueFPR (FT, fmt), + ValueFPR (FR, fmt), fmt)); } -// NMSUB.fmt -010011,5.FR,5.FT,5.FS,5.FD,111000:COP1X:32,f::NMSUB.S -"nmsub.s f, f, f, f" +010011,5.FR,5.FT,5.FS,5.FD,111,3.FMT:COP1X:64,f::NMSUB.fmt +"nmsub.%s f, f, f, f" *mipsIV: *mipsV: *mips64: *vr5000: { + int fmt = FMT; check_fpu (SD_); - StoreFPR(FD,fmt_single,Negate(Sub(Multiply(ValueFPR(FS,fmt_single),ValueFPR(FT,fmt_single),fmt_single),ValueFPR(FR,fmt_single),fmt_single),fmt_single)); + check_u64 (SD_, instruction_0); + check_fmt_p (SD_, fmt, instruction_0); + StoreFPR (FD, fmt, NegMultiplySub (ValueFPR (FS, fmt), ValueFPR (FT, fmt), + ValueFPR (FR, fmt), fmt)); } @@ -4579,7 +4534,7 @@ int fmt = FMT; check_fpu (SD_); check_fmt (SD_, fmt, instruction_0); - StoreFPR(FD,fmt,Recip(SquareRoot(ValueFPR(FS,fmt),fmt),fmt)); + StoreFPR (FD, fmt, RSquareRoot (ValueFPR (FS, fmt), fmt)); } Index: sim-main.h =================================================================== RCS file: /cvs/src/src/sim/mips/sim-main.h,v retrieving revision 1.20 diff -u -p -r1.20 sim-main.h --- sim-main.h 7 Jun 2002 00:13:24 -0000 1.20 +++ sim-main.h 7 Jun 2002 23:12:24 -0000 @@ -704,6 +704,20 @@ unsigned64 fp_recip (SIM_STATE, unsigned #define Recip(op,fmt) fp_recip(SIM_ARGS, op, fmt) unsigned64 fp_sqrt (SIM_STATE, unsigned64 op, FP_formats fmt); #define SquareRoot(op,fmt) fp_sqrt(SIM_ARGS, op, fmt) +unsigned64 fp_rsqrt (SIM_STATE, unsigned64 op, FP_formats fmt); +#define RSquareRoot(op,fmt) fp_rsqrt(SIM_ARGS, op, fmt) +unsigned64 fp_madd (SIM_STATE, unsigned64 op1, unsigned64 op2, + unsigned64 op3, FP_formats fmt); +#define MultiplyAdd(op1,op2,op3,fmt) fp_madd(SIM_ARGS, op1, op2, op3, fmt) +unsigned64 fp_msub (SIM_STATE, unsigned64 op1, unsigned64 op2, + unsigned64 op3, FP_formats fmt); +#define MultiplySub(op1,op2,op3,fmt) fp_msub(SIM_ARGS, op1, op2, op3, fmt) +unsigned64 fp_nmadd (SIM_STATE, unsigned64 op1, unsigned64 op2, + unsigned64 op3, FP_formats fmt); +#define NegMultiplyAdd(op1,op2,op3,fmt) fp_nmadd(SIM_ARGS, op1, op2, op3, fmt) +unsigned64 fp_nmsub (SIM_STATE, unsigned64 op1, unsigned64 op2, + unsigned64 op3, FP_formats fmt); +#define NegMultiplySub(op1,op2,op3,fmt) fp_nmsub(SIM_ARGS, op1, op2, op3, fmt) unsigned64 convert (SIM_STATE, int rm, unsigned64 op, FP_formats from, FP_formats to); #define Convert(rm,op,from,to) convert (SIM_ARGS, rm, op, from, to)