diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 60 |
1 files changed, 31 insertions, 29 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index e3ca02e98..4759c7653 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -4964,39 +4964,41 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 4964 | } | 4964 | } |
| 4965 | MSR_INST: | 4965 | MSR_INST: |
| 4966 | { | 4966 | { |
| 4967 | msr_inst *inst_cream = (msr_inst *)inst_base->component; | 4967 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 4968 | const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; | 4968 | msr_inst *inst_cream = (msr_inst *)inst_base->component; |
| 4969 | unsigned int inst = inst_cream->inst; | 4969 | const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; |
| 4970 | unsigned int operand; | 4970 | unsigned int inst = inst_cream->inst; |
| 4971 | unsigned int operand; | ||
| 4971 | 4972 | ||
| 4972 | if (BIT(inst, 25)) { | 4973 | if (BIT(inst, 25)) { |
| 4973 | int rot_imm = BITS(inst, 8, 11) * 2; | 4974 | int rot_imm = BITS(inst, 8, 11) * 2; |
| 4974 | operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); | 4975 | operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); |
| 4975 | } else { | ||
| 4976 | operand = cpu->Reg[BITS(inst, 0, 3)]; | ||
| 4977 | } | ||
| 4978 | uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) | ||
| 4979 | | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); | ||
| 4980 | uint32_t mask; | ||
| 4981 | if (!inst_cream->R) { | ||
| 4982 | if (InAPrivilegedMode(cpu)) { | ||
| 4983 | if ((operand & StateMask) != 0) { | ||
| 4984 | /// UNPREDICTABLE | ||
| 4985 | DEBUG_MSG; | ||
| 4986 | } else | ||
| 4987 | mask = byte_mask & (UserMask | PrivMask); | ||
| 4988 | } else { | 4976 | } else { |
| 4989 | mask = byte_mask & UserMask; | 4977 | operand = cpu->Reg[BITS(inst, 0, 3)]; |
| 4990 | } | 4978 | } |
| 4991 | SAVE_NZCVT; | 4979 | uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) |
| 4980 | | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); | ||
| 4981 | uint32_t mask; | ||
| 4982 | if (!inst_cream->R) { | ||
| 4983 | if (InAPrivilegedMode(cpu)) { | ||
| 4984 | if ((operand & StateMask) != 0) { | ||
| 4985 | /// UNPREDICTABLE | ||
| 4986 | DEBUG_MSG; | ||
| 4987 | } else | ||
| 4988 | mask = byte_mask & (UserMask | PrivMask); | ||
| 4989 | } else { | ||
| 4990 | mask = byte_mask & UserMask; | ||
| 4991 | } | ||
| 4992 | SAVE_NZCVT; | ||
| 4992 | 4993 | ||
| 4993 | cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); | 4994 | cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); |
| 4994 | switch_mode(cpu, cpu->Cpsr & 0x1f); | 4995 | switch_mode(cpu, cpu->Cpsr & 0x1f); |
| 4995 | LOAD_NZCVT; | 4996 | LOAD_NZCVT; |
| 4996 | } else { | 4997 | } else { |
| 4997 | if (CurrentModeHasSPSR) { | 4998 | if (CurrentModeHasSPSR) { |
| 4998 | mask = byte_mask & (UserMask | PrivMask | StateMask); | 4999 | mask = byte_mask & (UserMask | PrivMask | StateMask); |
| 4999 | cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); | 5000 | cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); |
| 5001 | } | ||
| 5000 | } | 5002 | } |
| 5001 | } | 5003 | } |
| 5002 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 5004 | cpu->Reg[15] += GET_INST_SIZE(cpu); |