From 458e1f58e6c99f16663e523eaee7cebf013afdf2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 20 Sep 1996 03:07:43 +0000 Subject: [PATCH] Fix multiplication, ldxc1, and floating point conversion. See ChangeLog. --- sim/mips/ChangeLog | 13 ++++++----- sim/mips/gencode.c | 56 +++++++++++++++++++++++++++++++++++++--------- sim/mips/interp.c | 14 ++++++++++++ 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index 49060fa2605..9c825049d03 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,13 +1,16 @@ Thu Sep 19 15:34:17 1996 Ian Lance Taylor + * gencode.c (MIPS_DECODE): Set UNSIGNED for multu instruction. + (process_instructions): Correct handling of nor instruction. + Correct shift count for 32 bit shift instructions. Correct sign + extension for arithmetic shifts to not shift the number of bits in + the type. Fix 64 bit multiply high word calculation. Fix 32 bit + unsigned multiply. Fix ldxc1 and friends to use coprocessor 1. + Fix madd. * interp.c (CHECKHILO): Don't set HIACCESS, LOACCESS, or HLPC. It's OK to have a mult follow a mult. What's not OK is to have a mult follow an mfhi. - - * gencode.c (process_instructions): Correct handling of nor - instruction. Correct shift count for 32 bit shift instructions. - Correct sign extension for arithmetic shifts to not shift the - number of bits in the type. + (Convert): Comment out incorrect rounding code. Mon Sep 16 11:38:16 1996 James G. Smith diff --git a/sim/mips/gencode.c b/sim/mips/gencode.c index 33ade54ed73..ff27ef6b531 100644 --- a/sim/mips/gencode.c +++ b/sim/mips/gencode.c @@ -486,7 +486,7 @@ struct instruction MIPS_DECODE[] = { {"MSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X, FPSUB, (FP | MULTIPLY | SINGLE)}, {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1, FPMUL, (FP | HI | LO)}, {"MULT", 1,"000000sssssggggg0000000000011000",SPECIAL,MUL, (WORD | WORD32 | HI | LO)}, - {"MULTU", 1,"000000sssssggggg0000000000011001",SPECIAL,MUL, (WORD | WORD32 | HI | LO)}, + {"MULTU", 1,"000000sssssggggg0000000000011001",SPECIAL,MUL, (WORD | WORD32 | UNSIGNED | HI | LO)}, {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD)}, {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1, FPNEG, (FP)}, {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X, FPADD, (FP | NOT | MULTIPLY | DOUBLE)}, @@ -1056,21 +1056,35 @@ process_instructions(doarch,features) printf(" {\n"); if (GETDATASIZE() == DOUBLEWORD) { printf(" uword64 mid;\n"); + printf(" uword64 midhi;\n"); printf(" uword64 temp;\n"); + if ((MIPS_DECODE[loop].flags & UNSIGNED) == 0) + { + printf(" int sign = 0;\n"); + printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n"); + printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n"); + } printf(" LO = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n"); printf(" HI = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n"); printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n"); - printf(" temp = (LO + SET64HI(WORD64LO(mid)));\n"); - printf(" if ((temp == mid) ? (LO != 0) : (temp < mid))\n"); + printf(" midhi = SET64HI(WORD64LO(mid));\n"); + printf(" temp = (LO + midhi);\n"); + printf(" if ((temp == midhi) ? (LO != 0) : (temp < midhi))\n"); printf(" HI += 1;\n"); printf(" HI += WORD64HI(mid);\n"); printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n"); - printf(" LO = (temp + SET64HI(WORD64LO(mid)));\n"); - printf(" if ((LO == mid) ? (temp != 0) : (LO < mid))\n"); + printf(" midhi = SET64HI(WORD64LO(mid));\n"); + printf(" LO = (temp + midhi);\n"); + printf(" if ((LO == midhi) ? (temp != 0) : (LO < midhi))\n"); printf(" HI += 1;\n"); printf(" HI += WORD64HI(mid);\n"); + if ((MIPS_DECODE[loop].flags & UNSIGNED) == 0) + printf(" if (sign & 1) { LO = - LO; HI = (LO == 0 ? 0 : -1) - HI; }\n"); } else { - printf(" uword64 temp = (op1 * op2);\n"); + if (MIPS_DECODE[loop].flags & UNSIGNED) + printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n"); + else + printf(" uword64 temp = (op1 * op2);\n"); printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype); printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype); } @@ -1585,7 +1599,10 @@ process_instructions(doarch,features) implementation will be needed to ascertain the correct operation. */ if (MIPS_DECODE[loop].flags & COPROC) - printf(" COP_LW(((instruction >> 26) & 0x3),destreg,(unsigned int)"); + printf(" COP_LW(%s,destreg,(unsigned int)", + ((MIPS_DECODE[loop].flags & REG) + ? "1" + : "((instruction >> 26) & 0x3)")); else printf(" GPR[destreg] = ("); @@ -1597,7 +1614,10 @@ process_instructions(doarch,features) printf(");\n"); } else { if (MIPS_DECODE[loop].flags & COPROC) - printf(" COP_LD(((instruction >> 26) & 0x3),destreg,memval);;\n"); + printf(" COP_LD(%s,destreg,memval);;\n", + ((MIPS_DECODE[loop].flags & REG) + ? "1" + : "((instruction >> 26) & 0x3)")); else printf(" GPR[destreg] = memval;\n"); } @@ -1628,12 +1648,21 @@ process_instructions(doarch,features) printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n"); printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n"); if (MIPS_DECODE[loop].flags & COPROC) - printf(" memval = (((uword64)COP_SW(((instruction >> 26) & 0x3),%s)) << (8 * byte));\n",((MIPS_DECODE[loop].flags & FP) ? "fs" : "destreg")); + printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n", + ((MIPS_DECODE[loop].flags & REG) + ? "1" + : "((instruction >> 26) & 0x3)"), + ((MIPS_DECODE[loop].flags & FP) ? "fs" : "destreg")); else printf(" memval = (op2 << (8 * byte));\n"); } else { /* !proc64 SC and SW, plus proc64 SD and SCD */ if (MIPS_DECODE[loop].flags & COPROC) - printf(" memval = (uword64)COP_S%c(((instruction >> 26) & 0x3),%s);\n",((datalen == 8) ? 'D' : 'W'),((MIPS_DECODE[loop].flags & FP) ? "fs" : "destreg")); + printf(" memval = (uword64)COP_S%c(%s,%s);\n", + ((datalen == 8) ? 'D' : 'W'), + ((MIPS_DECODE[loop].flags & REG) + ? "1" + : "((instruction >> 26) & 0x3)"), + ((MIPS_DECODE[loop].flags & FP) ? "fs" : "destreg")); else printf(" memval = op2;\n"); } @@ -1989,7 +2018,12 @@ process_instructions(doarch,features) fprintf(stderr,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZE()); exit(1); } - printf(" StoreFPR(destreg,%s,%s(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",type,((MIPS_DECODE[loop].flags & NOT) ? "Negate" : ""),type,type,type,type,type,type); + if (MIPS_DECODE[loop].flags & NOT) + printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n", + type, type, type, type, type, type, type); + else + printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n", + type, type, type, type, type, type); } else { printf(" if ((format != fmt_single) && (format != fmt_double))\n"); printf(" SignalException(ReservedInstruction,instruction);\n"); diff --git a/sim/mips/interp.c b/sim/mips/interp.c index 9c47b4aaa1a..18f79ba9d43 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -3364,6 +3364,11 @@ Convert(rm,op,from,to) break; } +#if 0 + /* FIXME: This code is incorrect. The rounding mode does not + round to integral values; it rounds to the nearest + representable value in the format. */ + switch (rm) { case FP_RM_NEAREST: /* Round result to nearest representable value. When two @@ -3398,6 +3403,8 @@ Convert(rm,op,from,to) tmp = (float)floor((double)tmp); break; } +#endif /* 0 */ + result = (uword64)*(unsigned int *)&tmp; } break; @@ -3425,6 +3432,11 @@ Convert(rm,op,from,to) break; } +#if 0 + /* FIXME: This code is incorrect. The rounding mode does not + round to integral values; it rounds to the nearest + representable value in the format. */ + switch (rm) { case FP_RM_NEAREST: #ifdef HAVE_ANINT @@ -3450,6 +3462,8 @@ Convert(rm,op,from,to) tmp = floor(*(double *)&tmp); break; } +#endif /* 0 */ + result = *(uword64 *)&tmp; } break; -- 2.30.2