summaryrefslogtreecommitdiff
path: root/compiler/utils/x86/assembler_x86.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils/x86/assembler_x86.h')
-rw-r--r--compiler/utils/x86/assembler_x86.h84
1 files changed, 82 insertions, 2 deletions
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 27fde26c80..a9050e6df1 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -73,6 +73,10 @@ class Operand : public ValueObject {
return static_cast<Register>(encoding_at(1) & 7);
}
+ int32_t disp() const {
+ return disp_;
+ }
+
int8_t disp8() const {
CHECK_GE(length_, 2);
return static_cast<int8_t>(encoding_[length_ - 1]);
@@ -92,7 +96,7 @@ class Operand : public ValueObject {
protected:
// Operand can be sub classed (e.g: Address).
- Operand() : length_(0), fixup_(nullptr) { }
+ Operand() : length_(0), disp_(0), fixup_(nullptr) { }
void SetModRM(int mod_in, Register rm_in) {
CHECK_EQ(mod_in & ~3, 0);
@@ -110,6 +114,7 @@ class Operand : public ValueObject {
void SetDisp8(int8_t disp) {
CHECK(length_ == 1 || length_ == 2);
encoding_[length_++] = static_cast<uint8_t>(disp);
+ disp_ = disp;
}
void SetDisp32(int32_t disp) {
@@ -117,6 +122,7 @@ class Operand : public ValueObject {
int disp_size = sizeof(disp);
memmove(&encoding_[length_], &disp, disp_size);
length_ += disp_size;
+ disp_ = disp;
}
AssemblerFixup* GetFixup() const {
@@ -130,12 +136,13 @@ class Operand : public ValueObject {
private:
uint8_t length_;
uint8_t encoding_[6];
+ int32_t disp_;
// A fixup can be associated with the operand, in order to be applied after the
// code has been generated. This is used for constant area fixups.
AssemblerFixup* fixup_;
- explicit Operand(Register reg) : fixup_(nullptr) { SetModRM(3, reg); }
+ explicit Operand(Register reg) : disp_(0), fixup_(nullptr) { SetModRM(3, reg); }
// Get the operand encoding byte at the given index.
uint8_t encoding_at(int index_in) const {
@@ -191,6 +198,23 @@ class Address : public Operand {
SetFixup(fixup);
}
+ Address displaceBy(int offset) {
+ if (rm() == ESP) {
+ // SIB addressing mode
+ return Address(base(), index(), scale(), disp() + offset, GetFixup());
+ } else {
+ return Address(rm(), disp() + offset, GetFixup());
+ }
+ }
+
+ Register GetBaseRegister() {
+ if (rm() == ESP) {
+ return base();
+ } else {
+ return rm();
+ }
+ }
+
static Address Absolute(uintptr_t addr) {
Address result;
result.SetModRM(0, EBP);
@@ -671,6 +695,10 @@ class X86Assembler final : public Assembler {
void fptan();
void fprem();
+ void xchgb(ByteRegister reg, const Address& address);
+ void xchgb(Register reg, const Address& address);
+ void xchgw(Register reg, const Address& address);
+
void xchgl(Register dst, Register src);
void xchgl(Register reg, const Address& address);
@@ -694,6 +722,7 @@ class X86Assembler final : public Assembler {
void andl(Register dst, const Immediate& imm);
void andl(Register dst, Register src);
void andl(Register dst, const Address& address);
+ void andw(const Address& address, const Immediate& imm);
void orl(Register dst, const Immediate& imm);
void orl(Register dst, Register src);
@@ -723,6 +752,7 @@ class X86Assembler final : public Assembler {
void cdq();
void idivl(Register reg);
+ void divl(Register reg);
void imull(Register dst, Register src);
void imull(Register reg, const Immediate& imm);
@@ -794,9 +824,15 @@ class X86Assembler final : public Assembler {
void rep_movsw();
X86Assembler* lock();
+ void cmpxchgb(const Address& address, ByteRegister reg);
+ void cmpxchgw(const Address& address, Register reg);
void cmpxchgl(const Address& address, Register reg);
void cmpxchg8b(const Address& address);
+ void xaddb(const Address& address, ByteRegister reg);
+ void xaddw(const Address& address, Register reg);
+ void xaddl(const Address& address, Register reg);
+
void mfence();
X86Assembler* fs();
@@ -811,6 +847,26 @@ class X86Assembler final : public Assembler {
void LoadLongConstant(XmmRegister dst, int64_t value);
void LoadDoubleConstant(XmmRegister dst, double value);
+ void LockCmpxchgb(const Address& address, Register reg) {
+ // For testing purpose
+ lock()->cmpxchgb(address, static_cast<ByteRegister>(reg));
+ }
+
+ void LockCmpxchgb(const Address& address, ByteRegister reg) {
+ lock()->cmpxchgb(address, reg);
+ }
+
+ void LockCmpxchgw(const Address& address, Register reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ // We make sure that the operand size override bytecode is emited before the lock bytecode.
+ // We test against clang which enforces this bytecode order.
+ EmitOperandSizeOverride();
+ EmitUint8(0xF0);
+ EmitUint8(0x0F);
+ EmitUint8(0xB1);
+ EmitOperand(reg, address);
+ }
+
void LockCmpxchgl(const Address& address, Register reg) {
lock()->cmpxchgl(address, reg);
}
@@ -819,6 +875,30 @@ class X86Assembler final : public Assembler {
lock()->cmpxchg8b(address);
}
+ void LockXaddb(const Address& address, Register reg) {
+ // For testing purpose
+ lock()->xaddb(address, static_cast<ByteRegister>(reg));
+ }
+
+ void LockXaddb(const Address& address, ByteRegister reg) {
+ lock()->xaddb(address, reg);
+ }
+
+ void LockXaddw(const Address& address, Register reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ // We make sure that the operand size override bytecode is emited before the lock bytecode.
+ // We test against clang which enforces this bytecode order.
+ EmitOperandSizeOverride();
+ EmitUint8(0xF0);
+ EmitUint8(0x0F);
+ EmitUint8(0xC1);
+ EmitOperand(reg, address);
+ }
+
+ void LockXaddl(const Address& address, Register reg) {
+ lock()->xaddl(address, reg);
+ }
+
//
// Misc. functionality
//