Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(846)

Unified Diff: src/assembler_ia32.h

Issue 574133002: Add initial integrated assembler w/ some Xmm ops. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: remove duplicate pxor, and use enum Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/assembler.cpp ('k') | src/assembler_ia32.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 &region, 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 &region) {
+ 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_
« no previous file with comments | « src/assembler.cpp ('k') | src/assembler_ia32.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698