Index: src/arm/simulator-arm.cc |
=================================================================== |
--- src/arm/simulator-arm.cc (revision 4740) |
+++ src/arm/simulator-arm.cc (working copy) |
@@ -2031,7 +2031,6 @@ |
void Simulator::DecodeType3(Instr* instr) { |
- 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); |
@@ -2058,21 +2057,51 @@ |
break; |
} |
case 3: { |
- // UBFX. |
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 lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); |
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); |
+ if (instr->Bit(22)) { |
+ // ubfx - unsigned bitfield extract. |
+ 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 { |
+ // sbfx - signed bitfield extract. |
+ int32_t rm_val = get_register(instr->RmField()); |
+ int32_t extr_val = rm_val << (31 - msbit); |
+ extr_val = extr_val >> (31 - widthminus1); |
+ set_register(instr->RdField(), extr_val); |
+ } |
} else { |
UNREACHABLE(); |
} |
return; |
+ } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) { |
+ uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7)); |
+ uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16)); |
+ if (msbit >= lsbit) { |
+ // bfc or bfi - bitfield clear/insert. |
+ uint32_t rd_val = |
+ static_cast<uint32_t>(get_register(instr->RdField())); |
+ uint32_t bitcount = msbit - lsbit + 1; |
+ uint32_t mask = (1 << bitcount) - 1; |
+ rd_val &= ~(mask << lsbit); |
+ if (instr->RmField() != 15) { |
+ // bfi - bitfield insert. |
+ uint32_t rm_val = |
+ static_cast<uint32_t>(get_register(instr->RmField())); |
+ rm_val &= mask; |
+ rd_val |= rm_val << lsbit; |
+ } |
+ set_register(instr->RdField(), rd_val); |
+ } else { |
+ UNREACHABLE(); |
+ } |
+ return; |
} else { |
// Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w"); |
addr = rn_val + shifter_operand; |