ARM: Add Ldrd/Strd to the macro assembler
The macro assembler now checks for ARMv7 support and generates instructions for Ldrd/Strd accordingly. INstructions ldrd/strd in the assembler requires ARMv7 support enabled. This removes the a check for CAN_USE_ARMV7_INSTRUCTIONS making the ARMv7 support in the simulator fully controled by the --enable-armv7 flag. Review URL: http://codereview.chromium.org/2226003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4726 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
4afc3d3c4f
commit
6de39cd1f0
@ -1363,46 +1363,25 @@ void Assembler::ldrsh(Register dst, const MemOperand& src, Condition cond) {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::ldrd(Register dst1,
|
||||
Register dst2,
|
||||
void Assembler::ldrd(Register dst1, Register dst2,
|
||||
const MemOperand& src, Condition cond) {
|
||||
ASSERT(CpuFeatures::IsEnabled(ARMv7));
|
||||
ASSERT(src.rm().is(no_reg));
|
||||
ASSERT(!dst1.is(lr)); // r14.
|
||||
ASSERT_EQ(0, dst1.code() % 2);
|
||||
ASSERT_EQ(dst1.code() + 1, dst2.code());
|
||||
#ifdef CAN_USE_ARMV7_INSTRUCTIONS
|
||||
addrmod3(cond | B7 | B6 | B4, dst1, src);
|
||||
#else
|
||||
// Generate two ldr instructions if ldrd is not available.
|
||||
MemOperand src2(src);
|
||||
src2.set_offset(src2.offset() + 4);
|
||||
if (dst1.is(src.rn())) {
|
||||
ldr(dst2, src2, cond);
|
||||
ldr(dst1, src, cond);
|
||||
} else {
|
||||
ldr(dst1, src, cond);
|
||||
ldr(dst2, src2, cond);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Assembler::strd(Register src1,
|
||||
Register src2,
|
||||
void Assembler::strd(Register src1, Register src2,
|
||||
const MemOperand& dst, Condition cond) {
|
||||
ASSERT(dst.rm().is(no_reg));
|
||||
ASSERT(!src1.is(lr)); // r14.
|
||||
ASSERT_EQ(0, src1.code() % 2);
|
||||
ASSERT_EQ(src1.code() + 1, src2.code());
|
||||
#ifdef CAN_USE_ARMV7_INSTRUCTIONS
|
||||
ASSERT(CpuFeatures::IsEnabled(ARMv7));
|
||||
addrmod3(cond | B7 | B6 | B5 | B4, src1, dst);
|
||||
#else
|
||||
// Generate two str instructions if strd is not available.
|
||||
MemOperand dst2(dst);
|
||||
dst2.set_offset(dst2.offset() + 4);
|
||||
str(src1, dst, cond);
|
||||
str(src2, dst2, cond);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Load/Store multiple instructions.
|
||||
|
@ -1514,7 +1514,7 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
|
||||
// Then process it as a normal function call.
|
||||
__ ldr(r0, MemOperand(sp, 3 * kPointerSize));
|
||||
__ ldr(r1, MemOperand(sp, 2 * kPointerSize));
|
||||
__ strd(r0, r1, MemOperand(sp, 2 * kPointerSize));
|
||||
__ Strd(r0, r1, MemOperand(sp, 2 * kPointerSize));
|
||||
|
||||
CallFunctionStub call_function(2, NOT_IN_LOOP, NO_CALL_FUNCTION_FLAGS);
|
||||
frame_->CallStub(&call_function, 3);
|
||||
@ -2307,7 +2307,7 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
|
||||
node->continue_target()->SetExpectedHeight();
|
||||
|
||||
// Load the current count to r0, load the length to r1.
|
||||
__ ldrd(r0, r1, frame_->ElementAt(0));
|
||||
__ Ldrd(r0, r1, frame_->ElementAt(0));
|
||||
__ cmp(r0, r1); // compare to the array length
|
||||
node->break_target()->Branch(hs);
|
||||
|
||||
@ -6379,7 +6379,7 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm,
|
||||
ConvertToDoubleStub stub1(r3, r2, r7, r6);
|
||||
__ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
|
||||
// Load rhs to a double in r0, r1.
|
||||
__ ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
||||
__ Ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
||||
__ pop(lr);
|
||||
}
|
||||
|
||||
@ -6414,7 +6414,7 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm,
|
||||
} else {
|
||||
__ push(lr);
|
||||
// Load lhs to a double in r2, r3.
|
||||
__ ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
|
||||
__ Ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
|
||||
// Convert rhs to a double in r0, r1.
|
||||
__ mov(r7, Operand(r0));
|
||||
ConvertToDoubleStub stub2(r1, r0, r7, r6);
|
||||
@ -6578,8 +6578,8 @@ static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
|
||||
__ sub(r7, r1, Operand(kHeapObjectTag));
|
||||
__ vldr(d7, r7, HeapNumber::kValueOffset);
|
||||
} else {
|
||||
__ ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
|
||||
__ ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
||||
__ Ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
|
||||
__ Ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
||||
}
|
||||
__ jmp(both_loaded_as_doubles);
|
||||
}
|
||||
@ -6956,7 +6956,7 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
|
||||
__ vldr(d7, r7, HeapNumber::kValueOffset);
|
||||
} else {
|
||||
// Calling convention says that second double is in r2 and r3.
|
||||
__ ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
||||
__ Ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
||||
}
|
||||
__ jmp(&finished_loading_r0);
|
||||
__ bind(&r0_is_smi);
|
||||
@ -7008,7 +7008,7 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
|
||||
__ vldr(d6, r7, HeapNumber::kValueOffset);
|
||||
} else {
|
||||
// Calling convention says that first double is in r0 and r1.
|
||||
__ ldrd(r0, r1, FieldMemOperand(r1, HeapNumber::kValueOffset));
|
||||
__ Ldrd(r0, r1, FieldMemOperand(r1, HeapNumber::kValueOffset));
|
||||
}
|
||||
__ jmp(&finished_loading_r1);
|
||||
__ bind(&r1_is_smi);
|
||||
@ -7079,7 +7079,7 @@ void GenericBinaryOpStub::HandleBinaryOpSlowCases(
|
||||
__ stc(p1, cr8, MemOperand(r4, HeapNumber::kValueOffset));
|
||||
#else
|
||||
// Double returned in registers 0 and 1.
|
||||
__ strd(r0, r1, FieldMemOperand(r5, HeapNumber::kValueOffset));
|
||||
__ Strd(r0, r1, FieldMemOperand(r5, HeapNumber::kValueOffset));
|
||||
#endif
|
||||
__ mov(r0, Operand(r5));
|
||||
// And we are done.
|
||||
|
@ -935,7 +935,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// Generate code for doing the condition check.
|
||||
__ bind(&loop);
|
||||
// Load the current count to r0, load the length to r1.
|
||||
__ ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
|
||||
__ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
|
||||
__ cmp(r0, r1); // Compare to the array length.
|
||||
__ b(hs, loop_statement.break_target());
|
||||
|
||||
|
@ -354,6 +354,51 @@ void MacroAssembler::RecordWrite(Register object, Register offset,
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::Ldrd(Register dst1, Register dst2,
|
||||
const MemOperand& src, Condition cond) {
|
||||
ASSERT(src.rm().is(no_reg));
|
||||
ASSERT(!dst1.is(lr)); // r14.
|
||||
ASSERT_EQ(0, dst1.code() % 2);
|
||||
ASSERT_EQ(dst1.code() + 1, dst2.code());
|
||||
|
||||
// Generate two ldr instructions if ldrd is not available.
|
||||
if (CpuFeatures::IsSupported(ARMv7)) {
|
||||
CpuFeatures::Scope scope(ARMv7);
|
||||
ldrd(dst1, dst2, src, cond);
|
||||
} else {
|
||||
MemOperand src2(src);
|
||||
src2.set_offset(src2.offset() + 4);
|
||||
if (dst1.is(src.rn())) {
|
||||
ldr(dst2, src2, cond);
|
||||
ldr(dst1, src, cond);
|
||||
} else {
|
||||
ldr(dst1, src, cond);
|
||||
ldr(dst2, src2, cond);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::Strd(Register src1, Register src2,
|
||||
const MemOperand& dst, Condition cond) {
|
||||
ASSERT(dst.rm().is(no_reg));
|
||||
ASSERT(!src1.is(lr)); // r14.
|
||||
ASSERT_EQ(0, src1.code() % 2);
|
||||
ASSERT_EQ(src1.code() + 1, src2.code());
|
||||
|
||||
// Generate two str instructions if strd is not available.
|
||||
if (CpuFeatures::IsSupported(ARMv7)) {
|
||||
CpuFeatures::Scope scope(ARMv7);
|
||||
strd(src1, src2, dst, cond);
|
||||
} else {
|
||||
MemOperand dst2(dst);
|
||||
dst2.set_offset(dst2.offset() + 4);
|
||||
str(src1, dst, cond);
|
||||
str(src2, dst2, cond);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::EnterFrame(StackFrame::Type type) {
|
||||
// r0-r3: preserved
|
||||
stm(db_w, sp, cp.bit() | fp.bit() | lr.bit());
|
||||
|
@ -185,6 +185,18 @@ class MacroAssembler: public Assembler {
|
||||
}
|
||||
}
|
||||
|
||||
// Load two consecutive registers with two consecutive memory locations.
|
||||
void Ldrd(Register dst1,
|
||||
Register dst2,
|
||||
const MemOperand& src,
|
||||
Condition cond = al);
|
||||
|
||||
// Store two consecutive registers to two consecutive memory locations.
|
||||
void Strd(Register src1,
|
||||
Register src2,
|
||||
const MemOperand& dst,
|
||||
Condition cond = al);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Stack limit support
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user