|
@@ -1394,6 +1394,14 @@ static const unsigned char cmptab[8] = {
|
|
|
IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
|
|
|
};
|
|
|
|
|
|
+static const unsigned char negative_cmptab[8] = {
|
|
|
+ 0, /* Reserved */
|
|
|
+ IEEE754_CLT | IEEE754_CGT | IEEE754_CEQ,
|
|
|
+ IEEE754_CLT | IEEE754_CGT | IEEE754_CUN,
|
|
|
+ IEEE754_CLT | IEEE754_CGT,
|
|
|
+ /* Reserved */
|
|
|
+};
|
|
|
+
|
|
|
|
|
|
/*
|
|
|
* Additional MIPS4 instructions
|
|
@@ -1838,7 +1846,7 @@ copcsr:
|
|
|
goto copcsr;
|
|
|
|
|
|
default:
|
|
|
- if (MIPSInst_FUNC(ir) >= fcmp_op) {
|
|
|
+ if (!NO_R6EMU && MIPSInst_FUNC(ir) >= fcmp_op) {
|
|
|
unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
|
|
|
union ieee754sp fs, ft;
|
|
|
|
|
@@ -2015,7 +2023,7 @@ dcopuop:
|
|
|
goto copcsr;
|
|
|
|
|
|
default:
|
|
|
- if (MIPSInst_FUNC(ir) >= fcmp_op) {
|
|
|
+ if (!NO_R6EMU && MIPSInst_FUNC(ir) >= fcmp_op) {
|
|
|
unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
|
|
|
union ieee754dp fs, ft;
|
|
|
|
|
@@ -2057,10 +2065,65 @@ dcopuop:
|
|
|
rv.d = ieee754dp_fint(fs.bits);
|
|
|
rfmt = d_fmt;
|
|
|
goto copcsr;
|
|
|
- default:
|
|
|
- return SIGILL;
|
|
|
+ default: {
|
|
|
+ /* Emulating the new CMP.condn.fmt R6 instruction */
|
|
|
+#define CMPOP_MASK 0x7
|
|
|
+#define SIGN_BIT (0x1 << 3)
|
|
|
+#define PREDICATE_BIT (0x1 << 4)
|
|
|
+
|
|
|
+ int cmpop = MIPSInst_FUNC(ir) & CMPOP_MASK;
|
|
|
+ int sig = MIPSInst_FUNC(ir) & SIGN_BIT;
|
|
|
+ union ieee754sp fs, ft;
|
|
|
+
|
|
|
+ /* This is an R6 only instruction */
|
|
|
+ if (!cpu_has_mips_r6 ||
|
|
|
+ (MIPSInst_FUNC(ir) & 0x20))
|
|
|
+ return SIGILL;
|
|
|
+
|
|
|
+ /* fmt is w_fmt for single precision so fix it */
|
|
|
+ rfmt = s_fmt;
|
|
|
+ /* default to false */
|
|
|
+ rv.w = 0;
|
|
|
+
|
|
|
+ /* CMP.condn.S */
|
|
|
+ SPFROMREG(fs, MIPSInst_FS(ir));
|
|
|
+ SPFROMREG(ft, MIPSInst_FT(ir));
|
|
|
+
|
|
|
+ /* positive predicates */
|
|
|
+ if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
|
|
|
+ if (ieee754sp_cmp(fs, ft, cmptab[cmpop],
|
|
|
+ sig))
|
|
|
+ rv.w = -1; /* true, all 1s */
|
|
|
+ if ((sig) &&
|
|
|
+ ieee754_cxtest(IEEE754_INVALID_OPERATION))
|
|
|
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
|
|
|
+ else
|
|
|
+ goto copcsr;
|
|
|
+ } else {
|
|
|
+ /* negative predicates */
|
|
|
+ switch (cmpop) {
|
|
|
+ case 1:
|
|
|
+ case 2:
|
|
|
+ case 3:
|
|
|
+ if (ieee754sp_cmp(fs, ft,
|
|
|
+ negative_cmptab[cmpop],
|
|
|
+ sig))
|
|
|
+ rv.w = -1; /* true, all 1s */
|
|
|
+ if (sig &&
|
|
|
+ ieee754_cxtest(IEEE754_INVALID_OPERATION))
|
|
|
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
|
|
|
+ else
|
|
|
+ goto copcsr;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ /* Reserved R6 ops */
|
|
|
+ pr_err("Reserved MIPS R6 CMP.condn.S operation\n");
|
|
|
+ return SIGILL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
- break;
|
|
|
}
|
|
|
|
|
|
case l_fmt:
|
|
@@ -2081,11 +2144,60 @@ dcopuop:
|
|
|
rv.d = ieee754dp_flong(bits);
|
|
|
rfmt = d_fmt;
|
|
|
goto copcsr;
|
|
|
- default:
|
|
|
- return SIGILL;
|
|
|
- }
|
|
|
- break;
|
|
|
+ default: {
|
|
|
+ /* Emulating the new CMP.condn.fmt R6 instruction */
|
|
|
+ int cmpop = MIPSInst_FUNC(ir) & CMPOP_MASK;
|
|
|
+ int sig = MIPSInst_FUNC(ir) & SIGN_BIT;
|
|
|
+ union ieee754dp fs, ft;
|
|
|
+
|
|
|
+ if (!cpu_has_mips_r6 ||
|
|
|
+ (MIPSInst_FUNC(ir) & 0x20))
|
|
|
+ return SIGILL;
|
|
|
|
|
|
+ /* fmt is l_fmt for double precision so fix it */
|
|
|
+ rfmt = d_fmt;
|
|
|
+ /* default to false */
|
|
|
+ rv.l = 0;
|
|
|
+
|
|
|
+ /* CMP.condn.D */
|
|
|
+ DPFROMREG(fs, MIPSInst_FS(ir));
|
|
|
+ DPFROMREG(ft, MIPSInst_FT(ir));
|
|
|
+
|
|
|
+ /* positive predicates */
|
|
|
+ if (!(MIPSInst_FUNC(ir) & PREDICATE_BIT)) {
|
|
|
+ if (ieee754dp_cmp(fs, ft,
|
|
|
+ cmptab[cmpop], sig))
|
|
|
+ rv.l = -1LL; /* true, all 1s */
|
|
|
+ if (sig &&
|
|
|
+ ieee754_cxtest(IEEE754_INVALID_OPERATION))
|
|
|
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
|
|
|
+ else
|
|
|
+ goto copcsr;
|
|
|
+ } else {
|
|
|
+ /* negative predicates */
|
|
|
+ switch (cmpop) {
|
|
|
+ case 1:
|
|
|
+ case 2:
|
|
|
+ case 3:
|
|
|
+ if (ieee754dp_cmp(fs, ft,
|
|
|
+ negative_cmptab[cmpop],
|
|
|
+ sig))
|
|
|
+ rv.l = -1LL; /* true, all 1s */
|
|
|
+ if (sig &&
|
|
|
+ ieee754_cxtest(IEEE754_INVALID_OPERATION))
|
|
|
+ rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
|
|
|
+ else
|
|
|
+ goto copcsr;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ /* Reserved R6 ops */
|
|
|
+ pr_err("Reserved MIPS R6 CMP.condn.D operation\n");
|
|
|
+ return SIGILL;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
default:
|
|
|
return SIGILL;
|
|
|
}
|