diff options
Diffstat (limited to 'deps/v8/src/compiler/arm/code-generator-arm.cc')
-rw-r--r-- | deps/v8/src/compiler/arm/code-generator-arm.cc | 276 |
1 files changed, 245 insertions, 31 deletions
diff --git a/deps/v8/src/compiler/arm/code-generator-arm.cc b/deps/v8/src/compiler/arm/code-generator-arm.cc index c473b9b6aa..a721f6a3be 100644 --- a/deps/v8/src/compiler/arm/code-generator-arm.cc +++ b/deps/v8/src/compiler/arm/code-generator-arm.cc @@ -32,6 +32,7 @@ class ArmOperandConverter final : public InstructionOperandConverter { case kFlags_branch: case kFlags_deoptimize: case kFlags_set: + case kFlags_trap: return SetCC; case kFlags_none: return LeaveCC; @@ -1504,6 +1505,110 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( DCHECK_EQ(LeaveCC, i.OutputSBit()); break; } + case kArmFloat32x4Splat: { + __ vdup(i.OutputSimd128Register(), i.InputFloatRegister(0)); + break; + } + case kArmFloat32x4ExtractLane: { + __ ExtractLane(i.OutputFloatRegister(), i.InputSimd128Register(0), + kScratchReg, i.InputInt8(1)); + break; + } + case kArmFloat32x4ReplaceLane: { + __ ReplaceLane(i.OutputSimd128Register(), i.InputSimd128Register(0), + i.InputFloatRegister(2), kScratchReg, i.InputInt8(1)); + break; + } + case kArmFloat32x4FromInt32x4: { + __ vcvt_f32_s32(i.OutputSimd128Register(), i.InputSimd128Register(0)); + break; + } + case kArmFloat32x4FromUint32x4: { + __ vcvt_f32_u32(i.OutputSimd128Register(), i.InputSimd128Register(0)); + break; + } + case kArmFloat32x4Abs: { + __ vabs(i.OutputSimd128Register(), i.InputSimd128Register(0)); + break; + } + case kArmFloat32x4Neg: { + __ vneg(i.OutputSimd128Register(), i.InputSimd128Register(0)); + break; + } + case kArmFloat32x4Add: { + __ vadd(i.OutputSimd128Register(), i.InputSimd128Register(0), + i.InputSimd128Register(1)); + break; + } + case kArmFloat32x4Sub: { + __ vsub(i.OutputSimd128Register(), i.InputSimd128Register(0), + i.InputSimd128Register(1)); + break; + } + case kArmFloat32x4Eq: { + __ vceq(i.OutputSimd128Register(), i.InputSimd128Register(0), + i.InputSimd128Register(1)); + break; + } + case kArmFloat32x4Ne: { + Simd128Register dst = i.OutputSimd128Register(); + __ vceq(dst, i.InputSimd128Register(0), i.InputSimd128Register(1)); + __ vmvn(dst, dst); + break; + } + case kArmInt32x4Splat: { + __ vdup(Neon32, i.OutputSimd128Register(), i.InputRegister(0)); + break; + } + case kArmInt32x4ExtractLane: { + __ ExtractLane(i.OutputRegister(), i.InputSimd128Register(0), NeonS32, + i.InputInt8(1)); + break; + } + case kArmInt32x4ReplaceLane: { + __ ReplaceLane(i.OutputSimd128Register(), i.InputSimd128Register(0), + i.InputRegister(2), NeonS32, i.InputInt8(1)); + break; + } + case kArmInt32x4FromFloat32x4: { + __ vcvt_s32_f32(i.OutputSimd128Register(), i.InputSimd128Register(0)); + break; + } + case kArmUint32x4FromFloat32x4: { + __ vcvt_u32_f32(i.OutputSimd128Register(), i.InputSimd128Register(0)); + break; + } + case kArmInt32x4Add: { + __ vadd(Neon32, i.OutputSimd128Register(), i.InputSimd128Register(0), + i.InputSimd128Register(1)); + break; + } + case kArmInt32x4Sub: { + __ vsub(Neon32, i.OutputSimd128Register(), i.InputSimd128Register(0), + i.InputSimd128Register(1)); + break; + } + case kArmInt32x4Eq: { + __ vceq(Neon32, i.OutputSimd128Register(), i.InputSimd128Register(0), + i.InputSimd128Register(1)); + break; + } + case kArmInt32x4Ne: { + Simd128Register dst = i.OutputSimd128Register(); + __ vceq(Neon32, dst, i.InputSimd128Register(0), + i.InputSimd128Register(1)); + __ vmvn(dst, dst); + break; + } + case kArmSimd32x4Select: { + // Select is a ternary op, so we need to move one input into the + // destination. Use vtst to canonicalize the 'boolean' input #0. + __ vtst(Neon32, i.OutputSimd128Register(), i.InputSimd128Register(0), + i.InputSimd128Register(0)); + __ vbsl(i.OutputSimd128Register(), i.InputSimd128Register(1), + i.InputSimd128Register(2)); + break; + } case kCheckedLoadInt8: ASSEMBLE_CHECKED_LOAD_INTEGER(ldrsb); break; @@ -1590,6 +1695,67 @@ void CodeGenerator::AssembleArchJump(RpoNumber target) { if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target)); } +void CodeGenerator::AssembleArchTrap(Instruction* instr, + FlagsCondition condition) { + class OutOfLineTrap final : public OutOfLineCode { + public: + OutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr) + : OutOfLineCode(gen), + frame_elided_(frame_elided), + instr_(instr), + gen_(gen) {} + + void Generate() final { + ArmOperandConverter i(gen_, instr_); + + Runtime::FunctionId trap_id = static_cast<Runtime::FunctionId>( + i.InputInt32(instr_->InputCount() - 1)); + bool old_has_frame = __ has_frame(); + if (frame_elided_) { + __ set_has_frame(true); + __ EnterFrame(StackFrame::WASM_COMPILED); + } + GenerateCallToTrap(trap_id); + if (frame_elided_) { + __ set_has_frame(old_has_frame); + } + if (FLAG_debug_code) { + __ stop(GetBailoutReason(kUnexpectedReturnFromWasmTrap)); + } + } + + private: + void GenerateCallToTrap(Runtime::FunctionId trap_id) { + if (trap_id == Runtime::kNumFunctions) { + // We cannot test calls to the runtime in cctest/test-run-wasm. + // Therefore we emit a call to C here instead of a call to the runtime. + // We use the context register as the scratch register, because we do + // not have a context here. + __ PrepareCallCFunction(0, 0, cp); + __ CallCFunction( + ExternalReference::wasm_call_trap_callback_for_testing(isolate()), + 0); + } else { + __ Move(cp, isolate()->native_context()); + gen_->AssembleSourcePosition(instr_); + __ CallRuntime(trap_id); + } + ReferenceMap* reference_map = + new (gen_->zone()) ReferenceMap(gen_->zone()); + gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0, + Safepoint::kNoLazyDeopt); + } + + bool frame_elided_; + Instruction* instr_; + CodeGenerator* gen_; + }; + bool frame_elided = !frame_access_state()->has_frame(); + auto ool = new (zone()) OutOfLineTrap(this, frame_elided, instr); + Label* tlabel = ool->entry(); + Condition cc = FlagsConditionToCondition(condition); + __ b(cc, tlabel); +} // Assembles boolean materializations after an instruction. void CodeGenerator::AssembleArchBoolean(Instruction* instr, @@ -1824,9 +1990,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, destination->IsRegister() ? g.ToRegister(destination) : kScratchReg; switch (src.type()) { case Constant::kInt32: - if (src.rmode() == RelocInfo::WASM_MEMORY_REFERENCE || - src.rmode() == RelocInfo::WASM_GLOBAL_REFERENCE || - src.rmode() == RelocInfo::WASM_MEMORY_SIZE_REFERENCE) { + if (RelocInfo::IsWasmReference(src.rmode())) { __ mov(dst, Operand(src.ToInt32(), src.rmode())); } else { __ mov(dst, Operand(src.ToInt32())); @@ -1891,8 +2055,7 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, DCHECK(destination->IsDoubleStackSlot()); __ vstr(src, g.ToMemOperand(destination)); } - } else { - DCHECK_EQ(MachineRepresentation::kFloat32, rep); + } else if (rep == MachineRepresentation::kFloat32) { // GapResolver may give us reg codes that don't map to actual s-registers. // Generate code to work around those cases. int src_code = LocationOperand::cast(source)->register_code(); @@ -1903,6 +2066,19 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, DCHECK(destination->IsFloatStackSlot()); __ VmovExtended(g.ToMemOperand(destination), src_code, kScratchReg); } + } else { + DCHECK_EQ(MachineRepresentation::kSimd128, rep); + QwNeonRegister src = g.ToSimd128Register(source); + if (destination->IsSimd128Register()) { + QwNeonRegister dst = g.ToSimd128Register(destination); + __ Move(dst, src); + } else { + DCHECK(destination->IsSimd128StackSlot()); + MemOperand dst = g.ToMemOperand(destination); + __ add(kScratchReg, dst.rn(), Operand(dst.offset())); + __ vst1(Neon8, NeonListOperand(src.low(), 2), + NeonMemOperand(kScratchReg)); + } } } else if (source->IsFPStackSlot()) { MemOperand src = g.ToMemOperand(source); @@ -1911,24 +2087,38 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, if (destination->IsFPRegister()) { if (rep == MachineRepresentation::kFloat64) { __ vldr(g.ToDoubleRegister(destination), src); - } else { - DCHECK_EQ(MachineRepresentation::kFloat32, rep); + } else if (rep == MachineRepresentation::kFloat32) { // GapResolver may give us reg codes that don't map to actual // s-registers. Generate code to work around those cases. int dst_code = LocationOperand::cast(destination)->register_code(); __ VmovExtended(dst_code, src, kScratchReg); + } else { + DCHECK_EQ(MachineRepresentation::kSimd128, rep); + QwNeonRegister dst = g.ToSimd128Register(destination); + __ add(kScratchReg, src.rn(), Operand(src.offset())); + __ vld1(Neon8, NeonListOperand(dst.low(), 2), + NeonMemOperand(kScratchReg)); } - } else { + } else if (rep == MachineRepresentation::kFloat64) { DCHECK(destination->IsFPStackSlot()); if (rep == MachineRepresentation::kFloat64) { DwVfpRegister temp = kScratchDoubleReg; __ vldr(temp, src); __ vstr(temp, g.ToMemOperand(destination)); - } else { - DCHECK_EQ(MachineRepresentation::kFloat32, rep); + } else if (rep == MachineRepresentation::kFloat32) { SwVfpRegister temp = kScratchDoubleReg.low(); __ vldr(temp, src); __ vstr(temp, g.ToMemOperand(destination)); + } else { + DCHECK_EQ(MachineRepresentation::kSimd128, rep); + MemOperand dst = g.ToMemOperand(destination); + __ add(kScratchReg, src.rn(), Operand(src.offset())); + __ vld1(Neon8, NeonListOperand(kScratchQuadReg.low(), 2), + NeonMemOperand(kScratchReg)); + __ add(kScratchReg, dst.rn(), Operand(dst.offset())); + __ vst1(Neon8, NeonListOperand(kScratchQuadReg.low(), 2), + NeonMemOperand(kScratchReg)); + __ veor(kDoubleRegZero, kDoubleRegZero, kDoubleRegZero); } } } else { @@ -1936,7 +2126,6 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, } } - void CodeGenerator::AssembleSwap(InstructionOperand* source, InstructionOperand* destination) { ArmOperandConverter g(this, nullptr); @@ -1975,7 +2164,7 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source, DwVfpRegister src = g.ToDoubleRegister(source); if (destination->IsFPRegister()) { DwVfpRegister dst = g.ToDoubleRegister(destination); - __ vswp(src, dst); + __ Swap(src, dst); } else { DCHECK(destination->IsFPStackSlot()); MemOperand dst = g.ToMemOperand(destination); @@ -1983,8 +2172,7 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source, __ vldr(src, dst); __ vstr(temp, dst); } - } else { - DCHECK_EQ(MachineRepresentation::kFloat32, rep); + } else if (rep == MachineRepresentation::kFloat32) { int src_code = LocationOperand::cast(source)->register_code(); if (destination->IsFPRegister()) { int dst_code = LocationOperand::cast(destination)->register_code(); @@ -1998,29 +2186,55 @@ void CodeGenerator::AssembleSwap(InstructionOperand* source, __ VmovExtended(src_code, dst, kScratchReg); __ vstr(temp.low(), dst); } + } else { + DCHECK_EQ(MachineRepresentation::kSimd128, rep); + QwNeonRegister src = g.ToSimd128Register(source); + if (destination->IsFPRegister()) { + QwNeonRegister dst = g.ToSimd128Register(destination); + __ Swap(src, dst); + } else { + DCHECK(destination->IsFPStackSlot()); + MemOperand dst = g.ToMemOperand(destination); + __ Move(kScratchQuadReg, src); + __ add(kScratchReg, dst.rn(), Operand(dst.offset())); + __ vld1(Neon8, NeonListOperand(src.low(), 2), + NeonMemOperand(kScratchReg)); + __ vst1(Neon8, NeonListOperand(kScratchQuadReg.low(), 2), + NeonMemOperand(kScratchReg)); + __ veor(kDoubleRegZero, kDoubleRegZero, kDoubleRegZero); + } } } else if (source->IsFPStackSlot()) { DCHECK(destination->IsFPStackSlot()); - Register temp_0 = kScratchReg; - LowDwVfpRegister temp_1 = kScratchDoubleReg; - MemOperand src0 = g.ToMemOperand(source); - MemOperand dst0 = g.ToMemOperand(destination); + MemOperand src = g.ToMemOperand(source); + MemOperand dst = g.ToMemOperand(destination); MachineRepresentation rep = LocationOperand::cast(source)->representation(); if (rep == MachineRepresentation::kFloat64) { - MemOperand src1(src0.rn(), src0.offset() + kPointerSize); - MemOperand dst1(dst0.rn(), dst0.offset() + kPointerSize); - __ vldr(temp_1, dst0); // Save destination in temp_1. - __ ldr(temp_0, src0); // Then use temp_0 to copy source to destination. - __ str(temp_0, dst0); - __ ldr(temp_0, src1); - __ str(temp_0, dst1); - __ vstr(temp_1, src0); + __ vldr(kScratchDoubleReg, dst); + __ vldr(kDoubleRegZero, src); + __ vstr(kScratchDoubleReg, src); + __ vstr(kDoubleRegZero, dst); + // Restore the 0 register. + __ veor(kDoubleRegZero, kDoubleRegZero, kDoubleRegZero); + } else if (rep == MachineRepresentation::kFloat32) { + __ vldr(kScratchDoubleReg.low(), dst); + __ vldr(kScratchDoubleReg.high(), src); + __ vstr(kScratchDoubleReg.low(), src); + __ vstr(kScratchDoubleReg.high(), dst); } else { - DCHECK_EQ(MachineRepresentation::kFloat32, rep); - __ vldr(temp_1.low(), dst0); // Save destination in temp_1. - __ ldr(temp_0, src0); // Then use temp_0 to copy source to destination. - __ str(temp_0, dst0); - __ vstr(temp_1.low(), src0); + DCHECK_EQ(MachineRepresentation::kSimd128, rep); + __ vldr(kScratchDoubleReg, dst); + __ vldr(kDoubleRegZero, src); + __ vstr(kScratchDoubleReg, src); + __ vstr(kDoubleRegZero, dst); + src.set_offset(src.offset() + kDoubleSize); + dst.set_offset(dst.offset() + kDoubleSize); + __ vldr(kScratchDoubleReg, dst); + __ vldr(kDoubleRegZero, src); + __ vstr(kScratchDoubleReg, src); + __ vstr(kDoubleRegZero, dst); + // Restore the 0 register. + __ veor(kDoubleRegZero, kDoubleRegZero, kDoubleRegZero); } } else { // No other combinations are possible. |