Index: src/arm/simulator-arm.cc |
=================================================================== |
--- src/arm/simulator-arm.cc (revision 3799) |
+++ src/arm/simulator-arm.cc (working copy) |
@@ -1741,7 +1741,7 @@ |
void Simulator::DecodeType3(Instr* instr) { |
- ASSERT(instr->Bit(4) == 0); |
+ ASSERT(instr->Bits(6, 4) == 0x5 || instr->Bit(4) == 0); |
int rd = instr->RdField(); |
int rn = instr->RnField(); |
int32_t rn_val = get_register(rn); |
@@ -1768,10 +1768,26 @@ |
break; |
} |
case 3: { |
- // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); |
- addr = rn_val + shifter_operand; |
- if (instr->HasW()) { |
- set_register(rn, addr); |
+ if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) { |
+ uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16)); |
+ uint32_t lsbit = static_cast<uint32_t>(instr->ShiftAmountField()); |
+ uint32_t msbit = widthminus1 + lsbit; |
+ if (msbit <= 31) { |
+ uint32_t rm_val = |
+ static_cast<uint32_t>(get_register(instr->RmField())); |
+ uint32_t extr_val = rm_val << (31 - msbit); |
+ extr_val = extr_val >> (31 - widthminus1); |
+ set_register(instr->RdField(), extr_val); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ return; |
+ } else { |
+ // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); |
+ addr = rn_val + shifter_operand; |
+ if (instr->HasW()) { |
+ set_register(rn, addr); |
+ } |
} |
break; |
} |