From 6de39cd1f0617a695e672e624a939337aa062b07 Mon Sep 17 00:00:00 2001 From: "sgjesse@chromium.org" Date: Wed, 26 May 2010 11:19:39 +0000 Subject: [PATCH] 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 --- src/arm/assembler-arm.cc | 29 +++------------------- src/arm/codegen-arm.cc | 18 +++++++------- src/arm/full-codegen-arm.cc | 2 +- src/arm/macro-assembler-arm.cc | 45 ++++++++++++++++++++++++++++++++++ src/arm/macro-assembler-arm.h | 12 +++++++++ 5 files changed, 71 insertions(+), 35 deletions(-) diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc index a3966a2a0f..050e15bcc2 100644 --- a/src/arm/assembler-arm.cc +++ b/src/arm/assembler-arm.cc @@ -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. diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc index 062f955263..64ed425a77 100644 --- a/src/arm/codegen-arm.cc +++ b/src/arm/codegen-arm.cc @@ -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. diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 37fa6c94a8..fecc2137d3 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -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()); diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index e356d55e1b..29c48a400f 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -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()); diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index 9cf93da341..494f2b6926 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -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