ARM: Make double registers low/high safe

This patch prevents taking the low/high part of a double-precision VFP register that has no corresponding single-precision VFP registers.

BUG=none
TEST=Added to test-disasm-arm.cc, test-assembler-arm.cc

Review URL: https://codereview.chromium.org/19560003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15885 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 32e2e372
...@@ -2373,15 +2373,16 @@ void Assembler::vmov(const DwVfpRegister dst, ...@@ -2373,15 +2373,16 @@ void Assembler::vmov(const DwVfpRegister dst,
if (scratch.is(no_reg)) { if (scratch.is(no_reg)) {
if (dst.code() < 16) { if (dst.code() < 16) {
const LowDwVfpRegister loc = LowDwVfpRegister::from_code(dst.code());
// Move the low part of the double into the lower of the corresponsing S // Move the low part of the double into the lower of the corresponsing S
// registers of D register dst. // registers of D register dst.
mov(ip, Operand(lo)); mov(ip, Operand(lo));
vmov(dst.low(), ip); vmov(loc.low(), ip);
// Move the high part of the double into the higher of the // Move the high part of the double into the higher of the
// corresponsing S registers of D register dst. // corresponsing S registers of D register dst.
mov(ip, Operand(hi)); mov(ip, Operand(hi));
vmov(dst.high(), ip); vmov(loc.high(), ip);
} else { } else {
// D16-D31 does not have S registers, so move the low and high parts // D16-D31 does not have S registers, so move the low and high parts
// directly to the D register using vmov.32. // directly to the D register using vmov.32.
...@@ -2446,6 +2447,22 @@ void Assembler::vmov(const DwVfpRegister dst, ...@@ -2446,6 +2447,22 @@ void Assembler::vmov(const DwVfpRegister dst,
} }
void Assembler::vmov(const Register dst,
const VmovIndex index,
const DwVfpRegister src,
const Condition cond) {
// Dd[index] = Rt
// Instruction details available in ARM DDI 0406C.b, A8.8.342.
// cond(31-28) | 1110(27-24) | U=0(23) | opc1=0index(22-21) | 1(20) |
// Vn(19-16) | Rt(15-12) | 1011(11-8) | N(7) | opc2=00(6-5) | 1(4) | 0000(3-0)
ASSERT(index.index == 0 || index.index == 1);
int vn, n;
src.split_code(&vn, &n);
emit(cond | 0xE*B24 | index.index*B21 | B20 | vn*B16 | dst.code()*B12 |
0xB*B8 | n*B7 | B4);
}
void Assembler::vmov(const DwVfpRegister dst, void Assembler::vmov(const DwVfpRegister dst,
const Register src1, const Register src1,
const Register src2, const Register src2,
......
...@@ -267,22 +267,6 @@ struct DwVfpRegister { ...@@ -267,22 +267,6 @@ struct DwVfpRegister {
return 0 <= code_ && code_ < kMaxNumRegisters; return 0 <= code_ && code_ < kMaxNumRegisters;
} }
bool is(DwVfpRegister reg) const { return code_ == reg.code_; } bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
SwVfpRegister low() const {
ASSERT(code_ < 16);
SwVfpRegister reg;
reg.code_ = code_ * 2;
ASSERT(reg.is_valid());
return reg;
}
SwVfpRegister high() const {
ASSERT(code_ < 16);
SwVfpRegister reg;
reg.code_ = (code_ * 2) + 1;
ASSERT(reg.is_valid());
return reg;
}
int code() const { int code() const {
ASSERT(is_valid()); ASSERT(is_valid());
return code_; return code_;
...@@ -304,6 +288,47 @@ struct DwVfpRegister { ...@@ -304,6 +288,47 @@ struct DwVfpRegister {
typedef DwVfpRegister DoubleRegister; typedef DwVfpRegister DoubleRegister;
// Double word VFP register d0-15.
struct LowDwVfpRegister {
public:
static const int kMaxNumLowRegisters = 16;
operator DwVfpRegister() const {
DwVfpRegister r = { code_ };
return r;
}
static LowDwVfpRegister from_code(int code) {
LowDwVfpRegister r = { code };
return r;
}
bool is_valid() const {
return 0 <= code_ && code_ < kMaxNumLowRegisters;
}
bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
int code() const {
ASSERT(is_valid());
return code_;
}
SwVfpRegister low() const {
SwVfpRegister reg;
reg.code_ = code_ * 2;
ASSERT(reg.is_valid());
return reg;
}
SwVfpRegister high() const {
SwVfpRegister reg;
reg.code_ = (code_ * 2) + 1;
ASSERT(reg.is_valid());
return reg;
}
int code_;
};
// Quad word NEON register. // Quad word NEON register.
struct QwNeonRegister { struct QwNeonRegister {
static const int kMaxNumRegisters = 16; static const int kMaxNumRegisters = 16;
...@@ -370,22 +395,22 @@ const SwVfpRegister s30 = { 30 }; ...@@ -370,22 +395,22 @@ const SwVfpRegister s30 = { 30 };
const SwVfpRegister s31 = { 31 }; const SwVfpRegister s31 = { 31 };
const DwVfpRegister no_dreg = { -1 }; const DwVfpRegister no_dreg = { -1 };
const DwVfpRegister d0 = { 0 }; const LowDwVfpRegister d0 = { 0 };
const DwVfpRegister d1 = { 1 }; const LowDwVfpRegister d1 = { 1 };
const DwVfpRegister d2 = { 2 }; const LowDwVfpRegister d2 = { 2 };
const DwVfpRegister d3 = { 3 }; const LowDwVfpRegister d3 = { 3 };
const DwVfpRegister d4 = { 4 }; const LowDwVfpRegister d4 = { 4 };
const DwVfpRegister d5 = { 5 }; const LowDwVfpRegister d5 = { 5 };
const DwVfpRegister d6 = { 6 }; const LowDwVfpRegister d6 = { 6 };
const DwVfpRegister d7 = { 7 }; const LowDwVfpRegister d7 = { 7 };
const DwVfpRegister d8 = { 8 }; const LowDwVfpRegister d8 = { 8 };
const DwVfpRegister d9 = { 9 }; const LowDwVfpRegister d9 = { 9 };
const DwVfpRegister d10 = { 10 }; const LowDwVfpRegister d10 = { 10 };
const DwVfpRegister d11 = { 11 }; const LowDwVfpRegister d11 = { 11 };
const DwVfpRegister d12 = { 12 }; const LowDwVfpRegister d12 = { 12 };
const DwVfpRegister d13 = { 13 }; const LowDwVfpRegister d13 = { 13 };
const DwVfpRegister d14 = { 14 }; const LowDwVfpRegister d14 = { 14 };
const DwVfpRegister d15 = { 15 }; const LowDwVfpRegister d15 = { 15 };
const DwVfpRegister d16 = { 16 }; const DwVfpRegister d16 = { 16 };
const DwVfpRegister d17 = { 17 }; const DwVfpRegister d17 = { 17 };
const DwVfpRegister d18 = { 18 }; const DwVfpRegister d18 = { 18 };
...@@ -420,6 +445,7 @@ const QwNeonRegister q13 = { 13 }; ...@@ -420,6 +445,7 @@ const QwNeonRegister q13 = { 13 };
const QwNeonRegister q14 = { 14 }; const QwNeonRegister q14 = { 14 };
const QwNeonRegister q15 = { 15 }; const QwNeonRegister q15 = { 15 };
// Aliases for double registers. Defined using #define instead of // Aliases for double registers. Defined using #define instead of
// "static const DwVfpRegister&" because Clang complains otherwise when a // "static const DwVfpRegister&" because Clang complains otherwise when a
// compilation unit that includes this header doesn't use the variables. // compilation unit that includes this header doesn't use the variables.
...@@ -1109,6 +1135,10 @@ class Assembler : public AssemblerBase { ...@@ -1109,6 +1135,10 @@ class Assembler : public AssemblerBase {
const VmovIndex index, const VmovIndex index,
const Register src, const Register src,
const Condition cond = al); const Condition cond = al);
void vmov(const Register dst,
const VmovIndex index,
const DwVfpRegister src,
const Condition cond = al);
void vmov(const DwVfpRegister dst, void vmov(const DwVfpRegister dst,
const Register src1, const Register src1,
const Register src2, const Register src2,
......
...@@ -1897,7 +1897,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { ...@@ -1897,7 +1897,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
Register right = r0; Register right = r0;
Register scratch1 = r7; Register scratch1 = r7;
Register scratch2 = r9; Register scratch2 = r9;
DwVfpRegister double_scratch = d0; LowDwVfpRegister double_scratch = d0;
Register heap_number_result = no_reg; Register heap_number_result = no_reg;
Register heap_number_map = r6; Register heap_number_map = r6;
...@@ -1972,7 +1972,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { ...@@ -1972,7 +1972,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) {
Label not_zero; Label not_zero;
ASSERT(kSmiTag == 0); ASSERT(kSmiTag == 0);
__ b(ne, &not_zero); __ b(ne, &not_zero);
__ vmov(scratch2, d5.high()); __ VmovHigh(scratch2, d5);
__ tst(scratch2, Operand(HeapNumber::kSignMask)); __ tst(scratch2, Operand(HeapNumber::kSignMask));
__ b(ne, &transition); __ b(ne, &transition);
__ bind(&not_zero); __ bind(&not_zero);
...@@ -3817,7 +3817,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { ...@@ -3817,7 +3817,7 @@ void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX))); Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX)));
// Copy the JS object part. // Copy the JS object part.
__ CopyFields(r0, r4, d0, s0, JSObject::kHeaderSize / kPointerSize); __ CopyFields(r0, r4, d0, JSObject::kHeaderSize / kPointerSize);
// Get the length (smi tagged) and set that as an in-object property too. // Get the length (smi tagged) and set that as an in-object property too.
STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0);
...@@ -6804,7 +6804,7 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { ...@@ -6804,7 +6804,7 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
// Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
__ bind(&double_elements); __ bind(&double_elements);
__ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
__ StoreNumberToDoubleElements(r0, r3, r5, r6, &slow_elements); __ StoreNumberToDoubleElements(r0, r3, r5, r6, d0, &slow_elements);
__ Ret(); __ Ret();
} }
......
...@@ -1345,6 +1345,14 @@ void Decoder::DecodeTypeVFP(Instruction* instr) { ...@@ -1345,6 +1345,14 @@ void Decoder::DecodeTypeVFP(Instruction* instr) {
} else { } else {
Format(instr, "vmov'cond.32 'Dd[1], 'rt"); Format(instr, "vmov'cond.32 'Dd[1], 'rt");
} }
} else if ((instr->VLValue() == 0x1) &&
(instr->VCValue() == 0x1) &&
(instr->Bit(23) == 0x0)) {
if (instr->Bit(21) == 0x0) {
Format(instr, "vmov'cond.32 'rt, 'Dd[0]");
} else {
Format(instr, "vmov'cond.32 'rt, 'Dd[1]");
}
} else if ((instr->VCValue() == 0x0) && } else if ((instr->VCValue() == 0x0) &&
(instr->VAValue() == 0x7) && (instr->VAValue() == 0x7) &&
(instr->Bits(19, 16) == 0x1)) { (instr->Bits(19, 16) == 0x1)) {
......
...@@ -1623,7 +1623,7 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { ...@@ -1623,7 +1623,7 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
// r0: Newly allocated regexp. // r0: Newly allocated regexp.
// r5: Materialized regexp. // r5: Materialized regexp.
// r2: temp. // r2: temp.
__ CopyFields(r0, r5, d0, s0, size / kPointerSize); __ CopyFields(r0, r5, d0, size / kPointerSize);
context()->Plug(r0); context()->Plug(r0);
} }
......
...@@ -1361,7 +1361,7 @@ static void KeyedStoreGenerateGenericHelper( ...@@ -1361,7 +1361,7 @@ static void KeyedStoreGenerateGenericHelper(
__ b(ne, slow); __ b(ne, slow);
} }
__ bind(&fast_double_without_map_check); __ bind(&fast_double_without_map_check);
__ StoreNumberToDoubleElements(value, key, elements, r3, __ StoreNumberToDoubleElements(value, key, elements, r3, d0,
&transition_double_elements); &transition_double_elements);
if (increment_length == kIncrementLength) { if (increment_length == kIncrementLength) {
// Add 1 to receiver->length. // Add 1 to receiver->length.
......
...@@ -2057,7 +2057,7 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { ...@@ -2057,7 +2057,7 @@ LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) {
Representation input_rep = value->representation(); Representation input_rep = value->representation();
LOperand* reg = UseRegister(value); LOperand* reg = UseRegister(value);
if (input_rep.IsDouble()) { if (input_rep.IsDouble()) {
return DefineAsRegister(new(zone()) LClampDToUint8(reg, FixedTemp(d11))); return DefineAsRegister(new(zone()) LClampDToUint8(reg));
} else if (input_rep.IsInteger32()) { } else if (input_rep.IsInteger32()) {
return DefineAsRegister(new(zone()) LClampIToUint8(reg)); return DefineAsRegister(new(zone()) LClampIToUint8(reg));
} else { } else {
......
...@@ -2420,15 +2420,13 @@ class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> { ...@@ -2420,15 +2420,13 @@ class LCheckNonSmi: public LTemplateInstruction<0, 1, 0> {
}; };
class LClampDToUint8: public LTemplateInstruction<1, 1, 1> { class LClampDToUint8: public LTemplateInstruction<1, 1, 0> {
public: public:
LClampDToUint8(LOperand* unclamped, LOperand* temp) { explicit LClampDToUint8(LOperand* unclamped) {
inputs_[0] = unclamped; inputs_[0] = unclamped;
temps_[0] = temp;
} }
LOperand* unclamped() { return inputs_[0]; } LOperand* unclamped() { return inputs_[0]; }
LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8") DECLARE_CONCRETE_INSTRUCTION(ClampDToUint8, "clamp-d-to-uint8")
}; };
......
This diff is collapsed.
...@@ -200,7 +200,7 @@ class LCodeGen BASE_EMBEDDED { ...@@ -200,7 +200,7 @@ class LCodeGen BASE_EMBEDDED {
HGraph* graph() const { return chunk()->graph(); } HGraph* graph() const { return chunk()->graph(); }
Register scratch0() { return r9; } Register scratch0() { return r9; }
DwVfpRegister double_scratch0() { return kScratchDoubleReg; } LowDwVfpRegister double_scratch0() { return kScratchDoubleReg; }
int GetNextEmittedBlock() const; int GetNextEmittedBlock() const;
LInstruction* GetNextInstruction(); LInstruction* GetNextInstruction();
......
This diff is collapsed.
...@@ -484,6 +484,11 @@ class MacroAssembler: public Assembler { ...@@ -484,6 +484,11 @@ class MacroAssembler: public Assembler {
const double imm, const double imm,
const Register scratch = no_reg); const Register scratch = no_reg);
void VmovHigh(Register dst, DwVfpRegister src);
void VmovHigh(DwVfpRegister dst, Register src);
void VmovLow(Register dst, DwVfpRegister src);
void VmovLow(DwVfpRegister dst, Register src);
// Converts the smi or heap number in object to an int32 using the rules // Converts the smi or heap number in object to an int32 using the rules
// for ToInt32 as described in ECMAScript 9.5.: the value is truncated // for ToInt32 as described in ECMAScript 9.5.: the value is truncated
// and brought into the range -2^31 .. +2^31 - 1. // and brought into the range -2^31 .. +2^31 - 1.
...@@ -494,14 +499,14 @@ class MacroAssembler: public Assembler { ...@@ -494,14 +499,14 @@ class MacroAssembler: public Assembler {
Register scratch2, Register scratch2,
Register scratch3, Register scratch3,
DwVfpRegister double_scratch1, DwVfpRegister double_scratch1,
DwVfpRegister double_scratch2, LowDwVfpRegister double_scratch2,
Label* not_int32); Label* not_int32);
// Loads the number from object into dst register. // Loads the number from object into dst register.
// If |object| is neither smi nor heap number, |not_number| is jumped to // If |object| is neither smi nor heap number, |not_number| is jumped to
// with |object| still intact. // with |object| still intact.
void LoadNumber(Register object, void LoadNumber(Register object,
DwVfpRegister dst, LowDwVfpRegister dst,
Register heap_number_map, Register heap_number_map,
Register scratch, Register scratch,
Label* not_number); Label* not_number);
...@@ -515,7 +520,7 @@ class MacroAssembler: public Assembler { ...@@ -515,7 +520,7 @@ class MacroAssembler: public Assembler {
DwVfpRegister double_dst, DwVfpRegister double_dst,
Register heap_number_map, Register heap_number_map,
Register scratch, Register scratch,
DwVfpRegister double_scratch, LowDwVfpRegister double_scratch,
Label* not_int32); Label* not_int32);
// Loads the number from object into dst as a 32-bit integer. // Loads the number from object into dst as a 32-bit integer.
...@@ -528,7 +533,7 @@ class MacroAssembler: public Assembler { ...@@ -528,7 +533,7 @@ class MacroAssembler: public Assembler {
Register heap_number_map, Register heap_number_map,
Register scratch, Register scratch,
DwVfpRegister double_scratch0, DwVfpRegister double_scratch0,
DwVfpRegister double_scratch1, LowDwVfpRegister double_scratch1,
Label* not_int32); Label* not_int32);
...@@ -796,8 +801,7 @@ class MacroAssembler: public Assembler { ...@@ -796,8 +801,7 @@ class MacroAssembler: public Assembler {
// Copies a fixed number of fields of heap objects from src to dst. // Copies a fixed number of fields of heap objects from src to dst.
void CopyFields(Register dst, void CopyFields(Register dst,
Register src, Register src,
DwVfpRegister double_scratch, LowDwVfpRegister double_scratch,
SwVfpRegister single_scratch,
int field_count); int field_count);
// Copies a number of bytes from src to dst. All registers are clobbered. On // Copies a number of bytes from src to dst. All registers are clobbered. On
...@@ -874,6 +878,7 @@ class MacroAssembler: public Assembler { ...@@ -874,6 +878,7 @@ class MacroAssembler: public Assembler {
Register key_reg, Register key_reg,
Register elements_reg, Register elements_reg,
Register scratch1, Register scratch1,
LowDwVfpRegister double_scratch,
Label* fail, Label* fail,
int elements_offset = 0); int elements_offset = 0);
...@@ -957,26 +962,27 @@ class MacroAssembler: public Assembler { ...@@ -957,26 +962,27 @@ class MacroAssembler: public Assembler {
// Load the value of a smi object into a double register. // Load the value of a smi object into a double register.
// The register value must be between d0 and d15. // The register value must be between d0 and d15.
void SmiToDouble(DwVfpRegister value, Register smi); void SmiToDouble(LowDwVfpRegister value, Register smi);
// Check if a double can be exactly represented as a signed 32-bit integer. // Check if a double can be exactly represented as a signed 32-bit integer.
// Z flag set to one if true. // Z flag set to one if true.
void TestDoubleIsInt32(DwVfpRegister double_input, void TestDoubleIsInt32(DwVfpRegister double_input,
DwVfpRegister double_scratch); LowDwVfpRegister double_scratch);
// Try to convert a double to a signed 32-bit integer. // Try to convert a double to a signed 32-bit integer.
// Z flag set to one and result assigned if the conversion is exact. // Z flag set to one and result assigned if the conversion is exact.
void TryDoubleToInt32Exact(Register result, void TryDoubleToInt32Exact(Register result,
DwVfpRegister double_input, DwVfpRegister double_input,
DwVfpRegister double_scratch); LowDwVfpRegister double_scratch);
// Floor a double and writes the value to the result register. // Floor a double and writes the value to the result register.
// Go to exact if the conversion is exact (to be able to test -0), // Go to exact if the conversion is exact (to be able to test -0),
// fall through calling code if an overflow occurred, else go to done. // fall through calling code if an overflow occurred, else go to done.
// In return, input_high is loaded with high bits of input.
void TryInt32Floor(Register result, void TryInt32Floor(Register result,
DwVfpRegister double_input, DwVfpRegister double_input,
Register input_high, Register input_high,
DwVfpRegister double_scratch, LowDwVfpRegister double_scratch,
Label* done, Label* done,
Label* exact); Label* exact);
...@@ -989,7 +995,7 @@ class MacroAssembler: public Assembler { ...@@ -989,7 +995,7 @@ class MacroAssembler: public Assembler {
Register scratch, Register scratch,
Register scratch_high, Register scratch_high,
Register scratch_low, Register scratch_low,
DwVfpRegister double_scratch); LowDwVfpRegister double_scratch);
// Check whether d16-d31 are available on the CPU. The result is given by the // Check whether d16-d31 are available on the CPU. The result is given by the
// Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise. // Z condition flag: Z==0 if d16-d31 available, Z==1 otherwise.
...@@ -1311,7 +1317,7 @@ class MacroAssembler: public Assembler { ...@@ -1311,7 +1317,7 @@ class MacroAssembler: public Assembler {
void ClampDoubleToUint8(Register result_reg, void ClampDoubleToUint8(Register result_reg,
DwVfpRegister input_reg, DwVfpRegister input_reg,
DwVfpRegister temp_double_reg); LowDwVfpRegister double_scratch);
void LoadInstanceDescriptors(Register map, Register descriptors); void LoadInstanceDescriptors(Register map, Register descriptors);
......
...@@ -3110,6 +3110,15 @@ void Simulator::DecodeTypeVFP(Instruction* instr) { ...@@ -3110,6 +3110,15 @@ void Simulator::DecodeTypeVFP(Instruction* instr) {
data[instr->Bit(21)] = get_register(instr->RtValue()); data[instr->Bit(21)] = get_register(instr->RtValue());
OS::MemCopy(&dd_value, data, 8); OS::MemCopy(&dd_value, data, 8);
set_d_register_from_double(vd, dd_value); set_d_register_from_double(vd, dd_value);
} else if ((instr->VLValue() == 0x1) &&
(instr->VCValue() == 0x1) &&
(instr->Bit(23) == 0x0)) {
// vmov (scalar to ARM core register)
int vn = instr->Bits(19, 16) | (instr->Bit(7) << 4);
double dn_value = get_double_from_d_register(vn);
int32_t data[2];
OS::MemCopy(data, &dn_value, 8);
set_register(instr->RtValue(), data[instr->Bit(21)]);
} else if ((instr->VLValue() == 0x1) && } else if ((instr->VLValue() == 0x1) &&
(instr->VCValue() == 0x0) && (instr->VCValue() == 0x0) &&
(instr->VAValue() == 0x7) && (instr->VAValue() == 0x7) &&
......
...@@ -1813,7 +1813,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall( ...@@ -1813,7 +1813,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
__ b(gt, &call_builtin); __ b(gt, &call_builtin);
__ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize));
__ StoreNumberToDoubleElements(r4, r0, elements, r5, __ StoreNumberToDoubleElements(r4, r0, elements, r5, d0,
&call_builtin, argc * kDoubleSize); &call_builtin, argc * kDoubleSize);
// Save new length. // Save new length.
...@@ -3194,7 +3194,7 @@ static void GenerateSmiKeyCheck(MacroAssembler* masm, ...@@ -3194,7 +3194,7 @@ static void GenerateSmiKeyCheck(MacroAssembler* masm,
Register key, Register key,
Register scratch0, Register scratch0,
DwVfpRegister double_scratch0, DwVfpRegister double_scratch0,
DwVfpRegister double_scratch1, LowDwVfpRegister double_scratch1,
Label* fail) { Label* fail) {
Label key_ok; Label key_ok;
// Check for smi or a smi inside a heap number. We convert the heap // Check for smi or a smi inside a heap number. We convert the heap
...@@ -3603,7 +3603,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( ...@@ -3603,7 +3603,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
__ bind(&finish_store); __ bind(&finish_store);
__ StoreNumberToDoubleElements(value_reg, key_reg, elements_reg, __ StoreNumberToDoubleElements(value_reg, key_reg, elements_reg,
scratch1, &transition_elements_kind); scratch1, d0, &transition_elements_kind);
__ Ret(); __ Ret();
// Handle store cache miss, replacing the ic with the generic stub. // Handle store cache miss, replacing the ic with the generic stub.
...@@ -3651,7 +3651,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( ...@@ -3651,7 +3651,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
__ mov(scratch1, elements_reg); __ mov(scratch1, elements_reg);
__ StoreNumberToDoubleElements(value_reg, key_reg, scratch1, __ StoreNumberToDoubleElements(value_reg, key_reg, scratch1,
scratch2, &transition_elements_kind); scratch2, d0, &transition_elements_kind);
__ mov(scratch1, Operand(kHoleNanLower32)); __ mov(scratch1, Operand(kHoleNanLower32));
__ mov(scratch2, Operand(kHoleNanUpper32)); __ mov(scratch2, Operand(kHoleNanUpper32));
......
...@@ -1049,6 +1049,8 @@ TEST(13) { ...@@ -1049,6 +1049,8 @@ TEST(13) {
double i; double i;
double j; double j;
double k; double k;
uint32_t low;
uint32_t high;
} T; } T;
T t; T t;
...@@ -1113,6 +1115,11 @@ TEST(13) { ...@@ -1113,6 +1115,11 @@ TEST(13) {
__ vmov(d22, VmovIndexHi, r2); __ vmov(d22, VmovIndexHi, r2);
__ add(r4, r0, Operand(OFFSET_OF(T, i))); __ add(r4, r0, Operand(OFFSET_OF(T, i)));
__ vstm(ia_w, r4, d20, d22); __ vstm(ia_w, r4, d20, d22);
// Move d22 into low and high.
__ vmov(r4, VmovIndexLo, d22);
__ str(r4, MemOperand(r0, OFFSET_OF(T, low)));
__ vmov(r4, VmovIndexHi, d22);
__ str(r4, MemOperand(r0, OFFSET_OF(T, high)));
__ ldm(ia_w, sp, r4.bit() | pc.bit()); __ ldm(ia_w, sp, r4.bit() | pc.bit());
...@@ -1144,6 +1151,8 @@ TEST(13) { ...@@ -1144,6 +1151,8 @@ TEST(13) {
CHECK_EQ(14.7610017472335499, t.i); CHECK_EQ(14.7610017472335499, t.i);
CHECK_EQ(16.0, t.j); CHECK_EQ(16.0, t.j);
CHECK_EQ(73.8818412254460241, t.k); CHECK_EQ(73.8818412254460241, t.k);
CHECK_EQ(372106121, t.low);
CHECK_EQ(1079146608, t.high);
} }
} }
......
...@@ -500,6 +500,11 @@ TEST(Vfp) { ...@@ -500,6 +500,11 @@ TEST(Vfp) {
COMPARE(vmov(d0, VmovIndexHi, r0), COMPARE(vmov(d0, VmovIndexHi, r0),
"ee200b10 vmov.32 d0[1], r0"); "ee200b10 vmov.32 d0[1], r0");
COMPARE(vmov(r2, VmovIndexLo, d15),
"ee1f2b10 vmov.32 r2, d15[0]");
COMPARE(vmov(r3, VmovIndexHi, d14),
"ee3e3b10 vmov.32 r3, d14[1]");
COMPARE(vldr(s0, r0, 0), COMPARE(vldr(s0, r0, 0),
"ed900a00 vldr s0, [r0 + 4*0]"); "ed900a00 vldr s0, [r0 + 4*0]");
COMPARE(vldr(s1, r1, 4), COMPARE(vldr(s1, r1, 4),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment