| Index: runtime/vm/assembler_arm.cc
|
| ===================================================================
|
| --- runtime/vm/assembler_arm.cc (revision 36258)
|
| +++ runtime/vm/assembler_arm.cc (working copy)
|
| @@ -555,6 +555,9 @@
|
| Condition cond) {
|
| ASSERT(regs != 0);
|
| EmitMultiMemOp(cond, am, true, base, regs);
|
| + if (TargetCPUFeatures::arm_version() == ARMv5TE) {
|
| + nop();
|
| + }
|
| }
|
|
|
|
|
| @@ -612,6 +615,7 @@
|
|
|
|
|
| void Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(sn != kNoSRegister);
|
| ASSERT(rt != kNoRegister);
|
| ASSERT(rt != SP);
|
| @@ -627,6 +631,7 @@
|
|
|
|
|
| void Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(sn != kNoSRegister);
|
| ASSERT(rt != kNoRegister);
|
| ASSERT(rt != SP);
|
| @@ -643,6 +648,7 @@
|
|
|
| void Assembler::vmovsrr(SRegister sm, Register rt, Register rt2,
|
| Condition cond) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(sm != kNoSRegister);
|
| ASSERT(sm != S31);
|
| ASSERT(rt != kNoRegister);
|
| @@ -664,6 +670,7 @@
|
|
|
| void Assembler::vmovrrs(Register rt, Register rt2, SRegister sm,
|
| Condition cond) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(sm != kNoSRegister);
|
| ASSERT(sm != S31);
|
| ASSERT(rt != kNoRegister);
|
| @@ -686,6 +693,7 @@
|
|
|
| void Assembler::vmovdrr(DRegister dm, Register rt, Register rt2,
|
| Condition cond) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(dm != kNoDRegister);
|
| ASSERT(rt != kNoRegister);
|
| ASSERT(rt != SP);
|
| @@ -706,6 +714,7 @@
|
|
|
| void Assembler::vmovrrd(Register rt, Register rt2, DRegister dm,
|
| Condition cond) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(dm != kNoDRegister);
|
| ASSERT(rt != kNoRegister);
|
| ASSERT(rt != SP);
|
| @@ -726,6 +735,7 @@
|
|
|
|
|
| void Assembler::vldrs(SRegister sd, Address ad, Condition cond) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(sd != kNoSRegister);
|
| ASSERT(cond != kNoCondition);
|
| int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
|
| @@ -738,6 +748,7 @@
|
|
|
|
|
| void Assembler::vstrs(SRegister sd, Address ad, Condition cond) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)) != PC);
|
| ASSERT(sd != kNoSRegister);
|
| ASSERT(cond != kNoCondition);
|
| @@ -751,6 +762,7 @@
|
|
|
|
|
| void Assembler::vldrd(DRegister dd, Address ad, Condition cond) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(dd != kNoDRegister);
|
| ASSERT(cond != kNoCondition);
|
| int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
|
| @@ -763,6 +775,7 @@
|
|
|
|
|
| void Assembler::vstrd(DRegister dd, Address ad, Condition cond) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(static_cast<Register>(ad.encoding_ & (0xf << kRnShift)) != PC);
|
| ASSERT(dd != kNoDRegister);
|
| ASSERT(cond != kNoCondition);
|
| @@ -780,6 +793,7 @@
|
| Register base,
|
| SRegister start,
|
| uint32_t count) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(base != kNoRegister);
|
| ASSERT(cond != kNoCondition);
|
| ASSERT(start != kNoSRegister);
|
| @@ -803,10 +817,12 @@
|
| Register base,
|
| DRegister start,
|
| int32_t count) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(base != kNoRegister);
|
| ASSERT(cond != kNoCondition);
|
| ASSERT(start != kNoDRegister);
|
| ASSERT(static_cast<int32_t>(start) + count <= kNumberOfDRegisters);
|
| + const int armv5te = TargetCPUFeatures::arm_version() == ARMv5TE ? 1 : 0;
|
|
|
| int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
|
| B27 | B26 | B11 | B9 | B8 |
|
| @@ -815,7 +831,7 @@
|
| (static_cast<int32_t>(base) << kRnShift) |
|
| ((static_cast<int32_t>(start) & 0x10) ? D : 0) |
|
| ((static_cast<int32_t>(start) & 0xf) << 12) |
|
| - (count << 1);
|
| + (count << 1) | armv5te;
|
| Emit(encoding);
|
| }
|
|
|
| @@ -856,6 +872,7 @@
|
|
|
| void Assembler::EmitVFPsss(Condition cond, int32_t opcode,
|
| SRegister sd, SRegister sn, SRegister sm) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(sd != kNoSRegister);
|
| ASSERT(sn != kNoSRegister);
|
| ASSERT(sm != kNoSRegister);
|
| @@ -874,6 +891,7 @@
|
|
|
| void Assembler::EmitVFPddd(Condition cond, int32_t opcode,
|
| DRegister dd, DRegister dn, DRegister dm) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(dd != kNoDRegister);
|
| ASSERT(dn != kNoDRegister);
|
| ASSERT(dm != kNoDRegister);
|
| @@ -1039,6 +1057,7 @@
|
|
|
| void Assembler::EmitVFPsd(Condition cond, int32_t opcode,
|
| SRegister sd, DRegister dm) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(sd != kNoSRegister);
|
| ASSERT(dm != kNoDRegister);
|
| ASSERT(cond != kNoCondition);
|
| @@ -1054,6 +1073,7 @@
|
|
|
| void Assembler::EmitVFPds(Condition cond, int32_t opcode,
|
| DRegister dd, SRegister sm) {
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(dd != kNoDRegister);
|
| ASSERT(sm != kNoSRegister);
|
| ASSERT(cond != kNoCondition);
|
| @@ -1138,6 +1158,7 @@
|
|
|
|
|
| void Assembler::vmstat(Condition cond) { // VMRS APSR_nzcv, FPSCR
|
| + ASSERT(TargetCPUFeatures::vfp_supported());
|
| ASSERT(cond != kNoCondition);
|
| int32_t encoding = (static_cast<int32_t>(cond) << kConditionShift) |
|
| B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 |
|
| @@ -1175,6 +1196,7 @@
|
|
|
| void Assembler::EmitSIMDqqq(int32_t opcode, OperandSize size,
|
| QRegister qd, QRegister qn, QRegister qm) {
|
| + ASSERT(TargetCPUFeatures::neon_supported());
|
| int sz = ShiftOfOperandSize(size);
|
| int32_t encoding =
|
| (static_cast<int32_t>(kSpecialCondition) << kConditionShift) |
|
| @@ -1192,6 +1214,7 @@
|
|
|
| void Assembler::EmitSIMDddd(int32_t opcode, OperandSize size,
|
| DRegister dd, DRegister dn, DRegister dm) {
|
| + ASSERT(TargetCPUFeatures::neon_supported());
|
| int sz = ShiftOfOperandSize(size);
|
| int32_t encoding =
|
| (static_cast<int32_t>(kSpecialCondition) << kConditionShift) |
|
| @@ -1724,10 +1747,11 @@
|
| PatchFarBranch() {}
|
|
|
| void Process(const MemoryRegion& region, intptr_t position) {
|
| - if (TargetCPUFeatures::arm_version() == ARMv6) {
|
| + const ARMVersion version = TargetCPUFeatures::arm_version();
|
| + if ((version == ARMv5TE) || (version == ARMv6)) {
|
| ProcessARMv6(region, position);
|
| } else {
|
| - ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
|
| + ASSERT(version == ARMv7);
|
| ProcessARMv7(region, position);
|
| }
|
| }
|
| @@ -1987,10 +2011,11 @@
|
|
|
|
|
| void Assembler::Bind(Label* label) {
|
| - if (TargetCPUFeatures::arm_version() == ARMv6) {
|
| + const ARMVersion version = TargetCPUFeatures::arm_version();
|
| + if ((version == ARMv5TE) || (version == ARMv6)) {
|
| BindARMv6(label);
|
| } else {
|
| - ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
|
| + ASSERT(version == ARMv7);
|
| BindARMv7(label);
|
| }
|
| }
|
| @@ -2238,7 +2263,8 @@
|
|
|
| void Assembler::LoadPatchableImmediate(
|
| Register rd, int32_t value, Condition cond) {
|
| - if (TargetCPUFeatures::arm_version() == ARMv6) {
|
| + const ARMVersion version = TargetCPUFeatures::arm_version();
|
| + if ((version == ARMv5TE) || (version == ARMv6)) {
|
| // This sequence is patched in a few places, and should remain fixed.
|
| const uint32_t byte0 = (value & 0x000000ff);
|
| const uint32_t byte1 = (value & 0x0000ff00) >> 8;
|
| @@ -2249,7 +2275,7 @@
|
| orr(rd, rd, ShifterOperand(12, byte1), cond);
|
| orr(rd, rd, ShifterOperand(byte0), cond);
|
| } else {
|
| - ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
|
| + ASSERT(version == ARMv7);
|
| const uint16_t value_low = Utils::Low16Bits(value);
|
| const uint16_t value_high = Utils::High16Bits(value);
|
| movw(rd, value_low, cond);
|
| @@ -2260,10 +2286,11 @@
|
|
|
| void Assembler::LoadDecodableImmediate(
|
| Register rd, int32_t value, Condition cond) {
|
| - if (TargetCPUFeatures::arm_version() == ARMv6) {
|
| + const ARMVersion version = TargetCPUFeatures::arm_version();
|
| + if ((version == ARMv5TE) || (version == ARMv6)) {
|
| LoadPatchableImmediate(rd, value, cond);
|
| } else {
|
| - ASSERT(TargetCPUFeatures::arm_version() == ARMv7);
|
| + ASSERT(version == ARMv7);
|
| movw(rd, Utils::Low16Bits(value), cond);
|
| const uint16_t value_high = Utils::High16Bits(value);
|
| if (value_high != 0) {
|
| @@ -2458,6 +2485,82 @@
|
| }
|
|
|
|
|
| +void Assembler::CopyDoubleField(
|
| + Register dst, Register src, Register tmp1, Register tmp2, DRegister dtmp) {
|
| + if (TargetCPUFeatures::vfp_supported()) {
|
| + LoadDFromOffset(dtmp, src, Double::value_offset() - kHeapObjectTag);
|
| + StoreDToOffset(dtmp, dst, Double::value_offset() - kHeapObjectTag);
|
| + } else {
|
| + LoadFromOffset(kWord, tmp1, src,
|
| + Double::value_offset() - kHeapObjectTag);
|
| + LoadFromOffset(kWord, tmp2, src,
|
| + Double::value_offset() + kWordSize - kHeapObjectTag);
|
| + StoreToOffset(kWord, tmp1, dst,
|
| + Double::value_offset() - kHeapObjectTag);
|
| + StoreToOffset(kWord, tmp2, dst,
|
| + Double::value_offset() + kWordSize - kHeapObjectTag);
|
| + }
|
| +}
|
| +
|
| +
|
| +void Assembler::CopyFloat32x4Field(
|
| + Register dst, Register src, Register tmp1, Register tmp2, DRegister dtmp) {
|
| + if (TargetCPUFeatures::neon_supported()) {
|
| + LoadMultipleDFromOffset(dtmp, 2, src,
|
| + Float32x4::value_offset() - kHeapObjectTag);
|
| + StoreMultipleDToOffset(dtmp, 2, dst,
|
| + Float32x4::value_offset() - kHeapObjectTag);
|
| + } else {
|
| + LoadFromOffset(kWord, tmp1, src,
|
| + (Float32x4::value_offset() + 0 * kWordSize) - kHeapObjectTag);
|
| + LoadFromOffset(kWord, tmp2, src,
|
| + (Float32x4::value_offset() + 1 * kWordSize) - kHeapObjectTag);
|
| + StoreToOffset(kWord, tmp1, dst,
|
| + (Float32x4::value_offset() + 0 * kWordSize) - kHeapObjectTag);
|
| + StoreToOffset(kWord, tmp2, dst,
|
| + (Float32x4::value_offset() + 1 * kWordSize) - kHeapObjectTag);
|
| +
|
| + LoadFromOffset(kWord, tmp1, src,
|
| + (Float32x4::value_offset() + 2 * kWordSize) - kHeapObjectTag);
|
| + LoadFromOffset(kWord, tmp2, src,
|
| + (Float32x4::value_offset() + 3 * kWordSize) - kHeapObjectTag);
|
| + StoreToOffset(kWord, tmp1, dst,
|
| + (Float32x4::value_offset() + 2 * kWordSize) - kHeapObjectTag);
|
| + StoreToOffset(kWord, tmp2, dst,
|
| + (Float32x4::value_offset() + 3 * kWordSize) - kHeapObjectTag);
|
| + }
|
| +}
|
| +
|
| +
|
| +void Assembler::CopyFloat64x2Field(
|
| + Register dst, Register src, Register tmp1, Register tmp2, DRegister dtmp) {
|
| + if (TargetCPUFeatures::neon_supported()) {
|
| + LoadMultipleDFromOffset(dtmp, 2, src,
|
| + Float64x2::value_offset() - kHeapObjectTag);
|
| + StoreMultipleDToOffset(dtmp, 2, dst,
|
| + Float64x2::value_offset() - kHeapObjectTag);
|
| + } else {
|
| + LoadFromOffset(kWord, tmp1, src,
|
| + (Float64x2::value_offset() + 0 * kWordSize) - kHeapObjectTag);
|
| + LoadFromOffset(kWord, tmp2, src,
|
| + (Float64x2::value_offset() + 1 * kWordSize) - kHeapObjectTag);
|
| + StoreToOffset(kWord, tmp1, dst,
|
| + (Float64x2::value_offset() + 0 * kWordSize) - kHeapObjectTag);
|
| + StoreToOffset(kWord, tmp2, dst,
|
| + (Float64x2::value_offset() + 1 * kWordSize) - kHeapObjectTag);
|
| +
|
| + LoadFromOffset(kWord, tmp1, src,
|
| + (Float64x2::value_offset() + 2 * kWordSize) - kHeapObjectTag);
|
| + LoadFromOffset(kWord, tmp2, src,
|
| + (Float64x2::value_offset() + 3 * kWordSize) - kHeapObjectTag);
|
| + StoreToOffset(kWord, tmp1, dst,
|
| + (Float64x2::value_offset() + 2 * kWordSize) - kHeapObjectTag);
|
| + StoreToOffset(kWord, tmp2, dst,
|
| + (Float64x2::value_offset() + 3 * kWordSize) - kHeapObjectTag);
|
| + }
|
| +}
|
| +
|
| +
|
| void Assembler::AddImmediate(Register rd, int32_t value, Condition cond) {
|
| AddImmediate(rd, rd, value, cond);
|
| }
|
| @@ -2708,14 +2811,16 @@
|
| EnterFrame(kDartVolatileCpuRegs | (1 << FP) | (1 << LR), 0);
|
|
|
| // Preserve all volatile FPU registers.
|
| - DRegister firstv = EvenDRegisterOf(kDartFirstVolatileFpuReg);
|
| - DRegister lastv = OddDRegisterOf(kDartLastVolatileFpuReg);
|
| - if ((lastv - firstv + 1) >= 16) {
|
| - DRegister mid = static_cast<DRegister>(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);
|
| + if (TargetCPUFeatures::vfp_supported()) {
|
| + DRegister firstv = EvenDRegisterOf(kDartFirstVolatileFpuReg);
|
| + DRegister lastv = OddDRegisterOf(kDartLastVolatileFpuReg);
|
| + if ((lastv - firstv + 1) >= 16) {
|
| + DRegister mid = static_cast<DRegister>(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);
|
| @@ -2726,20 +2831,25 @@
|
| // SP might have been modified to reserve space for arguments
|
| // and ensure proper alignment of the stack frame.
|
| // We need to restore it before restoring registers.
|
| + const intptr_t kPushedFpuRegisterSize =
|
| + TargetCPUFeatures::vfp_supported() ?
|
| + kDartVolatileFpuRegCount * kFpuRegisterSize : 0;
|
| +
|
| const intptr_t kPushedRegistersSize =
|
| - kDartVolatileCpuRegCount * kWordSize +
|
| - kDartVolatileFpuRegCount * kFpuRegisterSize;
|
| + kDartVolatileCpuRegCount * kWordSize + kPushedFpuRegisterSize;
|
| AddImmediate(SP, FP, -kPushedRegistersSize);
|
|
|
| // Restore all volatile FPU registers.
|
| - DRegister firstv = EvenDRegisterOf(kDartFirstVolatileFpuReg);
|
| - DRegister lastv = OddDRegisterOf(kDartLastVolatileFpuReg);
|
| - if ((lastv - firstv + 1) >= 16) {
|
| - DRegister mid = static_cast<DRegister>(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);
|
| + if (TargetCPUFeatures::vfp_supported()) {
|
| + DRegister firstv = EvenDRegisterOf(kDartFirstVolatileFpuReg);
|
| + DRegister lastv = OddDRegisterOf(kDartLastVolatileFpuReg);
|
| + if ((lastv - firstv + 1) >= 16) {
|
| + DRegister mid = static_cast<DRegister>(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.
|
| @@ -3018,7 +3128,7 @@
|
|
|
| static const char* fpu_reg_names[kNumberOfFpuRegisters] = {
|
| "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
|
| -#ifdef VFPv3_D32
|
| +#if defined(VFPv3_D32)
|
| "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
|
| #endif
|
| };
|
|
|