Chromium Code Reviews| 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. |