Fix SRAW on non PowerPC platforms.

This commit is contained in:
gbeauche 2003-11-27 23:53:41 +00:00
parent 8711c4afd6
commit 8ca440d0b5
2 changed files with 24 additions and 12 deletions

View File

@ -680,11 +680,18 @@ void OPPROTO op_srw_T0_T1(void)
void OPPROTO op_sraw_T0_T1(void)
{
const uint32 n = T1 & 0x3f;
const uint32 RD = ((int32)T0) >> n;
const bool ca = (((int32)T0) < 0) && (T0 & ~(0xffffffff << n));
powerpc_dyngen_helper::xer().set_ca(ca);
T1 &= 0x3f;
if (T1 & 0x20) {
const uint32 SB = T0 >> 31;
powerpc_dyngen_helper::xer().set_ca(SB);
T0 = -SB;
}
else {
const uint32 RD = ((int32)T0) >> T1;
const bool CA = (int32)T0 < 0 && (T0 & ~(0xffffffff << T1));
powerpc_dyngen_helper::xer().set_ca(CA);
T0 = RD;
}
dyngen_barrier();
}

View File

@ -272,15 +272,20 @@ void powerpc_cpu::execute_shift(uint32 opcode)
{
const uint32 n = SO::apply(SH::get(this, opcode));
const uint32 r = RA::get(this, opcode);
uint32 d;
// Shift operation is valid only if rB[26] = 0
// TODO: optimize srw case where shift operation would zero result
uint32 d = (n & 0x20) ? invalid_shift<OP>::value(r) : OP::apply(r, n);
// Set XER (CA) if instruction is algebraic variant
if (n & 0x20) {
d = invalid_shift<OP>::value(r);
if (CA::test(opcode))
xer().set_ca(d >> 31);
}
else {
d = OP::apply(r, n);
if (CA::test(opcode)) {
const uint32 carry = (r & 0x80000000) && (r & ~(0xffffffff << n));
xer().set_ca(carry);
const uint32 ca = (r & 0x80000000) && (r & ~(0xffffffff << n));
xer().set_ca(ca);
}
}
// Set CR0 (LT, GT, EQ, SO) if instruction has Rc set