Fix multiplication, ldxc1, and floating point conversion. See ChangeLog.

This commit is contained in:
Ian Lance Taylor 1996-09-20 03:07:43 +00:00
parent c12f5c678e
commit 458e1f58e6
3 changed files with 67 additions and 16 deletions

View File

@ -1,13 +1,16 @@
Thu Sep 19 15:34:17 1996 Ian Lance Taylor <ian@cygnus.com> Thu Sep 19 15:34:17 1996 Ian Lance Taylor <ian@cygnus.com>
* 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. * 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 It's OK to have a mult follow a mult. What's not OK is to have a
mult follow an mfhi. mult follow an mfhi.
(Convert): Comment out incorrect rounding code.
* 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.
Mon Sep 16 11:38:16 1996 James G. Smith <jsmith@cygnus.co.uk> Mon Sep 16 11:38:16 1996 James G. Smith <jsmith@cygnus.co.uk>

View File

@ -486,7 +486,7 @@ struct instruction MIPS_DECODE[] = {
{"MSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X, FPSUB, (FP | MULTIPLY | SINGLE)}, {"MSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X, FPSUB, (FP | MULTIPLY | SINGLE)},
{"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1, FPMUL, (FP | HI | LO)}, {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1, FPMUL, (FP | HI | LO)},
{"MULT", 1,"000000sssssggggg0000000000011000",SPECIAL,MUL, (WORD | WORD32 | 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)}, {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD)},
{"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1, FPNEG, (FP)}, {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1, FPNEG, (FP)},
{"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X, FPADD, (FP | NOT | MULTIPLY | DOUBLE)}, {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X, FPADD, (FP | NOT | MULTIPLY | DOUBLE)},
@ -1056,20 +1056,34 @@ process_instructions(doarch,features)
printf(" {\n"); printf(" {\n");
if (GETDATASIZE() == DOUBLEWORD) { if (GETDATASIZE() == DOUBLEWORD) {
printf(" uword64 mid;\n"); printf(" uword64 mid;\n");
printf(" uword64 midhi;\n");
printf(" uword64 temp;\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(" LO = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n");
printf(" HI = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n"); printf(" HI = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n");
printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n"); printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
printf(" temp = (LO + SET64HI(WORD64LO(mid)));\n"); printf(" midhi = SET64HI(WORD64LO(mid));\n");
printf(" if ((temp == mid) ? (LO != 0) : (temp < mid))\n"); printf(" temp = (LO + midhi);\n");
printf(" if ((temp == midhi) ? (LO != 0) : (temp < midhi))\n");
printf(" HI += 1;\n"); printf(" HI += 1;\n");
printf(" HI += WORD64HI(mid);\n"); printf(" HI += WORD64HI(mid);\n");
printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n"); printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
printf(" LO = (temp + SET64HI(WORD64LO(mid)));\n"); printf(" midhi = SET64HI(WORD64LO(mid));\n");
printf(" if ((LO == mid) ? (temp != 0) : (LO < mid))\n"); printf(" LO = (temp + midhi);\n");
printf(" if ((LO == midhi) ? (temp != 0) : (LO < midhi))\n");
printf(" HI += 1;\n"); printf(" HI += 1;\n");
printf(" HI += WORD64HI(mid);\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 { } else {
if (MIPS_DECODE[loop].flags & UNSIGNED)
printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
else
printf(" uword64 temp = (op1 * op2);\n"); printf(" uword64 temp = (op1 * op2);\n");
printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype); printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype);
printf(" HI = SIGNEXTEND((%s)WORD64HI(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 implementation will be needed to ascertain the
correct operation. */ correct operation. */
if (MIPS_DECODE[loop].flags & COPROC) 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 else
printf(" GPR[destreg] = ("); printf(" GPR[destreg] = (");
@ -1597,7 +1614,10 @@ process_instructions(doarch,features)
printf(");\n"); printf(");\n");
} else { } else {
if (MIPS_DECODE[loop].flags & COPROC) 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 else
printf(" GPR[destreg] = memval;\n"); printf(" GPR[destreg] = memval;\n");
} }
@ -1628,12 +1648,21 @@ process_instructions(doarch,features)
printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n"); printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n"); printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
if (MIPS_DECODE[loop].flags & COPROC) 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 else
printf(" memval = (op2 << (8 * byte));\n"); printf(" memval = (op2 << (8 * byte));\n");
} else { /* !proc64 SC and SW, plus proc64 SD and SCD */ } else { /* !proc64 SC and SW, plus proc64 SD and SCD */
if (MIPS_DECODE[loop].flags & COPROC) 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 else
printf(" memval = op2;\n"); 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()); fprintf(stderr,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZE());
exit(1); 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 { } else {
printf(" if ((format != fmt_single) && (format != fmt_double))\n"); printf(" if ((format != fmt_single) && (format != fmt_double))\n");
printf(" SignalException(ReservedInstruction,instruction);\n"); printf(" SignalException(ReservedInstruction,instruction);\n");

View File

@ -3364,6 +3364,11 @@ Convert(rm,op,from,to)
break; 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) { switch (rm) {
case FP_RM_NEAREST: case FP_RM_NEAREST:
/* Round result to nearest representable value. When two /* Round result to nearest representable value. When two
@ -3398,6 +3403,8 @@ Convert(rm,op,from,to)
tmp = (float)floor((double)tmp); tmp = (float)floor((double)tmp);
break; break;
} }
#endif /* 0 */
result = (uword64)*(unsigned int *)&tmp; result = (uword64)*(unsigned int *)&tmp;
} }
break; break;
@ -3425,6 +3432,11 @@ Convert(rm,op,from,to)
break; 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) { switch (rm) {
case FP_RM_NEAREST: case FP_RM_NEAREST:
#ifdef HAVE_ANINT #ifdef HAVE_ANINT
@ -3450,6 +3462,8 @@ Convert(rm,op,from,to)
tmp = floor(*(double *)&tmp); tmp = floor(*(double *)&tmp);
break; break;
} }
#endif /* 0 */
result = *(uword64 *)&tmp; result = *(uword64 *)&tmp;
} }
break; break;