mirror of
https://github.com/qemu/qemu.git
synced 2024-11-27 22:03:35 +08:00
target-mips: fix rndrashift_short_acc and code for EXTR_ instructions
Fix for rndrashift_short_acc to set correct value to higher 64 bits. This change also corrects conditions when bit 23 of the DSPControl register is set. The existing test files have been extended with several examples that trigger the issues. One bug/example in the test file for EXTR_RS_W has been found and reported by Klaus Peichl. Signed-off-by: Petar Jovanovic <petar.jovanovic@imgtec.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
b1999e87b4
commit
8b758d0568
@ -517,13 +517,8 @@ static inline void mipsdsp_rndrashift_short_acc(int64_t *p,
|
||||
|
||||
acc = ((int64_t)env->active_tc.HI[ac] << 32) |
|
||||
((int64_t)env->active_tc.LO[ac] & 0xFFFFFFFF);
|
||||
if (shift == 0) {
|
||||
p[0] = acc << 1;
|
||||
p[1] = (acc >> 63) & 0x01;
|
||||
} else {
|
||||
p[0] = acc >> (shift - 1);
|
||||
p[1] = 0;
|
||||
}
|
||||
p[0] = (shift == 0) ? (acc << 1) : (acc >> (shift - 1));
|
||||
p[1] = (acc >> 63) & 0x01;
|
||||
}
|
||||
|
||||
/* 128 bits long. p[0] is LO, p[1] is HI */
|
||||
@ -3161,8 +3156,8 @@ target_ulong helper_extr_w(target_ulong ac, target_ulong shift,
|
||||
tempDL[1] += 1;
|
||||
}
|
||||
|
||||
if ((!(tempDL[1] == 0 && (tempDL[0] & MIPSDSP_LHI) == 0x00)) &&
|
||||
(!(tempDL[1] == 1 && (tempDL[0] & MIPSDSP_LHI) == MIPSDSP_LHI))) {
|
||||
if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
|
||||
((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
|
||||
set_DSPControl_overflow_flag(1, 23, env);
|
||||
}
|
||||
|
||||
@ -3187,8 +3182,8 @@ target_ulong helper_extr_r_w(target_ulong ac, target_ulong shift,
|
||||
tempDL[1] += 1;
|
||||
}
|
||||
|
||||
if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
|
||||
(tempDL[1] != 1 && (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
|
||||
if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
|
||||
((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
|
||||
set_DSPControl_overflow_flag(1, 23, env);
|
||||
}
|
||||
|
||||
@ -3214,9 +3209,9 @@ target_ulong helper_extr_rs_w(target_ulong ac, target_ulong shift,
|
||||
}
|
||||
tempI = tempDL[0] >> 1;
|
||||
|
||||
if ((tempDL[1] != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
|
||||
(tempDL[1] != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
|
||||
temp64 = tempDL[1];
|
||||
if (((tempDL[1] & 0x01) != 0 || (tempDL[0] & MIPSDSP_LHI) != 0) &&
|
||||
((tempDL[1] & 0x01) != 1 || (tempDL[0] & MIPSDSP_LHI) != MIPSDSP_LHI)) {
|
||||
temp64 = tempDL[1] & 0x01;
|
||||
if (temp64 == 0) {
|
||||
tempI = 0x7FFFFFFF;
|
||||
} else {
|
||||
|
@ -67,5 +67,28 @@ int main()
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
/* Clear dspcontrol */
|
||||
dsp = 0;
|
||||
__asm
|
||||
("wrdsp %0\n\t"
|
||||
:
|
||||
: "r"(dsp)
|
||||
);
|
||||
|
||||
ach = 0xFFFFFFFF;
|
||||
acl = 0xFFFFFFFF;
|
||||
result = 0;
|
||||
__asm
|
||||
("mthi %2, $ac1\n\t"
|
||||
"mtlo %3, $ac1\n\t"
|
||||
"extr_r.w %0, $ac1, 0x1F\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rt), "=r"(dsp)
|
||||
: "r"(ach), "r"(acl)
|
||||
);
|
||||
dsp = (dsp >> 23) & 0x01;
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -67,5 +67,51 @@ int main()
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
/* Clear dspcontrol */
|
||||
dsp = 0;
|
||||
__asm
|
||||
("wrdsp %0\n\t"
|
||||
:
|
||||
: "r"(dsp)
|
||||
);
|
||||
|
||||
ach = 0x80000000;
|
||||
acl = 0x00000000;
|
||||
result = 0x80000000;
|
||||
__asm
|
||||
("mthi %2, $ac1\n\t"
|
||||
"mtlo %3, $ac1\n\t"
|
||||
"extr_rs.w %0, $ac1, 0x1F\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rt), "=r"(dsp)
|
||||
: "r"(ach), "r"(acl)
|
||||
);
|
||||
dsp = (dsp >> 23) & 0x01;
|
||||
assert(dsp == 1);
|
||||
assert(result == rt);
|
||||
|
||||
/* Clear dspcontrol */
|
||||
dsp = 0;
|
||||
__asm
|
||||
("wrdsp %0\n\t"
|
||||
:
|
||||
: "r"(dsp)
|
||||
);
|
||||
|
||||
ach = 0xFFFFFFFF;
|
||||
acl = 0xFFFFFFFF;
|
||||
result = 0;
|
||||
__asm
|
||||
("mthi %2, $ac1\n\t"
|
||||
"mtlo %3, $ac1\n\t"
|
||||
"extr_rs.w %0, $ac1, 0x1F\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rt), "=r"(dsp)
|
||||
: "r"(ach), "r"(acl)
|
||||
);
|
||||
dsp = (dsp >> 23) & 0x01;
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -67,5 +67,28 @@ int main()
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
/* Clear dspcontrol */
|
||||
dsp = 0;
|
||||
__asm
|
||||
("wrdsp %0\n\t"
|
||||
:
|
||||
: "r"(dsp)
|
||||
);
|
||||
|
||||
ach = 0xFFFFFFFF;
|
||||
acl = 0xFFFFFFFF;
|
||||
result = 0xFFFFFFFF;
|
||||
__asm
|
||||
("mthi %2, $ac1\n\t"
|
||||
"mtlo %3, $ac1\n\t"
|
||||
"extr.w %0, $ac1, 0x1F\n\t"
|
||||
"rddsp %1\n\t"
|
||||
: "=r"(rt), "=r"(dsp)
|
||||
: "r"(ach), "r"(acl)
|
||||
);
|
||||
dsp = (dsp >> 23) & 0x01;
|
||||
assert(dsp == 0);
|
||||
assert(result == rt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user