diff options
Diffstat (limited to 'src/core/arm/interpreter/armemu.cpp')
-rw-r--r-- | src/core/arm/interpreter/armemu.cpp | 89 |
1 files changed, 70 insertions, 19 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp index 610e04f10..e69789142 100644 --- a/src/core/arm/interpreter/armemu.cpp +++ b/src/core/arm/interpreter/armemu.cpp @@ -5877,6 +5877,8 @@ L_stm_s_takeabort: state->Cpsr &= ~(1 << 18); state->Cpsr &= ~(1 << 19); } + + ARMul_CPSRAltered(state); return 1; } // SADD8/SSUB8 @@ -5948,6 +5950,7 @@ L_stm_s_takeabort: state->Cpsr &= ~(1 << 19); } + ARMul_CPSRAltered(state); state->Reg[rd_idx] = (lo_val1 | lo_val2 << 8 | hi_val1 << 16 | hi_val2 << 24); return 1; } @@ -6024,15 +6027,33 @@ L_stm_s_takeabort: if ((instr & 0x0F0) == 0x070) { // USUB16 h1 = ((u16)from - (u16)to); h2 = ((u16)(from >> 16) - (u16)(to >> 16)); - if (!(h1 & 0xffff0000)) state->Cpsr |= (3 << 16); - if (!(h2 & 0xffff0000)) state->Cpsr |= (3 << 18); + + if (!(h1 & 0xffff0000)) + state->Cpsr |= (3 << 16); + else + state->Cpsr &= ~(3 << 16); + + if (!(h2 & 0xffff0000)) + state->Cpsr |= (3 << 18); + else + state->Cpsr &= ~(3 << 18); } else { // UADD16 h1 = ((u16)from + (u16)to); h2 = ((u16)(from >> 16) + (u16)(to >> 16)); - if (h1 & 0xffff0000) state->Cpsr |= (3 << 16); - if (h2 & 0xffff0000) state->Cpsr |= (3 << 18); + + if (h1 & 0xffff0000) + state->Cpsr |= (3 << 16); + else + state->Cpsr &= ~(3 << 16); + + if (h2 & 0xffff0000) + state->Cpsr |= (3 << 18); + else + state->Cpsr &= ~(3 << 18); } + + ARMul_CPSRAltered(state); state->Reg[rd] = (u32)((h1 & 0xffff) | ((h2 & 0xffff) << 16)); return 1; } @@ -6045,10 +6066,26 @@ L_stm_s_takeabort: b2 = ((u8)(from >> 8) - (u8)(to >> 8)); b3 = ((u8)(from >> 16) - (u8)(to >> 16)); b4 = ((u8)(from >> 24) - (u8)(to >> 24)); - if (!(b1 & 0xffffff00)) state->Cpsr |= (1 << 16); - if (!(b2 & 0xffffff00)) state->Cpsr |= (1 << 17); - if (!(b3 & 0xffffff00)) state->Cpsr |= (1 << 18); - if (!(b4 & 0xffffff00)) state->Cpsr |= (1 << 19); + + if (!(b1 & 0xffffff00)) + state->Cpsr |= (1 << 16); + else + state->Cpsr &= ~(1 << 16); + + if (!(b2 & 0xffffff00)) + state->Cpsr |= (1 << 17); + else + state->Cpsr &= ~(1 << 17); + + if (!(b3 & 0xffffff00)) + state->Cpsr |= (1 << 18); + else + state->Cpsr &= ~(1 << 18); + + if (!(b4 & 0xffffff00)) + state->Cpsr |= (1 << 19); + else + state->Cpsr &= ~(1 << 19); } else { // UADD8 b1 = ((u8)from + (u8)to); @@ -6071,13 +6108,13 @@ L_stm_s_takeabort: else state->Cpsr &= ~(1 << 18); - if (b4 & 0xffffff00) state->Cpsr |= (1 << 19); else state->Cpsr &= ~(1 << 19); } + ARMul_CPSRAltered(state); state->Reg[rd] = (u32)(b1 | (b2 & 0xff) << 8 | (b3 & 0xff) << 16 | (b4 & 0xff) << 24); return 1; } @@ -6116,7 +6153,7 @@ L_stm_s_takeabort: u32 rm = (instr >> 0) & 0xF; u32 from = state->Reg[rn]; u32 to = state->Reg[rm]; - u32 cpsr = state->Cpsr; + u32 cpsr = ARMul_GetCPSR(state); if ((instr & 0xFF0) == 0xFB0) { // SEL u32 result; if (cpsr & (1 << 16)) @@ -6172,16 +6209,23 @@ L_stm_s_takeabort: s16 rn_lo = (state->Reg[rn_idx]); s16 rn_hi = (state->Reg[rn_idx] >> 16); - if (rn_lo > max) + if (rn_lo > max) { rn_lo = max; - else if (rn_lo < min) + state->Cpsr |= (1 << 27); + } else if (rn_lo < min) { rn_lo = min; + state->Cpsr |= (1 << 27); + } - if (rn_hi > max) + if (rn_hi > max) { rn_hi = max; - else if (rn_hi < min) + state->Cpsr |= (1 << 27); + } else if (rn_hi < min) { rn_hi = min; + state->Cpsr |= (1 << 27); + } + ARMul_CPSRAltered(state); state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi & 0xFFFF) << 16); return 1; } @@ -6313,16 +6357,23 @@ L_stm_s_takeabort: s16 rn_lo = (state->Reg[rn_idx]); s16 rn_hi = (state->Reg[rn_idx] >> 16); - if (max < rn_lo) + if (max < rn_lo) { rn_lo = max; - else if (rn_lo < 0) + state->Cpsr |= (1 << 27); + } else if (rn_lo < 0) { rn_lo = 0; + state->Cpsr |= (1 << 27); + } - if (max < rn_hi) + if (max < rn_hi) { rn_hi = max; - else if (rn_hi < 0) + state->Cpsr |= (1 << 27); + } else if (rn_hi < 0) { rn_hi = 0; - + state->Cpsr |= (1 << 27); + } + + ARMul_CPSRAltered(state); state->Reg[rd_idx] = (rn_lo & 0xFFFF) | ((rn_hi << 16) & 0xFFFF); return 1; } |