5#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_X64_H_
6#define RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_X64_H_
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
12#ifndef RUNTIME_VM_COMPILER_ASSEMBLER_ASSEMBLER_H_
13#error Do not include assembler_x64.h directly; use assembler.h instead.
29class FlowGraphCompiler;
34class Immediate :
public ValueObject {
40 int64_t
value()
const {
return value_; }
59 uint8_t
rex()
const {
return rex_; }
61 uint8_t
mod()
const {
return (encoding_at(0) >> 6) & 3; }
64 int rm_rex = (rex_ &
REX_B) << 3;
65 return static_cast<Register>(rm_rex + (encoding_at(0) & 7));
69 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
73 int index_rex = (rex_ &
REX_X) << 2;
74 return static_cast<Register>(index_rex + ((encoding_at(1) >> 3) & 7));
78 int base_rex = (rex_ &
REX_B) << 3;
79 return static_cast<Register>(base_rex + (encoding_at(1) & 7));
84 return static_cast<int8_t
>(encoding_[length_ - 1]);
89 return bit_copy<int32_t>(encoding_[length_ - 4]);
93 :
ValueObject(), length_(other.length_), rex_(other.rex_) {
94 memmove(&encoding_[0], &other.encoding_[0], other.length_);
98 length_ = other.length_;
100 memmove(&encoding_[0], &other.encoding_[0], other.length_);
105 if (length_ != other.length_)
return false;
106 if (rex_ != other.rex_)
return false;
107 for (uint8_t i = 0; i < length_; i++) {
108 if (encoding_[i] != other.encoding_[i])
return false;
118 if ((
rm > 7) && !((
rm ==
R12) && (
mod != 3))) {
121 encoding_[0] = (
mod << 6) | (
rm & 7);
138 ASSERT(length_ == 1 || length_ == 2);
139 encoding_[length_++] =
static_cast<uint8_t
>(disp);
143 ASSERT(length_ == 1 || length_ == 2);
144 memmove(&encoding_[length_], &disp,
sizeof(disp));
145 length_ +=
sizeof(disp);
151 uint8_t encoding_[6];
156 uint8_t encoding_at(intptr_t
index)
const {
158 return encoding_[
index];
163 bool IsRegister(
Register reg)
const {
164 return ((reg > 7 ? 1 : 0) == (rex_ &
REX_B))
165 && ((encoding_at(0) & 0xF8) == 0xC0)
166 && ((encoding_at(0) & 0x07) == reg);
172class Address :
public Operand {
175 if ((disp == 0) && ((
base & 7) !=
RBP)) {
212 if ((disp == 0) && ((
base & 7) !=
RBP)) {
237 return Address(RIPRelativeDisp(disp));
256 struct RIPRelativeDisp {
257 explicit RIPRelativeDisp(int32_t disp) : disp_(disp) {}
261 explicit Address(
const RIPRelativeDisp& disp) {
267class FieldAddress :
public Address {
289#if !defined(DART_COMPRESSED_POINTERS)
295class Assembler :
public AssemblerBase {
306 void call(
const Address& address) { EmitUnaryL(address, 0xFF, 2); }
317 void popq(
const Address& address) { EmitUnaryL(address, 0x8F, 0); }
326 bool enter_safepoint);
328 bool ignore_unwind_in_progress =
false);
331#define RR(width, name, ...) \
332 void name(Register dst, Register src) { Emit##width(dst, src, __VA_ARGS__); }
333#define RA(width, name, ...) \
334 void name(Register dst, const Address& src) { \
335 Emit##width(dst, src, __VA_ARGS__); \
337#define RAB(name, ...) \
338 void name(ByteRegister dst, const Address& src) { \
339 EmitB(dst, src, __VA_ARGS__); \
341#define AR(width, name, ...) \
342 void name(const Address& dst, Register src) { \
343 Emit##width(src, dst, __VA_ARGS__); \
345#define ARB(name, ...) \
346 void name(const Address& dst, ByteRegister src) { \
347 EmitB(src, dst, __VA_ARGS__); \
349#define REGULAR_INSTRUCTION(name, ...) \
350 RA(W, name##w, __VA_ARGS__) \
351 RA(L, name##l, __VA_ARGS__) \
352 RA(Q, name##q, __VA_ARGS__) \
353 RR(W, name##w, __VA_ARGS__) \
354 RR(L, name##l, __VA_ARGS__) \
355 RR(Q, name##q, __VA_ARGS__)
363#undef REGULAR_INSTRUCTION
377 AR(Q, cmpxchgq, 0xB1, 0x0F)
379 RA(Q, cmpxchgq, 0xB1, 0x0F)
381 RR(Q, cmpxchgq, 0xB1, 0x0F)
390#define DECLARE_CMOV(name, code) \
391 RR(Q, cmov##name##q, 0x40 + code, 0x0F) \
392 RR(L, cmov##name##l, 0x40 + code, 0x0F) \
393 RA(Q, cmov##name##q, 0x40 + code, 0x0F) \
394 RA(L, cmov##name##l, 0x40 + code, 0x0F)
401#define SIMPLE(name, ...) \
402 void name() { EmitSimple(__VA_ARGS__); }
411 SIMPLE(rep_movsq, 0xF3, 0x48, 0xA5)
414#define XX(width, name, ...) \
415 void name(XmmRegister dst, XmmRegister src) { \
416 Emit##width(dst, src, __VA_ARGS__); \
418#define XA(width, name, ...) \
419 void name(XmmRegister dst, const Address& src) { \
420 Emit##width(dst, src, __VA_ARGS__); \
422#define AX(width, name, ...) \
423 void name(const Address& dst, XmmRegister src) { \
424 Emit##width(src, dst, __VA_ARGS__); \
441#define DECLARE_XMM(name, code) \
442 XX(L, name##ps, 0x50 + code, 0x0F) \
443 XA(L, name##ps, 0x50 + code, 0x0F) \
444 AX(L, name##ps, 0x50 + code, 0x0F) \
445 XX(L, name##pd, 0x50 + code, 0x0F, 0x66) \
446 XA(L, name##pd, 0x50 + code, 0x0F, 0x66) \
447 AX(L, name##pd, 0x50 + code, 0x0F, 0x66) \
448 XX(L, name##sd, 0x50 + code, 0x0F, 0xF2) \
449 XA(L, name##sd, 0x50 + code, 0x0F, 0xF2) \
450 AX(L, name##sd, 0x50 + code, 0x0F, 0xF2) \
451 XX(L, name##ss, 0x50 + code, 0x0F, 0xF3) \
452 XA(L, name##ss, 0x50 + code, 0x0F, 0xF3) \
453 AX(L, name##ss, 0x50 + code, 0x0F, 0xF3)
467#define DECLARE_CMPPS(name, code) \
468 void cmpps##name(XmmRegister dst, XmmRegister src) { \
469 EmitL(dst, src, 0xC2, 0x0F); \
470 AssemblerBuffer::EnsureCapacity ensured(&buffer_); \
476#define DECLARE_SIMPLE(name, opcode) \
477 void name() { EmitSimple(opcode); }
494 EmitQ(src, dst, 0x7E, 0x0F, 0x66);
497 EmitL(src, dst, 0x7E, 0x0F, 0x66);
500 EmitL(src, dst, 0x11, 0x0F, 0xF3);
503 EmitL(src, dst, 0x11, 0x0F, 0xF2);
513 EmitQ(dst, src, 0x6E, 0x0F, 0x66);
517 EmitL(dst, src, 0x6E, 0x0F, 0x66);
520 EmitQ(dst, src, 0x2A, 0x0F, 0xF2);
523 EmitL(dst, src, 0x2A, 0x0F, 0xF2);
526 EmitQ(dst, src, 0x2C, 0x0F, 0xF2);
529 EmitL(dst, src, 0x2C, 0x0F, 0xF2);
532 EmitL(dst, src, 0x50, 0x0F, 0x66);
536 EmitL(dst, src, 0xD7, 0x0F, 0x66);
611 EmitQ(src, dst, 0xA5, 0x0F);
615 EmitQ(src, dst, 0xAD, 0x0F);
618#define DECLARE_ALU(op, c) \
619 void op##w(Register dst, Register src) { EmitW(dst, src, c * 8 + 3); } \
620 void op##l(Register dst, Register src) { EmitL(dst, src, c * 8 + 3); } \
621 void op##q(Register dst, Register src) { EmitQ(dst, src, c * 8 + 3); } \
622 void op##w(Register dst, const Address& src) { EmitW(dst, src, c * 8 + 3); } \
623 void op##l(Register dst, const Address& src) { EmitL(dst, src, c * 8 + 3); } \
624 void op##q(Register dst, const Address& src) { EmitQ(dst, src, c * 8 + 3); } \
625 void op##w(const Address& dst, Register src) { EmitW(src, dst, c * 8 + 1); } \
626 void op##l(const Address& dst, Register src) { EmitL(src, dst, c * 8 + 1); } \
627 void op##q(const Address& dst, Register src) { EmitQ(src, dst, c * 8 + 1); } \
628 void op##l(Register dst, const Immediate& imm) { AluL(c, dst, imm); } \
629 void op##q(Register dst, const Immediate& imm) { \
630 AluQ(c, c * 8 + 3, dst, imm); \
632 void op##b(const Address& dst, const Immediate& imm) { AluB(c, dst, imm); } \
633 void op##w(const Address& dst, const Immediate& imm) { AluW(c, dst, imm); } \
634 void op##l(const Address& dst, const Immediate& imm) { AluL(c, dst, imm); } \
635 void op##q(const Address& dst, const Immediate& imm) { \
636 AluQ(c, c * 8 + 3, dst, imm); \
646#define REGULAR_UNARY(name, opcode, modrm) \
647 void name##q(Register reg) { EmitUnaryQ(reg, opcode, modrm); } \
648 void name##l(Register reg) { EmitUnaryL(reg, opcode, modrm); } \
649 void name##q(const Address& address) { EmitUnaryQ(address, opcode, modrm); } \
650 void name##l(const Address& address) { EmitUnaryL(address, opcode, modrm); }
703 void jmp(
const Address& address) { EmitUnaryL(address, 0xFF, 4); }
740 j(condition, label, distance);
746 j(
ZERO, label, distance);
754 j(condition, label, distance);
842 const Object& equivalence,
855#if defined(DART_COMPRESSED_POINTERS)
893 cmpxchgq(address, reg);
935 Label* target)
override;
951 bool can_be_null =
false)
override;
953#if defined(DART_COMPRESSED_POINTERS)
977#if !defined(DART_COMPRESSED_POINTERS)
989#if !defined(DART_COMPRESSED_POINTERS)
1016 j(
ZERO, label, distance);
1031 jmp(label, distance);
1044 int32_t payload_offset,
1050#if defined(DART_COMPRESSED_POINTERS)
1105#if defined(TARGET_USES_THREAD_SANITIZER)
1106 void TsanLoadAcquire(
Address addr);
1107 void TsanStoreRelease(
Address addr);
1115 Load(dst, address, size);
1116#if defined(TARGET_USES_THREAD_SANITIZER)
1117 TsanLoadAcquire(address);
1120#if defined(DART_COMPRESSED_POINTERS)
1125#if defined(TARGET_USES_THREAD_SANITIZER)
1126 TsanLoadAcquire(address);
1135 Store(src, address, size);
1136#if defined(TARGET_USES_THREAD_SANITIZER)
1137 TsanStoreRelease(address);
1146 cmpl(
value, address);
1148 cmpq(
value, address);
1227 intptr_t instance_size,
1234 intptr_t instance_size,
1246 Stop(
"Allocation canary");
1294 intptr_t index_scale);
1298 intptr_t index_scale,
1303 intptr_t index_scale,
1313 field, target::Field::host_offset_or_field_id_offset()));
1314 const intptr_t field_table_offset =
1315 compiler::target::Thread::field_table_values_offset();
1317 static_assert(
kSmiTagShift == 1,
"adjust scale factor");
1318 leaq(address,
Address(address, scratch, TIMES_HALF_WORD_SIZE, 0));
1323 Register offset_in_words_as_smi)
override {
1324 static_assert(
kSmiTagShift == 1,
"adjust scale factor");
1328#if defined(DART_COMPRESSED_POINTERS)
1332 Register offset_in_words_as_smi)
override {
1333 static_assert(
kSmiTagShift == 1,
"adjust scale factor");
1341 int32_t
offset)
override {
1356 bool constant_pool_allowed_;
1358 void CallCodeThroughPool(intptr_t target_code_pool_index,
1362 void LoadObjectHelper(
1373 void AluQ(uint8_t modrm_opcode,
1377 void AluQ(uint8_t modrm_opcode,
1382 void EmitSimple(
int opcode,
int opcode2 = -1,
int opcode3 = -1);
1383 void EmitUnaryQ(
Register reg,
int opcode,
int modrm_code);
1384 void EmitUnaryL(
Register reg,
int opcode,
int modrm_code);
1385 void EmitUnaryQ(
const Address& address,
int opcode,
int modrm_code);
1386 void EmitUnaryL(
const Address& address,
int opcode,
int modrm_code);
1404 void EmitQ(
int dst,
int src,
int opcode,
int prefix2 = -1,
int prefix1 = -1);
1405 void EmitL(
int dst,
int src,
int opcode,
int prefix2 = -1,
int prefix1 = -1);
1411 void EmitB(
int reg,
const Address& address,
int opcode);
1414 inline void EmitUint8(uint8_t value);
1415 inline void EmitInt32(int32_t value);
1416 inline void EmitUInt32(uint32_t value);
1417 inline void EmitInt64(int64_t value);
1419 inline void EmitRegisterREX(
Register reg,
1421 bool force_emit =
false);
1422 inline void EmitOperandREX(
int rm,
const Operand& operand, uint8_t rex);
1423 inline void EmitRegisterOperand(
int rm,
int reg);
1425 inline void EmitOperandSizeOverride();
1426 inline void EmitRegRegRex(
int reg,
int base, uint8_t rex =
REX_NONE);
1427 void EmitOperand(
int rm,
const Operand& operand);
1428 void EmitImmediate(
const Immediate& imm);
1429 void EmitComplex(
int rm,
const Operand& operand,
const Immediate& immediate);
1430 void EmitSignExtendedInt8(
int rm,
1433 void EmitLabel(
Label* label, intptr_t instruction_size);
1434 void EmitLabelLink(
Label* label);
1435 void EmitNearLabelLink(
Label* label);
1438 void EmitGenericShift(
bool wide,
int rm,
Register operand,
Register shifter);
1440 enum BarrierFilterMode {
1450 void StoreIntoArrayBarrier(
Register object,
1456 void MoveImmediate(
const Address& dst,
1461 std::function<void(
Register reg)> generate_invoke_write_barrier_wrapper_;
1462 std::function<void()> generate_invoke_array_write_barrier_;
1468inline void Assembler::EmitUint8(uint8_t value) {
1472inline void Assembler::EmitInt32(int32_t value) {
1476inline void Assembler::EmitUInt32(uint32_t value) {
1480inline void Assembler::EmitInt64(int64_t value) {
1484inline void Assembler::EmitRegisterREX(
Register reg, uint8_t rex,
bool force) {
1491inline void Assembler::EmitOperandREX(
int rm,
1492 const Operand& operand,
1498inline void Assembler::EmitRegRegRex(
int reg,
int base, uint8_t rex) {
1502 if (reg > 7) rex |=
REX_R;
1507inline void Assembler::EmitFixup(AssemblerFixup* fixup) {
1511inline void Assembler::EmitOperandSizeOverride() {
static bool equals(T *a, T *b)
#define DECLARE_ALU(op, opcode, opcode2, modrm_opcode)
#define AX(width, name,...)
#define RR(width, name,...)
#define XX(width, name,...)
#define DECLARE_SIMPLE(name, opcode)
#define REGULAR_INSTRUCTION(name,...)
#define AR(width, name,...)
#define XA(width, name,...)
#define DECLARE_XMM(name, code)
#define DECLARE_CMPPS(name, code)
#define DECLARE_CMOV(name, code)
#define REGULAR_UNARY(name, opcode, modrm)
static bool IsInt(intptr_t N, T value)
static bool IsUint(intptr_t N, T value)
static Address AddressBaseImm32(Register base, int32_t disp)
Address(Register base, Register index, ScaleFactor scale, int32_t disp)
Address(Register index, ScaleFactor scale, int32_t disp)
static Address AddressRIPRelative(int32_t disp)
Address(Register base, Register r)
Address & operator=(const Address &other)
static Address AddressBaseImm32(Register base, Register r)
Address(Register base, int32_t disp)
Address(Register base, Register index, ScaleFactor scale, Register r)
Address(Register index, ScaleFactor scale, Register r)
Address(const Address &other)
void LoadCompressedSmi(Register dst, const Address &address)
void Stop(const char *message)
void LoadCompressed(Register dst, const Address &address)
ObjectPoolBuilder & object_pool_builder()
void LoadCompressedFieldAddressForRegOffset(Register address, Register instance, Register offset_in_words_as_smi)
void LoadIndexedCompressed(Register dst, Register base, int32_t offset, Register index)
void ExtendNonNegativeSmi(Register dst)
void LoadAcquireCompressed(Register dst, const Address &address)
void EmitFixup(AssemblerFixup *fixup)
void PushRegistersInOrder(std::initializer_list< Register > regs)
void PopRegisterPair(Register r0, Register r1)
void MoveUnboxedDouble(FpuRegister dst, FpuRegister src)
void LoadClassId(Register result, Register object)
void StoreObject(const Address &dst, const Object &obj, OperandSize size=kWordBytes)
void SmiUntagOrCheckClass(Register object, intptr_t class_id, Label *smi)
void sarq(Register reg, const Immediate &imm)
void RestoreCodePointer()
void LoadPoolPointer(Register pp=PP)
void Call(Address target)
void unpcklpd(XmmRegister dst, XmmRegister src)
static Address ElementAddressForRegIndex(bool is_external, intptr_t cid, intptr_t index_scale, bool index_unboxed, Register array, Register index)
bool CanLoadFromObjectPool(const Object &object) const
void CompareClassId(Register object, intptr_t class_id, Register scratch=kNoRegister)
void PushRegisters(const RegisterSet ®isters)
void StoreUnboxedDouble(FpuRegister src, Register base, int32_t offset)
void Jmp(const Code &code, Register pp=PP)
void CompareObject(Register reg, const Object &object)
void ZeroInitCompressedSmiField(const Address &dest)
void movsd(XmmRegister dst, XmmRegister src)
void MoveUnboxedSimd128(FpuRegister dst, FpuRegister src)
void LoadUniqueObject(Register dst, const Object &obj, ObjectPoolBuilderEntry::SnapshotBehavior snapshot_behavior=ObjectPoolBuilderEntry::kSnapshotable)
void abspd(XmmRegister dst, XmmRegister src)
void LoadObject(Register dst, const Object &obj)
void CombineHashes(Register dst, Register other) override
void MonomorphicCheckedEntryJIT()
void BranchIfSmi(Register reg, Label *label, JumpDistance distance=kFarJump) override
void LoadTaggedClassIdMayBeSmi(Register result, Register object)
void notps(XmmRegister dst, XmmRegister src)
void movups(XmmRegister dst, const Address &src)
void AddImmediate(const Address &address, const Immediate &imm)
void LoadStaticFieldAddress(Register address, Register field, Register scratch)
void Load(Register reg, const Address &address, OperandSize type, Condition cond)
void BranchIfZero(Register src, Label *label, JumpDistance distance=kFarJump)
void unpckhpd(XmmRegister dst, XmmRegister src)
void movq(const Address &dst, XmmRegister src)
void LoadQImmediate(FpuRegister dst, simd128_value_t immediate)
void PushRegisterPair(Register r0, Register r1)
void StoreZero(const Address &address, Register temp=kNoRegister)
void shlq(Register reg, const Immediate &imm)
void Call(const Code &stub_entry, ObjectPoolBuilderEntry::SnapshotBehavior snapshot_behavior=ObjectPoolBuilderEntry::kSnapshotable)
void EmitEntryFrameVerification()
void pxor(XmmRegister dst, XmmRegister src)
Assembler(ObjectPoolBuilder *object_pool_builder, intptr_t far_branch_level=0)
void jmp(const ExternalLabel *label)
void movlhps(XmmRegister dst, XmmRegister src)
void ZeroInitSmiField(const Address &dest)
void movq(Register dst, Register src)
void LoadImmediate(Register reg, int64_t immediate) override
void LoadDImmediate(FpuRegister dst, double immediate)
void movl(const Address &dst, const Immediate &imm)
void movd(XmmRegister dst, Register src)
void movl(Register dst, const Immediate &src)
void DoubleNegate(XmmRegister dst, XmmRegister src)
void j(Condition condition, Label *label, JumpDistance distance=kFarJump)
void SmiUntag(Register reg)
void absps(XmmRegister dst, XmmRegister src)
void CompareImmediate(Register reg, const Immediate &imm, OperandSize width=kEightBytes)
void Jump(Label *label, JumpDistance distance=kFarJump)
void AddImmediate(Register reg, const Immediate &imm, OperandSize width=kEightBytes)
void shldq(Register dst, Register src, const Immediate &imm)
void JmpPatchable(const Code &code, Register pp)
void LoadFromStack(Register dst, intptr_t depth)
void movmskpd(Register dst, XmmRegister src)
void cvtsi2sdq(XmmRegister dst, Register src)
void leal(Register dst, const Address &src)
void shufps(XmmRegister dst, XmmRegister src, const Immediate &mask)
void shll(Register reg, const Immediate &imm)
void movb(const Address &dst, const Immediate &imm)
void shufpd(XmmRegister dst, XmmRegister src, const Immediate &mask)
void ExtendValue(Register dst, Register src, OperandSize sz) override
void CompareImmediate(Register rn, int32_t value, Condition cond)
void LoadIndexedPayload(Register dst, Register base, int32_t payload_offset, Register index, ScaleFactor scale, OperandSize sz=kEightBytes) override
void PushRegister(Register r)
void LoadMemoryValue(Register dst, Register base, int32_t offset)
void MulImmediate(Register reg, int64_t imm, OperandSize width=kEightBytes) override
void CompareImmediate(const Address &address, const Immediate &imm, OperandSize width=kEightBytes)
void imulq(Register dst, const Immediate &imm)
void cvtpd2ps(XmmRegister dst, XmmRegister src)
void set1ps(XmmRegister dst, Register tmp, const Immediate &imm)
void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode)
void set_constant_pool_allowed(bool b)
void sarq(Register operand, Register shifter)
void cvtps2pd(XmmRegister dst, XmmRegister src)
void subpl(XmmRegister dst, XmmRegister src)
void movw(Register dst, const Address &src)
void zerowps(XmmRegister dst, XmmRegister src)
void OrImmediate(Register dst, int64_t value)
void PushImmediate(const Immediate &imm)
void movmskps(Register dst, XmmRegister src)
void jmp(Label *label, JumpDistance distance=kFarJump)
void Align(int alignment, intptr_t offset)
static bool AddressCanHoldConstantIndex(const Object &constant, bool is_external, intptr_t cid, intptr_t index_scale)
void StoreObjectIntoObjectNoBarrier(Register object, const Address &dest, const Object &value, MemoryOrder memory_order=kRelaxedNonAtomic, OperandSize size=kWordBytes) override
void MaybeTraceAllocation(Register cid, Label *trace, Register temp_reg=kNoRegister, JumpDistance distance=JumpDistance::kFarJump)
void EnterDartFrame(intptr_t frame_size, Register new_pp=kNoRegister)
void EnterFullSafepoint()
void LoadClassById(Register result, Register class_id)
void cvtss2sd(XmmRegister dst, XmmRegister src)
void movzxw(Register dst, Register src)
void PushValueAtOffset(Register base, int32_t offset)
void LoadIsolate(Register dst)
void MaybeTraceAllocation(intptr_t cid, Label *trace, Register temp_reg=kNoRegister, JumpDistance distance=JumpDistance::kFarJump)
void imull(Register reg, const Immediate &imm)
void movsd(XmmRegister dst, const Address &src)
void PushImmediate(int64_t value)
void AndImmediate(Register dst, int64_t value) override
void OrImmediate(Register dst, const Immediate &imm)
void CheckAllocationCanary(Register top)
void XorImmediate(Register dst, const Immediate &imm)
void shll(Register operand, Register shifter)
void mov(Register rd, Operand o, Condition cond=AL)
void SetReturnAddress(Register value)
void GenerateUnRelocatedPcRelativeCall(intptr_t offset_into_target=0)
void CallCFunction(Address address, bool restore_rsp=false)
void LoadInt32FromBoxOrSmi(Register result, Register value) override
void Exchange(Register reg, const Address &mem)
void BranchIf(Condition condition, Label *label, JumpDistance distance=kFarJump)
void EnterOsrFrame(intptr_t extra_size)
void comisd(XmmRegister a, XmmRegister b)
void btl(Register dst, Register src)
void PushObject(const Object &object)
void AndRegisters(Register dst, Register src1, Register src2=kNoRegister) override
void testb(const Address &address, const Immediate &imm)
void sarl(Register reg, const Immediate &imm)
void jmp(const Code &code)
void Exchange(const Address &mem1, const Address &mem2)
void cmp(Register rn, Operand o, Condition cond=AL)
void LoadUnboxedSimd128(FpuRegister dst, Register base, int32_t offset)
XA(L, movups, 0x10, 0x0F)
void StoreMemoryValue(Register src, Register base, int32_t offset)
void TransitionGeneratedToNative(Register destination_address, Register new_exit_frame, Register new_exit_through_ffi, bool enter_safepoint)
void CompareImmediate(Register reg, int64_t immediate, OperandSize width=kEightBytes) override
void pushq(const Immediate &imm)
void StoreToStack(Register src, intptr_t depth)
void TestImmediate(Register dst, const Immediate &imm, OperandSize width=kEightBytes)
void J(Condition condition, const Code &code, Register pp)
void CallWithEquivalence(const Code &code, const Object &equivalence, CodeEntryKind entry_kind=CodeEntryKind::kNormal)
void movw(const Address &dst, const Immediate &imm)
void popq(const Address &address)
void SmiUntagAndSignExtend(Register dst, Register src)
void SubRegisters(Register dest, Register src)
void PopRegisters(const RegisterSet ®isters)
void StoreInternalPointer(Register object, const Address &dest, Register value)
void CompareRegisters(Register a, Register b)
void MulImmediate(Register reg, int32_t imm, OperandSize width=kFourBytes) override
void AndImmediate(Register dst, const Immediate &imm)
void cvttsd2sil(Register dst, XmmRegister src)
void AddRegisters(Register dest, Register src)
void testq(Register reg, const Immediate &imm)
void Bind(Label *label) override
void ReserveAlignedFrameSpace(intptr_t frame_space)
void negateps(XmmRegister dst, XmmRegister src)
void btq(Register base, int bit)
void MonomorphicCheckedEntryAOT()
void AddImmediate(Register dest, Register src, int64_t value)
void SubImmediate(const Address &address, const Immediate &imm)
void LockCmpxchgq(const Address &address, Register reg)
void movq(const Address &dst, const Immediate &imm)
void RangeCheck(Register value, Register temp, intptr_t low, intptr_t high, RangeCheckCondition condition, Label *target) override
void enter(const Immediate &imm)
bool constant_pool_allowed() const
void setcc(Condition condition, ByteRegister dst)
void PopRegister(Register r)
void CallCFunction(Register reg, bool restore_rsp=false)
void AddImmediate(Register reg, int64_t value, OperandSize width=kEightBytes)
void ArrayStoreBarrier(Register object, Register slot, Register value, CanBeSmi can_be_smi, Register scratch) override
void testb(const Address &address, Register reg)
void btq(Register dst, Register src)
void LslRegister(Register dst, Register shift) override
void add(Register rd, Register rn, Operand o, Condition cond=AL)
void shrl(Register operand, Register shifter)
void CompareWithMemoryValue(Register value, Address address, OperandSize size=kEightBytes) override
void shrdq(Register dst, Register src, Register shifter)
void mul(Register rd, Register rn, Register rm, Condition cond=AL)
void TryAllocateArray(intptr_t cid, intptr_t instance_size, Label *failure, JumpDistance distance, Register instance, Register end_address, Register temp)
void WriteAllocationCanary(Register top)
void addpl(XmmRegister dst, XmmRegister src)
void Load(Register dst, const Address &address, OperandSize sz=kEightBytes) override
void CallRuntime(const RuntimeEntry &entry, intptr_t argument_count)
void ExtractInstanceSizeFromTags(Register result, Register tags)
void LockCmpxchgl(const Address &address, Register reg)
void CopyMemoryWords(Register src, Register dst, Register size, Register temp=kNoRegister)
void CompareToStack(Register src, intptr_t depth)
void LoadImmediate(Register rd, Immediate value, Condition cond=AL)
void shrq(Register operand, Register shifter)
void MulImmediate(Register reg, const Immediate &imm, OperandSize width=kEightBytes)
static Address VMTagAddress()
void AndImmediate(Register rd, Register rs, int32_t imm, Condition cond=AL)
void cvtsd2ss(XmmRegister dst, XmmRegister src)
void CompareObjectRegisters(Register a, Register b)
void Jump(const Address &address)
static bool IsSafeSmi(const Object &object)
void movsxb(Register dst, ByteRegister src)
void SmiUntagAndSignExtend(Register reg)
void LoadAcquire(Register dst, const Address &address, OperandSize size=kEightBytes) override
void shldq(Register dst, Register src, Register shifter)
void cvtsi2sdl(XmmRegister dst, Register src)
void EnterCFrame(intptr_t frame_space)
void StoreBarrier(Register object, Register value, CanBeSmi can_be_smi, Register scratch) override
void call(const Address &address)
void TryAllocateObject(intptr_t cid, intptr_t instance_size, Label *failure, JumpDistance distance, Register instance_reg, Register temp) override
void AddScaled(Register dest, Register src, ScaleFactor scale, int32_t value)
void shlq(Register operand, Register shifter)
void LoadSImmediate(FpuRegister dst, float immediate)
void VerifyStoreNeedsNoWriteBarrier(Register object, Register value) override
void IncrementCompressedSmiField(const Address &dest, int64_t increment)
void cvttsd2siq(Register dst, XmmRegister src)
void CompareWords(Register reg1, Register reg2, intptr_t offset, Register count, Register temp, Label *equals) override
void StoreWordToPoolIndex(Register src, intptr_t index)
void pushq(const Address &address)
void shldl(Register dst, Register src, const Immediate &imm)
void testl(Register reg, const Immediate &imm)
void movl(Register dst, const Immediate &imm)
void pmovmskb(Register dst, XmmRegister src)
void movhlps(XmmRegister dst, XmmRegister src)
void movb(Register dst, const Address &src)
void BranchIfNotSmi(Register reg, Label *label, JumpDistance distance=kFarJump)
void GenerateUnRelocatedPcRelativeTailCall(intptr_t offset_into_target=0)
void negatepd(XmmRegister dst, XmmRegister src)
void LoadInt64FromBoxOrSmi(Register result, Register value) override
void Store(Register src, const Address &address, OperandSize sz=kEightBytes) override
void SubImmediate(Register reg, const Immediate &imm, OperandSize width=kEightBytes)
void ExitFullSafepoint(bool ignore_unwind_in_progress)
void LslImmediate(Register dst, int32_t shift)
void EnterFrame(intptr_t frame_space)
void shrq(Register reg, const Immediate &imm)
static bool IsSafe(const Object &object)
void jmp(const Address &address)
void BranchIfBit(Register rn, intptr_t bit_number, Condition condition, Label *label, JumpDistance distance=kFarJump)
void Drop(intptr_t stack_elements, Register tmp=TMP)
void OrImmediate(Register rd, Register rs, int32_t imm, Condition cond=AL)
void StoreIntoSmiField(const Address &dest, Register value)
void Jump(Register target)
void call(const ExternalLabel *label)
void CallPatchable(const Code &code, CodeEntryKind entry_kind=CodeEntryKind::kNormal, ObjectPoolBuilderEntry::SnapshotBehavior snapshot_behavior=ObjectPoolBuilderEntry::kSnapshotable)
void LoadClassIdMayBeSmi(Register result, Register object)
void sarl(Register operand, Register shifter)
void LoadUnboxedDouble(FpuRegister dst, Register base, int32_t offset)
void shrl(Register reg, const Immediate &imm)
void movss(XmmRegister dst, XmmRegister src)
void LoadIsolateGroup(Register dst)
void LoadFieldAddressForRegOffset(Register address, Register instance, Register offset_in_words_as_smi) override
void AndImmediate(Register dst, Register src, int64_t value)
void BranchOnMonomorphicCheckedEntryJIT(Label *label)
void movl(Register dst, XmmRegister src)
void Store(Register reg, const Address &address, OperandSize type, Condition cond)
void movzxb(Register dst, ByteRegister src)
void movss(XmmRegister dst, const Address &src)
void movq(Register dst, XmmRegister src)
void cmpxchgl(const Address &address, Register reg)
void MoveRegister(Register rd, Register rm, Condition cond)
void Breakpoint() override
void TransitionNativeToGenerated(bool leave_safepoint, bool ignore_unwind_in_progress=false)
void LoadWordFromPoolIndex(Register dst, intptr_t index)
void DoubleAbs(XmmRegister dst, XmmRegister src)
void LoadFieldAddressForOffset(Register address, Register instance, int32_t offset) override
void neg(Register rd, Register rm)
void StoreUnboxedSimd128(FpuRegister dst, Register base, int32_t offset)
void ExtractClassIdFromTags(Register result, Register tags)
void movq(XmmRegister dst, Register src)
void fldl(const Address &src)
void unpckhps(XmmRegister dst, XmmRegister src)
void movq(Register dst, const Immediate &imm)
void FinalizeHashForSize(intptr_t bit_size, Register dst, Register scratch=TMP) override
void SmiUntag(Register dst, Register src)
void EnsureHasClassIdInDEBUG(intptr_t cid, Register src, Register scratch, bool can_be_null=false) override
void LoadDispatchTable(Register dst)
void AddImmediate(Register rd, int32_t value, Condition cond=AL)
void LsrImmediate(Register dst, int32_t shift) override
void MoveMemoryToMemory(const Address &dst, const Address &src)
void LoadNativeEntry(Register dst, const ExternalLabel *label, ObjectPoolBuilderEntry::Patchability patchable)
static Address ElementAddressForIntIndex(bool is_external, intptr_t cid, intptr_t index_scale, Register array, intptr_t index)
void LoadCompressedMemoryValue(Register dst, Register base, int32_t offset)
void movsxw(Register dst, Register src)
void StoreRelease(Register src, const Address &address, OperandSize size=kWordBytes) override
void LoadImmediate(Register reg, const Immediate &imm)
void fstpl(const Address &dst)
void SmiTag(Register reg) override
void LoadUnboxedSingle(FpuRegister dst, Register base, int32_t offset)
void unpcklps(XmmRegister dst, XmmRegister src)
void ffree(intptr_t value)
void ArithmeticShiftRightImmediate(Register reg, intptr_t shift) override
void movaps(XmmRegister dst, XmmRegister src)
FieldAddress & operator=(const FieldAddress &other)
FieldAddress(Register base, Register r)
FieldAddress(Register base, Register index, ScaleFactor scale, Register r)
FieldAddress(const FieldAddress &other)
FieldAddress(Register base, Register index, ScaleFactor scale, int32_t disp)
FieldAddress(Register base, int32_t disp)
void div(Register rd, Register rs1, Register rs2)
intptr_t far_branch_level() const
bool Equals(const Operand &other) const
void SetSIB(ScaleFactor scale, Register index, Register base)
Operand(const Operand &other)
void SetDisp8(int8_t disp)
Operand & operator=(const Operand &other)
void SetModRM(int mod, Register rm)
void SetDisp32(int32_t disp)
ScaleFactor scale() const
#define X86_CONDITIONAL_SUFFIXES(F)
#define XMM_CONDITIONAL_CODES(F)
#define X86_ZERO_OPERAND_1_BYTE_INSTRUCTIONS(F)
constexpr OperandSize kWordBytes
@ TIMES_COMPRESSED_HALF_WORD_SIZE
@ TIMES_COMPRESSED_WORD_SIZE
static constexpr intptr_t kAllocationCanary