Index: src/arm/simulator-arm.cc |
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc |
index 4630b94b630c0e0a597ea0f3b4d36d57889440ab..7687bbbe7c91f123db176c08f5a78f26df477142 100644 |
--- a/src/arm/simulator-arm.cc |
+++ b/src/arm/simulator-arm.cc |
@@ -1041,6 +1041,32 @@ ReturnType Simulator::GetFromVFPRegister(int reg_index) { |
return value; |
} |
+void Simulator::SetSpecialRegister(SRegisterFieldMask reg_and_mask, |
+ uint32_t value) { |
+ // Only CPSR_f is implemented. Of that, only N, Z, C and V are implemented. |
+ if ((reg_and_mask == CPSR_f) && ((value & ~kSpecialCondition) == 0)) { |
+ n_flag_ = ((value & (1 << 31)) != 0); |
+ z_flag_ = ((value & (1 << 30)) != 0); |
+ c_flag_ = ((value & (1 << 29)) != 0); |
+ v_flag_ = ((value & (1 << 28)) != 0); |
+ } else { |
+ UNIMPLEMENTED(); |
+ } |
+} |
+ |
+uint32_t Simulator::GetFromSpecialRegister(SRegister reg) { |
+ uint32_t result = 0; |
+ // Only CPSR_f is implemented. |
+ if (reg == CPSR) { |
+ if (n_flag_) result |= (1 << 31); |
+ if (z_flag_) result |= (1 << 30); |
+ if (c_flag_) result |= (1 << 29); |
+ if (v_flag_) result |= (1 << 28); |
+ } else { |
+ UNIMPLEMENTED(); |
+ } |
+ return result; |
+} |
// Runtime FP routines take: |
// - two double arguments |
@@ -2312,7 +2338,22 @@ void Simulator::DecodeType01(Instruction* instr) { |
return; |
} |
} else if ((type == 0) && instr->IsMiscType0()) { |
- if (instr->Bits(22, 21) == 1) { |
+ if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) && |
+ (instr->Bits(15, 4) == 0xf00)) { |
+ // MSR |
+ int rm = instr->RmValue(); |
+ DCHECK_NE(pc, rm); // UNPREDICTABLE |
+ SRegisterFieldMask sreg_and_mask = |
+ instr->BitField(22, 22) | instr->BitField(19, 16); |
+ SetSpecialRegister(sreg_and_mask, get_register(rm)); |
+ } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) && |
+ (instr->Bits(11, 0) == 0)) { |
+ // MRS |
+ int rd = instr->RdValue(); |
+ DCHECK_NE(pc, rd); // UNPREDICTABLE |
+ SRegister sreg = static_cast<SRegister>(instr->BitField(22, 22)); |
+ set_register(rd, GetFromSpecialRegister(sreg)); |
+ } else if (instr->Bits(22, 21) == 1) { |
int rm = instr->RmValue(); |
switch (instr->BitField(7, 4)) { |
case BX: |