citra-emu
/
citra
Archived
1
0
Fork 0

Merge pull request #467 from lioncash/msr

dyncom: Fix conditional execution of MSR
This commit is contained in:
bunnei 2015-01-11 18:51:03 -05:00
commit 1da04a72a2
1 changed files with 31 additions and 29 deletions

View File

@ -4964,39 +4964,41 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
} }
MSR_INST: MSR_INST:
{ {
msr_inst *inst_cream = (msr_inst *)inst_base->component; if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; msr_inst *inst_cream = (msr_inst *)inst_base->component;
unsigned int inst = inst_cream->inst; const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020;
unsigned int operand; unsigned int inst = inst_cream->inst;
unsigned int operand;
if (BIT(inst, 25)) { if (BIT(inst, 25)) {
int rot_imm = BITS(inst, 8, 11) * 2; int rot_imm = BITS(inst, 8, 11) * 2;
operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm);
} else {
operand = cpu->Reg[BITS(inst, 0, 3)];
}
uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
| (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
uint32_t mask;
if (!inst_cream->R) {
if (InAPrivilegedMode(cpu)) {
if ((operand & StateMask) != 0) {
/// UNPREDICTABLE
DEBUG_MSG;
} else
mask = byte_mask & (UserMask | PrivMask);
} else { } else {
mask = byte_mask & UserMask; operand = cpu->Reg[BITS(inst, 0, 3)];
} }
SAVE_NZCVT; uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0)
| (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0);
uint32_t mask;
if (!inst_cream->R) {
if (InAPrivilegedMode(cpu)) {
if ((operand & StateMask) != 0) {
/// UNPREDICTABLE
DEBUG_MSG;
} else
mask = byte_mask & (UserMask | PrivMask);
} else {
mask = byte_mask & UserMask;
}
SAVE_NZCVT;
cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask);
switch_mode(cpu, cpu->Cpsr & 0x1f); switch_mode(cpu, cpu->Cpsr & 0x1f);
LOAD_NZCVT; LOAD_NZCVT;
} else { } else {
if (CurrentModeHasSPSR) { if (CurrentModeHasSPSR) {
mask = byte_mask & (UserMask | PrivMask | StateMask); mask = byte_mask & (UserMask | PrivMask | StateMask);
cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask);
}
} }
} }
cpu->Reg[15] += GET_INST_SIZE(cpu); cpu->Reg[15] += GET_INST_SIZE(cpu);