5 #ifndef INCLUDED_FROM_MACRO_ASSEMBLER_H 6 #error This header must be included via macro-assembler.h 9 #ifndef V8_ARM_MACRO_ASSEMBLER_ARM_H_ 10 #define V8_ARM_MACRO_ASSEMBLER_ARM_H_ 12 #include "src/arm/assembler-arm.h" 13 #include "src/bailout-reason.h" 14 #include "src/contexts.h" 15 #include "src/globals.h" 21 constexpr Register kReturnRegister0 = r0;
22 constexpr Register kReturnRegister1 = r1;
23 constexpr Register kReturnRegister2 = r2;
24 constexpr Register kJSFunctionRegister = r1;
25 constexpr Register kContextRegister = r7;
26 constexpr Register kAllocateSizeRegister = r1;
27 constexpr Register kSpeculationPoisonRegister = r9;
28 constexpr Register kInterpreterAccumulatorRegister = r0;
29 constexpr Register kInterpreterBytecodeOffsetRegister = r5;
30 constexpr Register kInterpreterBytecodeArrayRegister = r6;
31 constexpr Register kInterpreterDispatchTableRegister = r8;
33 constexpr Register kJavaScriptCallArgCountRegister = r0;
34 constexpr Register kJavaScriptCallCodeStartRegister = r2;
35 constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
36 constexpr Register kJavaScriptCallNewTargetRegister = r3;
37 constexpr Register kJavaScriptCallExtraArg1Register = r2;
39 constexpr Register kOffHeapTrampolineRegister = ip;
40 constexpr Register kRuntimeCallFunctionRegister = r1;
41 constexpr Register kRuntimeCallArgCountRegister = r0;
42 constexpr Register kRuntimeCallArgvRegister = r2;
43 constexpr Register kWasmInstanceRegister = r3;
44 constexpr Register kWasmCompileLazyFuncIndexRegister = r4;
50 inline MemOperand FieldMemOperand(Register
object,
int offset) {
51 return MemOperand(
object, offset - kHeapObjectTag);
56 constexpr Register cp = r7;
57 constexpr Register kRootRegister = r10;
59 enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
60 enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
61 enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved };
64 Register GetRegisterThatIsNotOneOf(Register reg1,
65 Register reg2 = no_reg,
66 Register reg3 = no_reg,
67 Register reg4 = no_reg,
68 Register reg5 = no_reg,
69 Register reg6 = no_reg);
71 enum TargetAddressStorageMode {
72 CAN_INLINE_TARGET_ADDRESS,
73 NEVER_INLINE_TARGET_ADDRESS
82 void* buffer,
int buffer_size,
83 CodeObjectRequired create_code_object)
85 create_code_object) {}
88 void EnterFrame(StackFrame::Type
type,
89 bool load_constant_pool_pointer_reg =
false);
91 int LeaveFrame(StackFrame::Type
type);
94 void PushCommonFrame(
Register marker_reg = no_reg);
97 void StubPrologue(StackFrame::Type
type);
101 void PushStandardFrame(
Register function_reg);
103 void InitializeRootRegister();
105 void Push(
Register src) { push(src); }
112 if (src1.code() > src2.code()) {
113 stm(db_w, sp, src1.bit() | src2.bit(), cond);
115 str(src1,
MemOperand(sp, 4, NegPreIndex), cond);
116 str(src2,
MemOperand(sp, 4, NegPreIndex), cond);
122 if (src1.code() > src2.code()) {
123 if (src2.code() > src3.code()) {
124 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
126 stm(db_w, sp, src1.bit() | src2.bit(), cond);
127 str(src3,
MemOperand(sp, 4, NegPreIndex), cond);
130 str(src1,
MemOperand(sp, 4, NegPreIndex), cond);
131 Push(src2, src3, cond);
137 Condition cond = al) {
138 if (src1.code() > src2.code()) {
139 if (src2.code() > src3.code()) {
140 if (src3.code() > src4.code()) {
141 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
144 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
145 str(src4,
MemOperand(sp, 4, NegPreIndex), cond);
148 stm(db_w, sp, src1.bit() | src2.bit(), cond);
149 Push(src3, src4, cond);
152 str(src1,
MemOperand(sp, 4, NegPreIndex), cond);
153 Push(src2, src3, src4, cond);
159 Register src5, Condition cond = al) {
160 if (src1.code() > src2.code()) {
161 if (src2.code() > src3.code()) {
162 if (src3.code() > src4.code()) {
163 if (src4.code() > src5.code()) {
165 src1.bit() | src2.bit() | src3.bit() | src4.bit() | src5.bit(),
168 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
170 str(src5,
MemOperand(sp, 4, NegPreIndex), cond);
173 stm(db_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
174 Push(src4, src5, cond);
177 stm(db_w, sp, src1.bit() | src2.bit(), cond);
178 Push(src3, src4, src5, cond);
181 str(src1,
MemOperand(sp, 4, NegPreIndex), cond);
182 Push(src2, src3, src4, src5, cond);
186 void Pop(
Register dst) { pop(dst); }
190 DCHECK(src1 != src2);
191 if (src1.code() > src2.code()) {
192 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
194 ldr(src2,
MemOperand(sp, 4, PostIndex), cond);
195 ldr(src1,
MemOperand(sp, 4, PostIndex), cond);
201 DCHECK(!AreAliased(src1, src2, src3));
202 if (src1.code() > src2.code()) {
203 if (src2.code() > src3.code()) {
204 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
206 ldr(src3,
MemOperand(sp, 4, PostIndex), cond);
207 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
210 Pop(src2, src3, cond);
211 ldr(src1,
MemOperand(sp, 4, PostIndex), cond);
217 Condition cond = al) {
218 DCHECK(!AreAliased(src1, src2, src3, src4));
219 if (src1.code() > src2.code()) {
220 if (src2.code() > src3.code()) {
221 if (src3.code() > src4.code()) {
222 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit() | src4.bit(),
225 ldr(src4,
MemOperand(sp, 4, PostIndex), cond);
226 ldm(ia_w, sp, src1.bit() | src2.bit() | src3.bit(), cond);
229 Pop(src3, src4, cond);
230 ldm(ia_w, sp, src1.bit() | src2.bit(), cond);
233 Pop(src2, src3, src4, cond);
234 ldr(src1,
MemOperand(sp, 4, PostIndex), cond);
248 void PrepareCallCFunction(
int num_reg_arguments,
int num_double_registers = 0,
274 void CallCFunction(
Register function,
int num_arguments);
276 int num_double_arguments);
277 void CallCFunction(
Register function,
int num_reg_arguments,
278 int num_double_arguments);
285 void Assert(Condition cond, AbortReason reason);
289 void AssertUnreachable(AbortReason reason);
292 void Check(Condition cond, AbortReason reason);
295 void Abort(AbortReason msg);
297 inline bool AllowThisStubCall(
CodeStub* stub);
312 void LoadFromConstantsTable(
Register destination,
313 int constant_index)
override;
314 void LoadRootRegisterOffset(
Register destination, intptr_t offset)
override;
315 void LoadRootRelative(
Register destination, int32_t offset)
override;
319 void CallRuntimeWithCEntry(Runtime::FunctionId fid,
Register centry);
323 void Call(
Address target, RelocInfo::Mode rmode, Condition cond = al,
324 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS,
325 bool check_constant_pool =
true);
326 void Call(
Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
328 TargetAddressStorageMode mode = CAN_INLINE_TARGET_ADDRESS,
329 bool check_constant_pool =
true);
334 void CallForDeoptimization(
Address target,
int deopt_id,
335 RelocInfo::Mode rmode) {
338 CheckConstPool(
false,
false);
343 void Drop(
int count, Condition cond = al);
344 void Drop(
Register count, Condition cond = al);
346 void Ret(Condition cond = al);
347 void Ret(
int drop, Condition cond = al);
351 const Condition cond = al);
352 void VFPCompareAndSetFlags(
const SwVfpRegister src1,
const float src2,
353 const Condition cond = al);
357 const Condition cond = al);
358 void VFPCompareAndSetFlags(
const DwVfpRegister src1,
const double src2,
359 const Condition cond = al);
363 const Condition cond = al);
365 const Condition cond = al) {
366 VFPCanonicalizeNaN(value, value, cond);
374 void CheckPageFlag(
Register object,
Register scratch,
int mask, Condition cc,
375 Label* condition_met);
379 void CheckFor32DRegs(
Register scratch);
381 void SaveRegisters(
RegList registers);
382 void RestoreRegisters(
RegList registers);
385 RememberedSetAction remembered_set_action,
386 SaveFPRegsMode fp_mode);
388 RememberedSetAction remembered_set_action,
389 SaveFPRegsMode fp_mode,
Address wasm_target);
401 int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
404 Register exclusion3 = no_reg)
const;
408 int PushCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion1 = no_reg,
413 int PopCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion1 = no_reg,
416 void Jump(
Register target, Condition cond = al);
417 void Jump(
Address target, RelocInfo::Mode rmode, Condition cond = al);
418 void Jump(
Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
450 NeonDataType dt,
int lane);
460 Condition cond = al) {
461 if (!src.IsRegister() || src.rm() != dst || sbit != LeaveCC) {
462 mov(dst, src, sbit, cond);
470 void VmovExtended(
Register dst,
int src_code);
471 void VmovExtended(
int dst_code,
Register src);
473 void VmovExtended(
int dst_code,
int src_code);
474 void VmovExtended(
int dst_code,
const MemOperand& src);
475 void VmovExtended(
const MemOperand& dst,
int src_code);
483 static int ActivationFrameAlignment();
485 void Bfc(
Register dst,
Register src,
int lsb,
int width, Condition cond = al);
487 void SmiUntag(
Register reg, SBit s = LeaveCC) {
488 mov(reg, Operand::SmiUntag(reg), s);
491 mov(dst, Operand::SmiUntag(src), s);
495 void LoadRoot(
Register destination, RootIndex index)
override {
496 LoadRoot(destination, index, al);
498 void LoadRoot(
Register destination, RootIndex index, Condition cond);
522 bool use_eabi_hardfloat() {
524 return base::OS::ArmUsingHardFloat();
525 #elif USE_EABI_HARDFLOAT 534 void ComputeCodeStartAddress(
Register dst);
536 void ResetSpeculationPoisonRegister();
543 const Condition cond = al);
544 void VFPCompareAndLoadFlags(
const SwVfpRegister src1,
const float src2,
546 const Condition cond = al);
552 const Condition cond = al);
553 void VFPCompareAndLoadFlags(
const DwVfpRegister src1,
const double src2,
555 const Condition cond = al);
557 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al);
560 template <
typename T>
561 void FloatMaxHelper(
T result,
T left,
T right,
Label* out_of_line);
562 template <
typename T>
563 void FloatMinHelper(
T result,
T left,
T right,
Label* out_of_line);
564 template <
typename T>
565 void FloatMaxOutOfLineHelper(
T result,
T left,
T right);
566 template <
typename T>
567 void FloatMinOutOfLineHelper(
T result,
T left,
T right);
569 int CalculateStackPassedWords(
int num_reg_arguments,
570 int num_double_arguments);
572 void CallCFunctionHelper(
Register function,
int num_reg_arguments,
573 int num_double_arguments);
576 RememberedSetAction remembered_set_action,
588 CodeObjectRequired create_code_object)
589 :
MacroAssembler(isolate, AssemblerOptions::Default(isolate), buffer,
590 size, create_code_object) {}
593 void* buffer,
int size, CodeObjectRequired create_code_object);
596 Condition cond = al);
598 Condition cond = al);
600 Condition cond = al);
602 Condition cond = al);
613 InNewSpace(
object, scratch, eq, branch);
619 InNewSpace(
object, scratch, ne, branch);
624 Label* has_color,
int first_bit,
int second_bit);
639 void RecordWriteField(
641 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
642 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
643 SmiCheck smi_check = INLINE_SMI_CHECK);
650 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp,
651 RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
652 SmiCheck smi_check = INLINE_SMI_CHECK);
656 void PushSafepointRegisters();
657 void PopSafepointRegisters();
661 void EnterExitFrame(
bool save_doubles,
int stack_space = 0,
662 StackFrame::Type frame_type = StackFrame::EXIT);
667 void LeaveExitFrame(
bool save_doubles,
Register argument_count,
668 bool argument_count_is_length =
false);
673 void LoadNativeContextSlot(
int index,
Register dst);
697 void MaybeDropFrames();
702 void PushStackHandler();
706 void PopStackHandler();
719 void CompareObjectType(
Register heap_object,
727 void CompareInstanceType(
Register map,
733 void CompareRoot(
Register obj, RootIndex index);
734 void PushRoot(RootIndex index) {
737 LoadRoot(scratch, index);
742 void JumpIfRoot(
Register with, RootIndex index,
Label* if_equal) {
743 CompareRoot(with, index);
748 void JumpIfNotRoot(
Register with, RootIndex index,
Label* if_not_equal) {
749 CompareRoot(with, index);
755 void TryDoubleToInt32Exact(
Register result,
764 Condition cond = al);
767 void TailCallStub(
CodeStub* stub, Condition cond = al);
772 SaveFPRegsMode save_doubles = kDontSaveFPRegs);
776 SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
778 CallRuntime(
function, function->nargs, save_doubles);
782 void CallRuntime(Runtime::FunctionId fid,
int num_arguments,
783 SaveFPRegsMode save_doubles = kDontSaveFPRegs) {
784 CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles);
788 void TailCallRuntime(Runtime::FunctionId fid);
792 bool builtin_exit_frame =
false);
795 void JumpToInstructionStream(
Address entry);
812 void SmiTag(
Register reg, SBit s = LeaveCC);
831 void AssertConstructor(
Register object);
834 void AssertFunction(
Register object);
838 void AssertBoundFunction(
Register object);
842 void AssertGeneratorObject(
Register object);
848 template<
typename Field>
850 Ubfx(dst, src, Field::kShift, Field::kSize);
853 template<
typename Field>
855 DecodeField<Field>(reg, reg);
862 bool* definitely_mismatches, InvokeFlag flag);
871 static int SafepointRegisterStackIndex(
int reg_code);
882 return MemOperand(context, Context::SlotOffset(index));
886 inline MemOperand NativeContextMemOperand() {
887 return ContextMemOperand(cp, Context::NATIVE_CONTEXT_INDEX);
890 #define ACCESS_MASM(masm) masm-> 895 #endif // V8_ARM_MACRO_ASSEMBLER_ARM_H_