From af23dfc5b2f70fb17a154392f68bfe43caac0949 Mon Sep 17 00:00:00 2001 From: "zra@google.com" Date: Tue, 23 Jul 2013 18:25:44 +0000 Subject: [PATCH] Increases the number of ARM floating-point registers. This is to be consistent with VFPv3_D32. Later, we'll detect VFPv3_D16 at runtime. R=regis@google.com Review URL: https://codereview.chromium.org//19806005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@25352 260f80e4-7a28-3924-810f-c04153c831b5 --- runtime/vm/assembler_arm.cc | 30 ++++++++++++++++++------- runtime/vm/assembler_arm.h | 4 ++-- runtime/vm/assembler_arm_test.cc | 12 +++++----- runtime/vm/constants_arm.h | 2 +- runtime/vm/intermediate_language_arm.cc | 14 +++++++----- runtime/vm/simulator_arm.cc | 30 ++++++++++++++----------- runtime/vm/stub_code_arm.cc | 7 +++++- 7 files changed, 63 insertions(+), 36 deletions(-) diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc index f28f2902fa2..67e203932cb 100644 --- a/runtime/vm/assembler_arm.cc +++ b/runtime/vm/assembler_arm.cc @@ -917,18 +917,20 @@ void Assembler::vstms(BlockAddressMode am, Register base, void Assembler::vldmd(BlockAddressMode am, Register base, - DRegister first, DRegister last, Condition cond) { + DRegister first, intptr_t count, Condition cond) { ASSERT((am == IA) || (am == IA_W) || (am == DB_W)); - ASSERT(last > first); - EmitMultiVDMemOp(cond, am, true, base, first, last - first + 1); + ASSERT(count <= 16); + ASSERT(first + count <= kNumberOfDRegisters); + EmitMultiVDMemOp(cond, am, true, base, first, count); } void Assembler::vstmd(BlockAddressMode am, Register base, - DRegister first, DRegister last, Condition cond) { + DRegister first, intptr_t count, Condition cond) { ASSERT((am == IA) || (am == IA_W) || (am == DB_W)); - ASSERT(last > first); - EmitMultiVDMemOp(cond, am, false, base, first, last - first + 1); + ASSERT(count <= 16); + ASSERT(first + count <= kNumberOfDRegisters); + EmitMultiVDMemOp(cond, am, false, base, first, count); } @@ -2281,7 +2283,13 @@ void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { // Preserve all volatile FPU registers. DRegister firstv = EvenDRegisterOf(kDartFirstVolatileFpuReg); DRegister lastv = OddDRegisterOf(kDartLastVolatileFpuReg); - vstmd(DB_W, SP, firstv, lastv); + if ((lastv - firstv + 1) >= 16) { + DRegister mid = static_cast(firstv + 16); + vstmd(DB_W, SP, mid, lastv - mid + 1); + vstmd(DB_W, SP, firstv, 16); + } else { + vstmd(DB_W, SP, firstv, lastv - firstv + 1); + } ReserveAlignedFrameSpace(frame_space); } @@ -2299,7 +2307,13 @@ void Assembler::LeaveCallRuntimeFrame() { // Restore all volatile FPU registers. DRegister firstv = EvenDRegisterOf(kDartFirstVolatileFpuReg); DRegister lastv = OddDRegisterOf(kDartLastVolatileFpuReg); - vldmd(IA_W, SP, firstv, lastv); + if ((lastv - firstv + 1) > 16) { + DRegister mid = static_cast(firstv + 16); + vldmd(IA_W, SP, firstv, 16); + vldmd(IA_W, SP, mid, lastv - mid + 1); + } else { + vldmd(IA_W, SP, firstv, lastv - firstv + 1); + } // Restore volatile CPU registers. LeaveFrame(kDartVolatileCpuRegs | (1 << FP) | (1 << LR)); diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h index 19b9cd6d59a..77f11abcfbe 100644 --- a/runtime/vm/assembler_arm.h +++ b/runtime/vm/assembler_arm.h @@ -461,9 +461,9 @@ class Assembler : public ValueObject { SRegister first, SRegister last, Condition cond = AL); void vldmd(BlockAddressMode am, Register base, - DRegister first, DRegister last, Condition cond = AL); + DRegister first, intptr_t count, Condition cond = AL); void vstmd(BlockAddressMode am, Register base, - DRegister first, DRegister last, Condition cond = AL); + DRegister first, intptr_t count, Condition cond = AL); void vadds(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL); void vaddd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL); diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc index c24ff084103..3e613478c08 100644 --- a/runtime/vm/assembler_arm_test.cc +++ b/runtime/vm/assembler_arm_test.cc @@ -1094,13 +1094,13 @@ ASSEMBLER_TEST_GENERATE(VstmdVldmd, assembler) { __ LoadDImmediate(D2, 2.0, R0); __ LoadDImmediate(D3, 3.0, R0); __ LoadDImmediate(D4, 4.0, R0); - __ vstmd(DB_W, SP, D0, D4); // Push D0 - D4 onto the stack, dec SP + __ vstmd(DB_W, SP, D0, 5); // Push D0 - D4 onto the stack, dec SP __ LoadDImmediate(D0, 0.0, R0); __ LoadDImmediate(D1, 0.0, R0); __ LoadDImmediate(D2, 0.0, R0); __ LoadDImmediate(D3, 0.0, R0); __ LoadDImmediate(D4, 0.0, R0); - __ vldmd(IA_W, SP, D0, D4); // Pop stack into D0 - D4, inc SP + __ vldmd(IA_W, SP, D0, 5); // Pop stack into D0 - D4, inc SP // Load success value into R0 __ mov(R0, ShifterOperand(42)); @@ -1200,12 +1200,12 @@ ASSEMBLER_TEST_GENERATE(VstmdVldmd1, assembler) { __ LoadDImmediate(D2, 2.0, R0); __ LoadDImmediate(D3, 3.0, R0); __ LoadDImmediate(D4, 4.0, R0); - __ vstmd(DB_W, SP, D1, D4); // Push D1 - D4 onto the stack, dec SP + __ vstmd(DB_W, SP, D1, 4); // Push D1 - D4 onto the stack, dec SP __ LoadDImmediate(D1, 0.0, R0); __ LoadDImmediate(D2, 0.0, R0); __ LoadDImmediate(D3, 0.0, R0); __ LoadDImmediate(D4, 0.0, R0); - __ vldmd(IA_W, SP, D1, D4); // Pop stack into D1 - D4, inc SP + __ vldmd(IA_W, SP, D1, 4); // Pop stack into D1 - D4, inc SP // Load success value into R0 __ mov(R0, ShifterOperand(42)); @@ -1306,8 +1306,8 @@ ASSEMBLER_TEST_GENERATE(VstmdVldmd_off, assembler) { __ LoadDImmediate(D3, 3.0, R0); __ LoadDImmediate(D4, 4.0, R0); __ LoadDImmediate(D5, 5.0, R0); - __ vstmd(DB_W, SP, D0, D4); // Push D0 - D4 onto the stack, dec SP - __ vldmd(IA_W, SP, D5, D9); // Pop stack into D5 - D9, inc SP + __ vstmd(DB_W, SP, D0, 5); // Push D0 - D4 onto the stack, dec SP + __ vldmd(IA_W, SP, D5, 5); // Pop stack into D5 - D9, inc SP // Load success value into R0 __ mov(R0, ShifterOperand(42)); diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h index f2a48bd2cd7..5c1dd008ac8 100644 --- a/runtime/vm/constants_arm.h +++ b/runtime/vm/constants_arm.h @@ -12,7 +12,7 @@ namespace dart { // We support both VFPv3-D16 and VFPv3-D32 profiles, but currently only one at // a time. // TODO(zra): Detect number of registers at runtime by querying /proc/cpuinfo. -#define VFPv3_D16 +#define VFPv3_D32 #if defined(VFPv3_D16) == defined(VFPv3_D32) #error "Exactly one of VFPv3_D16 or VFPv3_D32 can be defined at a time." #endif diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc index 0b128735b45..b6d4e6ef1e1 100644 --- a/runtime/vm/intermediate_language_arm.cc +++ b/runtime/vm/intermediate_language_arm.cc @@ -2947,8 +2947,9 @@ LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const { const intptr_t kNumTemps = 0; LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); - summary->set_in(0, Location::RequiresFpuRegister()); - summary->set_out(Location::RequiresFpuRegister()); + // Low (< Q7) Q registers are needed for the vcvtds instruction. + summary->set_in(0, Location::FpuRegisterLocation(Q5)); + summary->set_out(Location::FpuRegisterLocation(Q6)); return summary; } @@ -3009,7 +3010,8 @@ LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary() const { summary->set_in(1, Location::RequiresFpuRegister()); summary->set_in(2, Location::RequiresFpuRegister()); summary->set_in(3, Location::RequiresFpuRegister()); - summary->set_out(Location::RequiresFpuRegister()); + // Low (< 7) Q registers are needed for the vcvtsd instruction. + summary->set_out(Location::FpuRegisterLocation(Q6)); return summary; } @@ -3179,7 +3181,8 @@ LocationSummary* Float32x4WithInstr::MakeLocationSummary() const { new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); summary->set_in(0, Location::RequiresFpuRegister()); summary->set_in(1, Location::RequiresFpuRegister()); - summary->set_out(Location::RequiresFpuRegister()); + // Low (< 7) Q registers are needed for the vmovs instruction. + summary->set_out(Location::FpuRegisterLocation(Q6)); return summary; } @@ -3246,7 +3249,8 @@ LocationSummary* Uint32x4GetFlagInstr::MakeLocationSummary() const { const intptr_t kNumTemps = 0; LocationSummary* summary = new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); - summary->set_in(0, Location::RequiresFpuRegister()); + // Low (< 7) Q registers are needed for the vmovrs instruction. + summary->set_in(0, Location::FpuRegisterLocation(Q6)); summary->set_out(Location::RequiresRegister()); return summary; } diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc index dc2a80a67b8..760fdfdca04 100644 --- a/runtime/vm/simulator_arm.cc +++ b/runtime/vm/simulator_arm.cc @@ -2504,20 +2504,24 @@ void Simulator::DecodeType6(Instr* instr) { } else { int32_t regs_cnt = imm_val >> 1; int32_t start = (instr->Bit(22) << 4) | instr->Bits(12, 4); - for (int i = start; i < start + regs_cnt; i++) { - DRegister dd = static_cast(i); - if (instr->Bit(20) == 1) { - // Format(instr, "vldmd'cond'pu 'rn'w, 'dlist"); - int64_t dd_val = Utils::LowHighTo64Bits(ReadW(addr, instr), - ReadW(addr + 4, instr)); - set_dregister_bits(dd, dd_val); - } else { - // Format(instr, "vstmd'cond'pu 'rn'w, 'dlist"); - int64_t dd_val = get_dregister_bits(dd); - WriteW(addr, Utils::Low32Bits(dd_val), instr); - WriteW(addr + 4, Utils::High32Bits(dd_val), instr); + if ((regs_cnt <= 16) && (start + regs_cnt <= kNumberOfDRegisters)) { + for (int i = start; i < start + regs_cnt; i++) { + DRegister dd = static_cast(i); + if (instr->Bit(20) == 1) { + // Format(instr, "vldmd'cond'pu 'rn'w, 'dlist"); + int64_t dd_val = Utils::LowHighTo64Bits(ReadW(addr, instr), + ReadW(addr + 4, instr)); + set_dregister_bits(dd, dd_val); + } else { + // Format(instr, "vstmd'cond'pu 'rn'w, 'dlist"); + int64_t dd_val = get_dregister_bits(dd); + WriteW(addr, Utils::Low32Bits(dd_val), instr); + WriteW(addr + 4, Utils::High32Bits(dd_val), instr); + } + addr += 8; } - addr += 8; + } else { + UnimplementedInstruction(instr); } } } diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc index db932ba99ac..d71bed8b292 100644 --- a/runtime/vm/stub_code_arm.cc +++ b/runtime/vm/stub_code_arm.cc @@ -352,7 +352,12 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, // lowest address. __ PushList(kAllCpuRegistersList); ASSERT(kFpuRegisterSize == 4 * kWordSize); - __ vstmd(DB_W, SP, D0, static_cast(kNumberOfDRegisters - 1)); + if (kNumberOfDRegisters > 16) { + __ vstmd(DB_W, SP, D16, kNumberOfDRegisters - 16); + __ vstmd(DB_W, SP, D0, 16); + } else { + __ vstmd(DB_W, SP, D0, kNumberOfDRegisters); + } __ mov(R0, ShifterOperand(SP)); // Pass address of saved registers block. __ ReserveAlignedFrameSpace(0);