Index: src/arm/simulator-arm.cc |
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc |
index 46797d950c32ffb97c0c00cc40a814c27c23178a..0e999cbf1326ae36456e44efcd8c8ee9e0cef8c8 100644 |
--- a/src/arm/simulator-arm.cc |
+++ b/src/arm/simulator-arm.cc |
@@ -1504,36 +1504,34 @@ static int count_bits(int bit_vector) { |
} |
-// Addressing Mode 4 - Load and Store Multiple |
-void Simulator::HandleRList(Instruction* instr, bool load) { |
+void Simulator::ProcessPUW(Instruction* instr, |
+ int num_regs, |
+ int reg_size, |
+ intptr_t* start_address, |
+ intptr_t* end_address) { |
int rn = instr->RnValue(); |
int32_t rn_val = get_register(rn); |
- int rlist = instr->RlistValue(); |
- int num_regs = count_bits(rlist); |
- |
- intptr_t start_address = 0; |
- intptr_t end_address = 0; |
switch (instr->PUField()) { |
case da_x: { |
UNIMPLEMENTED(); |
break; |
} |
case ia_x: { |
- start_address = rn_val; |
- end_address = rn_val + (num_regs * 4) - 4; |
- rn_val = rn_val + (num_regs * 4); |
+ *start_address = rn_val; |
+ *end_address = rn_val + (num_regs * reg_size) - reg_size; |
+ rn_val = rn_val + (num_regs * reg_size); |
break; |
} |
case db_x: { |
- start_address = rn_val - (num_regs * 4); |
- end_address = rn_val - 4; |
- rn_val = start_address; |
+ *start_address = rn_val - (num_regs * reg_size); |
+ *end_address = rn_val - reg_size; |
+ rn_val = *start_address; |
break; |
} |
case ib_x: { |
- start_address = rn_val + 4; |
- end_address = rn_val + (num_regs * 4); |
- rn_val = end_address; |
+ *start_address = rn_val + reg_size; |
+ *end_address = rn_val + (num_regs * reg_size); |
+ rn_val = *end_address; |
break; |
} |
default: { |
@@ -1544,6 +1542,17 @@ void Simulator::HandleRList(Instruction* instr, bool load) { |
if (instr->HasW()) { |
set_register(rn, rn_val); |
} |
+} |
+ |
+// Addressing Mode 4 - Load and Store Multiple |
+void Simulator::HandleRList(Instruction* instr, bool load) { |
+ int rlist = instr->RlistValue(); |
+ int num_regs = count_bits(rlist); |
+ |
+ intptr_t start_address = 0; |
+ intptr_t end_address = 0; |
+ ProcessPUW(instr, num_regs, kPointerSize, &start_address, &end_address); |
+ |
intptr_t* address = reinterpret_cast<intptr_t*>(start_address); |
int reg = 0; |
while (rlist != 0) { |
@@ -1562,6 +1571,56 @@ void Simulator::HandleRList(Instruction* instr, bool load) { |
} |
+// Addressing Mode 6 - Load and Store Multiple Coprocessor registers. |
+void Simulator::HandleVList(Instruction* instr, bool load) { |
+ VFPRegPrecision precision = |
+ (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision; |
+ int operand_size = (precision == kSinglePrecision) ? 4 : 8; |
+ |
+ int vd; |
+ int num_regs; |
+ if (precision == kSinglePrecision) { |
+ vd = instr->VdValue() << 1 | instr->DValue(); |
Rodolph Perfetta
2011/04/05 18:16:39
Use instr->VFPDregValue(kSinglePrecision) here.
Søren Thygesen Gjesse
2011/04/06 08:00:09
Used
vd = instr->VFPDRegValue(precision);
befo
|
+ num_regs = instr->Immed8Value(); |
+ } else { |
+ vd = instr->VdValue(); |
+ num_regs = instr->Immed8Value() / 2; |
+ } |
+ |
+ intptr_t start_address = 0; |
+ intptr_t end_address = 0; |
+ ProcessPUW(instr, num_regs, operand_size, &start_address, &end_address); |
+ |
+ intptr_t* address = reinterpret_cast<intptr_t*>(start_address); |
+ for (int reg = vd; reg < vd + num_regs; reg++) { |
+ if (precision == kSinglePrecision) { |
+ if (load) { |
+ set_s_register_from_sinteger( |
+ reg, ReadW(reinterpret_cast<int32_t>(address), instr)); |
+ } else { |
+ WriteW(reinterpret_cast<int32_t>(address), |
+ get_sinteger_from_s_register(reg), instr); |
+ } |
+ address += 1; |
+ } else { |
+ if (load) { |
+ set_s_register_from_sinteger( |
+ 2 * reg, ReadW(reinterpret_cast<int32_t>(address), instr)); |
+ set_s_register_from_sinteger( |
+ 2 * reg + 1, ReadW(reinterpret_cast<int32_t>(address + 1), instr)); |
+ } else { |
+ WriteW(reinterpret_cast<int32_t>(address), |
+ get_sinteger_from_s_register(2 * reg), instr); |
+ WriteW(reinterpret_cast<int32_t>(address + 1), |
+ get_sinteger_from_s_register(2 * reg + 1), instr); |
+ } |
+ address += 2; |
+ } |
+ } |
+ ASSERT_EQ(((intptr_t)address) - operand_size, end_address); |
+} |
+ |
+ |
// Calls into the V8 runtime are based on this very simple interface. |
// Note: To be able to return two values from some calls the code in runtime.cc |
// uses the ObjectPair which is essentially two 32-bit values stuffed into a |
@@ -2945,9 +3004,23 @@ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) { |
} |
break; |
} |
- default: |
- UNIMPLEMENTED(); // Not used by V8. |
+ default: { |
+ BlockAddrMode am = |
+ static_cast<BlockAddrMode>( |
+ instr->BitField(24, 21) & kBlockAddrModeMask); |
+ if (am == ia || am == ia_w || am == db_w) { |
+ bool to_arm_register = (instr->VLValue() == 0x1); |
Rodolph Perfetta
2011/04/05 18:16:39
Since the instruction encoding is given to HandleV
Søren Thygesen Gjesse
2011/04/06 08:00:09
No - argument removed.
|
+ if (to_arm_register) { |
+ // Load multiple single from memory: vldm. |
+ HandleVList(instr, true); |
+ } else { |
+ HandleVList(instr, false); |
+ } |
+ } else { |
+ UNIMPLEMENTED(); // Not used by V8. |
+ } |
break; |
+ } |
} |
} else if (instr->CoprocessorValue() == 0xB) { |
switch (instr->OpcodeValue()) { |
@@ -2994,9 +3067,23 @@ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) { |
} |
break; |
} |
- default: |
- UNIMPLEMENTED(); // Not used by V8. |
+ default: { |
+ BlockAddrMode am = |
+ static_cast<BlockAddrMode>( |
+ instr->BitField(24, 21) & kBlockAddrModeMask); |
+ if (am == ia || am == ia_w || am == db_w) { |
+ bool to_arm_register = (instr->VLValue() == 0x1); |
Rodolph Perfetta
2011/04/05 18:16:39
Ditto.
Søren Thygesen Gjesse
2011/04/06 08:00:09
Done.
|
+ if (to_arm_register) { |
+ // Load multiple double from memory: vldm. |
+ HandleVList(instr, true); |
+ } else { |
+ HandleVList(instr, false); |
+ } |
+ } else { |
+ UNIMPLEMENTED(); // Not used by V8. |
+ } |
break; |
+ } |
} |
} else { |
UNIMPLEMENTED(); // Not used by V8. |