Index: src/arm/simulator-arm.cc |
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc |
index c143cc58ec8584df813e22a83c5bf8a6dec876d0..d1535785362c1a00a7b3ace43602b19b032a1cc8 100644 |
--- a/src/arm/simulator-arm.cc |
+++ b/src/arm/simulator-arm.cc |
@@ -34,6 +34,7 @@ |
#include "disasm.h" |
#include "assembler.h" |
+#include "codegen.h" |
#include "arm/constants-arm.h" |
#include "arm/simulator-arm.h" |
@@ -764,7 +765,7 @@ Simulator::Simulator(Isolate* isolate) : isolate_(isolate) { |
// All registers are initialized to zero to start with |
// even though s_registers_ & d_registers_ share the same |
// physical registers in the target. |
- for (int i = 0; i < num_s_registers; i++) { |
+ for (int i = 0; i < num_d_registers * 2; i++) { |
vfp_register[i] = 0; |
} |
n_flag_FPSCR_ = false; |
@@ -949,7 +950,7 @@ template<class InputType, int register_size> |
void Simulator::SetVFPRegister(int reg_index, const InputType& value) { |
ASSERT(reg_index >= 0); |
if (register_size == 1) ASSERT(reg_index < num_s_registers); |
- if (register_size == 2) ASSERT(reg_index < num_d_registers); |
+ if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); |
char buffer[register_size * sizeof(vfp_register[0])]; |
memcpy(buffer, &value, register_size * sizeof(vfp_register[0])); |
@@ -962,7 +963,7 @@ template<class ReturnType, int register_size> |
ReturnType Simulator::GetFromVFPRegister(int reg_index) { |
ASSERT(reg_index >= 0); |
if (register_size == 1) ASSERT(reg_index < num_s_registers); |
- if (register_size == 2) ASSERT(reg_index < num_d_registers); |
+ if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters()); |
ReturnType value = 0; |
char buffer[register_size * sizeof(vfp_register[0])]; |
@@ -1613,15 +1614,19 @@ void Simulator::HandleVList(Instruction* 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)); |
+ int32_t data[] = { |
+ ReadW(reinterpret_cast<int32_t>(address), instr), |
+ ReadW(reinterpret_cast<int32_t>(address + 1), instr) |
+ }; |
+ double d; |
+ memcpy(&d, data, 8); |
+ set_d_register_from_double(reg, d); |
} 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); |
+ int32_t data[2]; |
+ double d = get_double_from_d_register(reg); |
+ memcpy(data, &d, 8); |
+ WriteW(reinterpret_cast<int32_t>(address), data[0], instr); |
+ WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr); |
} |
address += 2; |
} |
@@ -2810,6 +2815,17 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { |
if ((instr->VCValue() == 0x0) && |
(instr->VAValue() == 0x0)) { |
DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
+ } else if ((instr->VLValue() == 0x0) && |
+ (instr->VCValue() == 0x1) && |
+ (instr->Bit(23) == 0x0)) { |
+ // vmov (ARM core register to scalar) |
+ int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4); |
+ double dd_value = get_double_from_d_register(vd); |
+ int32_t data[2]; |
+ memcpy(data, &dd_value, 8); |
+ data[instr->Bit(21)] = get_register(instr->RtValue()); |
+ memcpy(&dd_value, data, 8); |
+ set_d_register_from_double(vd, dd_value); |
} else if ((instr->VLValue() == 0x1) && |
(instr->VCValue() == 0x0) && |
(instr->VAValue() == 0x7) && |
@@ -3148,31 +3164,32 @@ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) { |
switch (instr->OpcodeValue()) { |
case 0x2: |
// Load and store double to two GP registers |
- if (instr->Bits(7, 4) != 0x1) { |
+ if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) { |
UNIMPLEMENTED(); // Not used by V8. |
} else { |
int rt = instr->RtValue(); |
int rn = instr->RnValue(); |
- int vm = instr->VmValue(); |
+ int vm = instr->VFPMRegValue(kDoublePrecision); |
if (instr->HasL()) { |
- int32_t rt_int_value = get_sinteger_from_s_register(2*vm); |
- int32_t rn_int_value = get_sinteger_from_s_register(2*vm+1); |
- |
- set_register(rt, rt_int_value); |
- set_register(rn, rn_int_value); |
+ int32_t data[2]; |
+ double d = get_double_from_d_register(vm); |
+ memcpy(data, &d, 8); |
+ set_register(rt, data[0]); |
+ set_register(rn, data[1]); |
} else { |
- int32_t rs_val = get_register(rt); |
- int32_t rn_val = get_register(rn); |
- |
- set_s_register_from_sinteger(2*vm, rs_val); |
- set_s_register_from_sinteger((2*vm+1), rn_val); |
+ int32_t data[] = { get_register(rt), get_register(rn) }; |
+ double d; |
+ memcpy(&d, data, 8); |
+ set_d_register_from_double(vm, d); |
} |
} |
break; |
case 0x8: |
- case 0xC: { // Load and store double to memory. |
+ case 0xA: |
+ case 0xC: |
+ case 0xE: { // Load and store double to memory. |
int rn = instr->RnValue(); |
- int vd = instr->VdValue(); |
+ int vd = instr->VFPDRegValue(kDoublePrecision); |
int offset = instr->Immed8Value(); |
if (!instr->HasU()) { |
offset = -offset; |
@@ -3180,18 +3197,29 @@ void Simulator::DecodeType6CoprocessorIns(Instruction* instr) { |
int32_t address = get_register(rn) + 4 * offset; |
if (instr->HasL()) { |
// Load double from memory: vldr. |
- set_s_register_from_sinteger(2*vd, ReadW(address, instr)); |
- set_s_register_from_sinteger(2*vd + 1, ReadW(address + 4, instr)); |
+ int32_t data[] = { |
+ ReadW(address, instr), |
+ ReadW(address + 4, instr) |
+ }; |
+ double val; |
+ memcpy(&val, data, 8); |
+ set_d_register_from_double(vd, val); |
} else { |
// Store double to memory: vstr. |
- WriteW(address, get_sinteger_from_s_register(2*vd), instr); |
- WriteW(address + 4, get_sinteger_from_s_register(2*vd + 1), instr); |
+ int32_t data[2]; |
+ double val = get_double_from_d_register(vd); |
+ memcpy(data, &val, 8); |
+ WriteW(address, data[0], instr); |
+ WriteW(address + 4, data[1], instr); |
} |
break; |
} |
case 0x4: |
case 0x5: |
+ case 0x6: |
+ case 0x7: |
case 0x9: |
+ case 0xB: |
// Load/store multiple double from memory: vldm/vstm. |
HandleVList(instr); |
break; |