if (op != 3)
{
bu8 sgn0 = (acc >> 31) & 1;
+ bu8 sgn40 = (acc >> 39) & 1;
+ bu40 nosat_acc;
+
/* This can't saturate, so we don't keep track of the sat flag. */
bu64 res = decode_multfunc (cpu, h0, h1, src0, src1, mmod,
MM, &tsat);
break;
}
+ nosat_acc = acc;
/* Saturate. */
switch (mmod)
{
acc = 0x7fffffffffull, sat = 1;
break;
case M_TFU:
- if (!MM && acc > 0xFFFFFFFFFFull)
- acc = 0x0, sat = 1;
- if (MM && acc > 0xFFFFFFFF)
- acc &= 0xFFFFFFFF;
+ if (!MM && (bs64)acc < 0)
+ acc = 0, sat = 1;
+ if (!MM && (bs64)acc > 0xFFFFFFFFFFull)
+ acc = 0xFFFFFFFFFFull, sat = 1;
break;
case M_IU:
- if (acc & 0x8000000000000000ull)
+ if (!MM && acc & 0x8000000000000000ull)
acc = 0x0, sat = 1;
- if (acc > 0xFFFFFFFFFFull)
- acc &= 0xFFFFFFFFFFull, sat = 1;
- if (MM && acc > 0xFFFFFFFF)
- acc &= 0xFFFFFFFF;
- if (acc & 0x80000000)
- acc |= 0xffffffff00000000ull;
+ if (!MM && acc > 0xFFFFFFFFFFull)
+ acc = 0xFFFFFFFFFFull, sat = 1;
+ if (MM && acc > 0xFFFFFFFFFFull)
+ acc &= 0xFFFFFFFFFFull;
+ if (acc & 0x8000000000ull)
+ acc |= 0xffffff0000000000ull;
break;
case M_FU:
if (!MM && (bs64)acc < 0)
acc = 0xFFFFFFFFFFull, sat = 1;
if (MM && acc > 0xFFFFFFFFFFull)
acc &= 0xFFFFFFFFFFull;
- if (MM && acc & 0x80000000)
- acc |= 0xffffffff00000000ull;
+ if (MM && acc & 0x8000000000ull)
+ acc |= 0xffffff0000000000ull;
break;
case M_IH:
if ((bs64)acc < -0x80000000ll)
acc = 0x7fffffffull, sat = 1;
break;
case M_W32:
- if (sgn0 && (sgn0 != ((acc >> 31) & 1))
- && (((acc >> 32) & 0xFF) == 0xff))
- acc = 0x80000000;
+ /* check max negative value */
+ if (sgn40 && ((acc >> 31) != 0x1ffffffff)
+ && ((acc >> 31) != 0x0))
+ acc = 0x80000000, sat = 1;
+ if (!sat && !sgn40 && ((acc >> 31) != 0x0)
+ && ((acc >> 31) != 0x1ffffffff))
+ acc = 0x7FFFFFFF, sat = 1;
acc &= 0xffffffff;
if (acc & 0x80000000)
acc |= 0xffffffff00000000ull;
+ if (tsat)
+ sat = 1;
break;
default:
illegal_instruction (cpu);
STORE (ASTATREG (av[which]), sat);
if (sat)
STORE (ASTATREG (avs[which]), sat);
+
+ /* Figure out the overflow bit. */
+ if (sat)
+ {
+ if (fullword)
+ *overflow = 1;
+ else
+ ret = extract_mult (cpu, nosat_acc, mmod, MM, fullword, overflow);
+ }
}
ret = extract_mult (cpu, acc, mmod, MM, fullword, overflow);
int h01 = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
bu32 res = DREG (dst);
- bu32 v_i = 0, zero = 0, n_1 = 0, n_0 = 0;
+ bu32 v_0 = 0, v_1 = 0, zero = 0, n_1 = 0, n_0 = 0;
static const char * const ops[] = { "=", "+=", "-=" };
char _buf[128], *buf = _buf;
if (w1 == 1 || op1 != 3)
{
bu32 res1 = decode_macfunc (cpu, 1, op1, h01, h11, src0,
- src1, mmod, MM, P, &v_i, &n_1);
+ src1, mmod, MM, P, &v_1, &n_1);
if (w1)
buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
res = REG_H_L (res1 << 16, res);
}
}
+ else
+ v_1 = 0;
if (w0 == 1 || op0 != 3)
{
if (w0 == 1 || op0 != 3)
{
bu32 res0 = decode_macfunc (cpu, 0, op0, h00, h10, src0,
- src1, mmod, 0, P, &v_i, &n_0);
+ src1, mmod, 0, P, &v_0, &n_0);
if (w0)
buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
res = REG_H_L (res, res0);
}
}
+ else
+ v_0 = 0;
}
TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
if (!P && (w0 || w1))
{
STORE (DREG (dst), res);
- SET_ASTATREG (v, v_i);
- if (v_i)
- SET_ASTATREG (vs, v_i);
+ SET_ASTATREG (v, v_0 | v_1);
+ if (v_0 || v_1)
+ SET_ASTATREG (vs, 1);
}
else if (P)
{
- SET_ASTATREG (v, v_i);
- if (v_i)
- SET_ASTATREG (vs, v_i);
+ SET_ASTATREG (v, v_0 | v_1);
+ if (v_0 || v_1)
+ SET_ASTATREG (vs, 1);
}
if ((w0 == 1 && op0 == 3) || (w1 == 1 && op1 == 3))