5#ifndef V8_MAGLEV_ARM_MAGLEV_ASSEMBLER_ARM_INL_H_
6#define V8_MAGLEV_ARM_MAGLEV_ASSEMBLER_ARM_INL_H_
42class MaglevAssembler::TemporaryRegisterScope
43 :
public TemporaryRegisterScopeBase<TemporaryRegisterScope> {
47 struct SavedData :
public Base::SavedData {
107 Register temp = temps.AcquireScratch();
119template <
typename... Args>
129 if (input.operand().IsConstant()) {
131 Register scratch = temps.AcquireScratch();
132 input.node()->LoadToRegister(masm, scratch);
144 Register scratch = temps.AcquireScratch();
151template <
typename T,
typename... Args>
154 for (
auto iter = range.begin(),
end = range.end(); iter !=
end; ++iter) {
160template <
typename T,
typename... Args>
164 for (
auto iter = range.rbegin(),
end = range.rend(); iter !=
end; ++iter) {
169template <
typename... Args>
170struct PushAllHelper<
Input, Args...> {
181template <
typename Arg,
typename... Args>
182struct PushAllHelper<Arg, Args...> {
187 masm->MacroAssembler::Push(arg);
203template <
typename... T>
208template <
typename... T>
216 bind(block->label());
237 int value,
Label* fail,
250 int value,
Label* fail,
268 if (input.operand().IsRegister()) {
271 DCHECK(input.operand().IsStackSlot());
310 add(data_pointer, data_pointer,
base);
315 add(data_pointer, data_pointer,
349 AbortReason::kUnexpectedNegativeValue);
368 AbortReason::kUnexpectedValue);
370 AbortReason::kUnexpectedNegativeValue);
388 }
else if (size == 2) {
400 }
else if (size == 2) {
415 add(slot_reg,
object,
445 Move(scratch, value);
453 Move(scratch, value);
459 DCHECK(size == 1 || size == 2 || size == 4);
461 strb(value, operand);
462 }
else if (size == 2) {
463 strh(value, operand);
474 }
else if (size == 4) {
598 if (dst.
code() < 16) {
603 vldr(temp_vfps, src);
610 vstr(temp_vfps, dst);
637 rev(scratch, scratch);
641 rev(scratch, scratch);
664 rev(scratch, scratch);
668 rev(scratch, scratch);
690 Move(scratch, 255.0);
699template <
typename NodeT>
709 tst(scratch,
Operand(JSArrayBuffer::WasDetachedBit::kMask));
720 and_(scratch, scratch,
721 Operand(Map::Bits1::IsUndetectableBit::kMask |
722 Map::Bits1::IsCallableBit::kMask));
723 cmp(scratch,
Operand(Map::Bits1::IsCallableBit::kMask));
730 tst(scratch,
Operand(Map::Bits1::IsUndetectableBit::kMask |
731 Map::Bits1::IsCallableBit::kMask));
737 LoadMap(instance_type, heap_object);
777 Branch(
kEqual, if_true, true_distance, fallthrough_when_true, if_false,
778 false_distance, fallthrough_when_false);
819 bool fallthrough_when_false) {
825 if_false, false_distance, fallthrough_when_false);
832 static_assert(LAST_JS_RECEIVER_TYPE ==
LAST_TYPE);
836 FIRST_JS_RECEIVER_TYPE);
860 lower_limit, higher_limit);
869 JumpIf(cond, target, distance);
878 Branch(cond, if_true, if_false, next_block);
882 int num_double_registers) {
960 masm->
Jump(*is_not_hole);
962 value, scratch, is_hole, is_not_hole));
977 Register upper_bits = temps.AcquireScratch();
1047 Branch(cond, if_true, true_distance, fallthrough_when_true, if_false,
1048 false_distance, fallthrough_when_false);
1056 Branch(cond, if_true, true_distance, fallthrough_when_true, if_false,
1057 false_distance, fallthrough_when_false);
1065 Branch(cond, if_true, true_distance, fallthrough_when_true, if_false,
1066 false_distance, fallthrough_when_false);
1091 Cmp(scratch, right);
1092 JumpIf(cond, target, distance);
1119 JumpIf(cond, target, distance);
1133 vldr(value_double, operand);
1147 ldr(value, operand);
1155 ldrb(value, operand);
1169 ldr(value, operand);
1200 if (
result.code() < 16) {
1205 vmov(temp_vfps, src);
1218 if (
result.code() < 16) {
1223 vmov(temp_vfps, src);
1237 Assert(
eq, AbortReason::kStackAccessBelowStackPointer);
1242 int stack_check_offset) {
1247 sub(stack_cmp_reg, sp,
Operand(stack_check_offset));
1251 cmp(stack_cmp_reg, interrupt_stack_limit);
1257template <
typename NodeT>
1276 return ldr(dst, src);
1289 return str(src, dst);
#define Assert(condition)
interpreter::OperandScale scale
void rsb(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void and_(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void b(int branch_offset, Condition cond=al, RelocInfo::Mode rmode=RelocInfo::NO_INFO)
static VfpRegList DefaultFPTmpList()
void add(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void CheckConstPool(bool force_emit, bool require_jump)
void bl(int branch_offset, Condition cond=al, RelocInfo::Mode rmode=RelocInfo::NO_INFO)
void vmov(const SwVfpRegister dst, Float32 imm)
void vcvt_f64_s32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void cmp(Register src1, const Operand &src2, Condition cond=al)
void ldrsh(Register dst, const MemOperand &src, Condition cond=al)
void ldrsb(Register dst, const MemOperand &src, Condition cond=al)
void vcvt_f64_f32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void str(Register src, const MemOperand &dst, Condition cond=al)
void ldrh(Register dst, const MemOperand &src, Condition cond=al)
void sub(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void vrintn(const SwVfpRegister dst, const SwVfpRegister src)
void strb(Register src, const MemOperand &dst, Condition cond=al)
void lsl(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void ldrb(Register dst, const MemOperand &src, Condition cond=al)
void vcvt_f32_f64(const SwVfpRegister dst, const DwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
void strh(Register src, const MemOperand &dst, Condition cond=al)
void rev(Register dst, Register src, Condition cond=al)
void vcvt_f64_u32(const DwVfpRegister dst, const SwVfpRegister src, VFPConversionMode mode=kDefaultRoundToZero, const Condition cond=al)
static RegList DefaultTmpList()
void orr(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void vstr(const DwVfpRegister src, const Register base, int offset, const Condition cond=al)
void tst(Register src1, const Operand &src2, Condition cond=al)
void ldr(Register dst, const MemOperand &src, Condition cond=al)
void vldr(const DwVfpRegister dst, const Register base, int offset, const Condition cond=al)
void asr(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
static constexpr size_t kMaxSizeInHeap
SwVfpRegister low() const
void JumpIfRoot(Register with, RootIndex index, Label *if_equal)
void LoadStackLimit(Register destination, StackLimitKind kind)
void Cmp(const Register &rn, int imm)
void CompareInstanceType(Register map, Register type_reg, InstanceType type)
void mov(Register rd, Register rj)
void AssertNotSmi(Register object, AbortReason reason=AbortReason::kOperandIsASmi) NOOP_UNLESS_DEBUG_CODE
void JumpIfNotRoot(Register with, RootIndex index, Label *if_not_equal)
void CompareRoot(Register obj, RootIndex index)
void CompareObjectType(Register heap_object, Register map, Register type_reg, InstanceType type)
void Move(Register dst, Tagged< Smi > smi)
void JumpIfSmi(Register value, Label *smi_label)
void VFPCompareAndSetFlags(const SwVfpRegister src1, const SwVfpRegister src2, const Condition cond=al)
void VmovLow(Register dst, DwVfpRegister src)
void EnterExitFrame(Register scratch, int stack_space, StackFrame::Type frame_type)
void AssertSmi(Register object, AbortReason reason=AbortReason::kOperandIsNotASmi) NOOP_UNLESS_DEBUG_CODE
void StoreTaggedField(const Register &value, const MemOperand &dst_field_operand)
void LoadTaggedField(const Register &destination, const MemOperand &field_operand)
void CompareObjectTypeRange(Register heap_object, Register map, Register type_reg, Register scratch, InstanceType lower_limit, InstanceType higher_limit)
void JumpIfNotSmi(Register value, Label *not_smi_label)
void VmovHigh(Register dst, DwVfpRegister src)
void CmpTagged(const Register &r1, const Register &r2)
void CompareInstanceTypeRange(Register map, Register type_reg, Register scratch, InstanceType lower_limit, InstanceType higher_limit)
void PrepareCallCFunction(int num_reg_arguments, int num_double_registers=0, Register scratch=no_reg)
void LoadMap(Register destination, Register object)
void LoadTaggedFieldWithoutDecompressing(const Register &destination, const MemOperand &field_operand)
bool IsImmediateOffset() const
static Operand EmbeddedNumber(double number)
constexpr bool has(RegisterT reg) const
static constexpr LowDwVfpRegister from_code(int8_t code)
static constexpr SwVfpRegister no_reg()
constexpr int8_t code() const
static constexpr Register no_reg()
static constexpr Tagged< Smi > FromInt(int value)
static constexpr int kFixedFrameSizeFromFp
void SetAvailableVfp(VfpRegList available)
VfpRegList AvailableVfp()
void SetAvailable(RegList available)
void Include(const Register ®1, const Register ®2=no_reg)
Register GetRegister() const
static LocationOperand * cast(InstructionOperand *op)
TemporaryRegisterScope * prev_scope_
DoubleRegList available_double_
SavedData CopyForDeferBase()
Register AcquireScratch()
DoubleRegister AcquireScratchDouble()
UseScratchRegisterScope scratch_scope_
void ResetToDefaultImpl()
TemporaryRegisterScope(MaglevAssembler *masm)
void IncludeScratch(Register reg)
TemporaryRegisterScope(MaglevAssembler *masm, const SavedData &saved_data)
void CompareMapWithRoot(Register object, RootIndex index, Register scratch)
void LoadFixedArrayElement(Register result, Register array, Register index)
void CompareInstanceType(Register map, InstanceType instance_type)
void SmiAddConstant(Register dst, Register src, int value, Label *fail, Label::Distance distance=Label::kFar)
void JumpIfByte(Condition cc, Register value, int32_t byte, Label *target, Label::Distance distance=Label::kFar)
void JumpIfNotNan(DoubleRegister value, Label *target, Label::Distance distance=Label::kFar)
Condition IsNotCallableNorUndetactable(Register map, Register scratch)
void JumpIfRoot(Register with, RootIndex index, Label *if_equal, Label::Distance distance=Label::kFar)
void ToUint8Clamped(Register result, DoubleRegister value, Label *min, Label *max, Label *done)
Condition IsCallableAndNotUndetectable(Register map, Register scratch)
void LoadFloat32(DoubleRegister dst, MemOperand src)
void JumpIfNotObjectType(Register heap_object, InstanceType type, Label *target, Label::Distance distance=Label::kFar)
void ReverseByteOrderAndStoreUnalignedFloat64(Register base, Register index, DoubleRegister src)
void AssertStackSizeCorrect()
void IncrementInt32(Register reg)
void IntPtrToDouble(DoubleRegister result, Register src)
void Branch(Condition condition, BasicBlock *if_true, BasicBlock *if_false, BasicBlock *next_block)
void AndInt32(Register reg, int mask)
void AddInt32(Register reg, int amount)
MemOperand GetStackSlot(const compiler::AllocatedOperand &operand)
void StoreField(MemOperand operand, Register value, int element_size)
void LoadSignedField(Register result, MemOperand operand, int element_size)
void DecrementInt32(Register reg)
void JumpIfSmi(Register src, Label *on_smi, Label::Distance near_jump=Label::kFar)
void TestUint8AndJumpIfAllClear(MemOperand operand, uint8_t mask, Label *target, Label::Distance distance=Label::kFar)
void AssertObjectTypeInRange(Register heap_object, InstanceType lower_limit, InstanceType higher_limit, AbortReason reason)
void CompareInt32AndAssert(Register r1, Register r2, Condition cond, AbortReason reason)
void CompareDoubleAndJumpIfZeroOrNaN(DoubleRegister reg, Label *target, Label::Distance distance=Label::kFar)
void LoadFixedDoubleArrayElement(DoubleRegister result, Register array, Register index)
void LoadUnsignedField(Register result, MemOperand operand, int element_size)
void JumpIfObjectTypeInRange(Register heap_object, InstanceType lower_limit, InstanceType higher_limit, Label *target, Label::Distance distance=Label::kFar)
void CheckInt32IsSmi(Register obj, Label *fail, Register scratch=Register::no_reg())
void PushReverse(T... vals)
void ReverseByteOrder(Register value, int element_size)
Condition FunctionEntryStackCheck(int stack_check_offset)
void EmitEagerDeoptStress(Label *label)
void LoadHeapNumberValue(DoubleRegister result, Register heap_number)
void Jump(Label *target, Label::Distance distance=Label::kFar)
MemOperand DataViewElementOperand(Register data_pointer, Register index)
void StoreTaggedSignedField(Register object, int offset, Register value)
void CompareSmiAndJumpIf(Register r1, Tagged< Smi > value, Condition cond, Label *target, Label::Distance distance=Label::kFar)
TemporaryRegisterScope * scratch_register_scope() const
void TestUint8AndJumpIfAnySet(MemOperand operand, uint8_t mask, Label *target, Label::Distance distance=Label::kFar)
void MoveRepr(MachineRepresentation repr, Dest dst, Source src)
void StoreFixedDoubleArrayElement(Register array, Register index, DoubleRegister value)
void SmiTagInt32AndSetFlags(Register dst, Register src)
void BindBlock(BasicBlock *block)
void LoadInstanceType(Register instance_type, Register heap_object)
void StoreHeapInt32Value(Register value, Register heap_number)
void LoadInt32(Register dst, MemOperand src)
void StoreFixedArrayElementNoWriteBarrier(Register array, Register index, Register value)
void LoadAddress(Register dst, MemOperand location)
void JumpIfJSAnyIsNotPrimitive(Register heap_object, Label *target, Label::Distance distance=Label::kFar)
void LoadBoundedSizeFromObject(Register result, Register object, int offset)
void SetSlotAddressForTaggedField(Register slot_reg, Register object, int offset)
void CompareFloat64AndBranch(DoubleRegister src1, DoubleRegister src2, Condition cond, BasicBlock *if_true, BasicBlock *if_false, BasicBlock *next_block, BasicBlock *nan_failed)
void CompareTaggedAndJumpIf(Register reg, Tagged< Smi > smi, Condition cond, Label *target, Label::Distance distance=Label::kFar)
void StoreInt32Field(Register object, int offset, int32_t value)
Register GetFramePointer()
void BranchOnObjectTypeInRange(Register heap_object, InstanceType lower_limit, InstanceType higher_limit, Label *if_true, Label::Distance true_distance, bool fallthrough_when_true, Label *if_false, Label::Distance false_distance, bool fallthrough_when_false)
void LoadExternalPointerField(Register result, MemOperand operand)
void StoreInt32(MemOperand dst, Register src)
void BuildTypedArrayDataPointer(Register data_pointer, Register object)
void JumpIfObjectTypeNotInRange(Register heap_object, InstanceType lower_limit, InstanceType higher_limit, Label *target, Label::Distance distance=Label::kFar)
void ShiftLeft(Register reg, int amount)
void JumpIfNotRoot(Register with, RootIndex index, Label *if_not_equal, Label::Distance distance=Label::kFar)
void EmitEnterExitFrame(int extra_slots, StackFrame::Type frame_type, Register c_function, Register scratch)
void BranchOnObjectType(Register heap_object, InstanceType type, Label *if_true, Label::Distance true_distance, bool fallthrough_when_true, Label *if_false, Label::Distance false_distance, bool fallthrough_when_false)
void LoadHeapInt32Value(Register result, Register heap_number)
void CompareInstanceTypeRange(Register map, InstanceType lower_limit, InstanceType higher_limit)
void Move(StackSlot dst, Register src)
void SignExtend32To64Bits(Register dst, Register src)
void LoadFixedArrayElementWithoutDecompressing(Register result, Register array, Register index)
void LoadUnalignedFloat64AndReverseByteOrder(DoubleRegister dst, Register base, Register index)
void IncrementAddress(Register reg, int32_t delta)
Label * MakeDeferredCode(Function &&deferred_code_gen, Args &&... args)
void JumpIfNan(DoubleRegister value, Label *target, Label::Distance distance=Label::kFar)
void TruncateDoubleToInt32(Register dst, DoubleRegister src)
void JumpIfNotSmi(Register src, Label *on_not_smi, Label::Distance near_jump=Label::kFar)
MemOperand TypedArrayElementOperand(Register data_pointer, Register index, int element_size)
MaglevCompilationInfo * compilation_info() const
void TestInt32AndJumpIfAllClear(Register r1, int32_t mask, Label *target, Label::Distance distance=Label::kFar)
int GetFramePointerOffsetForStackSlot(const compiler::AllocatedOperand &operand)
void CompareInt32AndJumpIf(Register r1, Register r2, Condition cond, Label *target, Label::Distance distance=Label::kFar)
MaglevCodeGenState * code_gen_state() const
void SetSlotAddressForFixedArrayElement(Register slot_reg, Register object, Register index)
void LoadTaggedFieldByIndex(Register result, Register object, Register index, int scale, int offset)
void CompareIntPtrAndJumpIf(Register r1, Register r2, Condition cond, Label *target, Label::Distance distance=Label::kFar)
void CompareInt32AndBranch(Register r1, int32_t value, Condition cond, BasicBlock *if_true, BasicBlock *if_false, BasicBlock *next_block)
void CompareSmiAndAssert(Register r1, Tagged< Smi > value, Condition cond, AbortReason reason)
void JumpIf(Condition cond, Label *target, Label::Distance distance=Label::kFar)
void LoadFloat64(DoubleRegister dst, MemOperand src)
void LoadUnalignedFloat64(DoubleRegister dst, Register base, Register index)
void LoadTaggedFieldWithoutDecompressing(Register result, Register object, int offset)
Condition IsRootConstant(Input input, RootIndex root_index)
void StoreFloat32(MemOperand dst, DoubleRegister src)
void EmitEagerDeoptIf(Condition cond, DeoptimizeReason reason, NodeT *node)
void StoreFloat64(MemOperand dst, DoubleRegister src)
void NegateInt32(Register val)
bool IsDeoptLabel(Label *label)
void EmitEagerDeoptIfNotEqual(DeoptimizeReason reason, NodeT *node)
void StoreTaggedFieldNoWriteBarrier(Register object, int offset, Register value)
MemOperand ToMemOperand(const compiler::InstructionOperand &operand)
void MoveHeapNumber(Register dst, double value)
void LoadTaggedField(Register result, MemOperand operand)
void LoadByte(Register dst, MemOperand src)
void MoveTagged(Register dst, Handle< HeapObject > obj)
void JumpIfNotHoleNan(DoubleRegister value, Register scratch, Label *target, Label::Distance distance=Label::kFar)
void DeoptIfBufferDetached(Register array, Register scratch, NodeT *node)
void StoreUnalignedFloat64(Register base, Register index, DoubleRegister src)
void TestInt32AndJumpIfAnySet(Register r1, int32_t mask, Label *target, Label::Distance distance=Label::kFar)
void JumpIfHoleNan(DoubleRegister value, Register scratch, Label *target, Label::Distance distance=Label::kFar)
void Uint32ToDouble(DoubleRegister result, Register src)
void CompareFloat64AndJumpIf(DoubleRegister src1, DoubleRegister src2, Condition cond, Label *target, Label *nan_failed, Label::Distance distance=Label::kFar)
void CompareIntPtrAndBranch(Register r1, int32_t value, Condition cond, BasicBlock *if_true, BasicBlock *if_false, BasicBlock *next_block)
void Int32ToDouble(DoubleRegister result, Register src)
void JumpIfObjectType(Register heap_object, InstanceType type, Label *target, Label::Distance distance=Label::kFar)
void AssertObjectType(Register heap_object, InstanceType type, AbortReason reason)
void SmiSubConstant(Register dst, Register src, int value, Label *fail, Label::Distance distance=Label::kFar)
void OrInt32(Register reg, int mask)
void BindJumpTarget(Label *label)
void JumpToDeopt(Label *target)
MemOperand StackSlotOperand(StackSlot slot)
void CompareByteAndJumpIf(MemOperand left, int8_t right, Condition cond, Register scratch, Label *target, Label::Distance distance=Label::kFar)
void PrepareCallCFunction(int num_reg_arguments, int num_double_registers=0)
void MaybeEmitPlaceHolderForDeopt()
static int TemporaryCount(size_t map_count)
MapCompare(MaglevAssembler *masm, Register object, size_t map_count)
void Generate(Handle< Map > map, Condition cond, Label *if_true, Label::Distance distance=Label::kFar)
const compiler::InstructionOperand & operand() const
static ZoneLabelRef UnsafeFromLabelPointer(Label *label)
base::Vector< const DirectHandle< Object > > args
ZoneVector< RpoNumber > & result
base::SmallVector< int32_t, 1 > stack_slots
MaglevAssembler *const masm_
void PushIterator(MaglevAssembler *masm, base::iterator_range< T > range, Args... args)
void PushIteratorReverse(MaglevAssembler *masm, base::iterator_range< T > range, Args... args)
void PushInput(MaglevAssembler *masm, const Input &input)
constexpr Condition ConditionForNaN()
constexpr Condition ConditionFor(Operation operation)
int ShiftFromScale(int n)
Register ToRegister(const compiler::InstructionOperand &operand)
constexpr Condition ConditionForFloat64(Operation operation)
constexpr int kTaggedSize
@ kUnsignedGreaterThanEqual
constexpr AddrMode Offset
MemOperand FieldMemOperand(Register object, int offset)
constexpr int kSystemPointerSize
constexpr int kStackLimitSlackForDeoptimizationInBytes
constexpr int kTaggedSizeLog2
constexpr Register kMaglevExtraScratchRegister
Condition NegateCondition(Condition cond)
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr bool SmiValuesAre32Bits()
constexpr uint32_t kHoleNanUpper32
constexpr int kDoubleSizeLog2
constexpr int kDoubleSize
#define DCHECK_NE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
RegList available_scratch_
VfpRegList available_fp_scratch_
static void Push(MaglevAssembler *masm, Arg arg, Args... args)
static void PushReverse(MaglevAssembler *masm, Arg arg, Args... args)
static void PushReverse(MaglevAssembler *masm)
static void Push(MaglevAssembler *masm)
#define OFFSET_OF_DATA_START(Type)