Index: src/assembler_ia32.h |
diff --git a/src/assembler_ia32.h b/src/assembler_ia32.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..810fab33e82e0d8e05a8e65690dd68731534e5ce |
--- /dev/null |
+++ b/src/assembler_ia32.h |
@@ -0,0 +1,724 @@ |
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
+// for details. All rights reserved. Use of this source code is governed by a |
+// BSD-style license that can be found in the LICENSE file. |
+// |
+// Modified by the Subzero authors. |
+// |
+//===- subzero/src/assembler_ia32.h - Assembler for x86-32 ----------------===// |
+// |
+// The Subzero Code Generator |
+// |
+// This file is distributed under the University of Illinois Open Source |
+// License. See LICENSE.TXT for details. |
+// |
+//===----------------------------------------------------------------------===// |
+// |
+// This file implements the Assembler class for x86-32. |
+// |
+//===----------------------------------------------------------------------===// |
+ |
+#ifndef SUBZERO_SRC_ASSEMBLER_IA32_H_ |
+#define SUBZERO_SRC_ASSEMBLER_IA32_H_ |
+ |
+#include "IceDefs.h" |
+#include "IceConditionCodesX8632.h" |
+#include "IceRegistersX8632.h" |
+#include "IceTypes.h" |
+#include "IceUtils.h" |
+ |
+#include "assembler.h" |
+ |
+namespace Ice { |
+ |
+class Assembler; |
+class ConstantRelocatable; |
+ |
+using RegX8632::GPRRegister; |
+using RegX8632::XmmRegister; |
+using RegX8632::ByteRegister; |
+ |
+namespace x86 { |
+ |
+const int MAX_NOP_SIZE = 8; |
+ |
+enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; |
+ |
+class DisplacementRelocation : public AssemblerFixup { |
+public: |
+ static DisplacementRelocation *create(Assembler *Asm, FixupKind Kind, |
+ const ConstantRelocatable *Sym) { |
+ return new (Asm->Allocate<DisplacementRelocation>()) |
+ DisplacementRelocation(Kind, Sym); |
+ } |
+ |
+ void Process(const MemoryRegion ®ion, intptr_t position) { |
+ (void)region; |
+ (void)position; |
+ llvm_unreachable("We might not be using this Process() method later."); |
+ } |
+ |
+private: |
+ DisplacementRelocation(FixupKind Kind, const ConstantRelocatable *Sym) |
+ : AssemblerFixup(Kind, Sym) {} |
+ DisplacementRelocation(const DisplacementRelocation &) LLVM_DELETED_FUNCTION; |
+ DisplacementRelocation & |
+ operator=(const DisplacementRelocation &) LLVM_DELETED_FUNCTION; |
+}; |
+ |
+class Immediate { |
+public: |
+ explicit Immediate(int32_t value) : value_(value) {} |
+ |
+ Immediate(const Immediate &other) : value_(other.value_) {} |
+ |
+ int32_t value() const { return value_; } |
+ |
+ bool is_int8() const { return Utils::IsInt(8, value_); } |
+ bool is_uint8() const { return Utils::IsUint(8, value_); } |
+ bool is_uint16() const { return Utils::IsUint(16, value_); } |
+ |
+private: |
+ const int32_t value_; |
+}; |
+ |
+class Operand { |
+public: |
+ uint8_t mod() const { return (encoding_at(0) >> 6) & 3; } |
+ |
+ GPRRegister rm() const { |
+ return static_cast<GPRRegister>(encoding_at(0) & 7); |
+ } |
+ |
+ ScaleFactor scale() const { |
+ return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); |
+ } |
+ |
+ GPRRegister index() const { |
+ return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7); |
+ } |
+ |
+ GPRRegister base() const { |
+ return static_cast<GPRRegister>(encoding_at(1) & 7); |
+ } |
+ |
+ int8_t disp8() const { |
+ assert(length_ >= 2); |
+ return static_cast<int8_t>(encoding_[length_ - 1]); |
+ } |
+ |
+ int32_t disp32() const { |
+ assert(length_ >= 5); |
+ return bit_copy<int32_t>(encoding_[length_ - 4]); |
+ } |
+ |
+ AssemblerFixup *fixup() const { return fixup_; } |
+ |
+ Operand(const Operand &other) : length_(other.length_), fixup_(other.fixup_) { |
+ memmove(&encoding_[0], &other.encoding_[0], other.length_); |
+ } |
+ |
+ Operand &operator=(const Operand &other) { |
+ length_ = other.length_; |
+ fixup_ = other.fixup_; |
+ memmove(&encoding_[0], &other.encoding_[0], other.length_); |
+ return *this; |
+ } |
+ |
+protected: |
+ Operand() : length_(0), fixup_(NULL) {} // Needed by subclass Address. |
+ |
+ void SetModRM(int mod, GPRRegister rm) { |
+ assert((mod & ~3) == 0); |
+ encoding_[0] = (mod << 6) | rm; |
+ length_ = 1; |
+ } |
+ |
+ void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { |
+ assert(length_ == 1); |
+ assert((scale & ~3) == 0); |
+ encoding_[1] = (scale << 6) | (index << 3) | base; |
+ length_ = 2; |
+ } |
+ |
+ void SetDisp8(int8_t disp) { |
+ assert(length_ == 1 || length_ == 2); |
+ encoding_[length_++] = static_cast<uint8_t>(disp); |
+ } |
+ |
+ void SetDisp32(int32_t disp) { |
+ assert(length_ == 1 || length_ == 2); |
+ intptr_t disp_size = sizeof(disp); |
+ memmove(&encoding_[length_], &disp, disp_size); |
+ length_ += disp_size; |
+ } |
+ |
+ void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; } |
+ |
+private: |
+ uint8_t length_; |
+ uint8_t encoding_[6]; |
+ uint8_t padding_; |
+ AssemblerFixup *fixup_; |
+ |
+ explicit Operand(GPRRegister reg) : fixup_(NULL) { SetModRM(3, reg); } |
+ |
+ // Get the operand encoding byte at the given index. |
+ uint8_t encoding_at(intptr_t index) const { |
+ assert(index >= 0 && index < length_); |
+ return encoding_[index]; |
+ } |
+ |
+ // Returns whether or not this operand is really the given register in |
+ // disguise. Used from the assembler to generate better encodings. |
+ bool IsRegister(GPRRegister reg) const { |
+ return ((encoding_[0] & 0xF8) == 0xC0) // Addressing mode is register only. |
+ && ((encoding_[0] & 0x07) == reg); // Register codes match. |
+ } |
+ |
+ friend class AssemblerX86; |
+}; |
+ |
+class Address : public Operand { |
+public: |
+ Address(GPRRegister base, int32_t disp) { |
+ if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) { |
+ SetModRM(0, base); |
+ if (base == RegX8632::Encoded_Reg_esp) |
+ SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); |
+ } else if (Utils::IsInt(8, disp)) { |
+ SetModRM(1, base); |
+ if (base == RegX8632::Encoded_Reg_esp) |
+ SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); |
+ SetDisp8(disp); |
+ } else { |
+ SetModRM(2, base); |
+ if (base == RegX8632::Encoded_Reg_esp) |
+ SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base); |
+ SetDisp32(disp); |
+ } |
+ } |
+ |
+ Address(GPRRegister index, ScaleFactor scale, int32_t disp) { |
+ assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode. |
+ SetModRM(0, RegX8632::Encoded_Reg_esp); |
+ SetSIB(scale, index, RegX8632::Encoded_Reg_ebp); |
+ SetDisp32(disp); |
+ } |
+ |
+ Address(GPRRegister base, GPRRegister index, ScaleFactor scale, |
+ int32_t disp) { |
+ assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode. |
+ if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) { |
+ SetModRM(0, RegX8632::Encoded_Reg_esp); |
+ SetSIB(scale, index, base); |
+ } else if (Utils::IsInt(8, disp)) { |
+ SetModRM(1, RegX8632::Encoded_Reg_esp); |
+ SetSIB(scale, index, base); |
+ SetDisp8(disp); |
+ } else { |
+ SetModRM(2, RegX8632::Encoded_Reg_esp); |
+ SetSIB(scale, index, base); |
+ SetDisp32(disp); |
+ } |
+ } |
+ |
+ Address(const Address &other) : Operand(other) {} |
+ |
+ Address &operator=(const Address &other) { |
+ Operand::operator=(other); |
+ return *this; |
+ } |
+ |
+ static Address Absolute(const uintptr_t addr, AssemblerFixup *fixup) { |
+ Address result; |
+ result.SetModRM(0, RegX8632::Encoded_Reg_ebp); |
+ result.SetDisp32(addr); |
+ result.SetFixup(fixup); |
+ return result; |
+ } |
+ |
+ static Address ofConstPool(GlobalContext *Ctx, Assembler *Asm, |
+ const Constant *Imm); |
+ |
+private: |
+ Address() {} // Needed by Address::Absolute. |
+}; |
+ |
+class Label { |
+public: |
+ Label() : position_(0), num_unresolved_(0) { |
+#ifdef DEBUG |
+ for (int i = 0; i < kMaxUnresolvedBranches; i++) { |
+ unresolved_near_positions_[i] = -1; |
+ } |
+#endif // DEBUG |
+ } |
+ |
+ ~Label() { |
+ // Assert if label is being destroyed with unresolved branches pending. |
+ assert(!IsLinked()); |
+ assert(!HasNear()); |
+ } |
+ |
+ // TODO(jvoung): why are labels offset by this? |
+ static const uint32_t kWordSize = sizeof(uint32_t); |
+ |
+ // Returns the position for bound labels (branches that come after this |
+ // are considered backward branches). Cannot be used for unused or linked |
+ // labels. |
+ intptr_t Position() const { |
+ assert(IsBound()); |
+ return -position_ - kWordSize; |
+ } |
+ |
+ // Returns the position of an earlier branch instruction that was linked |
+ // to this label (branches that use this are considered forward branches). |
+ // The linked instructions form a linked list, of sorts, using the |
+ // instruction's displacement field for the location of the next |
+ // instruction that is also linked to this label. |
+ intptr_t LinkPosition() const { |
+ assert(IsLinked()); |
+ return position_ - kWordSize; |
+ } |
+ |
+ // Returns the position of an earlier branch instruction which |
+ // assumes that this label is "near", and bumps iterator to the |
+ // next near position. |
+ intptr_t NearPosition() { |
+ assert(HasNear()); |
+ return unresolved_near_positions_[--num_unresolved_]; |
+ } |
+ |
+ bool IsBound() const { return position_ < 0; } |
+ bool IsLinked() const { return position_ > 0; } |
+ bool IsUnused() const { return (position_ == 0) && (num_unresolved_ == 0); } |
+ bool HasNear() const { return num_unresolved_ != 0; } |
+ |
+private: |
+ void BindTo(intptr_t position) { |
+ assert(!IsBound()); |
+ assert(!HasNear()); |
+ position_ = -position - kWordSize; |
+ assert(IsBound()); |
+ } |
+ |
+ void LinkTo(intptr_t position) { |
+ assert(!IsBound()); |
+ position_ = position + kWordSize; |
+ assert(IsLinked()); |
+ } |
+ |
+ void NearLinkTo(intptr_t position) { |
+ assert(!IsBound()); |
+ assert(num_unresolved_ < kMaxUnresolvedBranches); |
+ unresolved_near_positions_[num_unresolved_++] = position; |
+ } |
+ |
+ static const int kMaxUnresolvedBranches = 20; |
+ |
+ intptr_t position_; |
+ intptr_t num_unresolved_; |
+ intptr_t unresolved_near_positions_[kMaxUnresolvedBranches]; |
+ |
+ friend class AssemblerX86; |
+ Label(const Label &) LLVM_DELETED_FUNCTION; |
+ Label &operator=(const Label &) LLVM_DELETED_FUNCTION; |
+}; |
+ |
+class AssemblerX86 : public Assembler { |
+public: |
+ explicit AssemblerX86(bool use_far_branches = false) : buffer_(*this) { |
+ // This mode is only needed and implemented for MIPS and ARM. |
+ assert(!use_far_branches); |
+ } |
+ ~AssemblerX86() {} |
+ |
+ static const bool kNearJump = true; |
+ static const bool kFarJump = false; |
+ |
+ // Operations to emit XMM instructions (and dispatch on operand type). |
+ typedef void (AssemblerX86::*TypedEmitXmmXmm)(Type, XmmRegister, XmmRegister); |
+ typedef void (AssemblerX86::*TypedEmitXmmAddr)(Type, XmmRegister, |
+ const Address &); |
+ typedef void (AssemblerX86::*TypedEmitAddrXmm)(Type, const Address &, |
+ XmmRegister); |
+ struct TypedXmmEmitters { |
+ TypedEmitXmmXmm XmmXmm; |
+ TypedEmitXmmAddr XmmAddr; |
+ TypedEmitAddrXmm AddrXmm; |
+ }; |
+ |
+ /* |
+ * Emit Machine Instructions. |
+ */ |
+ void call(GPRRegister reg); |
+ void call(const Address &address); |
+ void call(Label *label); |
+ void call(const ConstantRelocatable *label); |
+ |
+ static const intptr_t kCallExternalLabelSize = 5; |
+ |
+ void pushl(GPRRegister reg); |
+ void pushl(const Address &address); |
+ void pushl(const Immediate &imm); |
+ |
+ void popl(GPRRegister reg); |
+ void popl(const Address &address); |
+ |
+ void pushal(); |
+ void popal(); |
+ |
+ void setcc(CondX86::BrCond condition, ByteRegister dst); |
+ |
+ void movl(GPRRegister dst, const Immediate &src); |
+ void movl(GPRRegister dst, GPRRegister src); |
+ |
+ void movl(GPRRegister dst, const Address &src); |
+ void movl(const Address &dst, GPRRegister src); |
+ void movl(const Address &dst, const Immediate &imm); |
+ |
+ void movzxb(GPRRegister dst, ByteRegister src); |
+ void movzxb(GPRRegister dst, const Address &src); |
+ void movsxb(GPRRegister dst, ByteRegister src); |
+ void movsxb(GPRRegister dst, const Address &src); |
+ |
+ void movb(ByteRegister dst, const Address &src); |
+ void movb(const Address &dst, ByteRegister src); |
+ void movb(const Address &dst, const Immediate &imm); |
+ |
+ void movzxw(GPRRegister dst, GPRRegister src); |
+ void movzxw(GPRRegister dst, const Address &src); |
+ void movsxw(GPRRegister dst, GPRRegister src); |
+ void movsxw(GPRRegister dst, const Address &src); |
+ void movw(GPRRegister dst, const Address &src); |
+ void movw(const Address &dst, GPRRegister src); |
+ |
+ void leal(GPRRegister dst, const Address &src); |
+ |
+ void cmov(CondX86::BrCond cond, GPRRegister dst, GPRRegister src); |
+ |
+ void rep_movsb(); |
+ |
+ void movss(XmmRegister dst, const Address &src); |
+ void movss(const Address &dst, XmmRegister src); |
+ void movss(XmmRegister dst, XmmRegister src); |
+ |
+ void movd(XmmRegister dst, GPRRegister src); |
+ void movd(GPRRegister dst, XmmRegister src); |
+ |
+ void movq(const Address &dst, XmmRegister src); |
+ void movq(XmmRegister dst, const Address &src); |
+ |
+ void addss(Type Ty, XmmRegister dst, XmmRegister src); |
+ void addss(Type Ty, XmmRegister dst, const Address &src); |
+ void subss(Type Ty, XmmRegister dst, XmmRegister src); |
+ void subss(Type Ty, XmmRegister dst, const Address &src); |
+ void mulss(Type Ty, XmmRegister dst, XmmRegister src); |
+ void mulss(Type Ty, XmmRegister dst, const Address &src); |
+ void divss(Type Ty, XmmRegister dst, XmmRegister src); |
+ void divss(Type Ty, XmmRegister dst, const Address &src); |
+ |
+ void movsd(XmmRegister dst, const Address &src); |
+ void movsd(const Address &dst, XmmRegister src); |
+ void movsd(XmmRegister dst, XmmRegister src); |
+ |
+ void movaps(XmmRegister dst, XmmRegister src); |
+ |
+ void movups(XmmRegister dst, const Address &src); |
+ void movups(const Address &dst, XmmRegister src); |
+ |
+ void padd(Type Ty, XmmRegister dst, XmmRegister src); |
+ void padd(Type Ty, XmmRegister dst, const Address &src); |
+ void pand(Type Ty, XmmRegister dst, XmmRegister src); |
+ void pand(Type Ty, XmmRegister dst, const Address &src); |
+ void pandn(Type Ty, XmmRegister dst, XmmRegister src); |
+ void pandn(Type Ty, XmmRegister dst, const Address &src); |
+ void pmuludq(Type Ty, XmmRegister dst, XmmRegister src); |
+ void pmuludq(Type Ty, XmmRegister dst, const Address &src); |
+ void por(Type Ty, XmmRegister dst, XmmRegister src); |
+ void por(Type Ty, XmmRegister dst, const Address &src); |
+ void psub(Type Ty, XmmRegister dst, XmmRegister src); |
+ void psub(Type Ty, XmmRegister dst, const Address &src); |
+ void pxor(Type Ty, XmmRegister dst, XmmRegister src); |
+ void pxor(Type Ty, XmmRegister dst, const Address &src); |
+ |
+ void addps(Type Ty, XmmRegister dst, XmmRegister src); |
+ void addps(Type Ty, XmmRegister dst, const Address &src); |
+ void subps(Type Ty, XmmRegister dst, XmmRegister src); |
+ void subps(Type Ty, XmmRegister dst, const Address &src); |
+ void divps(Type Ty, XmmRegister dst, XmmRegister src); |
+ void divps(Type Ty, XmmRegister dst, const Address &src); |
+ void mulps(Type Ty, XmmRegister dst, XmmRegister src); |
+ void mulps(Type Ty, XmmRegister dst, const Address &src); |
+ void minps(XmmRegister dst, XmmRegister src); |
+ void maxps(XmmRegister dst, XmmRegister src); |
+ void andps(XmmRegister dst, XmmRegister src); |
+ void andps(XmmRegister dst, const Address &src); |
+ void orps(XmmRegister dst, XmmRegister src); |
+ |
+ void cmpps(XmmRegister dst, XmmRegister src, CondX86::CmppsCond CmpCondition); |
+ void cmpps(XmmRegister dst, const Address &src, |
+ CondX86::CmppsCond CmpCondition); |
+ |
+ void sqrtps(XmmRegister dst); |
+ void rsqrtps(XmmRegister dst); |
+ void reciprocalps(XmmRegister dst); |
+ void movhlps(XmmRegister dst, XmmRegister src); |
+ void movlhps(XmmRegister dst, XmmRegister src); |
+ void unpcklps(XmmRegister dst, XmmRegister src); |
+ void unpckhps(XmmRegister dst, XmmRegister src); |
+ void unpcklpd(XmmRegister dst, XmmRegister src); |
+ void unpckhpd(XmmRegister dst, XmmRegister src); |
+ |
+ void set1ps(XmmRegister dst, GPRRegister tmp, const Immediate &imm); |
+ void shufps(XmmRegister dst, XmmRegister src, const Immediate &mask); |
+ |
+ void minpd(XmmRegister dst, XmmRegister src); |
+ void maxpd(XmmRegister dst, XmmRegister src); |
+ void sqrtpd(XmmRegister dst); |
+ void cvtps2pd(XmmRegister dst, XmmRegister src); |
+ void cvtpd2ps(XmmRegister dst, XmmRegister src); |
+ void shufpd(XmmRegister dst, XmmRegister src, const Immediate &mask); |
+ |
+ void cvtsi2ss(XmmRegister dst, GPRRegister src); |
+ void cvtsi2sd(XmmRegister dst, GPRRegister src); |
+ |
+ void cvtss2si(GPRRegister dst, XmmRegister src); |
+ void cvtss2sd(XmmRegister dst, XmmRegister src); |
+ |
+ void cvtsd2si(GPRRegister dst, XmmRegister src); |
+ void cvtsd2ss(XmmRegister dst, XmmRegister src); |
+ |
+ void cvttss2si(GPRRegister dst, XmmRegister src); |
+ void cvttsd2si(GPRRegister dst, XmmRegister src); |
+ |
+ void cvtdq2pd(XmmRegister dst, XmmRegister src); |
+ |
+ void ucomiss(Type Ty, XmmRegister a, XmmRegister b); |
+ void ucomiss(Type Ty, XmmRegister a, const Address &b); |
+ |
+ void movmskpd(GPRRegister dst, XmmRegister src); |
+ void movmskps(GPRRegister dst, XmmRegister src); |
+ |
+ void sqrtss(Type Ty, XmmRegister dst, const Address &src); |
+ void sqrtss(Type Ty, XmmRegister dst, XmmRegister src); |
+ |
+ void xorpd(XmmRegister dst, const Address &src); |
+ void xorpd(XmmRegister dst, XmmRegister src); |
+ void xorps(XmmRegister dst, const Address &src); |
+ void xorps(XmmRegister dst, XmmRegister src); |
+ |
+ void andpd(XmmRegister dst, const Address &src); |
+ void andpd(XmmRegister dst, XmmRegister src); |
+ |
+ void orpd(XmmRegister dst, XmmRegister src); |
+ |
+ void pextrd(GPRRegister dst, XmmRegister src, const Immediate &imm); |
+ void pmovsxdq(XmmRegister dst, XmmRegister src); |
+ void pcmpeqq(XmmRegister dst, XmmRegister src); |
+ |
+ enum RoundingMode { |
+ kRoundToNearest = 0x0, |
+ kRoundDown = 0x1, |
+ kRoundUp = 0x2, |
+ kRoundToZero = 0x3 |
+ }; |
+ void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode); |
+ |
+ void flds(const Address &src); |
+ void fstps(const Address &dst); |
+ |
+ void fldl(const Address &src); |
+ void fstpl(const Address &dst); |
+ |
+ void fnstcw(const Address &dst); |
+ void fldcw(const Address &src); |
+ |
+ void fistpl(const Address &dst); |
+ void fistps(const Address &dst); |
+ void fildl(const Address &src); |
+ void filds(const Address &src); |
+ |
+ void fincstp(); |
+ |
+ void xchgl(GPRRegister dst, GPRRegister src); |
+ |
+ void cmpl(GPRRegister reg, const Immediate &imm); |
+ void cmpl(GPRRegister reg0, GPRRegister reg1); |
+ void cmpl(GPRRegister reg, const Address &address); |
+ void cmpl(const Address &address, GPRRegister reg); |
+ void cmpl(const Address &address, const Immediate &imm); |
+ void cmpb(const Address &address, const Immediate &imm); |
+ |
+ void testl(GPRRegister reg1, GPRRegister reg2); |
+ void testl(GPRRegister reg, const Immediate &imm); |
+ |
+ void andl(GPRRegister dst, const Immediate &imm); |
+ void andl(GPRRegister dst, GPRRegister src); |
+ void andl(GPRRegister dst, const Address &address); |
+ |
+ void orl(GPRRegister dst, const Immediate &imm); |
+ void orl(GPRRegister dst, GPRRegister src); |
+ void orl(GPRRegister dst, const Address &address); |
+ |
+ void xorl(GPRRegister dst, const Immediate &imm); |
+ void xorl(GPRRegister dst, GPRRegister src); |
+ void xorl(GPRRegister dst, const Address &address); |
+ |
+ void addl(GPRRegister dst, GPRRegister src); |
+ void addl(GPRRegister reg, const Immediate &imm); |
+ void addl(GPRRegister reg, const Address &address); |
+ |
+ void addl(const Address &address, GPRRegister reg); |
+ void addl(const Address &address, const Immediate &imm); |
+ |
+ void adcl(GPRRegister dst, GPRRegister src); |
+ void adcl(GPRRegister reg, const Immediate &imm); |
+ void adcl(GPRRegister dst, const Address &address); |
+ void adcl(const Address &dst, GPRRegister src); |
+ |
+ void subl(GPRRegister dst, GPRRegister src); |
+ void subl(GPRRegister reg, const Immediate &imm); |
+ void subl(GPRRegister reg, const Address &address); |
+ void subl(const Address &address, GPRRegister reg); |
+ |
+ void cdq(); |
+ |
+ void idivl(GPRRegister reg); |
+ |
+ void imull(GPRRegister dst, GPRRegister src); |
+ void imull(GPRRegister reg, const Immediate &imm); |
+ void imull(GPRRegister reg, const Address &address); |
+ |
+ void imull(GPRRegister reg); |
+ void imull(const Address &address); |
+ |
+ void mull(GPRRegister reg); |
+ void mull(const Address &address); |
+ |
+ void sbbl(GPRRegister dst, GPRRegister src); |
+ void sbbl(GPRRegister reg, const Immediate &imm); |
+ void sbbl(GPRRegister reg, const Address &address); |
+ void sbbl(const Address &address, GPRRegister reg); |
+ |
+ void incl(GPRRegister reg); |
+ void incl(const Address &address); |
+ |
+ void decl(GPRRegister reg); |
+ void decl(const Address &address); |
+ |
+ void shll(GPRRegister reg, const Immediate &imm); |
+ void shll(GPRRegister operand, GPRRegister shifter); |
+ void shll(const Address &operand, GPRRegister shifter); |
+ void shrl(GPRRegister reg, const Immediate &imm); |
+ void shrl(GPRRegister operand, GPRRegister shifter); |
+ void sarl(GPRRegister reg, const Immediate &imm); |
+ void sarl(GPRRegister operand, GPRRegister shifter); |
+ void sarl(const Address &address, GPRRegister shifter); |
+ void shld(GPRRegister dst, GPRRegister src); |
+ void shld(GPRRegister dst, GPRRegister src, const Immediate &imm); |
+ void shld(const Address &operand, GPRRegister src); |
+ void shrd(GPRRegister dst, GPRRegister src); |
+ void shrd(GPRRegister dst, GPRRegister src, const Immediate &imm); |
+ void shrd(const Address &dst, GPRRegister src); |
+ |
+ void negl(GPRRegister reg); |
+ void notl(GPRRegister reg); |
+ |
+ void bsrl(GPRRegister dst, GPRRegister src); |
+ |
+ void bt(GPRRegister base, GPRRegister offset); |
+ |
+ void ret(); |
+ void ret(const Immediate &imm); |
+ |
+ // 'size' indicates size in bytes and must be in the range 1..8. |
+ void nop(int size = 1); |
+ void int3(); |
+ void hlt(); |
+ |
+ void j(CondX86::BrCond condition, Label *label, bool near = kFarJump); |
+ void j(CondX86::BrCond condition, const ConstantRelocatable *label); |
+ |
+ void jmp(GPRRegister reg); |
+ void jmp(Label *label, bool near = kFarJump); |
+ void jmp(const ConstantRelocatable *label); |
+ |
+ void lock(); |
+ void cmpxchgl(const Address &address, GPRRegister reg); |
+ |
+ void LockCmpxchgl(const Address &address, GPRRegister reg) { |
+ lock(); |
+ cmpxchgl(address, reg); |
+ } |
+ |
+ intptr_t PreferredLoopAlignment() { return 16; } |
+ void Align(intptr_t alignment, intptr_t offset); |
+ void Bind(Label *label); |
+ |
+ intptr_t CodeSize() const { return buffer_.Size(); } |
+ |
+ void FinalizeInstructions(const MemoryRegion ®ion) { |
+ buffer_.FinalizeInstructions(region); |
+ } |
+ |
+ // Expose the buffer, for bringup... |
+ intptr_t GetPosition() const { return buffer_.GetPosition(); } |
+ template <typename T> T LoadBuffer(intptr_t position) const { |
+ return buffer_.Load<T>(position); |
+ } |
+ AssemblerFixup *GetLatestFixup() const { return buffer_.GetLatestFixup(); } |
+ |
+private: |
+ inline void EmitUint8(uint8_t value); |
+ inline void EmitInt32(int32_t value); |
+ inline void EmitRegisterOperand(int rm, int reg); |
+ inline void EmitXmmRegisterOperand(int rm, XmmRegister reg); |
+ inline void EmitFixup(AssemblerFixup *fixup); |
+ inline void EmitOperandSizeOverride(); |
+ |
+ void EmitOperand(int rm, const Operand &operand); |
+ void EmitImmediate(const Immediate &imm); |
+ void EmitComplexI8(int rm, const Operand &operand, |
+ const Immediate &immediate); |
+ void EmitComplex(int rm, const Operand &operand, const Immediate &immediate); |
+ void EmitLabel(Label *label, intptr_t instruction_size); |
+ void EmitLabelLink(Label *label); |
+ void EmitNearLabelLink(Label *label); |
+ |
+ void EmitGenericShift(int rm, GPRRegister reg, const Immediate &imm); |
+ void EmitGenericShift(int rm, const Operand &operand, GPRRegister shifter); |
+ |
+ AssemblerBuffer buffer_; |
+ |
+ AssemblerX86(const AssemblerX86 &) LLVM_DELETED_FUNCTION; |
+ AssemblerX86 &operator=(const AssemblerX86 &) LLVM_DELETED_FUNCTION; |
+}; |
+ |
+inline void AssemblerX86::EmitUint8(uint8_t value) { |
+ buffer_.Emit<uint8_t>(value); |
+} |
+ |
+inline void AssemblerX86::EmitInt32(int32_t value) { |
+ buffer_.Emit<int32_t>(value); |
+} |
+ |
+inline void AssemblerX86::EmitRegisterOperand(int rm, int reg) { |
+ assert(rm >= 0 && rm < 8); |
+ buffer_.Emit<uint8_t>(0xC0 + (rm << 3) + reg); |
+} |
+ |
+inline void AssemblerX86::EmitXmmRegisterOperand(int rm, XmmRegister reg) { |
+ EmitRegisterOperand(rm, static_cast<GPRRegister>(reg)); |
+} |
+ |
+inline void AssemblerX86::EmitFixup(AssemblerFixup *fixup) { |
+ buffer_.EmitFixup(fixup); |
+} |
+ |
+inline void AssemblerX86::EmitOperandSizeOverride() { EmitUint8(0x66); } |
+ |
+} // end of namespace x86 |
+} // end of namespace Ice |
+ |
+#endif // SUBZERO_SRC_ASSEMBLER_IA32_H_ |