5 #ifndef INCLUDED_FROM_MACRO_ASSEMBLER_H 6 #error This header must be included via macro-assembler.h 9 #ifndef V8_IA32_MACRO_ASSEMBLER_IA32_H_ 10 #define V8_IA32_MACRO_ASSEMBLER_IA32_H_ 12 #include "src/assembler.h" 13 #include "src/bailout-reason.h" 14 #include "src/globals.h" 15 #include "src/ia32/assembler-ia32.h" 21 constexpr Register kReturnRegister0 = eax;
22 constexpr Register kReturnRegister1 = edx;
23 constexpr Register kReturnRegister2 = edi;
24 constexpr Register kJSFunctionRegister = edi;
25 constexpr Register kContextRegister = esi;
26 constexpr Register kAllocateSizeRegister = edx;
27 constexpr Register kInterpreterAccumulatorRegister = eax;
28 constexpr Register kInterpreterBytecodeOffsetRegister = edx;
29 constexpr Register kInterpreterBytecodeArrayRegister = edi;
30 constexpr Register kInterpreterDispatchTableRegister = esi;
32 constexpr Register kJavaScriptCallArgCountRegister = eax;
33 constexpr Register kJavaScriptCallCodeStartRegister = ecx;
34 constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
35 constexpr Register kJavaScriptCallNewTargetRegister = edx;
40 constexpr Register kJavaScriptCallExtraArg1Register = ecx;
44 constexpr Register kOffHeapTrampolineRegister = no_reg;
46 constexpr Register kRuntimeCallFunctionRegister = edx;
47 constexpr Register kRuntimeCallArgCountRegister = eax;
48 constexpr Register kRuntimeCallArgvRegister = ecx;
49 constexpr Register kWasmInstanceRegister = esi;
50 constexpr Register kWasmCompileLazyFuncIndexRegister = edi;
52 constexpr Register kRootRegister = ebx;
55 constexpr Register kSpeculationPoisonRegister = no_reg;
59 typedef Operand MemOperand;
61 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
62 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
64 class V8_EXPORT_PRIVATE TurboAssembler :
public TurboAssemblerBase {
66 TurboAssembler(
const AssemblerOptions& options,
void* buffer,
int buffer_size)
67 : TurboAssemblerBase(options, buffer, buffer_size) {}
69 TurboAssembler(Isolate* isolate,
const AssemblerOptions& options,
70 void* buffer,
int buffer_size,
71 CodeObjectRequired create_code_object)
72 : TurboAssemblerBase(isolate, options, buffer, buffer_size,
73 create_code_object) {}
75 void CheckPageFlag(Register
object, Register scratch,
int mask, Condition cc,
77 Label::Distance condition_met_distance = Label::kFar);
80 void EnterFrame(StackFrame::Type type);
81 void EnterFrame(StackFrame::Type type,
bool load_constant_pool_pointer_reg) {
85 void LeaveFrame(StackFrame::Type type);
95 void AllocateStackFrame(Register bytes_scratch);
97 void AllocateStackFrame(Register bytes) { sub(esp, bytes); }
101 void Abort(AbortReason reason);
105 void Assert(Condition cc, AbortReason reason);
109 void AssertUnreachable(AbortReason reason);
112 void Check(Condition cc, AbortReason reason);
115 void CheckStackAlignment();
118 void Move(Register dst,
const Immediate& src);
119 void Move(Register dst, Smi src) { Move(dst, Immediate(src)); }
120 void Move(Register dst, Handle<HeapObject> src);
121 void Move(Register dst, Register src);
122 void Move(Operand dst,
const Immediate& src);
125 void Move(XMMRegister dst,
uint32_t src);
126 void Move(XMMRegister dst, uint64_t src);
127 void Move(XMMRegister dst,
float src) { Move(dst, bit_cast<uint32_t>(src)); }
128 void Move(XMMRegister dst,
double src) { Move(dst, bit_cast<uint64_t>(src)); }
130 void Call(Register reg) { call(reg); }
131 void Call(Label* target) { call(target); }
132 void Call(Handle<Code> code_object, RelocInfo::Mode rmode);
134 void Jump(Handle<Code> code_object, RelocInfo::Mode rmode);
136 void RetpolineCall(Register reg);
137 void RetpolineCall(Address destination, RelocInfo::Mode rmode);
139 void RetpolineJump(Register reg);
141 void CallForDeoptimization(Address target,
int deopt_id,
142 RelocInfo::Mode rmode) {
147 inline bool AllowThisStubCall(CodeStub* stub);
151 void CallRuntimeWithCEntry(Runtime::FunctionId fid, Register centry);
154 inline void JumpIfSmi(Register value, Label* smi_label,
155 Label::Distance distance = Label::kFar) {
156 test(value, Immediate(kSmiTagMask));
157 j(zero, smi_label, distance);
160 inline void JumpIfSmi(Operand value, Label* smi_label,
161 Label::Distance distance = Label::kFar) {
162 test(value, Immediate(kSmiTagMask));
163 j(zero, smi_label, distance);
166 void JumpIfEqual(Register a, int32_t b, Label* dest) {
167 cmp(a, Immediate(b));
171 void JumpIfLessThan(Register a, int32_t b, Label* dest) {
172 cmp(a, Immediate(b));
176 void SmiUntag(Register reg) { sar(reg, kSmiTagSize); }
186 void PrepareForTailCall(
const ParameterCount& callee_args_count,
187 Register caller_args_count_reg, Register scratch0,
189 int number_of_temp_values_after_return_address);
198 void PrepareCallCFunction(
int num_arguments, Register scratch);
205 void CallCFunction(ExternalReference
function,
int num_arguments);
206 void CallCFunction(Register
function,
int num_arguments);
208 void ShlPair(Register high, Register low, uint8_t imm8);
209 void ShlPair_cl(Register high, Register low);
210 void ShrPair(Register high, Register low, uint8_t imm8);
211 void ShrPair_cl(Register high, Register low);
212 void SarPair(Register high, Register low, uint8_t imm8);
213 void SarPair_cl(Register high, Register low);
216 void StubPrologue(StackFrame::Type type);
219 void Lzcnt(Register dst, Register src) { Lzcnt(dst, Operand(src)); }
220 void Lzcnt(Register dst, Operand src);
222 void Tzcnt(Register dst, Register src) { Tzcnt(dst, Operand(src)); }
223 void Tzcnt(Register dst, Operand src);
225 void Popcnt(Register dst, Register src) { Popcnt(dst, Operand(src)); }
226 void Popcnt(Register dst, Operand src);
232 void InitializeRootRegister();
234 void LoadRoot(Register destination, RootIndex index)
override;
237 void LoadFromConstantsTable(Register destination,
238 int constant_index)
override;
239 void LoadRootRegisterOffset(Register destination, intptr_t offset)
override;
240 void LoadRootRelative(Register destination, int32_t offset)
override;
248 Operand ExternalReferenceAsOperand(ExternalReference reference,
250 Operand ExternalReferenceAddressAsOperand(ExternalReference reference);
251 Operand HeapObjectAsOperand(Handle<HeapObject>
object);
253 void LoadAddress(Register destination, ExternalReference source);
255 void CompareStackLimit(Register with);
256 void CompareRealStackLimit(Register with);
257 void CompareRoot(Register with, RootIndex index);
258 void CompareRoot(Register with, Register scratch, RootIndex index);
262 void Ret(
int bytes_dropped, Register scratch);
264 void Pshufhw(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
265 Pshufhw(dst, Operand(src), shuffle);
267 void Pshufhw(XMMRegister dst, Operand src, uint8_t shuffle);
268 void Pshuflw(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
269 Pshuflw(dst, Operand(src), shuffle);
271 void Pshuflw(XMMRegister dst, Operand src, uint8_t shuffle);
272 void Pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle) {
273 Pshufd(dst, Operand(src), shuffle);
275 void Pshufd(XMMRegister dst, Operand src, uint8_t shuffle);
276 void Psraw(XMMRegister dst, uint8_t shift);
277 void Psrlw(XMMRegister dst, uint8_t shift);
280 #define AVX_OP2_WITH_TYPE(macro_name, name, dst_type, src_type) \ 281 void macro_name(dst_type dst, src_type src) { \ 282 if (CpuFeatures::IsSupported(AVX)) { \ 283 CpuFeatureScope scope(this, AVX); \ 290 AVX_OP2_WITH_TYPE(Rcpps, rcpps, XMMRegister,
const Operand&)
291 AVX_OP2_WITH_TYPE(Rsqrtps, rsqrtps, XMMRegister,
const Operand&)
292 AVX_OP2_WITH_TYPE(Movdqu, movdqu, XMMRegister, Operand)
293 AVX_OP2_WITH_TYPE(Movdqu, movdqu, Operand, XMMRegister)
294 AVX_OP2_WITH_TYPE(Movd, movd, XMMRegister, Register)
295 AVX_OP2_WITH_TYPE(Movd, movd, XMMRegister, Operand)
296 AVX_OP2_WITH_TYPE(Movd, movd, Register, XMMRegister)
297 AVX_OP2_WITH_TYPE(Movd, movd, Operand, XMMRegister)
298 AVX_OP2_WITH_TYPE(Cvtdq2ps, cvtdq2ps, XMMRegister, Operand)
300 #undef AVX_OP2_WITH_TYPE 304 #define AVX_OP3_WITH_TYPE(macro_name, name, dst_type, src_type) \ 305 void macro_name(dst_type dst, src_type src) { \ 306 if (CpuFeatures::IsSupported(AVX)) { \ 307 CpuFeatureScope scope(this, AVX); \ 308 v##name(dst, dst, src); \ 313 #define AVX_OP3_XO(macro_name, name) \ 314 AVX_OP3_WITH_TYPE(macro_name, name, XMMRegister, XMMRegister) \ 315 AVX_OP3_WITH_TYPE(macro_name, name, XMMRegister, Operand) 317 AVX_OP3_XO(Packsswb, packsswb)
318 AVX_OP3_XO(Packuswb, packuswb)
319 AVX_OP3_XO(Pcmpeqb, pcmpeqb)
320 AVX_OP3_XO(Pcmpeqw, pcmpeqw)
321 AVX_OP3_XO(Pcmpeqd, pcmpeqd)
322 AVX_OP3_XO(Psubb, psubb)
323 AVX_OP3_XO(Psubw, psubw)
324 AVX_OP3_XO(Psubd, psubd)
325 AVX_OP3_XO(Punpcklbw, punpcklbw)
326 AVX_OP3_XO(Punpckhbw, punpckhbw)
327 AVX_OP3_XO(Pxor, pxor)
328 AVX_OP3_XO(Andps, andps)
329 AVX_OP3_XO(Andpd, andpd)
330 AVX_OP3_XO(Xorps, xorps)
331 AVX_OP3_XO(Xorpd, xorpd)
332 AVX_OP3_XO(Sqrtss, sqrtss)
333 AVX_OP3_XO(Sqrtsd, sqrtsd)
336 #undef AVX_OP3_WITH_TYPE 339 #define AVX_OP2_WITH_TYPE_SCOPE(macro_name, name, dst_type, src_type, \ 341 void macro_name(dst_type dst, src_type src) { \ 342 if (CpuFeatures::IsSupported(AVX)) { \ 343 CpuFeatureScope scope(this, AVX); \ 347 if (CpuFeatures::IsSupported(sse_scope)) { \ 348 CpuFeatureScope scope(this, sse_scope); \ 354 #define AVX_OP2_XO_SSE4(macro_name, name) \ 355 AVX_OP2_WITH_TYPE_SCOPE(macro_name, name, XMMRegister, XMMRegister, SSE4_1) \ 356 AVX_OP2_WITH_TYPE_SCOPE(macro_name, name, XMMRegister, Operand, SSE4_1) 358 AVX_OP2_XO_SSE4(Ptest, ptest)
359 AVX_OP2_XO_SSE4(Pmovsxbw, pmovsxbw)
360 AVX_OP2_XO_SSE4(Pmovsxwd, pmovsxwd)
361 AVX_OP2_XO_SSE4(Pmovzxbw, pmovzxbw)
362 AVX_OP2_XO_SSE4(Pmovzxwd, pmovzxwd)
364 #undef AVX_OP2_WITH_TYPE_SCOPE 365 #undef AVX_OP2_XO_SSE4 367 void Pshufb(XMMRegister dst, XMMRegister src) { Pshufb(dst, Operand(src)); }
368 void Pshufb(XMMRegister dst, Operand src);
369 void Pblendw(XMMRegister dst, XMMRegister src, uint8_t imm8) {
370 Pblendw(dst, Operand(src), imm8);
372 void Pblendw(XMMRegister dst, Operand src, uint8_t imm8);
374 void Psignb(XMMRegister dst, XMMRegister src) { Psignb(dst, Operand(src)); }
375 void Psignb(XMMRegister dst, Operand src);
376 void Psignw(XMMRegister dst, XMMRegister src) { Psignw(dst, Operand(src)); }
377 void Psignw(XMMRegister dst, Operand src);
378 void Psignd(XMMRegister dst, XMMRegister src) { Psignd(dst, Operand(src)); }
379 void Psignd(XMMRegister dst, Operand src);
381 void Palignr(XMMRegister dst, XMMRegister src, uint8_t imm8) {
382 Palignr(dst, Operand(src), imm8);
384 void Palignr(XMMRegister dst, Operand src, uint8_t imm8);
386 void Pextrb(Register dst, XMMRegister src, uint8_t imm8);
387 void Pextrw(Register dst, XMMRegister src, uint8_t imm8);
388 void Pextrd(Register dst, XMMRegister src, uint8_t imm8);
389 void Pinsrd(XMMRegister dst, Register src, uint8_t imm8) {
390 Pinsrd(dst, Operand(src), imm8);
392 void Pinsrd(XMMRegister dst, Operand src, uint8_t imm8);
398 void Cvtsi2ss(XMMRegister dst, Register src) { Cvtsi2ss(dst, Operand(src)); }
399 void Cvtsi2ss(XMMRegister dst, Operand src);
400 void Cvtsi2sd(XMMRegister dst, Register src) { Cvtsi2sd(dst, Operand(src)); }
401 void Cvtsi2sd(XMMRegister dst, Operand src);
403 void Cvtui2ss(XMMRegister dst, Register src, Register tmp) {
404 Cvtui2ss(dst, Operand(src), tmp);
406 void Cvtui2ss(XMMRegister dst, Operand src, Register tmp);
407 void Cvttss2ui(Register dst, XMMRegister src, XMMRegister tmp) {
408 Cvttss2ui(dst, Operand(src), tmp);
410 void Cvttss2ui(Register dst, Operand src, XMMRegister tmp);
411 void Cvtui2sd(XMMRegister dst, Register src, Register scratch) {
412 Cvtui2sd(dst, Operand(src), scratch);
414 void Cvtui2sd(XMMRegister dst, Operand src, Register scratch);
415 void Cvttsd2ui(Register dst, XMMRegister src, XMMRegister tmp) {
416 Cvttsd2ui(dst, Operand(src), tmp);
418 void Cvttsd2ui(Register dst, Operand src, XMMRegister tmp);
420 void Push(Register src) { push(src); }
421 void Push(Operand src) { push(src); }
422 void Push(Immediate value);
423 void Push(Handle<HeapObject> handle) { push(Immediate(handle)); }
424 void Push(Smi smi) { Push(Immediate(smi)); }
426 void SaveRegisters(RegList registers);
427 void RestoreRegisters(RegList registers);
429 void CallRecordWriteStub(Register
object, Register address,
430 RememberedSetAction remembered_set_action,
431 SaveFPRegsMode fp_mode);
432 void CallRecordWriteStub(Register
object, Register address,
433 RememberedSetAction remembered_set_action,
434 SaveFPRegsMode fp_mode, Address wasm_target);
438 int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
439 Register exclusion1 = no_reg,
440 Register exclusion2 = no_reg,
441 Register exclusion3 = no_reg)
const;
450 int PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
451 Register exclusion2 = no_reg,
452 Register exclusion3 = no_reg);
455 int PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg,
456 Register exclusion2 = no_reg,
457 Register exclusion3 = no_reg);
461 void ComputeCodeStartAddress(Register dst);
464 void ResetSpeculationPoisonRegister() { UNREACHABLE(); }
466 void CallRecordWriteStub(Register
object, Register address,
467 RememberedSetAction remembered_set_action,
468 SaveFPRegsMode fp_mode, Handle<Code> code_target,
469 Address wasm_target);
473 class MacroAssembler :
public TurboAssembler {
475 MacroAssembler(
const AssemblerOptions& options,
void* buffer,
int size)
476 : TurboAssembler(options, buffer, size) {}
478 MacroAssembler(Isolate* isolate,
void* buffer,
int size,
479 CodeObjectRequired create_code_object)
480 : MacroAssembler(isolate, AssemblerOptions::Default(isolate), buffer,
481 size, create_code_object) {}
483 MacroAssembler(Isolate* isolate,
const AssemblerOptions& options,
484 void* buffer,
int size, CodeObjectRequired create_code_object);
487 void Set(Register dst, int32_t x) {
491 mov(dst, Immediate(x));
494 void Set(Operand dst, int32_t x) { mov(dst, Immediate(x)); }
496 void PushRoot(RootIndex index);
499 void JumpIfRoot(Register with, RootIndex index, Label* if_equal,
500 Label::Distance if_equal_distance = Label::kFar) {
501 CompareRoot(with, index);
502 j(equal, if_equal, if_equal_distance);
506 void JumpIfNotRoot(Register with, RootIndex index, Label* if_not_equal,
507 Label::Distance if_not_equal_distance = Label::kFar) {
508 CompareRoot(with, index);
509 j(not_equal, if_not_equal, if_not_equal_distance);
519 void RecordWriteField(
520 Register
object,
int offset, Register value, Register scratch,
521 SaveFPRegsMode save_fp,
522 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
523 SmiCheck smi_check = INLINE_SMI_CHECK);
531 Register
object, Register address, Register value, SaveFPRegsMode save_fp,
532 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
533 SmiCheck smi_check = INLINE_SMI_CHECK);
536 void MaybeDropFrames();
542 void EnterExitFrame(
int argc,
bool save_doubles, StackFrame::Type frame_type);
544 void EnterApiExitFrame(
int argc, Register scratch);
549 void LeaveExitFrame(
bool save_doubles,
bool pop_arguments =
true);
553 void LeaveApiExitFrame();
556 void LoadGlobalProxy(Register dst);
559 void LoadGlobalFunction(
int index, Register
function);
562 void PushSafepointRegisters() { pushad(); }
563 void PopSafepointRegisters() { popad(); }
571 void InvokeFunctionCode(Register
function, Register new_target,
572 const ParameterCount& expected,
573 const ParameterCount& actual, InvokeFlag flag);
577 void CheckDebugHook(Register fun, Register new_target,
578 const ParameterCount& expected,
579 const ParameterCount& actual);
583 void InvokeFunction(Register
function, Register new_target,
584 const ParameterCount& actual, InvokeFlag flag);
588 void CmpObjectType(Register heap_object, InstanceType type, Register map);
591 void CmpInstanceType(Register map, InstanceType type);
593 void DoubleToI(Register result_reg, XMMRegister input_reg,
594 XMMRegister scratch, Label* lost_precision, Label* is_nan,
595 Label::Distance dst = Label::kFar);
598 void SmiTag(Register reg) {
599 STATIC_ASSERT(kSmiTag == 0);
600 STATIC_ASSERT(kSmiTagSize == 1);
605 void UntagSmi(Register reg, Label* is_smi) {
606 STATIC_ASSERT(kSmiTagSize == 1);
607 sar(reg, kSmiTagSize);
608 STATIC_ASSERT(kSmiTag == 0);
609 j(not_carry, is_smi);
613 inline void JumpIfNotSmi(Register value, Label* not_smi_label,
614 Label::Distance distance = Label::kFar) {
615 test(value, Immediate(kSmiTagMask));
616 j(not_zero, not_smi_label, distance);
619 inline void JumpIfNotSmi(Operand value, Label* smi_label,
620 Label::Distance distance = Label::kFar) {
621 test(value, Immediate(kSmiTagMask));
622 j(not_zero, smi_label, distance);
625 template<
typename Field>
626 void DecodeField(Register reg) {
627 static const int shift = Field::kShift;
628 static const int mask = Field::kMask >> Field::kShift;
632 and_(reg, Immediate(mask));
636 void AssertSmi(Register
object);
639 void AssertNotSmi(Register
object);
642 void AssertFunction(Register
object);
645 void AssertConstructor(Register
object);
649 void AssertBoundFunction(Register
object);
653 void AssertGeneratorObject(Register
object);
657 void AssertUndefinedOrAllocationSite(Register
object, Register scratch);
663 void PushStackHandler(Register scratch);
666 void PopStackHandler(Register scratch);
672 void CallStub(CodeStub* stub);
675 void TailCallStub(CodeStub* stub);
678 void CallRuntime(
const Runtime::Function* f,
int num_arguments,
679 SaveFPRegsMode save_doubles = kDontSaveFPRegs);
682 void CallRuntime(Runtime::FunctionId fid,
683 SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
684 const Runtime::Function*
function = Runtime::FunctionForId(fid);
685 CallRuntime(
function, function->nargs, save_doubles);
689 void CallRuntime(Runtime::FunctionId fid,
int num_arguments,
690 SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
691 CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles);
695 void TailCallRuntime(Runtime::FunctionId fid);
698 void JumpToExternalReference(
const ExternalReference& ext,
699 bool builtin_exit_frame =
false);
702 void JumpToInstructionStream(Address entry);
709 void Drop(
int element_count);
711 void Pop(Register dst) { pop(dst); }
712 void Pop(Operand dst) { pop(dst); }
713 void PushReturnAddressFrom(Register src) { push(src); }
714 void PopReturnAddressTo(Register dst) { pop(dst); }
718 void LoadWeakValue(Register in_out, Label* target_if_cleared);
723 void IncrementCounter(StatsCounter* counter,
int value, Register scratch);
724 void DecrementCounter(StatsCounter* counter,
int value, Register scratch);
726 static int SafepointRegisterStackIndex(Register reg) {
727 return SafepointRegisterStackIndex(reg.code());
732 void InvokePrologue(
const ParameterCount& expected,
733 const ParameterCount& actual, Label* done,
734 bool* definitely_mismatches, InvokeFlag flag,
735 Label::Distance done_distance);
737 void EnterExitFramePrologue(StackFrame::Type frame_type, Register scratch);
738 void EnterExitFrameEpilogue(
int argc,
bool save_doubles);
740 void LeaveExitFrameEpilogue();
743 void InNewSpace(Register
object, Register scratch, Condition cc,
744 Label* condition_met,
745 Label::Distance condition_met_distance = Label::kFar);
748 static int SafepointRegisterStackIndex(
int reg_code);
752 friend class StandardFrame;
759 inline Operand FieldOperand(Register
object,
int offset) {
760 return Operand(
object, offset - kHeapObjectTag);
764 inline Operand FieldOperand(Register
object, Register index, ScaleFactor scale,
766 return Operand(
object, index, scale, offset - kHeapObjectTag);
769 inline Operand FixedArrayElementOperand(Register array, Register index_as_smi,
770 int additional_offset = 0) {
771 int offset = FixedArray::kHeaderSize + additional_offset * kPointerSize;
772 return FieldOperand(array, index_as_smi, times_half_pointer_size, offset);
775 inline Operand ContextOperand(Register context,
int index) {
776 return Operand(context, Context::SlotOffset(index));
779 inline Operand ContextOperand(Register context, Register index) {
780 return Operand(context, index, times_pointer_size, Context::SlotOffset(0));
783 inline Operand NativeContextOperand() {
784 return ContextOperand(esi, Context::NATIVE_CONTEXT_INDEX);
787 #define ACCESS_MASM(masm) masm-> 792 #endif // V8_IA32_MACRO_ASSEMBLER_IA32_H_