5 #include "src/compiler/backend/code-generator.h" 7 #include "src/assembler-inl.h" 8 #include "src/boxed-float.h" 9 #include "src/compiler/backend/code-generator-impl.h" 10 #include "src/compiler/backend/gap-resolver.h" 11 #include "src/compiler/node-matchers.h" 12 #include "src/compiler/osr.h" 13 #include "src/double.h" 14 #include "src/heap/heap-inl.h" 15 #include "src/macro-assembler.h" 16 #include "src/optimized-compilation-info.h" 17 #include "src/wasm/wasm-code-manager.h" 18 #include "src/wasm/wasm-objects.h" 32 SBit OutputSBit()
const {
33 switch (instr_->flags_mode()) {
35 case kFlags_branch_and_poison:
36 case kFlags_deoptimize:
37 case kFlags_deoptimize_and_poison:
47 Operand InputImmediate(
size_t index) {
48 return ToImmediate(instr_->InputAt(index));
51 Operand InputOperand2(
size_t first_index) {
52 const size_t index = first_index;
53 switch (AddressingModeField::decode(instr_->opcode())) {
58 case kMode_Operand2_I:
59 return InputImmediate(index + 0);
60 case kMode_Operand2_R:
61 return Operand(InputRegister(index + 0));
62 case kMode_Operand2_R_ASR_I:
63 return Operand(InputRegister(index + 0), ASR, InputInt5(index + 1));
64 case kMode_Operand2_R_ASR_R:
65 return Operand(InputRegister(index + 0), ASR, InputRegister(index + 1));
66 case kMode_Operand2_R_LSL_I:
67 return Operand(InputRegister(index + 0), LSL, InputInt5(index + 1));
68 case kMode_Operand2_R_LSL_R:
69 return Operand(InputRegister(index + 0), LSL, InputRegister(index + 1));
70 case kMode_Operand2_R_LSR_I:
71 return Operand(InputRegister(index + 0), LSR, InputInt5(index + 1));
72 case kMode_Operand2_R_LSR_R:
73 return Operand(InputRegister(index + 0), LSR, InputRegister(index + 1));
74 case kMode_Operand2_R_ROR_I:
75 return Operand(InputRegister(index + 0), ROR, InputInt5(index + 1));
76 case kMode_Operand2_R_ROR_R:
77 return Operand(InputRegister(index + 0), ROR, InputRegister(index + 1));
83 const size_t index = *first_index;
84 switch (AddressingModeField::decode(instr_->opcode())) {
86 case kMode_Operand2_I:
87 case kMode_Operand2_R:
88 case kMode_Operand2_R_ASR_I:
89 case kMode_Operand2_R_ASR_R:
90 case kMode_Operand2_R_LSL_R:
91 case kMode_Operand2_R_LSR_I:
92 case kMode_Operand2_R_LSR_R:
93 case kMode_Operand2_R_ROR_I:
94 case kMode_Operand2_R_ROR_R:
96 case kMode_Operand2_R_LSL_I:
98 return MemOperand(InputRegister(index + 0), InputRegister(index + 1),
99 LSL, InputInt32(index + 2));
100 case kMode_Offset_RI:
102 return MemOperand(InputRegister(index + 0), InputInt32(index + 1));
103 case kMode_Offset_RR:
105 return MemOperand(InputRegister(index + 0), InputRegister(index + 1));
110 MemOperand InputOffset(
size_t first_index = 0) {
111 return InputOffset(&first_index);
115 Constant constant = ToConstant(operand);
116 switch (constant.type()) {
117 case Constant::kInt32:
118 if (RelocInfo::IsWasmReference(constant.rmode())) {
119 return Operand(constant.ToInt32(), constant.rmode());
121 return Operand(constant.ToInt32());
123 case Constant::kFloat32:
124 return Operand::EmbeddedNumber(constant.ToFloat32());
125 case Constant::kFloat64:
126 return Operand::EmbeddedNumber(constant.ToFloat64().value());
127 case Constant::kExternalReference:
128 return Operand(constant.ToExternalReference());
129 case Constant::kDelayedStringConstant:
130 return Operand::EmbeddedStringConstant(
131 constant.ToDelayedStringConstant());
132 case Constant::kInt64:
133 case Constant::kHeapObject:
135 case Constant::kRpoNumber:
143 DCHECK(op->IsStackSlot() || op->IsFPStackSlot());
144 return SlotToMemOperand(AllocatedOperand::cast(op)->index());
148 FrameOffset offset = frame_access_state()->GetFrameOffset(slot);
149 return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset());
153 const size_t index = first_index;
154 switch (AddressingModeField::decode(instr_->opcode())) {
155 case kMode_Offset_RR:
157 InputRegister(index + 1));
158 case kMode_Operand2_R:
173 RecordWriteMode mode, StubCallMode stub_mode,
183 stub_mode_(stub_mode),
184 must_save_lr_(!gen->frame_access_state()->has_frame()),
185 unwinding_info_writer_(unwinding_info_writer),
186 zone_(gen->zone()) {}
188 OutOfLineRecordWrite(CodeGenerator* gen,
Register object, int32_t index,
190 RecordWriteMode mode, StubCallMode stub_mode,
191 UnwindingInfoWriter* unwinding_info_writer)
192 : OutOfLineCode(gen),
195 index_immediate_(index),
200 stub_mode_(stub_mode),
201 must_save_lr_(!gen->frame_access_state()->has_frame()),
202 unwinding_info_writer_(unwinding_info_writer),
203 zone_(gen->zone()) {}
205 void Generate() final {
206 if (mode_ > RecordWriteMode::kValueIsPointer) {
207 __ JumpIfSmi(value_, exit());
209 __ CheckPageFlag(value_, scratch0_,
210 MemoryChunk::kPointersToHereAreInterestingMask, eq,
212 if (index_ == no_reg) {
213 __ add(scratch1_, object_, Operand(index_immediate_));
215 DCHECK_EQ(0, index_immediate_);
216 __ add(scratch1_, object_, Operand(index_));
218 RememberedSetAction
const remembered_set_action =
219 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
220 : OMIT_REMEMBERED_SET;
221 SaveFPRegsMode
const save_fp_mode =
222 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
226 unwinding_info_writer_->MarkLinkRegisterOnTopOfStack(__ pc_offset());
228 if (stub_mode_ == StubCallMode::kCallWasmRuntimeStub) {
229 __ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
230 save_fp_mode, wasm::WasmCode::kWasmRecordWrite);
232 __ CallRecordWriteStub(object_, scratch1_, remembered_set_action,
237 unwinding_info_writer_->MarkPopLinkRegisterFromTopOfStack(__ pc_offset());
242 Register
const object_;
243 Register
const index_;
244 int32_t
const index_immediate_;
245 Register
const value_;
246 Register
const scratch0_;
247 Register
const scratch1_;
248 RecordWriteMode
const mode_;
249 StubCallMode stub_mode_;
251 UnwindingInfoWriter*
const unwinding_info_writer_;
255 template <
typename T>
256 class OutOfLineFloatMin final :
public OutOfLineCode {
258 OutOfLineFloatMin(CodeGenerator* gen, T result, T left, T right)
259 : OutOfLineCode(gen), result_(result), left_(left), right_(right) {}
261 void Generate() final { __ FloatMinOutOfLine(result_, left_, right_); }
268 typedef OutOfLineFloatMin<SwVfpRegister> OutOfLineFloat32Min;
269 typedef OutOfLineFloatMin<DwVfpRegister> OutOfLineFloat64Min;
271 template <
typename T>
272 class OutOfLineFloatMax final :
public OutOfLineCode {
274 OutOfLineFloatMax(CodeGenerator* gen, T result, T left, T right)
275 : OutOfLineCode(gen), result_(result), left_(left), right_(right) {}
277 void Generate() final { __ FloatMaxOutOfLine(result_, left_, right_); }
284 typedef OutOfLineFloatMax<SwVfpRegister> OutOfLineFloat32Max;
285 typedef OutOfLineFloatMax<DwVfpRegister> OutOfLineFloat64Max;
287 Condition FlagsConditionToCondition(FlagsCondition condition) {
293 case kSignedLessThan:
295 case kSignedGreaterThanOrEqual:
297 case kSignedLessThanOrEqual:
299 case kSignedGreaterThan:
301 case kUnsignedLessThan:
303 case kUnsignedGreaterThanOrEqual:
305 case kUnsignedLessThanOrEqual:
307 case kUnsignedGreaterThan:
309 case kFloatLessThanOrUnordered:
311 case kFloatGreaterThanOrEqual:
313 case kFloatLessThanOrEqual:
315 case kFloatGreaterThanOrUnordered:
319 case kFloatGreaterThanOrEqualOrUnordered:
321 case kFloatLessThanOrEqualOrUnordered:
323 case kFloatGreaterThan:
329 case kPositiveOrZero:
339 void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen,
340 InstructionCode opcode,
341 ArmOperandConverter&
i) {
342 const MemoryAccessMode access_mode =
343 static_cast<MemoryAccessMode
>(MiscField::decode(opcode));
344 if (access_mode == kMemoryAccessPoisoned) {
345 Register value =
i.OutputRegister();
346 codegen->tasm()->and_(value, value, Operand(kSpeculationPoisonRegister));
350 void ComputePoisonedAddressForLoad(CodeGenerator* codegen,
351 InstructionCode opcode,
352 ArmOperandConverter&
i, Register address) {
353 DCHECK_EQ(kMemoryAccessPoisoned,
354 static_cast<MemoryAccessMode>(MiscField::decode(opcode)));
355 switch (AddressingModeField::decode(opcode)) {
356 case kMode_Offset_RI:
357 codegen->tasm()->mov(address,
i.InputImmediate(1));
358 codegen->tasm()->add(address, address,
i.InputRegister(0));
360 case kMode_Offset_RR:
361 codegen->tasm()->add(address,
i.InputRegister(0),
i.InputRegister(1));
366 codegen->tasm()->and_(address, address, Operand(kSpeculationPoisonRegister));
371 #define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr) \ 373 __ asm_instr(i.OutputRegister(), \ 374 MemOperand(i.InputRegister(0), i.InputRegister(1))); \ 378 #define ASSEMBLE_ATOMIC_STORE_INTEGER(asm_instr) \ 381 __ asm_instr(i.InputRegister(2), \ 382 MemOperand(i.InputRegister(0), i.InputRegister(1))); \ 386 #define ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(load_instr, store_instr) \ 389 __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); \ 391 __ bind(&exchange); \ 392 __ load_instr(i.OutputRegister(0), i.TempRegister(1)); \ 393 __ store_instr(i.TempRegister(0), i.InputRegister(2), i.TempRegister(1)); \ 394 __ teq(i.TempRegister(0), Operand(0)); \ 395 __ b(ne, &exchange); \ 399 #define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(load_instr, store_instr, \ 402 Label compareExchange; \ 405 __ bind(&compareExchange); \ 406 __ load_instr(i.OutputRegister(0), i.TempRegister(1)); \ 407 __ teq(cmp_reg, Operand(i.OutputRegister(0))); \ 409 __ store_instr(i.TempRegister(0), i.InputRegister(3), i.TempRegister(1)); \ 410 __ teq(i.TempRegister(0), Operand(0)); \ 411 __ b(ne, &compareExchange); \ 416 #define ASSEMBLE_ATOMIC_BINOP(load_instr, store_instr, bin_instr) \ 419 __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); \ 422 __ load_instr(i.OutputRegister(0), i.TempRegister(1)); \ 423 __ bin_instr(i.TempRegister(0), i.OutputRegister(0), \ 424 Operand(i.InputRegister(2))); \ 425 __ store_instr(i.TempRegister(2), i.TempRegister(0), i.TempRegister(1)); \ 426 __ teq(i.TempRegister(2), Operand(0)); \ 431 #define ASSEMBLE_ATOMIC64_ARITH_BINOP(instr1, instr2) \ 434 __ add(i.TempRegister(0), i.InputRegister(2), i.InputRegister(3)); \ 437 __ ldrexd(r2, r3, i.TempRegister(0)); \ 438 __ instr1(i.TempRegister(1), r2, i.InputRegister(0), SBit::SetCC); \ 439 __ instr2(i.TempRegister(2), r3, Operand(i.InputRegister(1))); \ 440 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ 441 __ strexd(i.TempRegister(3), i.TempRegister(1), i.TempRegister(2), \ 442 i.TempRegister(0)); \ 443 __ teq(i.TempRegister(3), Operand(0)); \ 448 #define ASSEMBLE_ATOMIC64_LOGIC_BINOP(instr) \ 451 __ add(i.TempRegister(0), i.InputRegister(2), i.InputRegister(3)); \ 454 __ ldrexd(r2, r3, i.TempRegister(0)); \ 455 __ instr(i.TempRegister(1), r2, Operand(i.InputRegister(0))); \ 456 __ instr(i.TempRegister(2), r3, Operand(i.InputRegister(1))); \ 457 __ strexd(i.TempRegister(3), i.TempRegister(1), i.TempRegister(2), \ 458 i.TempRegister(0)); \ 459 __ teq(i.TempRegister(3), Operand(0)); \ 464 #define ASSEMBLE_IEEE754_BINOP(name) \ 468 FrameScope scope(tasm(), StackFrame::MANUAL); \ 469 __ PrepareCallCFunction(0, 2); \ 470 __ MovToFloatParameters(i.InputDoubleRegister(0), \ 471 i.InputDoubleRegister(1)); \ 472 __ CallCFunction(ExternalReference::ieee754_##name##_function(), 0, 2); \ 474 __ MovFromFloatResult(i.OutputDoubleRegister()); \ 475 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ 478 #define ASSEMBLE_IEEE754_UNOP(name) \ 482 FrameScope scope(tasm(), StackFrame::MANUAL); \ 483 __ PrepareCallCFunction(0, 1); \ 484 __ MovToFloatParameter(i.InputDoubleRegister(0)); \ 485 __ CallCFunction(ExternalReference::ieee754_##name##_function(), 0, 1); \ 487 __ MovFromFloatResult(i.OutputDoubleRegister()); \ 488 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ 491 #define ASSEMBLE_NEON_NARROWING_OP(dt) \ 493 Simd128Register dst = i.OutputSimd128Register(), \ 494 src0 = i.InputSimd128Register(0), \ 495 src1 = i.InputSimd128Register(1); \ 496 if (dst == src0 && dst == src1) { \ 497 __ vqmovn(dt, dst.low(), src0); \ 498 __ vmov(dst.high(), dst.low()); \ 499 } else if (dst == src0) { \ 500 __ vqmovn(dt, dst.low(), src0); \ 501 __ vqmovn(dt, dst.high(), src1); \ 503 __ vqmovn(dt, dst.high(), src1); \ 504 __ vqmovn(dt, dst.low(), src0); \ 508 #define ASSEMBLE_NEON_PAIRWISE_OP(op, size) \ 510 Simd128Register dst = i.OutputSimd128Register(), \ 511 src0 = i.InputSimd128Register(0), \ 512 src1 = i.InputSimd128Register(1); \ 514 __ op(size, dst.low(), src0.low(), src0.high()); \ 516 __ vmov(dst.high(), dst.low()); \ 518 __ op(size, dst.high(), src1.low(), src1.high()); \ 521 __ op(size, dst.high(), src1.low(), src1.high()); \ 522 __ op(size, dst.low(), src0.low(), src0.high()); \ 526 void CodeGenerator::AssembleDeconstructFrame() {
527 __ LeaveFrame(StackFrame::MANUAL);
528 unwinding_info_writer_.MarkFrameDeconstructed(__ pc_offset());
531 void CodeGenerator::AssemblePrepareTailCall() {
532 if (frame_access_state()->has_frame()) {
533 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset));
534 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
536 frame_access_state()->SetFrameAccessToSP();
539 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
543 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
547 __ ldr(scratch1, MemOperand(fp, StandardFrameConstants::kContextOffset));
549 Operand(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)));
554 Register caller_args_count_reg = scratch1;
555 __ ldr(caller_args_count_reg,
556 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
557 __ SmiUntag(caller_args_count_reg);
559 ParameterCount callee_args_count(args_reg);
560 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
567 void FlushPendingPushRegisters(TurboAssembler* tasm,
568 FrameAccessState* frame_access_state,
569 ZoneVector<Register>* pending_pushes) {
570 switch (pending_pushes->size()) {
574 tasm->push((*pending_pushes)[0]);
577 tasm->Push((*pending_pushes)[0], (*pending_pushes)[1]);
580 tasm->Push((*pending_pushes)[0], (*pending_pushes)[1],
581 (*pending_pushes)[2]);
587 frame_access_state->IncreaseSPDelta(pending_pushes->size());
588 pending_pushes->clear();
591 void AdjustStackPointerForTailCall(
592 TurboAssembler* tasm, FrameAccessState* state,
int new_slot_above_sp,
593 ZoneVector<Register>* pending_pushes =
nullptr,
594 bool allow_shrinkage =
true) {
595 int current_sp_offset = state->GetSPToFPSlotCount() +
596 StandardFrameConstants::kFixedSlotCountAboveFp;
597 int stack_slot_delta = new_slot_above_sp - current_sp_offset;
598 if (stack_slot_delta > 0) {
599 if (pending_pushes !=
nullptr) {
600 FlushPendingPushRegisters(tasm, state, pending_pushes);
602 tasm->sub(sp, sp, Operand(stack_slot_delta * kPointerSize));
603 state->IncreaseSPDelta(stack_slot_delta);
604 }
else if (allow_shrinkage && stack_slot_delta < 0) {
605 if (pending_pushes !=
nullptr) {
606 FlushPendingPushRegisters(tasm, state, pending_pushes);
608 tasm->add(sp, sp, Operand(-stack_slot_delta * kPointerSize));
609 state->IncreaseSPDelta(stack_slot_delta);
614 bool VerifyOutputOfAtomicPairInstr(ArmOperandConverter* converter,
615 const Instruction* instr, Register low,
617 if (instr->OutputCount() > 0) {
618 if (converter->OutputRegister(0) != low)
return false;
619 if (instr->OutputCount() == 2 && converter->OutputRegister(1) != high)
628 void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr,
629 int first_unused_stack_slot) {
630 ZoneVector<MoveOperands*> pushes(zone());
631 GetPushCompatibleMoves(instr, kRegisterPush, &pushes);
633 if (!pushes.empty() &&
634 (LocationOperand::cast(pushes.back()->destination()).index() + 1 ==
635 first_unused_stack_slot)) {
636 ArmOperandConverter g(
this, instr);
637 ZoneVector<Register> pending_pushes(zone());
638 for (
auto move : pushes) {
639 LocationOperand destination_location(
640 LocationOperand::cast(move->destination()));
641 InstructionOperand source(move->source());
642 AdjustStackPointerForTailCall(
643 tasm(), frame_access_state(),
644 destination_location.index() - pending_pushes.size(),
647 DCHECK(source.IsRegister());
648 LocationOperand source_location(LocationOperand::cast(source));
649 pending_pushes.push_back(source_location.GetRegister());
652 if (pending_pushes.size() == 3) {
653 FlushPendingPushRegisters(tasm(), frame_access_state(),
658 FlushPendingPushRegisters(tasm(), frame_access_state(), &pending_pushes);
660 AdjustStackPointerForTailCall(tasm(), frame_access_state(),
661 first_unused_stack_slot,
nullptr,
false);
664 void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
665 int first_unused_stack_slot) {
666 AdjustStackPointerForTailCall(tasm(), frame_access_state(),
667 first_unused_stack_slot);
671 void CodeGenerator::AssembleCodeStartRegisterCheck() {
672 UseScratchRegisterScope temps(tasm());
673 Register scratch = temps.Acquire();
674 __ ComputeCodeStartAddress(scratch);
675 __ cmp(scratch, kJavaScriptCallCodeStartRegister);
676 __ Assert(eq, AbortReason::kWrongFunctionCodeStart);
686 void CodeGenerator::BailoutIfDeoptimized() {
687 UseScratchRegisterScope temps(tasm());
688 Register scratch = temps.Acquire();
689 int offset = Code::kCodeDataContainerOffset - Code::kHeaderSize;
690 __ ldr(scratch, MemOperand(kJavaScriptCallCodeStartRegister, offset));
692 FieldMemOperand(scratch, CodeDataContainer::kKindSpecificFlagsOffset));
693 __ tst(scratch, Operand(1 << Code::kMarkedForDeoptimizationBit));
696 DCHECK(!isolate()->ShouldLoadConstantsFromRootList());
697 Handle<Code> code = isolate()->builtins()->builtin_handle(
698 Builtins::kCompileLazyDeoptimizedCode);
699 __ Jump(code, RelocInfo::CODE_TARGET, ne);
702 void CodeGenerator::GenerateSpeculationPoisonFromCodeStartRegister() {
703 UseScratchRegisterScope temps(tasm());
704 Register scratch = temps.Acquire();
708 __ ComputeCodeStartAddress(scratch);
709 __ cmp(kJavaScriptCallCodeStartRegister, scratch);
710 __ mov(kSpeculationPoisonRegister, Operand(-1), SBit::LeaveCC, eq);
711 __ mov(kSpeculationPoisonRegister, Operand(0), SBit::LeaveCC, ne);
715 void CodeGenerator::AssembleRegisterArgumentPoisoning() {
716 __ and_(kJSFunctionRegister, kJSFunctionRegister, kSpeculationPoisonRegister);
717 __ and_(kContextRegister, kContextRegister, kSpeculationPoisonRegister);
718 __ and_(sp, sp, kSpeculationPoisonRegister);
722 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
723 Instruction* instr) {
724 ArmOperandConverter
i(
this, instr);
726 __ MaybeCheckConstPool();
727 InstructionCode opcode = instr->opcode();
728 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
729 switch (arch_opcode) {
730 case kArchCallCodeObject: {
731 if (instr->InputAt(0)->IsImmediate()) {
732 __ Call(
i.InputCode(0), RelocInfo::CODE_TARGET);
734 Register reg =
i.InputRegister(0);
736 HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
737 reg == kJavaScriptCallCodeStartRegister);
738 __ add(reg, reg, Operand(Code::kHeaderSize - kHeapObjectTag));
741 RecordCallPosition(instr);
742 DCHECK_EQ(LeaveCC,
i.OutputSBit());
743 frame_access_state()->ClearSPDelta();
746 case kArchCallWasmFunction: {
747 if (instr->InputAt(0)->IsImmediate()) {
748 Constant constant =
i.ToConstant(instr->InputAt(0));
749 Address wasm_code =
static_cast<Address
>(constant.ToInt32());
750 __ Call(wasm_code, constant.rmode());
752 __ Call(
i.InputRegister(0));
754 RecordCallPosition(instr);
755 DCHECK_EQ(LeaveCC,
i.OutputSBit());
756 frame_access_state()->ClearSPDelta();
759 case kArchTailCallCodeObjectFromJSFunction:
760 case kArchTailCallCodeObject: {
761 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
762 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
763 i.TempRegister(0),
i.TempRegister(1),
766 if (instr->InputAt(0)->IsImmediate()) {
767 __ Jump(
i.InputCode(0), RelocInfo::CODE_TARGET);
769 Register reg =
i.InputRegister(0);
771 HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
772 reg == kJavaScriptCallCodeStartRegister);
773 __ add(reg, reg, Operand(Code::kHeaderSize - kHeapObjectTag));
776 DCHECK_EQ(LeaveCC,
i.OutputSBit());
777 unwinding_info_writer_.MarkBlockWillExit();
778 frame_access_state()->ClearSPDelta();
779 frame_access_state()->SetFrameAccessToDefault();
782 case kArchTailCallWasm: {
783 if (instr->InputAt(0)->IsImmediate()) {
784 Constant constant =
i.ToConstant(instr->InputAt(0));
785 Address wasm_code =
static_cast<Address
>(constant.ToInt32());
786 __ Jump(wasm_code, constant.rmode());
788 __ Jump(
i.InputRegister(0));
790 DCHECK_EQ(LeaveCC,
i.OutputSBit());
791 unwinding_info_writer_.MarkBlockWillExit();
792 frame_access_state()->ClearSPDelta();
793 frame_access_state()->SetFrameAccessToDefault();
796 case kArchTailCallAddress: {
797 CHECK(!instr->InputAt(0)->IsImmediate());
798 Register reg =
i.InputRegister(0);
800 HasCallDescriptorFlag(instr, CallDescriptor::kFixedTargetRegister),
801 reg == kJavaScriptCallCodeStartRegister);
803 unwinding_info_writer_.MarkBlockWillExit();
804 frame_access_state()->ClearSPDelta();
805 frame_access_state()->SetFrameAccessToDefault();
808 case kArchCallJSFunction: {
809 Register func =
i.InputRegister(0);
810 if (FLAG_debug_code) {
811 UseScratchRegisterScope temps(tasm());
812 Register scratch = temps.Acquire();
814 __ ldr(scratch, FieldMemOperand(func, JSFunction::kContextOffset));
816 __ Assert(eq, AbortReason::kWrongFunctionContext);
818 static_assert(kJavaScriptCallCodeStartRegister == r2,
"ABI mismatch");
819 __ ldr(r2, FieldMemOperand(func, JSFunction::kCodeOffset));
820 __ add(r2, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
822 RecordCallPosition(instr);
823 DCHECK_EQ(LeaveCC,
i.OutputSBit());
824 frame_access_state()->ClearSPDelta();
827 case kArchPrepareCallCFunction: {
828 int const num_parameters = MiscField::decode(instr->opcode());
829 __ PrepareCallCFunction(num_parameters);
831 frame_access_state()->SetFrameAccessToFP();
834 case kArchSaveCallerRegisters: {
836 static_cast<SaveFPRegsMode
>(MiscField::decode(instr->opcode()));
837 DCHECK(fp_mode_ == kDontSaveFPRegs || fp_mode_ == kSaveFPRegs);
839 int bytes = __ PushCallerSaved(fp_mode_, kReturnRegister0);
840 DCHECK_EQ(0, bytes % kPointerSize);
841 DCHECK_EQ(0, frame_access_state()->sp_delta());
842 frame_access_state()->IncreaseSPDelta(bytes / kPointerSize);
843 DCHECK(!caller_registers_saved_);
844 caller_registers_saved_ =
true;
847 case kArchRestoreCallerRegisters: {
849 static_cast<SaveFPRegsMode>(MiscField::decode(instr->opcode())));
850 DCHECK(fp_mode_ == kDontSaveFPRegs || fp_mode_ == kSaveFPRegs);
852 int bytes = __ PopCallerSaved(fp_mode_, kReturnRegister0);
853 frame_access_state()->IncreaseSPDelta(-(bytes / kPointerSize));
854 DCHECK_EQ(0, frame_access_state()->sp_delta());
855 DCHECK(caller_registers_saved_);
856 caller_registers_saved_ =
false;
859 case kArchPrepareTailCall:
860 AssemblePrepareTailCall();
862 case kArchCallCFunction: {
863 int const num_parameters = MiscField::decode(instr->opcode());
864 if (instr->InputAt(0)->IsImmediate()) {
865 ExternalReference ref =
i.InputExternalReference(0);
866 __ CallCFunction(ref, num_parameters);
868 Register func =
i.InputRegister(0);
869 __ CallCFunction(func, num_parameters);
871 frame_access_state()->SetFrameAccessToDefault();
877 frame_access_state()->ClearSPDelta();
878 if (caller_registers_saved_) {
885 __ RequiredStackSizeForCallerSaved(fp_mode_, kReturnRegister0);
886 frame_access_state()->IncreaseSPDelta(bytes / kPointerSize);
891 AssembleArchJump(
i.InputRpo(0));
892 DCHECK_EQ(LeaveCC,
i.OutputSBit());
894 case kArchBinarySearchSwitch:
895 AssembleArchBinarySearchSwitch(instr);
897 case kArchLookupSwitch:
898 AssembleArchLookupSwitch(instr);
899 DCHECK_EQ(LeaveCC,
i.OutputSBit());
901 case kArchTableSwitch:
902 AssembleArchTableSwitch(instr);
903 DCHECK_EQ(LeaveCC,
i.OutputSBit());
905 case kArchDebugAbort:
906 DCHECK(
i.InputRegister(0) == r1);
907 if (!frame_access_state()->has_frame()) {
910 FrameScope scope(tasm(), StackFrame::NONE);
911 __ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
912 RelocInfo::CODE_TARGET);
914 __ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
915 RelocInfo::CODE_TARGET);
917 __ stop(
"kArchDebugAbort");
918 unwinding_info_writer_.MarkBlockWillExit();
920 case kArchDebugBreak:
921 __ stop(
"kArchDebugBreak");
924 __ RecordComment(reinterpret_cast<const char*>(
i.InputInt32(0)));
926 case kArchThrowTerminator:
927 DCHECK_EQ(LeaveCC,
i.OutputSBit());
928 unwinding_info_writer_.MarkBlockWillExit();
932 DCHECK_EQ(LeaveCC,
i.OutputSBit());
934 case kArchDeoptimize: {
936 BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore());
937 CodeGenResult result =
938 AssembleDeoptimizerCall(deopt_state_id, current_source_position_);
939 if (result != kSuccess)
return result;
940 unwinding_info_writer_.MarkBlockWillExit();
944 AssembleReturn(instr->InputAt(0));
945 DCHECK_EQ(LeaveCC,
i.OutputSBit());
947 case kArchStackPointer:
948 __ mov(
i.OutputRegister(), sp);
949 DCHECK_EQ(LeaveCC,
i.OutputSBit());
951 case kArchFramePointer:
952 __ mov(
i.OutputRegister(), fp);
953 DCHECK_EQ(LeaveCC,
i.OutputSBit());
955 case kArchParentFramePointer:
956 if (frame_access_state()->has_frame()) {
957 __ ldr(
i.OutputRegister(), MemOperand(fp, 0));
959 __ mov(
i.OutputRegister(), fp);
962 case kArchTruncateDoubleToI:
963 __ TruncateDoubleToI(isolate(), zone(),
i.OutputRegister(),
964 i.InputDoubleRegister(0), DetermineStubCallMode());
965 DCHECK_EQ(LeaveCC,
i.OutputSBit());
967 case kArchStoreWithWriteBarrier: {
968 RecordWriteMode mode =
969 static_cast<RecordWriteMode
>(MiscField::decode(instr->opcode()));
970 Register
object =
i.InputRegister(0);
971 Register value =
i.InputRegister(2);
972 Register scratch0 =
i.TempRegister(0);
973 Register scratch1 =
i.TempRegister(1);
974 OutOfLineRecordWrite* ool;
976 AddressingMode addressing_mode =
977 AddressingModeField::decode(instr->opcode());
978 if (addressing_mode == kMode_Offset_RI) {
979 int32_t index =
i.InputInt32(1);
980 ool =
new (zone()) OutOfLineRecordWrite(
981 this,
object, index, value, scratch0, scratch1, mode,
982 DetermineStubCallMode(), &unwinding_info_writer_);
983 __ str(value, MemOperand(
object, index));
985 DCHECK_EQ(kMode_Offset_RR, addressing_mode);
986 Register index(
i.InputRegister(1));
987 ool =
new (zone()) OutOfLineRecordWrite(
988 this,
object, index, value, scratch0, scratch1, mode,
989 DetermineStubCallMode(), &unwinding_info_writer_);
990 __ str(value, MemOperand(
object, index));
992 __ CheckPageFlag(
object, scratch0,
993 MemoryChunk::kPointersFromHereAreInterestingMask, ne,
995 __ bind(ool->exit());
998 case kArchStackSlot: {
1000 frame_access_state()->GetFrameOffset(
i.InputInt32(0));
1001 Register base = offset.from_stack_pointer() ? sp : fp;
1002 __ add(
i.OutputRegister(0), base, Operand(offset.offset()));
1005 case kIeee754Float64Acos:
1006 ASSEMBLE_IEEE754_UNOP(acos);
1008 case kIeee754Float64Acosh:
1009 ASSEMBLE_IEEE754_UNOP(acosh);
1011 case kIeee754Float64Asin:
1012 ASSEMBLE_IEEE754_UNOP(asin);
1014 case kIeee754Float64Asinh:
1015 ASSEMBLE_IEEE754_UNOP(asinh);
1017 case kIeee754Float64Atan:
1018 ASSEMBLE_IEEE754_UNOP(atan);
1020 case kIeee754Float64Atanh:
1021 ASSEMBLE_IEEE754_UNOP(atanh);
1023 case kIeee754Float64Atan2:
1024 ASSEMBLE_IEEE754_BINOP(atan2);
1026 case kIeee754Float64Cbrt:
1027 ASSEMBLE_IEEE754_UNOP(cbrt);
1029 case kIeee754Float64Cos:
1030 ASSEMBLE_IEEE754_UNOP(cos);
1032 case kIeee754Float64Cosh:
1033 ASSEMBLE_IEEE754_UNOP(cosh);
1035 case kIeee754Float64Exp:
1036 ASSEMBLE_IEEE754_UNOP(exp);
1038 case kIeee754Float64Expm1:
1039 ASSEMBLE_IEEE754_UNOP(expm1);
1041 case kIeee754Float64Log:
1042 ASSEMBLE_IEEE754_UNOP(log);
1044 case kIeee754Float64Log1p:
1045 ASSEMBLE_IEEE754_UNOP(log1p);
1047 case kIeee754Float64Log2:
1048 ASSEMBLE_IEEE754_UNOP(log2);
1050 case kIeee754Float64Log10:
1051 ASSEMBLE_IEEE754_UNOP(log10);
1053 case kIeee754Float64Pow: {
1054 __ Call(BUILTIN_CODE(isolate(), MathPowInternal), RelocInfo::CODE_TARGET);
1058 case kIeee754Float64Sin:
1059 ASSEMBLE_IEEE754_UNOP(sin);
1061 case kIeee754Float64Sinh:
1062 ASSEMBLE_IEEE754_UNOP(sinh);
1064 case kIeee754Float64Tan:
1065 ASSEMBLE_IEEE754_UNOP(tan);
1067 case kIeee754Float64Tanh:
1068 ASSEMBLE_IEEE754_UNOP(tanh);
1071 __ add(
i.OutputRegister(),
i.InputRegister(0),
i.InputOperand2(1),
1075 __ and_(
i.OutputRegister(),
i.InputRegister(0),
i.InputOperand2(1),
1079 __ bic(
i.OutputRegister(),
i.InputRegister(0),
i.InputOperand2(1),
1083 __ mul(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1),
1087 __ mla(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1),
1088 i.InputRegister(2),
i.OutputSBit());
1091 CpuFeatureScope scope(tasm(), ARMv7);
1092 __ mls(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1),
1093 i.InputRegister(2));
1094 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1098 __ smull(
i.OutputRegister(0),
i.OutputRegister(1),
i.InputRegister(0),
1099 i.InputRegister(1));
1102 __ smmul(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1));
1103 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1106 __ smmla(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1),
1107 i.InputRegister(2));
1108 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1111 __ umull(
i.OutputRegister(0),
i.OutputRegister(1),
i.InputRegister(0),
1112 i.InputRegister(1),
i.OutputSBit());
1115 CpuFeatureScope scope(tasm(), SUDIV);
1116 __ sdiv(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1));
1117 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1121 CpuFeatureScope scope(tasm(), SUDIV);
1122 __ udiv(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1));
1123 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1127 __ Move(
i.OutputRegister(),
i.InputOperand2(0),
i.OutputSBit());
1130 __ mvn(
i.OutputRegister(),
i.InputOperand2(0),
i.OutputSBit());
1133 __ orr(
i.OutputRegister(),
i.InputRegister(0),
i.InputOperand2(1),
1137 __ eor(
i.OutputRegister(),
i.InputRegister(0),
i.InputOperand2(1),
1141 __ sub(
i.OutputRegister(),
i.InputRegister(0),
i.InputOperand2(1),
1145 __ rsb(
i.OutputRegister(),
i.InputRegister(0),
i.InputOperand2(1),
1149 CpuFeatureScope scope(tasm(), ARMv7);
1150 __ bfc(
i.OutputRegister(),
i.InputInt8(1),
i.InputInt8(2));
1151 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1155 CpuFeatureScope scope(tasm(), ARMv7);
1156 __ ubfx(
i.OutputRegister(),
i.InputRegister(0),
i.InputInt8(1),
1158 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1162 CpuFeatureScope scope(tasm(), ARMv7);
1163 __ sbfx(
i.OutputRegister(),
i.InputRegister(0),
i.InputInt8(1),
1165 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1169 __ sxtb(
i.OutputRegister(),
i.InputRegister(0),
i.InputInt32(1));
1170 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1173 __ sxth(
i.OutputRegister(),
i.InputRegister(0),
i.InputInt32(1));
1174 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1177 __ sxtab(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1),
1179 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1182 __ sxtah(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1),
1184 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1187 __ uxtb(
i.OutputRegister(),
i.InputRegister(0),
i.InputInt32(1));
1188 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1191 __ uxth(
i.OutputRegister(),
i.InputRegister(0),
i.InputInt32(1));
1192 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1195 __ uxtab(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1),
1197 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1200 __ uxtah(
i.OutputRegister(),
i.InputRegister(0),
i.InputRegister(1),
1202 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1205 CpuFeatureScope scope(tasm(), ARMv7);
1206 __ rbit(
i.OutputRegister(),
i.InputRegister(0));
1207 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1211 __ rev(
i.OutputRegister(),
i.InputRegister(0));
1212 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1215 __ clz(
i.OutputRegister(),
i.InputRegister(0));
1216 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1219 __ cmp(
i.InputRegister(0),
i.InputOperand2(1));
1220 DCHECK_EQ(SetCC,
i.OutputSBit());
1223 __ cmn(
i.InputRegister(0),
i.InputOperand2(1));
1224 DCHECK_EQ(SetCC,
i.OutputSBit());
1227 __ tst(
i.InputRegister(0),
i.InputOperand2(1));
1228 DCHECK_EQ(SetCC,
i.OutputSBit());
1231 __ teq(
i.InputRegister(0),
i.InputOperand2(1));
1232 DCHECK_EQ(SetCC,
i.OutputSBit());
1239 __ add(
i.OutputRegister(0),
i.InputRegister(0),
i.InputRegister(2),
1241 __ adc(
i.OutputRegister(1),
i.InputRegister(1),
1242 Operand(
i.InputRegister(3)));
1243 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1250 __ sub(
i.OutputRegister(0),
i.InputRegister(0),
i.InputRegister(2),
1252 __ sbc(
i.OutputRegister(1),
i.InputRegister(1),
1253 Operand(
i.InputRegister(3)));
1254 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1261 __ umull(
i.OutputRegister(0),
i.OutputRegister(1),
i.InputRegister(0),
1262 i.InputRegister(2));
1263 __ mla(
i.OutputRegister(1),
i.InputRegister(0),
i.InputRegister(3),
1264 i.OutputRegister(1));
1265 __ mla(
i.OutputRegister(1),
i.InputRegister(2),
i.InputRegister(1),
1266 i.OutputRegister(1));
1269 Register second_output =
1270 instr->OutputCount() >= 2 ?
i.OutputRegister(1) :
i.TempRegister(0);
1271 if (instr->InputAt(2)->IsImmediate()) {
1272 __ LslPair(
i.OutputRegister(0), second_output,
i.InputRegister(0),
1273 i.InputRegister(1),
i.InputInt32(2));
1275 __ LslPair(
i.OutputRegister(0), second_output,
i.InputRegister(0),
1276 i.InputRegister(1),
i.InputRegister(2));
1281 Register second_output =
1282 instr->OutputCount() >= 2 ?
i.OutputRegister(1) :
i.TempRegister(0);
1283 if (instr->InputAt(2)->IsImmediate()) {
1284 __ LsrPair(
i.OutputRegister(0), second_output,
i.InputRegister(0),
1285 i.InputRegister(1),
i.InputInt32(2));
1287 __ LsrPair(
i.OutputRegister(0), second_output,
i.InputRegister(0),
1288 i.InputRegister(1),
i.InputRegister(2));
1293 Register second_output =
1294 instr->OutputCount() >= 2 ?
i.OutputRegister(1) :
i.TempRegister(0);
1295 if (instr->InputAt(2)->IsImmediate()) {
1296 __ AsrPair(
i.OutputRegister(0), second_output,
i.InputRegister(0),
1297 i.InputRegister(1),
i.InputInt32(2));
1299 __ AsrPair(
i.OutputRegister(0), second_output,
i.InputRegister(0),
1300 i.InputRegister(1),
i.InputRegister(2));
1305 if (instr->InputAt(1)->IsFPRegister()) {
1306 __ VFPCompareAndSetFlags(
i.InputFloatRegister(0),
1307 i.InputFloatRegister(1));
1309 DCHECK(instr->InputAt(1)->IsImmediate());
1311 DCHECK_EQ(0.0f,
i.InputFloat32(1));
1312 __ VFPCompareAndSetFlags(
i.InputFloatRegister(0),
i.InputFloat32(1));
1314 DCHECK_EQ(SetCC,
i.OutputSBit());
1317 __ vadd(
i.OutputFloatRegister(),
i.InputFloatRegister(0),
1318 i.InputFloatRegister(1));
1319 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1322 __ vsub(
i.OutputFloatRegister(),
i.InputFloatRegister(0),
1323 i.InputFloatRegister(1));
1324 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1327 __ vmul(
i.OutputFloatRegister(),
i.InputFloatRegister(0),
1328 i.InputFloatRegister(1));
1329 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1332 __ vmla(
i.OutputFloatRegister(),
i.InputFloatRegister(1),
1333 i.InputFloatRegister(2));
1334 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1337 __ vmls(
i.OutputFloatRegister(),
i.InputFloatRegister(1),
1338 i.InputFloatRegister(2));
1339 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1342 __ vdiv(
i.OutputFloatRegister(),
i.InputFloatRegister(0),
1343 i.InputFloatRegister(1));
1344 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1347 __ vsqrt(
i.OutputFloatRegister(),
i.InputFloatRegister(0));
1350 __ vabs(
i.OutputFloatRegister(),
i.InputFloatRegister(0));
1353 __ vneg(
i.OutputFloatRegister(),
i.InputFloatRegister(0));
1356 if (instr->InputAt(1)->IsFPRegister()) {
1357 __ VFPCompareAndSetFlags(
i.InputDoubleRegister(0),
1358 i.InputDoubleRegister(1));
1360 DCHECK(instr->InputAt(1)->IsImmediate());
1362 DCHECK_EQ(0.0,
i.InputDouble(1));
1363 __ VFPCompareAndSetFlags(
i.InputDoubleRegister(0),
i.InputDouble(1));
1365 DCHECK_EQ(SetCC,
i.OutputSBit());
1368 __ vadd(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0),
1369 i.InputDoubleRegister(1));
1370 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1373 __ vsub(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0),
1374 i.InputDoubleRegister(1));
1375 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1378 __ vmul(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0),
1379 i.InputDoubleRegister(1));
1380 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1383 __ vmla(
i.OutputDoubleRegister(),
i.InputDoubleRegister(1),
1384 i.InputDoubleRegister(2));
1385 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1388 __ vmls(
i.OutputDoubleRegister(),
i.InputDoubleRegister(1),
1389 i.InputDoubleRegister(2));
1390 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1393 __ vdiv(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0),
1394 i.InputDoubleRegister(1));
1395 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1400 FrameScope scope(tasm(), StackFrame::MANUAL);
1401 __ PrepareCallCFunction(0, 2);
1402 __ MovToFloatParameters(
i.InputDoubleRegister(0),
1403 i.InputDoubleRegister(1));
1404 __ CallCFunction(ExternalReference::mod_two_doubles_operation(), 0, 2);
1406 __ MovFromFloatResult(
i.OutputDoubleRegister());
1407 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1411 __ vsqrt(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0));
1414 __ vabs(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0));
1417 __ vneg(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0));
1419 case kArmVrintmF32: {
1420 CpuFeatureScope scope(tasm(), ARMv8);
1421 __ vrintm(
i.OutputFloatRegister(),
i.InputFloatRegister(0));
1424 case kArmVrintmF64: {
1425 CpuFeatureScope scope(tasm(), ARMv8);
1426 __ vrintm(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0));
1429 case kArmVrintpF32: {
1430 CpuFeatureScope scope(tasm(), ARMv8);
1431 __ vrintp(
i.OutputFloatRegister(),
i.InputFloatRegister(0));
1434 case kArmVrintpF64: {
1435 CpuFeatureScope scope(tasm(), ARMv8);
1436 __ vrintp(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0));
1439 case kArmVrintzF32: {
1440 CpuFeatureScope scope(tasm(), ARMv8);
1441 __ vrintz(
i.OutputFloatRegister(),
i.InputFloatRegister(0));
1444 case kArmVrintzF64: {
1445 CpuFeatureScope scope(tasm(), ARMv8);
1446 __ vrintz(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0));
1449 case kArmVrintaF64: {
1450 CpuFeatureScope scope(tasm(), ARMv8);
1451 __ vrinta(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0));
1454 case kArmVrintnF32: {
1455 CpuFeatureScope scope(tasm(), ARMv8);
1456 __ vrintn(
i.OutputFloatRegister(),
i.InputFloatRegister(0));
1459 case kArmVrintnF64: {
1460 CpuFeatureScope scope(tasm(), ARMv8);
1461 __ vrintn(
i.OutputDoubleRegister(),
i.InputDoubleRegister(0));
1464 case kArmVcvtF32F64: {
1465 __ vcvt_f32_f64(
i.OutputFloatRegister(),
i.InputDoubleRegister(0));
1466 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1469 case kArmVcvtF64F32: {
1470 __ vcvt_f64_f32(
i.OutputDoubleRegister(),
i.InputFloatRegister(0));
1471 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1474 case kArmVcvtF32S32: {
1475 UseScratchRegisterScope temps(tasm());
1476 SwVfpRegister scratch = temps.AcquireS();
1477 __ vmov(scratch,
i.InputRegister(0));
1478 __ vcvt_f32_s32(
i.OutputFloatRegister(), scratch);
1479 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1482 case kArmVcvtF32U32: {
1483 UseScratchRegisterScope temps(tasm());
1484 SwVfpRegister scratch = temps.AcquireS();
1485 __ vmov(scratch,
i.InputRegister(0));
1486 __ vcvt_f32_u32(
i.OutputFloatRegister(), scratch);
1487 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1490 case kArmVcvtF64S32: {
1491 UseScratchRegisterScope temps(tasm());
1492 SwVfpRegister scratch = temps.AcquireS();
1493 __ vmov(scratch,
i.InputRegister(0));
1494 __ vcvt_f64_s32(
i.OutputDoubleRegister(), scratch);
1495 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1498 case kArmVcvtF64U32: {
1499 UseScratchRegisterScope temps(tasm());
1500 SwVfpRegister scratch = temps.AcquireS();
1501 __ vmov(scratch,
i.InputRegister(0));
1502 __ vcvt_f64_u32(
i.OutputDoubleRegister(), scratch);
1503 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1506 case kArmVcvtS32F32: {
1507 UseScratchRegisterScope temps(tasm());
1508 SwVfpRegister scratch = temps.AcquireS();
1509 __ vcvt_s32_f32(scratch,
i.InputFloatRegister(0));
1510 __ vmov(
i.OutputRegister(), scratch);
1513 __ cmn(
i.OutputRegister(), Operand(1));
1514 __ mov(
i.OutputRegister(), Operand(INT32_MIN), SBit::LeaveCC, vs);
1515 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1518 case kArmVcvtU32F32: {
1519 UseScratchRegisterScope temps(tasm());
1520 SwVfpRegister scratch = temps.AcquireS();
1521 __ vcvt_u32_f32(scratch,
i.InputFloatRegister(0));
1522 __ vmov(
i.OutputRegister(), scratch);
1525 __ cmn(
i.OutputRegister(), Operand(1));
1526 __ adc(
i.OutputRegister(),
i.OutputRegister(), Operand::Zero());
1527 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1530 case kArmVcvtS32F64: {
1531 UseScratchRegisterScope temps(tasm());
1532 SwVfpRegister scratch = temps.AcquireS();
1533 __ vcvt_s32_f64(scratch,
i.InputDoubleRegister(0));
1534 __ vmov(
i.OutputRegister(), scratch);
1535 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1538 case kArmVcvtU32F64: {
1539 UseScratchRegisterScope temps(tasm());
1540 SwVfpRegister scratch = temps.AcquireS();
1541 __ vcvt_u32_f64(scratch,
i.InputDoubleRegister(0));
1542 __ vmov(
i.OutputRegister(), scratch);
1543 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1546 case kArmVmovU32F32:
1547 __ vmov(
i.OutputRegister(),
i.InputFloatRegister(0));
1548 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1550 case kArmVmovF32U32:
1551 __ vmov(
i.OutputFloatRegister(),
i.InputRegister(0));
1552 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1554 case kArmVmovLowU32F64:
1555 __ VmovLow(
i.OutputRegister(),
i.InputDoubleRegister(0));
1556 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1558 case kArmVmovLowF64U32:
1559 __ VmovLow(
i.OutputDoubleRegister(),
i.InputRegister(1));
1560 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1562 case kArmVmovHighU32F64:
1563 __ VmovHigh(
i.OutputRegister(),
i.InputDoubleRegister(0));
1564 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1566 case kArmVmovHighF64U32:
1567 __ VmovHigh(
i.OutputDoubleRegister(),
i.InputRegister(1));
1568 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1570 case kArmVmovF64U32U32:
1571 __ vmov(
i.OutputDoubleRegister(),
i.InputRegister(0),
i.InputRegister(1));
1572 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1574 case kArmVmovU32U32F64:
1575 __ vmov(
i.OutputRegister(0),
i.OutputRegister(1),
1576 i.InputDoubleRegister(0));
1577 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1580 __ ldrb(
i.OutputRegister(),
i.InputOffset());
1581 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1582 EmitWordLoadPoisoningIfNeeded(
this, opcode,
i);
1585 __ ldrsb(
i.OutputRegister(),
i.InputOffset());
1586 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1587 EmitWordLoadPoisoningIfNeeded(
this, opcode,
i);
1590 __ strb(
i.InputRegister(0),
i.InputOffset(1));
1591 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1594 __ ldrh(
i.OutputRegister(),
i.InputOffset());
1595 EmitWordLoadPoisoningIfNeeded(
this, opcode,
i);
1598 __ ldrsh(
i.OutputRegister(),
i.InputOffset());
1599 EmitWordLoadPoisoningIfNeeded(
this, opcode,
i);
1602 __ strh(
i.InputRegister(0),
i.InputOffset(1));
1603 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1606 __ ldr(
i.OutputRegister(),
i.InputOffset());
1607 EmitWordLoadPoisoningIfNeeded(
this, opcode,
i);
1610 __ str(
i.InputRegister(0),
i.InputOffset(1));
1611 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1614 const MemoryAccessMode access_mode =
1615 static_cast<MemoryAccessMode
>(MiscField::decode(opcode));
1616 if (access_mode == kMemoryAccessPoisoned) {
1617 UseScratchRegisterScope temps(tasm());
1618 Register address = temps.Acquire();
1619 ComputePoisonedAddressForLoad(
this, opcode,
i, address);
1620 __ vldr(
i.OutputFloatRegister(), address, 0);
1622 __ vldr(
i.OutputFloatRegister(),
i.InputOffset());
1624 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1628 __ vstr(
i.InputFloatRegister(0),
i.InputOffset(1));
1629 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1632 __ vld1(Neon8, NeonListOperand(
i.OutputDoubleRegister()),
1633 i.NeonInputOperand(0));
1637 __ vst1(Neon8, NeonListOperand(
i.InputDoubleRegister(0)),
1638 i.NeonInputOperand(1));
1641 case kArmVld1S128: {
1642 __ vld1(Neon8, NeonListOperand(
i.OutputSimd128Register()),
1643 i.NeonInputOperand(0));
1646 case kArmVst1S128: {
1647 __ vst1(Neon8, NeonListOperand(
i.InputSimd128Register(0)),
1648 i.NeonInputOperand(1));
1652 const MemoryAccessMode access_mode =
1653 static_cast<MemoryAccessMode
>(MiscField::decode(opcode));
1654 if (access_mode == kMemoryAccessPoisoned) {
1655 UseScratchRegisterScope temps(tasm());
1656 Register address = temps.Acquire();
1657 ComputePoisonedAddressForLoad(
this, opcode,
i, address);
1658 __ vldr(
i.OutputDoubleRegister(), address, 0);
1660 __ vldr(
i.OutputDoubleRegister(),
i.InputOffset());
1662 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1666 __ vstr(
i.InputDoubleRegister(0),
i.InputOffset(1));
1667 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1669 case kArmFloat32Max: {
1670 SwVfpRegister result =
i.OutputFloatRegister();
1671 SwVfpRegister left =
i.InputFloatRegister(0);
1672 SwVfpRegister right =
i.InputFloatRegister(1);
1673 if (left == right) {
1674 __ Move(result, left);
1676 auto ool =
new (zone()) OutOfLineFloat32Max(
this, result, left, right);
1677 __ FloatMax(result, left, right, ool->entry());
1678 __ bind(ool->exit());
1680 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1683 case kArmFloat64Max: {
1684 DwVfpRegister result =
i.OutputDoubleRegister();
1685 DwVfpRegister left =
i.InputDoubleRegister(0);
1686 DwVfpRegister right =
i.InputDoubleRegister(1);
1687 if (left == right) {
1688 __ Move(result, left);
1690 auto ool =
new (zone()) OutOfLineFloat64Max(
this, result, left, right);
1691 __ FloatMax(result, left, right, ool->entry());
1692 __ bind(ool->exit());
1694 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1697 case kArmFloat32Min: {
1698 SwVfpRegister result =
i.OutputFloatRegister();
1699 SwVfpRegister left =
i.InputFloatRegister(0);
1700 SwVfpRegister right =
i.InputFloatRegister(1);
1701 if (left == right) {
1702 __ Move(result, left);
1704 auto ool =
new (zone()) OutOfLineFloat32Min(
this, result, left, right);
1705 __ FloatMin(result, left, right, ool->entry());
1706 __ bind(ool->exit());
1708 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1711 case kArmFloat64Min: {
1712 DwVfpRegister result =
i.OutputDoubleRegister();
1713 DwVfpRegister left =
i.InputDoubleRegister(0);
1714 DwVfpRegister right =
i.InputDoubleRegister(1);
1715 if (left == right) {
1716 __ Move(result, left);
1718 auto ool =
new (zone()) OutOfLineFloat64Min(
this, result, left, right);
1719 __ FloatMin(result, left, right, ool->entry());
1720 __ bind(ool->exit());
1722 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1725 case kArmFloat64SilenceNaN: {
1726 DwVfpRegister value =
i.InputDoubleRegister(0);
1727 DwVfpRegister result =
i.OutputDoubleRegister();
1728 __ VFPCanonicalizeNaN(result, value);
1732 if (instr->InputAt(0)->IsFPRegister()) {
1733 LocationOperand* op = LocationOperand::cast(instr->InputAt(0));
1734 switch (op->representation()) {
1735 case MachineRepresentation::kFloat32:
1736 __ vpush(
i.InputFloatRegister(0));
1737 frame_access_state()->IncreaseSPDelta(1);
1739 case MachineRepresentation::kFloat64:
1740 __ vpush(
i.InputDoubleRegister(0));
1741 frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
1743 case MachineRepresentation::kSimd128: {
1744 __ vpush(
i.InputSimd128Register(0));
1745 frame_access_state()->IncreaseSPDelta(kSimd128Size / kPointerSize);
1753 __ push(
i.InputRegister(0));
1754 frame_access_state()->IncreaseSPDelta(1);
1756 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1759 int const slot = MiscField::decode(instr->opcode());
1760 __ str(
i.InputRegister(0), MemOperand(sp, slot * kPointerSize));
1761 DCHECK_EQ(LeaveCC,
i.OutputSBit());
1766 int reverse_slot =
i.InputInt32(0) + 1;
1768 FrameSlotToFPOffset(frame()->GetTotalFrameSlotCount() - reverse_slot);
1769 if (instr->OutputAt(0)->IsFPRegister()) {
1770 LocationOperand* op = LocationOperand::cast(instr->OutputAt(0));
1771 if (op->representation() == MachineRepresentation::kFloat64) {
1772 __ vldr(
i.OutputDoubleRegister(), MemOperand(fp, offset));
1774 DCHECK_EQ(MachineRepresentation::kFloat32, op->representation());
1775 __ vldr(
i.OutputFloatRegister(), MemOperand(fp, offset));
1778 __ ldr(
i.OutputRegister(), MemOperand(fp, offset));
1787 case kArchWordPoisonOnSpeculation:
1788 __ and_(
i.OutputRegister(0),
i.InputRegister(0),
1789 Operand(kSpeculationPoisonRegister));
1791 case kArmF32x4Splat: {
1792 int src_code =
i.InputFloatRegister(0).code();
1793 __ vdup(Neon32,
i.OutputSimd128Register(),
1794 DwVfpRegister::from_code(src_code / 2), src_code % 2);
1797 case kArmF32x4ExtractLane: {
1798 __ ExtractLane(
i.OutputFloatRegister(),
i.InputSimd128Register(0),
1802 case kArmF32x4ReplaceLane: {
1803 __ ReplaceLane(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1804 i.InputFloatRegister(2),
i.InputInt8(1));
1807 case kArmF32x4SConvertI32x4: {
1808 __ vcvt_f32_s32(
i.OutputSimd128Register(),
i.InputSimd128Register(0));
1811 case kArmF32x4UConvertI32x4: {
1812 __ vcvt_f32_u32(
i.OutputSimd128Register(),
i.InputSimd128Register(0));
1815 case kArmF32x4Abs: {
1816 __ vabs(
i.OutputSimd128Register(),
i.InputSimd128Register(0));
1819 case kArmF32x4Neg: {
1820 __ vneg(
i.OutputSimd128Register(),
i.InputSimd128Register(0));
1823 case kArmF32x4RecipApprox: {
1824 __ vrecpe(
i.OutputSimd128Register(),
i.InputSimd128Register(0));
1827 case kArmF32x4RecipSqrtApprox: {
1828 __ vrsqrte(
i.OutputSimd128Register(),
i.InputSimd128Register(0));
1831 case kArmF32x4Add: {
1832 __ vadd(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1833 i.InputSimd128Register(1));
1836 case kArmF32x4AddHoriz: {
1837 Simd128Register dst =
i.OutputSimd128Register(),
1838 src0 =
i.InputSimd128Register(0),
1839 src1 =
i.InputSimd128Register(1);
1842 __ vpadd(dst.low(), src0.low(), src0.high());
1844 __ vmov(dst.high(), dst.low());
1846 __ vpadd(dst.high(), src1.low(), src1.high());
1849 __ vpadd(dst.high(), src1.low(), src1.high());
1850 __ vpadd(dst.low(), src0.low(), src0.high());
1854 case kArmF32x4Sub: {
1855 __ vsub(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1856 i.InputSimd128Register(1));
1859 case kArmF32x4Mul: {
1860 __ vmul(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1861 i.InputSimd128Register(1));
1864 case kArmF32x4Min: {
1865 __ vmin(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1866 i.InputSimd128Register(1));
1869 case kArmF32x4Max: {
1870 __ vmax(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1871 i.InputSimd128Register(1));
1875 __ vceq(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1876 i.InputSimd128Register(1));
1880 Simd128Register dst =
i.OutputSimd128Register();
1881 __ vceq(dst,
i.InputSimd128Register(0),
i.InputSimd128Register(1));
1886 __ vcgt(
i.OutputSimd128Register(),
i.InputSimd128Register(1),
1887 i.InputSimd128Register(0));
1891 __ vcge(
i.OutputSimd128Register(),
i.InputSimd128Register(1),
1892 i.InputSimd128Register(0));
1895 case kArmI32x4Splat: {
1896 __ vdup(Neon32,
i.OutputSimd128Register(),
i.InputRegister(0));
1899 case kArmI32x4ExtractLane: {
1900 __ ExtractLane(
i.OutputRegister(),
i.InputSimd128Register(0), NeonS32,
1904 case kArmI32x4ReplaceLane: {
1905 __ ReplaceLane(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1906 i.InputRegister(2), NeonS32,
i.InputInt8(1));
1909 case kArmI32x4SConvertF32x4: {
1910 __ vcvt_s32_f32(
i.OutputSimd128Register(),
i.InputSimd128Register(0));
1913 case kArmI32x4SConvertI16x8Low: {
1914 __ vmovl(NeonS16,
i.OutputSimd128Register(),
1915 i.InputSimd128Register(0).low());
1918 case kArmI32x4SConvertI16x8High: {
1919 __ vmovl(NeonS16,
i.OutputSimd128Register(),
1920 i.InputSimd128Register(0).high());
1923 case kArmI32x4Neg: {
1924 __ vneg(Neon32,
i.OutputSimd128Register(),
i.InputSimd128Register(0));
1927 case kArmI32x4Shl: {
1928 __ vshl(NeonS32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1932 case kArmI32x4ShrS: {
1933 __ vshr(NeonS32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1937 case kArmI32x4Add: {
1938 __ vadd(Neon32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1939 i.InputSimd128Register(1));
1942 case kArmI32x4AddHoriz:
1943 ASSEMBLE_NEON_PAIRWISE_OP(vpadd, Neon32);
1945 case kArmI32x4Sub: {
1946 __ vsub(Neon32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1947 i.InputSimd128Register(1));
1950 case kArmI32x4Mul: {
1951 __ vmul(Neon32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1952 i.InputSimd128Register(1));
1955 case kArmI32x4MinS: {
1956 __ vmin(NeonS32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1957 i.InputSimd128Register(1));
1960 case kArmI32x4MaxS: {
1961 __ vmax(NeonS32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1962 i.InputSimd128Register(1));
1966 __ vceq(Neon32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1967 i.InputSimd128Register(1));
1971 Simd128Register dst =
i.OutputSimd128Register();
1972 __ vceq(Neon32, dst,
i.InputSimd128Register(0),
1973 i.InputSimd128Register(1));
1977 case kArmI32x4GtS: {
1978 __ vcgt(NeonS32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1979 i.InputSimd128Register(1));
1982 case kArmI32x4GeS: {
1983 __ vcge(NeonS32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
1984 i.InputSimd128Register(1));
1987 case kArmI32x4UConvertF32x4: {
1988 __ vcvt_u32_f32(
i.OutputSimd128Register(),
i.InputSimd128Register(0));
1991 case kArmI32x4UConvertI16x8Low: {
1992 __ vmovl(NeonU16,
i.OutputSimd128Register(),
1993 i.InputSimd128Register(0).low());
1996 case kArmI32x4UConvertI16x8High: {
1997 __ vmovl(NeonU16,
i.OutputSimd128Register(),
1998 i.InputSimd128Register(0).high());
2001 case kArmI32x4ShrU: {
2002 __ vshr(NeonU32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2006 case kArmI32x4MinU: {
2007 __ vmin(NeonU32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2008 i.InputSimd128Register(1));
2011 case kArmI32x4MaxU: {
2012 __ vmax(NeonU32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2013 i.InputSimd128Register(1));
2016 case kArmI32x4GtU: {
2017 __ vcgt(NeonU32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2018 i.InputSimd128Register(1));
2021 case kArmI32x4GeU: {
2022 __ vcge(NeonU32,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2023 i.InputSimd128Register(1));
2026 case kArmI16x8Splat: {
2027 __ vdup(Neon16,
i.OutputSimd128Register(),
i.InputRegister(0));
2030 case kArmI16x8ExtractLane: {
2031 __ ExtractLane(
i.OutputRegister(),
i.InputSimd128Register(0), NeonS16,
2035 case kArmI16x8ReplaceLane: {
2036 __ ReplaceLane(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2037 i.InputRegister(2), NeonS16,
i.InputInt8(1));
2040 case kArmI16x8SConvertI8x16Low: {
2041 __ vmovl(NeonS8,
i.OutputSimd128Register(),
2042 i.InputSimd128Register(0).low());
2045 case kArmI16x8SConvertI8x16High: {
2046 __ vmovl(NeonS8,
i.OutputSimd128Register(),
2047 i.InputSimd128Register(0).high());
2050 case kArmI16x8Neg: {
2051 __ vneg(Neon16,
i.OutputSimd128Register(),
i.InputSimd128Register(0));
2054 case kArmI16x8Shl: {
2055 __ vshl(NeonS16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2059 case kArmI16x8ShrS: {
2060 __ vshr(NeonS16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2064 case kArmI16x8SConvertI32x4:
2065 ASSEMBLE_NEON_NARROWING_OP(NeonS16);
2067 case kArmI16x8Add: {
2068 __ vadd(Neon16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2069 i.InputSimd128Register(1));
2072 case kArmI16x8AddSaturateS: {
2073 __ vqadd(NeonS16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2074 i.InputSimd128Register(1));
2077 case kArmI16x8AddHoriz:
2078 ASSEMBLE_NEON_PAIRWISE_OP(vpadd, Neon16);
2080 case kArmI16x8Sub: {
2081 __ vsub(Neon16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2082 i.InputSimd128Register(1));
2085 case kArmI16x8SubSaturateS: {
2086 __ vqsub(NeonS16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2087 i.InputSimd128Register(1));
2090 case kArmI16x8Mul: {
2091 __ vmul(Neon16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2092 i.InputSimd128Register(1));
2095 case kArmI16x8MinS: {
2096 __ vmin(NeonS16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2097 i.InputSimd128Register(1));
2100 case kArmI16x8MaxS: {
2101 __ vmax(NeonS16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2102 i.InputSimd128Register(1));
2106 __ vceq(Neon16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2107 i.InputSimd128Register(1));
2111 Simd128Register dst =
i.OutputSimd128Register();
2112 __ vceq(Neon16, dst,
i.InputSimd128Register(0),
2113 i.InputSimd128Register(1));
2117 case kArmI16x8GtS: {
2118 __ vcgt(NeonS16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2119 i.InputSimd128Register(1));
2122 case kArmI16x8GeS: {
2123 __ vcge(NeonS16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2124 i.InputSimd128Register(1));
2127 case kArmI16x8UConvertI8x16Low: {
2128 __ vmovl(NeonU8,
i.OutputSimd128Register(),
2129 i.InputSimd128Register(0).low());
2132 case kArmI16x8UConvertI8x16High: {
2133 __ vmovl(NeonU8,
i.OutputSimd128Register(),
2134 i.InputSimd128Register(0).high());
2137 case kArmI16x8ShrU: {
2138 __ vshr(NeonU16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2142 case kArmI16x8UConvertI32x4:
2143 ASSEMBLE_NEON_NARROWING_OP(NeonU16);
2145 case kArmI16x8AddSaturateU: {
2146 __ vqadd(NeonU16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2147 i.InputSimd128Register(1));
2150 case kArmI16x8SubSaturateU: {
2151 __ vqsub(NeonU16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2152 i.InputSimd128Register(1));
2155 case kArmI16x8MinU: {
2156 __ vmin(NeonU16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2157 i.InputSimd128Register(1));
2160 case kArmI16x8MaxU: {
2161 __ vmax(NeonU16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2162 i.InputSimd128Register(1));
2165 case kArmI16x8GtU: {
2166 __ vcgt(NeonU16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2167 i.InputSimd128Register(1));
2170 case kArmI16x8GeU: {
2171 __ vcge(NeonU16,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2172 i.InputSimd128Register(1));
2175 case kArmI8x16Splat: {
2176 __ vdup(Neon8,
i.OutputSimd128Register(),
i.InputRegister(0));
2179 case kArmI8x16ExtractLane: {
2180 __ ExtractLane(
i.OutputRegister(),
i.InputSimd128Register(0), NeonS8,
2184 case kArmI8x16ReplaceLane: {
2185 __ ReplaceLane(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2186 i.InputRegister(2), NeonS8,
i.InputInt8(1));
2189 case kArmI8x16Neg: {
2190 __ vneg(Neon8,
i.OutputSimd128Register(),
i.InputSimd128Register(0));
2193 case kArmI8x16Shl: {
2194 __ vshl(NeonS8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2198 case kArmI8x16ShrS: {
2199 __ vshr(NeonS8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2203 case kArmI8x16SConvertI16x8:
2204 ASSEMBLE_NEON_NARROWING_OP(NeonS8);
2206 case kArmI8x16Add: {
2207 __ vadd(Neon8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2208 i.InputSimd128Register(1));
2211 case kArmI8x16AddSaturateS: {
2212 __ vqadd(NeonS8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2213 i.InputSimd128Register(1));
2216 case kArmI8x16Sub: {
2217 __ vsub(Neon8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2218 i.InputSimd128Register(1));
2221 case kArmI8x16SubSaturateS: {
2222 __ vqsub(NeonS8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2223 i.InputSimd128Register(1));
2226 case kArmI8x16Mul: {
2227 __ vmul(Neon8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2228 i.InputSimd128Register(1));
2231 case kArmI8x16MinS: {
2232 __ vmin(NeonS8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2233 i.InputSimd128Register(1));
2236 case kArmI8x16MaxS: {
2237 __ vmax(NeonS8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2238 i.InputSimd128Register(1));
2242 __ vceq(Neon8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2243 i.InputSimd128Register(1));
2247 Simd128Register dst =
i.OutputSimd128Register();
2248 __ vceq(Neon8, dst,
i.InputSimd128Register(0),
i.InputSimd128Register(1));
2252 case kArmI8x16GtS: {
2253 __ vcgt(NeonS8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2254 i.InputSimd128Register(1));
2257 case kArmI8x16GeS: {
2258 __ vcge(NeonS8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2259 i.InputSimd128Register(1));
2262 case kArmI8x16ShrU: {
2263 __ vshr(NeonU8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2267 case kArmI8x16UConvertI16x8:
2268 ASSEMBLE_NEON_NARROWING_OP(NeonU8);
2270 case kArmI8x16AddSaturateU: {
2271 __ vqadd(NeonU8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2272 i.InputSimd128Register(1));
2275 case kArmI8x16SubSaturateU: {
2276 __ vqsub(NeonU8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2277 i.InputSimd128Register(1));
2280 case kArmI8x16MinU: {
2281 __ vmin(NeonU8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2282 i.InputSimd128Register(1));
2285 case kArmI8x16MaxU: {
2286 __ vmax(NeonU8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2287 i.InputSimd128Register(1));
2290 case kArmI8x16GtU: {
2291 __ vcgt(NeonU8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2292 i.InputSimd128Register(1));
2295 case kArmI8x16GeU: {
2296 __ vcge(NeonU8,
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2297 i.InputSimd128Register(1));
2300 case kArmS128Zero: {
2301 __ veor(
i.OutputSimd128Register(),
i.OutputSimd128Register(),
2302 i.OutputSimd128Register());
2306 NeonSize size =
static_cast<NeonSize
>(
i.InputInt32(1));
2307 int lanes = kSimd128Size >> size;
2308 int index =
i.InputInt32(2);
2309 DCHECK(index < lanes);
2310 int d_lanes = lanes / 2;
2311 int src_d_index = index & (d_lanes - 1);
2312 int src_d_code =
i.InputSimd128Register(0).low().code() + index / d_lanes;
2313 __ vdup(size,
i.OutputSimd128Register(),
2314 DwVfpRegister::from_code(src_d_code), src_d_index);
2318 __ vand(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2319 i.InputSimd128Register(1));
2323 __ vorr(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2324 i.InputSimd128Register(1));
2328 __ veor(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2329 i.InputSimd128Register(1));
2333 __ vmvn(
i.OutputSimd128Register(),
i.InputSimd128Register(0));
2336 case kArmS128Select: {
2337 Simd128Register dst =
i.OutputSimd128Register();
2338 DCHECK(dst ==
i.InputSimd128Register(0));
2339 __ vbsl(dst,
i.InputSimd128Register(1),
i.InputSimd128Register(2));
2342 case kArmS32x4ZipLeft: {
2343 Simd128Register dst =
i.OutputSimd128Register(),
2344 src1 =
i.InputSimd128Register(1);
2345 DCHECK(dst ==
i.InputSimd128Register(0));
2347 __ vmov(dst.high(), src1.low());
2348 __ vtrn(Neon32, dst.low(), dst.high());
2351 case kArmS32x4ZipRight: {
2352 Simd128Register dst =
i.OutputSimd128Register(),
2353 src1 =
i.InputSimd128Register(1);
2354 DCHECK(dst ==
i.InputSimd128Register(0));
2356 __ vmov(dst.low(), src1.high());
2357 __ vtrn(Neon32, dst.low(), dst.high());
2360 case kArmS32x4UnzipLeft: {
2361 Simd128Register dst =
i.OutputSimd128Register(),
2362 src1 =
i.InputSimd128Register(1);
2363 DCHECK(dst ==
i.InputSimd128Register(0));
2364 UseScratchRegisterScope temps(tasm());
2365 Simd128Register scratch = temps.AcquireQ();
2367 __ vmov(scratch, src1);
2368 __ vuzp(Neon32, dst, scratch);
2371 case kArmS32x4UnzipRight: {
2372 Simd128Register dst =
i.OutputSimd128Register(),
2373 src1 =
i.InputSimd128Register(1);
2374 DCHECK(dst ==
i.InputSimd128Register(0));
2375 UseScratchRegisterScope temps(tasm());
2376 Simd128Register scratch = temps.AcquireQ();
2378 __ vmov(scratch, src1);
2379 __ vuzp(Neon32, scratch, dst);
2382 case kArmS32x4TransposeLeft: {
2383 Simd128Register dst =
i.OutputSimd128Register(),
2384 src1 =
i.InputSimd128Register(1);
2385 DCHECK(dst ==
i.InputSimd128Register(0));
2386 UseScratchRegisterScope temps(tasm());
2387 Simd128Register scratch = temps.AcquireQ();
2389 __ vmov(scratch, src1);
2390 __ vtrn(Neon32, dst, scratch);
2393 case kArmS32x4Shuffle: {
2394 Simd128Register dst =
i.OutputSimd128Register(),
2395 src0 =
i.InputSimd128Register(0),
2396 src1 =
i.InputSimd128Register(1);
2397 DCHECK_NE(dst, src0);
2398 DCHECK_NE(dst, src1);
2400 int dst_code = dst.code() * 4;
2401 int src0_code = src0.code() * 4;
2402 int src1_code = src1.code() * 4;
2403 int32_t shuffle =
i.InputInt32(2);
2404 for (
int i = 0;
i < 4;
i++) {
2405 int lane = shuffle & 0x7;
2406 int src_code = src0_code;
2408 src_code = src1_code;
2411 __ VmovExtended(dst_code +
i, src_code + lane);
2416 case kArmS32x4TransposeRight: {
2417 Simd128Register dst =
i.OutputSimd128Register(),
2418 src1 =
i.InputSimd128Register(1);
2419 UseScratchRegisterScope temps(tasm());
2420 Simd128Register scratch = temps.AcquireQ();
2421 DCHECK(dst ==
i.InputSimd128Register(0));
2423 __ vmov(scratch, src1);
2424 __ vtrn(Neon32, scratch, dst);
2427 case kArmS16x8ZipLeft: {
2428 Simd128Register dst =
i.OutputSimd128Register(),
2429 src1 =
i.InputSimd128Register(1);
2431 DCHECK(dst ==
i.InputSimd128Register(0));
2432 __ vmov(dst.high(), src1.low());
2433 __ vzip(Neon16, dst.low(), dst.high());
2436 case kArmS16x8ZipRight: {
2437 Simd128Register dst =
i.OutputSimd128Register(),
2438 src1 =
i.InputSimd128Register(1);
2439 DCHECK(dst ==
i.InputSimd128Register(0));
2441 __ vmov(dst.low(), src1.high());
2442 __ vzip(Neon16, dst.low(), dst.high());
2445 case kArmS16x8UnzipLeft: {
2446 Simd128Register dst =
i.OutputSimd128Register(),
2447 src1 =
i.InputSimd128Register(1);
2448 UseScratchRegisterScope temps(tasm());
2449 Simd128Register scratch = temps.AcquireQ();
2450 DCHECK(dst ==
i.InputSimd128Register(0));
2452 __ vmov(scratch, src1);
2453 __ vuzp(Neon16, dst, scratch);
2456 case kArmS16x8UnzipRight: {
2457 Simd128Register dst =
i.OutputSimd128Register(),
2458 src1 =
i.InputSimd128Register(1);
2459 UseScratchRegisterScope temps(tasm());
2460 Simd128Register scratch = temps.AcquireQ();
2461 DCHECK(dst ==
i.InputSimd128Register(0));
2463 __ vmov(scratch, src1);
2464 __ vuzp(Neon16, scratch, dst);
2467 case kArmS16x8TransposeLeft: {
2468 Simd128Register dst =
i.OutputSimd128Register(),
2469 src1 =
i.InputSimd128Register(1);
2470 UseScratchRegisterScope temps(tasm());
2471 Simd128Register scratch = temps.AcquireQ();
2472 DCHECK(dst ==
i.InputSimd128Register(0));
2474 __ vmov(scratch, src1);
2475 __ vtrn(Neon16, dst, scratch);
2478 case kArmS16x8TransposeRight: {
2479 Simd128Register dst =
i.OutputSimd128Register(),
2480 src1 =
i.InputSimd128Register(1);
2481 UseScratchRegisterScope temps(tasm());
2482 Simd128Register scratch = temps.AcquireQ();
2483 DCHECK(dst ==
i.InputSimd128Register(0));
2485 __ vmov(scratch, src1);
2486 __ vtrn(Neon16, scratch, dst);
2489 case kArmS8x16ZipLeft: {
2490 Simd128Register dst =
i.OutputSimd128Register(),
2491 src1 =
i.InputSimd128Register(1);
2492 DCHECK(dst ==
i.InputSimd128Register(0));
2494 __ vmov(dst.high(), src1.low());
2495 __ vzip(Neon8, dst.low(), dst.high());
2498 case kArmS8x16ZipRight: {
2499 Simd128Register dst =
i.OutputSimd128Register(),
2500 src1 =
i.InputSimd128Register(1);
2501 DCHECK(dst ==
i.InputSimd128Register(0));
2503 __ vmov(dst.low(), src1.high());
2504 __ vzip(Neon8, dst.low(), dst.high());
2507 case kArmS8x16UnzipLeft: {
2508 Simd128Register dst =
i.OutputSimd128Register(),
2509 src1 =
i.InputSimd128Register(1);
2510 UseScratchRegisterScope temps(tasm());
2511 Simd128Register scratch = temps.AcquireQ();
2512 DCHECK(dst ==
i.InputSimd128Register(0));
2514 __ vmov(scratch, src1);
2515 __ vuzp(Neon8, dst, scratch);
2518 case kArmS8x16UnzipRight: {
2519 Simd128Register dst =
i.OutputSimd128Register(),
2520 src1 =
i.InputSimd128Register(1);
2521 UseScratchRegisterScope temps(tasm());
2522 Simd128Register scratch = temps.AcquireQ();
2523 DCHECK(dst ==
i.InputSimd128Register(0));
2525 __ vmov(scratch, src1);
2526 __ vuzp(Neon8, scratch, dst);
2529 case kArmS8x16TransposeLeft: {
2530 Simd128Register dst =
i.OutputSimd128Register(),
2531 src1 =
i.InputSimd128Register(1);
2532 UseScratchRegisterScope temps(tasm());
2533 Simd128Register scratch = temps.AcquireQ();
2534 DCHECK(dst ==
i.InputSimd128Register(0));
2536 __ vmov(scratch, src1);
2537 __ vtrn(Neon8, dst, scratch);
2540 case kArmS8x16TransposeRight: {
2541 Simd128Register dst =
i.OutputSimd128Register(),
2542 src1 =
i.InputSimd128Register(1);
2543 UseScratchRegisterScope temps(tasm());
2544 Simd128Register scratch = temps.AcquireQ();
2545 DCHECK(dst ==
i.InputSimd128Register(0));
2547 __ vmov(scratch, src1);
2548 __ vtrn(Neon8, scratch, dst);
2551 case kArmS8x16Concat: {
2552 __ vext(
i.OutputSimd128Register(),
i.InputSimd128Register(0),
2553 i.InputSimd128Register(1),
i.InputInt4(2));
2556 case kArmS8x16Shuffle: {
2557 Simd128Register dst =
i.OutputSimd128Register(),
2558 src0 =
i.InputSimd128Register(0),
2559 src1 =
i.InputSimd128Register(1);
2560 DwVfpRegister table_base = src0.low();
2561 UseScratchRegisterScope temps(tasm());
2562 Simd128Register scratch = temps.AcquireQ();
2565 int table_size = src0 == src1 ? 2 : 4;
2566 DCHECK_IMPLIES(src0 != src1, src0.code() + 1 == src1.code());
2568 int scratch_s_base = scratch.code() * 4;
2569 for (
int j = 0; j < 4; j++) {
2570 uint32_t four_lanes =
i.InputUint32(2 + j);
2572 four_lanes &= 0x1F1F1F1F;
2573 __ vmov(SwVfpRegister::from_code(scratch_s_base + j),
2574 Float32::FromBits(four_lanes));
2576 NeonListOperand table(table_base, table_size);
2577 if (dst != src0 && dst != src1) {
2578 __ vtbl(dst.low(), table, scratch.low());
2579 __ vtbl(dst.high(), table, scratch.high());
2581 __ vtbl(scratch.low(), table, scratch.low());
2582 __ vtbl(scratch.high(), table, scratch.high());
2583 __ vmov(dst, scratch);
2587 case kArmS32x2Reverse: {
2588 __ vrev64(Neon32,
i.OutputSimd128Register(),
i.InputSimd128Register(0));
2591 case kArmS16x4Reverse: {
2592 __ vrev64(Neon16,
i.OutputSimd128Register(),
i.InputSimd128Register(0));
2595 case kArmS16x2Reverse: {
2596 __ vrev32(Neon16,
i.OutputSimd128Register(),
i.InputSimd128Register(0));
2599 case kArmS8x8Reverse: {
2600 __ vrev64(Neon8,
i.OutputSimd128Register(),
i.InputSimd128Register(0));
2603 case kArmS8x4Reverse: {
2604 __ vrev32(Neon8,
i.OutputSimd128Register(),
i.InputSimd128Register(0));
2607 case kArmS8x2Reverse: {
2608 __ vrev16(Neon8,
i.OutputSimd128Register(),
i.InputSimd128Register(0));
2611 case kArmS1x4AnyTrue: {
2612 const QwNeonRegister& src =
i.InputSimd128Register(0);
2613 UseScratchRegisterScope temps(tasm());
2614 DwVfpRegister scratch = temps.AcquireD();
2615 __ vpmax(NeonU32, scratch, src.low(), src.high());
2616 __ vpmax(NeonU32, scratch, scratch, scratch);
2617 __ ExtractLane(
i.OutputRegister(), scratch, NeonS32, 0);
2620 case kArmS1x4AllTrue: {
2621 const QwNeonRegister& src =
i.InputSimd128Register(0);
2622 UseScratchRegisterScope temps(tasm());
2623 DwVfpRegister scratch = temps.AcquireD();
2624 __ vpmin(NeonU32, scratch, src.low(), src.high());
2625 __ vpmin(NeonU32, scratch, scratch, scratch);
2626 __ ExtractLane(
i.OutputRegister(), scratch, NeonS32, 0);
2629 case kArmS1x8AnyTrue: {
2630 const QwNeonRegister& src =
i.InputSimd128Register(0);
2631 UseScratchRegisterScope temps(tasm());
2632 DwVfpRegister scratch = temps.AcquireD();
2633 __ vpmax(NeonU16, scratch, src.low(), src.high());
2634 __ vpmax(NeonU16, scratch, scratch, scratch);
2635 __ vpmax(NeonU16, scratch, scratch, scratch);
2636 __ ExtractLane(
i.OutputRegister(), scratch, NeonS16, 0);
2639 case kArmS1x8AllTrue: {
2640 const QwNeonRegister& src =
i.InputSimd128Register(0);
2641 UseScratchRegisterScope temps(tasm());
2642 DwVfpRegister scratch = temps.AcquireD();
2643 __ vpmin(NeonU16, scratch, src.low(), src.high());
2644 __ vpmin(NeonU16, scratch, scratch, scratch);
2645 __ vpmin(NeonU16, scratch, scratch, scratch);
2646 __ ExtractLane(
i.OutputRegister(), scratch, NeonS16, 0);
2649 case kArmS1x16AnyTrue: {
2650 const QwNeonRegister& src =
i.InputSimd128Register(0);
2651 UseScratchRegisterScope temps(tasm());
2652 QwNeonRegister q_scratch = temps.AcquireQ();
2653 DwVfpRegister d_scratch = q_scratch.low();
2654 __ vpmax(NeonU8, d_scratch, src.low(), src.high());
2655 __ vpmax(NeonU8, d_scratch, d_scratch, d_scratch);
2659 __ vtst(Neon32, q_scratch, q_scratch, q_scratch);
2660 __ ExtractLane(
i.OutputRegister(), d_scratch, NeonS32, 0);
2663 case kArmS1x16AllTrue: {
2664 const QwNeonRegister& src =
i.InputSimd128Register(0);
2665 UseScratchRegisterScope temps(tasm());
2666 DwVfpRegister scratch = temps.AcquireD();
2667 __ vpmin(NeonU8, scratch, src.low(), src.high());
2668 __ vpmin(NeonU8, scratch, scratch, scratch);
2669 __ vpmin(NeonU8, scratch, scratch, scratch);
2670 __ vpmin(NeonU8, scratch, scratch, scratch);
2671 __ ExtractLane(
i.OutputRegister(), scratch, NeonS8, 0);
2674 case kWord32AtomicLoadInt8:
2675 ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrsb);
2677 case kWord32AtomicLoadUint8:
2678 ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrb);
2680 case kWord32AtomicLoadInt16:
2681 ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrsh);
2683 case kWord32AtomicLoadUint16:
2684 ASSEMBLE_ATOMIC_LOAD_INTEGER(ldrh);
2686 case kWord32AtomicLoadWord32:
2687 ASSEMBLE_ATOMIC_LOAD_INTEGER(ldr);
2689 case kWord32AtomicStoreWord8:
2690 ASSEMBLE_ATOMIC_STORE_INTEGER(strb);
2692 case kWord32AtomicStoreWord16:
2693 ASSEMBLE_ATOMIC_STORE_INTEGER(strh);
2695 case kWord32AtomicStoreWord32:
2696 ASSEMBLE_ATOMIC_STORE_INTEGER(str);
2698 case kWord32AtomicExchangeInt8:
2699 ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrexb, strexb);
2700 __ sxtb(
i.OutputRegister(0),
i.OutputRegister(0));
2702 case kWord32AtomicExchangeUint8:
2703 ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrexb, strexb);
2705 case kWord32AtomicExchangeInt16:
2706 ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrexh, strexh);
2707 __ sxth(
i.OutputRegister(0),
i.OutputRegister(0));
2709 case kWord32AtomicExchangeUint16:
2710 ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrexh, strexh);
2712 case kWord32AtomicExchangeWord32:
2713 ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrex, strex);
2715 case kWord32AtomicCompareExchangeInt8:
2716 __ add(
i.TempRegister(1),
i.InputRegister(0),
i.InputRegister(1));
2717 __ uxtb(
i.TempRegister(2),
i.InputRegister(2));
2718 ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb,
2720 __ sxtb(
i.OutputRegister(0),
i.OutputRegister(0));
2722 case kWord32AtomicCompareExchangeUint8:
2723 __ add(
i.TempRegister(1),
i.InputRegister(0),
i.InputRegister(1));
2724 __ uxtb(
i.TempRegister(2),
i.InputRegister(2));
2725 ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb,
2728 case kWord32AtomicCompareExchangeInt16:
2729 __ add(
i.TempRegister(1),
i.InputRegister(0),
i.InputRegister(1));
2730 __ uxth(
i.TempRegister(2),
i.InputRegister(2));
2731 ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh,
2733 __ sxth(
i.OutputRegister(0),
i.OutputRegister(0));
2735 case kWord32AtomicCompareExchangeUint16:
2736 __ add(
i.TempRegister(1),
i.InputRegister(0),
i.InputRegister(1));
2737 __ uxth(
i.TempRegister(2),
i.InputRegister(2));
2738 ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh,
2741 case kWord32AtomicCompareExchangeWord32:
2742 __ add(
i.TempRegister(1),
i.InputRegister(0),
i.InputRegister(1));
2743 ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrex, strex,
2744 i.InputRegister(2));
2746 #define ATOMIC_BINOP_CASE(op, inst) \ 2747 case kWord32Atomic##op##Int8: \ 2748 ASSEMBLE_ATOMIC_BINOP(ldrexb, strexb, inst); \ 2749 __ sxtb(i.OutputRegister(0), i.OutputRegister(0)); \ 2751 case kWord32Atomic##op##Uint8: \ 2752 ASSEMBLE_ATOMIC_BINOP(ldrexb, strexb, inst); \ 2754 case kWord32Atomic##op##Int16: \ 2755 ASSEMBLE_ATOMIC_BINOP(ldrexh, strexh, inst); \ 2756 __ sxth(i.OutputRegister(0), i.OutputRegister(0)); \ 2758 case kWord32Atomic##op##Uint16: \ 2759 ASSEMBLE_ATOMIC_BINOP(ldrexh, strexh, inst); \ 2761 case kWord32Atomic##op##Word32: \ 2762 ASSEMBLE_ATOMIC_BINOP(ldrex, strex, inst); \ 2764 ATOMIC_BINOP_CASE(Add, add)
2765 ATOMIC_BINOP_CASE(Sub, sub)
2766 ATOMIC_BINOP_CASE(And, and_)
2767 ATOMIC_BINOP_CASE(Or, orr)
2768 ATOMIC_BINOP_CASE(Xor, eor)
2769 #undef ATOMIC_BINOP_CASE 2770 case kArmWord32AtomicPairLoad: {
2771 DCHECK(VerifyOutputOfAtomicPairInstr(&
i, instr, r0, r1));
2772 __ add(
i.TempRegister(0),
i.InputRegister(0),
i.InputRegister(1));
2773 __ ldrexd(r0, r1,
i.TempRegister(0));
2777 case kArmWord32AtomicPairStore: {
2779 __ add(
i.TempRegister(0),
i.InputRegister(0),
i.InputRegister(1));
2782 __ ldrexd(
i.TempRegister(1),
i.TempRegister(2),
i.TempRegister(0));
2783 __ strexd(
i.TempRegister(1),
i.InputRegister(2),
i.InputRegister(3),
2785 __ teq(
i.TempRegister(1), Operand(0));
2790 #define ATOMIC_ARITH_BINOP_CASE(op, instr1, instr2) \ 2791 case kArmWord32AtomicPair##op: { \ 2792 DCHECK(VerifyOutputOfAtomicPairInstr(&i, instr, r2, r3)); \ 2793 ASSEMBLE_ATOMIC64_ARITH_BINOP(instr1, instr2); \ 2796 ATOMIC_ARITH_BINOP_CASE(Add, add, adc)
2797 ATOMIC_ARITH_BINOP_CASE(Sub, sub, sbc)
2798 #undef ATOMIC_ARITH_BINOP_CASE 2799 #define ATOMIC_LOGIC_BINOP_CASE(op, instr1) \ 2800 case kArmWord32AtomicPair##op: { \ 2801 DCHECK(VerifyOutputOfAtomicPairInstr(&i, instr, r2, r3)); \ 2802 ASSEMBLE_ATOMIC64_LOGIC_BINOP(instr1); \ 2805 ATOMIC_LOGIC_BINOP_CASE(And, and_)
2806 ATOMIC_LOGIC_BINOP_CASE(Or, orr)
2807 ATOMIC_LOGIC_BINOP_CASE(Xor, eor)
2808 #undef ATOMIC_LOGIC_BINOP_CASE 2809 case kArmWord32AtomicPairExchange: {
2810 DCHECK(VerifyOutputOfAtomicPairInstr(&
i, instr, r6, r7));
2812 __ add(
i.TempRegister(0),
i.InputRegister(2),
i.InputRegister(3));
2815 __ ldrexd(r6, r7,
i.TempRegister(0));
2816 __ strexd(
i.TempRegister(1),
i.InputRegister(0),
i.InputRegister(1),
2818 __ teq(
i.TempRegister(1), Operand(0));
2819 __ b(ne, &exchange);
2823 case kArmWord32AtomicPairCompareExchange: {
2824 DCHECK(VerifyOutputOfAtomicPairInstr(&
i, instr, r2, r3));
2825 __ add(
i.TempRegister(0),
i.InputRegister(4),
i.InputRegister(5));
2826 Label compareExchange;
2829 __ bind(&compareExchange);
2830 __ ldrexd(r2, r3,
i.TempRegister(0));
2831 __ teq(
i.InputRegister(0), Operand(r2));
2833 __ teq(
i.InputRegister(1), Operand(r3));
2835 __ strexd(
i.TempRegister(1),
i.InputRegister(2),
i.InputRegister(3),
2837 __ teq(
i.TempRegister(1), Operand(0));
2838 __ b(ne, &compareExchange);
2843 #undef ASSEMBLE_ATOMIC_LOAD_INTEGER 2844 #undef ASSEMBLE_ATOMIC_STORE_INTEGER 2845 #undef ASSEMBLE_ATOMIC_EXCHANGE_INTEGER 2846 #undef ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER 2847 #undef ASSEMBLE_ATOMIC_BINOP 2848 #undef ASSEMBLE_ATOMIC64_ARITH_BINOP 2849 #undef ASSEMBLE_ATOMIC64_LOGIC_BINOP 2850 #undef ASSEMBLE_IEEE754_BINOP 2851 #undef ASSEMBLE_IEEE754_UNOP 2852 #undef ASSEMBLE_NEON_NARROWING_OP 2853 #undef ASSEMBLE_NEON_PAIRWISE_OP 2859 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
2860 ArmOperandConverter
i(
this, instr);
2861 Label* tlabel = branch->true_label;
2862 Label* flabel = branch->false_label;
2863 Condition cc = FlagsConditionToCondition(branch->condition);
2865 if (!branch->fallthru) __ b(flabel);
2868 void CodeGenerator::AssembleBranchPoisoning(FlagsCondition condition,
2869 Instruction* instr) {
2871 if (condition == kUnorderedEqual || condition == kUnorderedNotEqual) {
2875 condition = NegateFlagsCondition(condition);
2876 __ eor(kSpeculationPoisonRegister, kSpeculationPoisonRegister,
2877 Operand(kSpeculationPoisonRegister), SBit::LeaveCC,
2878 FlagsConditionToCondition(condition));
2882 void CodeGenerator::AssembleArchDeoptBranch(Instruction* instr,
2883 BranchInfo* branch) {
2884 AssembleArchBranch(instr, branch);
2887 void CodeGenerator::AssembleArchJump(RpoNumber target) {
2888 if (!IsNextInAssemblyOrder(target)) __ b(GetLabel(target));
2891 void CodeGenerator::AssembleArchTrap(Instruction* instr,
2892 FlagsCondition condition) {
2893 class OutOfLineTrap final :
public OutOfLineCode {
2895 OutOfLineTrap(CodeGenerator* gen, Instruction* instr)
2896 : OutOfLineCode(gen), instr_(instr), gen_(gen) {}
2898 void Generate() final {
2899 ArmOperandConverter
i(gen_, instr_);
2901 static_cast<TrapId
>(
i.InputInt32(instr_->InputCount() - 1));
2902 GenerateCallToTrap(trap_id);
2906 void GenerateCallToTrap(TrapId trap_id) {
2907 if (trap_id == TrapId::kInvalid) {
2912 __ PrepareCallCFunction(0, 0);
2914 ExternalReference::wasm_call_trap_callback_for_testing(), 0);
2915 __ LeaveFrame(StackFrame::WASM_COMPILED);
2916 auto call_descriptor = gen_->linkage()->GetIncomingDescriptor();
2918 static_cast<int>(call_descriptor->StackParameterCount());
2922 gen_->AssembleSourcePosition(instr_);
2926 __ Call(static_cast<Address>(trap_id), RelocInfo::WASM_STUB_CALL);
2927 ReferenceMap* reference_map =
2928 new (gen_->zone()) ReferenceMap(gen_->zone());
2929 gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
2930 Safepoint::kNoLazyDeopt);
2931 if (FLAG_debug_code) {
2932 __ stop(GetAbortReason(AbortReason::kUnexpectedReturnFromWasmTrap));
2937 Instruction* instr_;
2938 CodeGenerator* gen_;
2940 auto ool =
new (zone()) OutOfLineTrap(
this, instr);
2941 Label* tlabel = ool->entry();
2942 Condition cc = FlagsConditionToCondition(condition);
2947 void CodeGenerator::AssembleArchBoolean(Instruction* instr,
2948 FlagsCondition condition) {
2949 ArmOperandConverter
i(
this, instr);
2953 DCHECK_NE(0u, instr->OutputCount());
2954 Register reg =
i.OutputRegister(instr->OutputCount() - 1);
2955 Condition cc = FlagsConditionToCondition(condition);
2956 __ mov(reg, Operand(0));
2957 __ mov(reg, Operand(1), LeaveCC, cc);
2960 void CodeGenerator::AssembleArchBinarySearchSwitch(Instruction* instr) {
2961 ArmOperandConverter
i(
this, instr);
2962 Register input =
i.InputRegister(0);
2963 std::vector<std::pair<int32_t, Label*>> cases;
2964 for (
size_t index = 2; index < instr->InputCount(); index += 2) {
2965 cases.push_back({
i.InputInt32(index + 0), GetLabel(
i.InputRpo(index + 1))});
2967 AssembleArchBinarySearchSwitchRange(input,
i.InputRpo(1), cases.data(),
2968 cases.data() + cases.size());
2971 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) {
2972 ArmOperandConverter
i(
this, instr);
2973 Register input =
i.InputRegister(0);
2974 for (
size_t index = 2; index < instr->InputCount(); index += 2) {
2975 __ cmp(input, Operand(
i.InputInt32(index + 0)));
2976 __ b(eq, GetLabel(
i.InputRpo(index + 1)));
2978 AssembleArchJump(
i.InputRpo(1));
2981 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) {
2982 ArmOperandConverter
i(
this, instr);
2983 Register input =
i.InputRegister(0);
2984 size_t const case_count = instr->InputCount() - 2;
2986 __ CheckConstPool(
true,
true);
2987 __ cmp(input, Operand(case_count));
2988 __ BlockConstPoolFor(case_count + 2);
2989 __ add(pc, pc, Operand(input, LSL, 2), LeaveCC, lo);
2990 __ b(GetLabel(
i.InputRpo(1)));
2991 for (
size_t index = 0; index < case_count; ++index) {
2992 __ b(GetLabel(
i.InputRpo(index + 2)));
2996 void CodeGenerator::FinishFrame(Frame* frame) {
2997 auto call_descriptor = linkage()->GetIncomingDescriptor();
2999 const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
3000 if (saves_fp != 0) {
3001 frame->AlignSavedCalleeRegisterSlots();
3004 if (saves_fp != 0) {
3006 STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
3007 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
3008 uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
3009 DCHECK_EQ((last - first + 1), base::bits::CountPopulation(saves_fp));
3010 frame->AllocateSavedCalleeRegisterSlots((last - first + 1) *
3011 (kDoubleSize / kPointerSize));
3013 const RegList saves = call_descriptor->CalleeSavedRegisters();
3016 frame->AllocateSavedCalleeRegisterSlots(base::bits::CountPopulation(saves));
3020 void CodeGenerator::AssembleConstructFrame() {
3021 auto call_descriptor = linkage()->GetIncomingDescriptor();
3022 if (frame_access_state()->has_frame()) {
3023 if (call_descriptor->IsCFunctionCall()) {
3026 }
else if (call_descriptor->IsJSFunctionCall()) {
3028 if (call_descriptor->PushArgumentCount()) {
3029 __ Push(kJavaScriptCallArgCountRegister);
3032 __ StubPrologue(info()->GetOutputStackFrameType());
3033 if (call_descriptor->IsWasmFunctionCall()) {
3034 __ Push(kWasmInstanceRegister);
3035 }
else if (call_descriptor->IsWasmImportWrapper()) {
3040 __ ldr(kJSFunctionRegister,
3041 FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue2Offset));
3042 __ ldr(kWasmInstanceRegister,
3043 FieldMemOperand(kWasmInstanceRegister, Tuple2::kValue1Offset));
3044 __ Push(kWasmInstanceRegister);
3048 unwinding_info_writer_.MarkFrameConstructed(__ pc_offset());
3051 int shrink_slots = frame()->GetTotalFrameSlotCount() -
3052 call_descriptor->CalculateFixedFrameSize();
3054 if (info()->is_osr()) {
3056 __ Abort(AbortReason::kShouldNotDirectlyEnterOsrFunction);
3062 if (FLAG_code_comments) __ RecordComment(
"-- OSR entrypoint --");
3063 osr_pc_offset_ = __ pc_offset();
3064 shrink_slots -= osr_helper()->UnoptimizedFrameSlots();
3065 ResetSpeculationPoison();
3068 const RegList saves = call_descriptor->CalleeSavedRegisters();
3069 const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
3071 if (shrink_slots > 0) {
3072 DCHECK(frame_access_state()->has_frame());
3073 if (info()->IsWasm() && shrink_slots > 128) {
3083 if ((shrink_slots * kPointerSize) < (FLAG_stack_size * 1024)) {
3084 UseScratchRegisterScope temps(tasm());
3085 Register scratch = temps.Acquire();
3086 __ ldr(scratch, FieldMemOperand(
3087 kWasmInstanceRegister,
3088 WasmInstanceObject::kRealStackLimitAddressOffset));
3089 __ ldr(scratch, MemOperand(scratch));
3090 __ add(scratch, scratch, Operand(shrink_slots * kPointerSize));
3091 __ cmp(sp, scratch);
3095 __ ldr(r2, FieldMemOperand(kWasmInstanceRegister,
3096 WasmInstanceObject::kCEntryStubOffset));
3097 __ Move(cp, Smi::zero());
3098 __ CallRuntimeWithCEntry(Runtime::kThrowWasmStackOverflow, r2);
3100 ReferenceMap* reference_map =
new (zone()) ReferenceMap(zone());
3101 RecordSafepoint(reference_map, Safepoint::kSimple, 0,
3102 Safepoint::kNoLazyDeopt);
3103 if (FLAG_debug_code) {
3104 __ stop(GetAbortReason(AbortReason::kUnexpectedReturnFromThrow));
3111 shrink_slots -= base::bits::CountPopulation(saves);
3112 shrink_slots -= frame()->GetReturnSlotCount();
3113 shrink_slots -= 2 * base::bits::CountPopulation(saves_fp);
3114 if (shrink_slots > 0) {
3115 __ sub(sp, sp, Operand(shrink_slots * kPointerSize));
3119 if (saves_fp != 0) {
3121 STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
3122 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
3123 uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
3124 DCHECK_EQ((last - first + 1), base::bits::CountPopulation(saves_fp));
3125 __ vstm(db_w, sp, DwVfpRegister::from_code(first),
3126 DwVfpRegister::from_code(last));
3131 __ stm(db_w, sp, saves);
3134 const int returns = frame()->GetReturnSlotCount();
3137 __ sub(sp, sp, Operand(returns * kPointerSize));
3141 void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
3142 auto call_descriptor = linkage()->GetIncomingDescriptor();
3143 int pop_count =
static_cast<int>(call_descriptor->StackParameterCount());
3145 const int returns = frame()->GetReturnSlotCount();
3148 __ add(sp, sp, Operand(returns * kPointerSize));
3152 const RegList saves = call_descriptor->CalleeSavedRegisters();
3154 __ ldm(ia_w, sp, saves);
3158 const RegList saves_fp = call_descriptor->CalleeSavedFPRegisters();
3159 if (saves_fp != 0) {
3160 STATIC_ASSERT(DwVfpRegister::kNumRegisters == 32);
3161 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1;
3162 uint32_t first = base::bits::CountTrailingZeros32(saves_fp);
3163 __ vldm(ia_w, sp, DwVfpRegister::from_code(first),
3164 DwVfpRegister::from_code(last));
3167 unwinding_info_writer_.MarkBlockWillExit();
3169 ArmOperandConverter g(
this,
nullptr);
3170 if (call_descriptor->IsCFunctionCall()) {
3171 AssembleDeconstructFrame();
3172 }
else if (frame_access_state()->has_frame()) {
3175 if (pop->IsImmediate() && g.ToConstant(pop).ToInt32() == 0) {
3176 if (return_label_.is_bound()) {
3177 __ b(&return_label_);
3180 __ bind(&return_label_);
3181 AssembleDeconstructFrame();
3184 AssembleDeconstructFrame();
3188 if (pop->IsImmediate()) {
3189 DCHECK_EQ(Constant::kInt32, g.ToConstant(pop).type());
3190 pop_count += g.ToConstant(pop).ToInt32();
3192 __ Drop(g.ToRegister(pop));
3198 void CodeGenerator::FinishCode() { __ CheckConstPool(
true,
false); }
3200 void CodeGenerator::AssembleMove(InstructionOperand* source,
3201 InstructionOperand* destination) {
3202 ArmOperandConverter g(
this,
nullptr);
3204 auto MoveConstantToRegister = [&](Register dst, Constant src) {
3205 if (src.type() == Constant::kHeapObject) {
3206 Handle<HeapObject> src_object = src.ToHeapObject();
3208 if (IsMaterializableFromRoot(src_object, &index)) {
3209 __ LoadRoot(dst, index);
3211 __ Move(dst, src_object);
3213 }
else if (src.type() == Constant::kExternalReference) {
3214 __ Move(dst, src.ToExternalReference());
3216 __ mov(dst, g.ToImmediate(source));
3219 switch (MoveType::InferMove(source, destination)) {
3220 case MoveType::kRegisterToRegister:
3221 if (source->IsRegister()) {
3222 __ mov(g.ToRegister(destination), g.ToRegister(source));
3223 }
else if (source->IsFloatRegister()) {
3224 DCHECK(destination->IsFloatRegister());
3227 int src_code = LocationOperand::cast(source)->register_code();
3228 int dst_code = LocationOperand::cast(destination)->register_code();
3229 __ VmovExtended(dst_code, src_code);
3230 }
else if (source->IsDoubleRegister()) {
3231 __ Move(g.ToDoubleRegister(destination), g.ToDoubleRegister(source));
3233 __ Move(g.ToSimd128Register(destination), g.ToSimd128Register(source));
3236 case MoveType::kRegisterToStack: {
3237 MemOperand dst = g.ToMemOperand(destination);
3238 if (source->IsRegister()) {
3239 __ str(g.ToRegister(source), dst);
3240 }
else if (source->IsFloatRegister()) {
3243 int src_code = LocationOperand::cast(source)->register_code();
3244 __ VmovExtended(dst, src_code);
3245 }
else if (source->IsDoubleRegister()) {
3246 __ vstr(g.ToDoubleRegister(source), dst);
3248 UseScratchRegisterScope temps(tasm());
3249 Register temp = temps.Acquire();
3250 QwNeonRegister src = g.ToSimd128Register(source);
3251 __ add(temp, dst.rn(), Operand(dst.offset()));
3252 __ vst1(Neon8, NeonListOperand(src.low(), 2), NeonMemOperand(temp));
3256 case MoveType::kStackToRegister: {
3257 MemOperand src = g.ToMemOperand(source);
3258 if (source->IsStackSlot()) {
3259 __ ldr(g.ToRegister(destination), src);
3260 }
else if (source->IsFloatStackSlot()) {
3261 DCHECK(destination->IsFloatRegister());
3264 int dst_code = LocationOperand::cast(destination)->register_code();
3265 __ VmovExtended(dst_code, src);
3266 }
else if (source->IsDoubleStackSlot()) {
3267 __ vldr(g.ToDoubleRegister(destination), src);
3269 UseScratchRegisterScope temps(tasm());
3270 Register temp = temps.Acquire();
3271 QwNeonRegister dst = g.ToSimd128Register(destination);
3272 __ add(temp, src.rn(), Operand(src.offset()));
3273 __ vld1(Neon8, NeonListOperand(dst.low(), 2), NeonMemOperand(temp));
3277 case MoveType::kStackToStack: {
3278 MemOperand src = g.ToMemOperand(source);
3279 MemOperand dst = g.ToMemOperand(destination);
3280 UseScratchRegisterScope temps(tasm());
3281 if (source->IsStackSlot() || source->IsFloatStackSlot()) {
3282 SwVfpRegister temp = temps.AcquireS();
3285 }
else if (source->IsDoubleStackSlot()) {
3286 DwVfpRegister temp = temps.AcquireD();
3290 DCHECK(source->IsSimd128StackSlot());
3291 Register temp = temps.Acquire();
3292 QwNeonRegister temp_q = temps.AcquireQ();
3293 __ add(temp, src.rn(), Operand(src.offset()));
3294 __ vld1(Neon8, NeonListOperand(temp_q.low(), 2), NeonMemOperand(temp));
3295 __ add(temp, dst.rn(), Operand(dst.offset()));
3296 __ vst1(Neon8, NeonListOperand(temp_q.low(), 2), NeonMemOperand(temp));
3300 case MoveType::kConstantToRegister: {
3301 Constant src = g.ToConstant(source);
3302 if (destination->IsRegister()) {
3303 MoveConstantToRegister(g.ToRegister(destination), src);
3304 }
else if (destination->IsFloatRegister()) {
3305 __ vmov(g.ToFloatRegister(destination),
3306 Float32::FromBits(src.ToFloat32AsInt()));
3310 __ vmov(g.ToDoubleRegister(destination), src.ToFloat64());
3314 case MoveType::kConstantToStack: {
3315 Constant src = g.ToConstant(source);
3316 MemOperand dst = g.ToMemOperand(destination);
3317 if (destination->IsStackSlot()) {
3318 UseScratchRegisterScope temps(tasm());
3321 SwVfpRegister s_temp = temps.AcquireS();
3325 UseScratchRegisterScope temps(tasm());
3326 Register temp = temps.Acquire();
3327 MoveConstantToRegister(temp, src);
3328 __ vmov(s_temp, temp);
3330 __ vstr(s_temp, dst);
3331 }
else if (destination->IsFloatStackSlot()) {
3332 UseScratchRegisterScope temps(tasm());
3333 SwVfpRegister temp = temps.AcquireS();
3334 __ vmov(temp, Float32::FromBits(src.ToFloat32AsInt()));
3337 DCHECK(destination->IsDoubleStackSlot());
3338 UseScratchRegisterScope temps(tasm());
3339 DwVfpRegister temp = temps.AcquireD();
3342 __ vmov(temp, src.ToFloat64());
3343 __ vstr(temp, g.ToMemOperand(destination));
3351 void CodeGenerator::AssembleSwap(InstructionOperand* source,
3352 InstructionOperand* destination) {
3353 ArmOperandConverter g(
this,
nullptr);
3354 switch (MoveType::InferSwap(source, destination)) {
3355 case MoveType::kRegisterToRegister:
3356 if (source->IsRegister()) {
3357 __ Swap(g.ToRegister(source), g.ToRegister(destination));
3358 }
else if (source->IsFloatRegister()) {
3359 DCHECK(destination->IsFloatRegister());
3362 UseScratchRegisterScope temps(tasm());
3363 LowDwVfpRegister temp = temps.AcquireLowD();
3364 int src_code = LocationOperand::cast(source)->register_code();
3365 int dst_code = LocationOperand::cast(destination)->register_code();
3366 __ VmovExtended(temp.low().code(), src_code);
3367 __ VmovExtended(src_code, dst_code);
3368 __ VmovExtended(dst_code, temp.low().code());
3369 }
else if (source->IsDoubleRegister()) {
3370 __ Swap(g.ToDoubleRegister(source), g.ToDoubleRegister(destination));
3372 __ Swap(g.ToSimd128Register(source), g.ToSimd128Register(destination));
3375 case MoveType::kRegisterToStack: {
3376 MemOperand dst = g.ToMemOperand(destination);
3377 if (source->IsRegister()) {
3378 Register src = g.ToRegister(source);
3379 UseScratchRegisterScope temps(tasm());
3380 SwVfpRegister temp = temps.AcquireS();
3384 }
else if (source->IsFloatRegister()) {
3385 int src_code = LocationOperand::cast(source)->register_code();
3386 UseScratchRegisterScope temps(tasm());
3387 LowDwVfpRegister temp = temps.AcquireLowD();
3388 __ VmovExtended(temp.low().code(), src_code);
3389 __ VmovExtended(src_code, dst);
3390 __ vstr(temp.low(), dst);
3391 }
else if (source->IsDoubleRegister()) {
3392 UseScratchRegisterScope temps(tasm());
3393 DwVfpRegister temp = temps.AcquireD();
3394 DwVfpRegister src = g.ToDoubleRegister(source);
3399 QwNeonRegister src = g.ToSimd128Register(source);
3400 UseScratchRegisterScope temps(tasm());
3401 Register temp = temps.Acquire();
3402 QwNeonRegister temp_q = temps.AcquireQ();
3403 __ Move(temp_q, src);
3404 __ add(temp, dst.rn(), Operand(dst.offset()));
3405 __ vld1(Neon8, NeonListOperand(src.low(), 2), NeonMemOperand(temp));
3406 __ vst1(Neon8, NeonListOperand(temp_q.low(), 2), NeonMemOperand(temp));
3410 case MoveType::kStackToStack: {
3411 MemOperand src = g.ToMemOperand(source);
3412 MemOperand dst = g.ToMemOperand(destination);
3413 if (source->IsStackSlot() || source->IsFloatStackSlot()) {
3414 UseScratchRegisterScope temps(tasm());
3415 SwVfpRegister temp_0 = temps.AcquireS();
3416 SwVfpRegister temp_1 = temps.AcquireS();
3417 __ vldr(temp_0, dst);
3418 __ vldr(temp_1, src);
3419 __ vstr(temp_0, src);
3420 __ vstr(temp_1, dst);
3421 }
else if (source->IsDoubleStackSlot()) {
3422 UseScratchRegisterScope temps(tasm());
3423 LowDwVfpRegister temp = temps.AcquireLowD();
3424 if (temps.CanAcquireD()) {
3425 DwVfpRegister temp_0 = temp;
3426 DwVfpRegister temp_1 = temps.AcquireD();
3427 __ vldr(temp_0, dst);
3428 __ vldr(temp_1, src);
3429 __ vstr(temp_0, src);
3430 __ vstr(temp_1, dst);
3434 MemOperand src0 = src;
3435 MemOperand dst0 = dst;
3436 MemOperand src1(src.rn(), src.offset() + kFloatSize);
3437 MemOperand dst1(dst.rn(), dst.offset() + kFloatSize);
3438 SwVfpRegister temp_0 = temp.low();
3439 SwVfpRegister temp_1 = temp.high();
3440 __ vldr(temp_0, dst0);
3441 __ vldr(temp_1, src0);
3442 __ vstr(temp_0, src0);
3443 __ vstr(temp_1, dst0);
3444 __ vldr(temp_0, dst1);
3445 __ vldr(temp_1, src1);
3446 __ vstr(temp_0, src1);
3447 __ vstr(temp_1, dst1);
3450 DCHECK(source->IsSimd128StackSlot());
3451 MemOperand src0 = src;
3452 MemOperand dst0 = dst;
3453 MemOperand src1(src.rn(), src.offset() + kDoubleSize);
3454 MemOperand dst1(dst.rn(), dst.offset() + kDoubleSize);
3455 UseScratchRegisterScope temps(tasm());
3456 DwVfpRegister temp_0 = temps.AcquireD();
3457 DwVfpRegister temp_1 = temps.AcquireD();
3458 __ vldr(temp_0, dst0);
3459 __ vldr(temp_1, src0);
3460 __ vstr(temp_0, src0);
3461 __ vstr(temp_1, dst0);
3462 __ vldr(temp_0, dst1);
3463 __ vldr(temp_1, src1);
3464 __ vstr(temp_0, src1);
3465 __ vstr(temp_1, dst1);
3475 void CodeGenerator::AssembleJumpTable(Label** targets,
size_t target_count) {