summaryrefslogtreecommitdiffstats
path: root/compiler/utils
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils')
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.cc135
-rw-r--r--compiler/utils/x86_64/assembler_x86_64.h13
-rw-r--r--compiler/utils/x86_64/assembler_x86_64_test.cc101
3 files changed, 246 insertions, 3 deletions
diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc
index 32204a9970..1ff99df118 100644
--- a/compiler/utils/x86_64/assembler_x86_64.cc
+++ b/compiler/utils/x86_64/assembler_x86_64.cc
@@ -128,6 +128,16 @@ void X86_64Assembler::movl(CpuRegister dst, const Immediate& imm) {
}
+void X86_64Assembler::movq(const Address& dst, const Immediate& imm) {
+ CHECK(imm.is_int32());
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitRex64(dst);
+ EmitUint8(0xC7);
+ EmitOperand(0, dst);
+ EmitImmediate(imm);
+}
+
+
void X86_64Assembler::movq(CpuRegister dst, CpuRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
// 0x89 is movq r/m64 <- r64, with op1 in r/m and op2 in reg: so reverse EmitRex64
@@ -652,6 +662,21 @@ void X86_64Assembler::cvtsi2ss(XmmRegister dst, CpuRegister src, bool is64bit) {
}
+void X86_64Assembler::cvtsi2ss(XmmRegister dst, const Address& src, bool is64bit) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0xF3);
+ if (is64bit) {
+ // Emit a REX.W prefix if the operand size is 64 bits.
+ EmitRex64(dst, src);
+ } else {
+ EmitOptionalRex32(dst, src);
+ }
+ EmitUint8(0x0F);
+ EmitUint8(0x2A);
+ EmitOperand(dst.LowBits(), src);
+}
+
+
void X86_64Assembler::cvtsi2sd(XmmRegister dst, CpuRegister src) {
cvtsi2sd(dst, src, false);
}
@@ -672,6 +697,21 @@ void X86_64Assembler::cvtsi2sd(XmmRegister dst, CpuRegister src, bool is64bit) {
}
+void X86_64Assembler::cvtsi2sd(XmmRegister dst, const Address& src, bool is64bit) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0xF2);
+ if (is64bit) {
+ // Emit a REX.W prefix if the operand size is 64 bits.
+ EmitRex64(dst, src);
+ } else {
+ EmitOptionalRex32(dst, src);
+ }
+ EmitUint8(0x0F);
+ EmitUint8(0x2A);
+ EmitOperand(dst.LowBits(), src);
+}
+
+
void X86_64Assembler::cvtss2si(CpuRegister dst, XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF3);
@@ -692,6 +732,16 @@ void X86_64Assembler::cvtss2sd(XmmRegister dst, XmmRegister src) {
}
+void X86_64Assembler::cvtss2sd(XmmRegister dst, const Address& src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0xF3);
+ EmitOptionalRex32(dst, src);
+ EmitUint8(0x0F);
+ EmitUint8(0x5A);
+ EmitOperand(dst.LowBits(), src);
+}
+
+
void X86_64Assembler::cvtsd2si(CpuRegister dst, XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF2);
@@ -752,6 +802,16 @@ void X86_64Assembler::cvtsd2ss(XmmRegister dst, XmmRegister src) {
}
+void X86_64Assembler::cvtsd2ss(XmmRegister dst, const Address& src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0xF2);
+ EmitOptionalRex32(dst, src);
+ EmitUint8(0x0F);
+ EmitUint8(0x5A);
+ EmitOperand(dst.LowBits(), src);
+}
+
+
void X86_64Assembler::cvtdq2pd(XmmRegister dst, XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xF3);
@@ -771,6 +831,15 @@ void X86_64Assembler::comiss(XmmRegister a, XmmRegister b) {
}
+void X86_64Assembler::comiss(XmmRegister a, const Address& b) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitOptionalRex32(a, b);
+ EmitUint8(0x0F);
+ EmitUint8(0x2F);
+ EmitOperand(a.LowBits(), b);
+}
+
+
void X86_64Assembler::comisd(XmmRegister a, XmmRegister b) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x66);
@@ -780,6 +849,17 @@ void X86_64Assembler::comisd(XmmRegister a, XmmRegister b) {
EmitXmmRegisterOperand(a.LowBits(), b);
}
+
+void X86_64Assembler::comisd(XmmRegister a, const Address& b) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0x66);
+ EmitOptionalRex32(a, b);
+ EmitUint8(0x0F);
+ EmitUint8(0x2F);
+ EmitOperand(a.LowBits(), b);
+}
+
+
void X86_64Assembler::ucomiss(XmmRegister a, XmmRegister b) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitOptionalRex32(a, b);
@@ -789,6 +869,15 @@ void X86_64Assembler::ucomiss(XmmRegister a, XmmRegister b) {
}
+void X86_64Assembler::ucomiss(XmmRegister a, const Address& b) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitOptionalRex32(a, b);
+ EmitUint8(0x0F);
+ EmitUint8(0x2E);
+ EmitOperand(a.LowBits(), b);
+}
+
+
void X86_64Assembler::ucomisd(XmmRegister a, XmmRegister b) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x66);
@@ -799,6 +888,16 @@ void X86_64Assembler::ucomisd(XmmRegister a, XmmRegister b) {
}
+void X86_64Assembler::ucomisd(XmmRegister a, const Address& b) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0x66);
+ EmitOptionalRex32(a, b);
+ EmitUint8(0x0F);
+ EmitUint8(0x2E);
+ EmitOperand(a.LowBits(), b);
+}
+
+
void X86_64Assembler::roundsd(XmmRegister dst, XmmRegister src, const Immediate& imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0x66);
@@ -1161,7 +1260,7 @@ void X86_64Assembler::cmpq(CpuRegister reg, const Immediate& imm) {
void X86_64Assembler::cmpq(CpuRegister reg, const Address& address) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitRex64(reg);
+ EmitRex64(reg, address);
EmitUint8(0x3B);
EmitOperand(reg.LowBits(), address);
}
@@ -1288,6 +1387,14 @@ void X86_64Assembler::andq(CpuRegister dst, CpuRegister src) {
}
+void X86_64Assembler::andq(CpuRegister dst, const Address& src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitRex64(dst, src);
+ EmitUint8(0x23);
+ EmitOperand(dst.LowBits(), src);
+}
+
+
void X86_64Assembler::orl(CpuRegister dst, CpuRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitOptionalRex32(dst, src);
@@ -1327,6 +1434,14 @@ void X86_64Assembler::orq(CpuRegister dst, CpuRegister src) {
}
+void X86_64Assembler::orq(CpuRegister dst, const Address& src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitRex64(dst, src);
+ EmitUint8(0x0B);
+ EmitOperand(dst.LowBits(), src);
+}
+
+
void X86_64Assembler::xorl(CpuRegister dst, CpuRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitOptionalRex32(dst, src);
@@ -1365,6 +1480,14 @@ void X86_64Assembler::xorq(CpuRegister dst, const Immediate& imm) {
EmitComplex(6, Operand(dst), imm);
}
+void X86_64Assembler::xorq(CpuRegister dst, const Address& src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitRex64(dst, src);
+ EmitUint8(0x33);
+ EmitOperand(dst.LowBits(), src);
+}
+
+
#if 0
void X86_64Assembler::rex(bool force, bool w, Register* r, Register* x, Register* b) {
// REX.WRXB
@@ -2182,9 +2305,15 @@ void X86_64Assembler::EmitRex64(CpuRegister dst, const Operand& operand) {
if (dst.NeedsRex()) {
rex |= 0x44; // REX.0R00
}
- if (rex != 0) {
- EmitUint8(rex);
+ EmitUint8(rex);
+}
+
+void X86_64Assembler::EmitRex64(XmmRegister dst, const Operand& operand) {
+ uint8_t rex = 0x48 | operand.rex(); // REX.W000
+ if (dst.NeedsRex()) {
+ rex |= 0x44; // REX.0R00
}
+ EmitUint8(rex);
}
void X86_64Assembler::EmitOptionalByteRegNormalizingRex32(CpuRegister dst, CpuRegister src) {
diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h
index 16ef70b85e..79ad8f53e3 100644
--- a/compiler/utils/x86_64/assembler_x86_64.h
+++ b/compiler/utils/x86_64/assembler_x86_64.h
@@ -328,6 +328,7 @@ class X86_64Assembler FINAL : public Assembler {
void movq(CpuRegister dst, const Address& src);
void movl(CpuRegister dst, const Address& src);
void movq(const Address& dst, CpuRegister src);
+ void movq(const Address& dst, const Immediate& src);
void movl(const Address& dst, CpuRegister src);
void movl(const Address& dst, const Immediate& imm);
@@ -391,14 +392,18 @@ class X86_64Assembler FINAL : public Assembler {
void cvtsi2ss(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version.
void cvtsi2ss(XmmRegister dst, CpuRegister src, bool is64bit);
+ void cvtsi2ss(XmmRegister dst, const Address& src, bool is64bit);
void cvtsi2sd(XmmRegister dst, CpuRegister src); // Note: this is the r/m32 version.
void cvtsi2sd(XmmRegister dst, CpuRegister src, bool is64bit);
+ void cvtsi2sd(XmmRegister dst, const Address& src, bool is64bit);
void cvtss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
void cvtss2sd(XmmRegister dst, XmmRegister src);
+ void cvtss2sd(XmmRegister dst, const Address& src);
void cvtsd2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
void cvtsd2ss(XmmRegister dst, XmmRegister src);
+ void cvtsd2ss(XmmRegister dst, const Address& src);
void cvttss2si(CpuRegister dst, XmmRegister src); // Note: this is the r32 version.
void cvttss2si(CpuRegister dst, XmmRegister src, bool is64bit);
@@ -408,9 +413,13 @@ class X86_64Assembler FINAL : public Assembler {
void cvtdq2pd(XmmRegister dst, XmmRegister src);
void comiss(XmmRegister a, XmmRegister b);
+ void comiss(XmmRegister a, const Address& b);
void comisd(XmmRegister a, XmmRegister b);
+ void comisd(XmmRegister a, const Address& b);
void ucomiss(XmmRegister a, XmmRegister b);
+ void ucomiss(XmmRegister a, const Address& b);
void ucomisd(XmmRegister a, XmmRegister b);
+ void ucomisd(XmmRegister a, const Address& b);
void roundsd(XmmRegister dst, XmmRegister src, const Immediate& imm);
void roundss(XmmRegister dst, XmmRegister src, const Immediate& imm);
@@ -487,18 +496,21 @@ class X86_64Assembler FINAL : public Assembler {
void andl(CpuRegister reg, const Address& address);
void andq(CpuRegister dst, const Immediate& imm);
void andq(CpuRegister dst, CpuRegister src);
+ void andq(CpuRegister reg, const Address& address);
void orl(CpuRegister dst, const Immediate& imm);
void orl(CpuRegister dst, CpuRegister src);
void orl(CpuRegister reg, const Address& address);
void orq(CpuRegister dst, CpuRegister src);
void orq(CpuRegister dst, const Immediate& imm);
+ void orq(CpuRegister reg, const Address& address);
void xorl(CpuRegister dst, CpuRegister src);
void xorl(CpuRegister dst, const Immediate& imm);
void xorl(CpuRegister reg, const Address& address);
void xorq(CpuRegister dst, const Immediate& imm);
void xorq(CpuRegister dst, CpuRegister src);
+ void xorq(CpuRegister reg, const Address& address);
void addl(CpuRegister dst, CpuRegister src);
void addl(CpuRegister reg, const Immediate& imm);
@@ -789,6 +801,7 @@ class X86_64Assembler FINAL : public Assembler {
void EmitRex64(const Operand& operand);
void EmitRex64(CpuRegister dst, CpuRegister src);
void EmitRex64(CpuRegister dst, const Operand& operand);
+ void EmitRex64(XmmRegister dst, const Operand& operand);
void EmitRex64(XmmRegister dst, CpuRegister src);
void EmitRex64(CpuRegister dst, XmmRegister src);
diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc
index 5ca0373a6a..454cb029b5 100644
--- a/compiler/utils/x86_64/assembler_x86_64_test.cc
+++ b/compiler/utils/x86_64/assembler_x86_64_test.cc
@@ -667,6 +667,107 @@ TEST_F(AssemblerX86_64Test, Movw) {
DriverStr(expected, "movw");
}
+TEST_F(AssemblerX86_64Test, MovqAddrImm) {
+ GetAssembler()->movq(x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
+ x86_64::Immediate(-5));
+ const char* expected = "movq $-5, 0(%RAX)\n";
+ DriverStr(expected, "movq");
+}
+
+TEST_F(AssemblerX86_64Test, Cvtsi2ssAddr) {
+ GetAssembler()->cvtsi2ss(x86_64::XmmRegister(x86_64::XMM0),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
+ false);
+ GetAssembler()->cvtsi2ss(x86_64::XmmRegister(x86_64::XMM0),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
+ true);
+ const char* expected = "cvtsi2ss 0(%RAX), %xmm0\n"
+ "cvtsi2ssq 0(%RAX), %xmm0\n";
+ DriverStr(expected, "cvtsi2ss");
+}
+
+TEST_F(AssemblerX86_64Test, Cvtsi2sdAddr) {
+ GetAssembler()->cvtsi2sd(x86_64::XmmRegister(x86_64::XMM0),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
+ false);
+ GetAssembler()->cvtsi2sd(x86_64::XmmRegister(x86_64::XMM0),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0),
+ true);
+ const char* expected = "cvtsi2sd 0(%RAX), %xmm0\n"
+ "cvtsi2sdq 0(%RAX), %xmm0\n";
+ DriverStr(expected, "cvtsi2sd");
+}
+
+TEST_F(AssemblerX86_64Test, CmpqAddr) {
+ GetAssembler()->cmpq(x86_64::CpuRegister(x86_64::R12),
+ x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0));
+ const char* expected = "cmpq 0(%R9), %R12\n";
+ DriverStr(expected, "cmpq");
+}
+
+TEST_F(AssemblerX86_64Test, Cvtss2sdAddr) {
+ GetAssembler()->cvtss2sd(x86_64::XmmRegister(x86_64::XMM0),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
+ const char* expected = "cvtss2sd 0(%RAX), %xmm0\n";
+ DriverStr(expected, "cvtss2sd");
+}
+
+TEST_F(AssemblerX86_64Test, Cvtsd2ssAddr) {
+ GetAssembler()->cvtsd2ss(x86_64::XmmRegister(x86_64::XMM0),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
+ const char* expected = "cvtsd2ss 0(%RAX), %xmm0\n";
+ DriverStr(expected, "cvtsd2ss");
+}
+
+TEST_F(AssemblerX86_64Test, ComissAddr) {
+ GetAssembler()->comiss(x86_64::XmmRegister(x86_64::XMM14),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
+ const char* expected = "comiss 0(%RAX), %xmm14\n";
+ DriverStr(expected, "comiss");
+}
+
+TEST_F(AssemblerX86_64Test, ComisdAddr) {
+ GetAssembler()->comisd(x86_64::XmmRegister(x86_64::XMM0),
+ x86_64::Address(x86_64::CpuRegister(x86_64::R9), 0));
+ const char* expected = "comisd 0(%R9), %xmm0\n";
+ DriverStr(expected, "comisd");
+}
+
+TEST_F(AssemblerX86_64Test, UComissAddr) {
+ GetAssembler()->ucomiss(x86_64::XmmRegister(x86_64::XMM0),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
+ const char* expected = "ucomiss 0(%RAX), %xmm0\n";
+ DriverStr(expected, "ucomiss");
+}
+
+TEST_F(AssemblerX86_64Test, UComisdAddr) {
+ GetAssembler()->ucomisd(x86_64::XmmRegister(x86_64::XMM0),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
+ const char* expected = "ucomisd 0(%RAX), %xmm0\n";
+ DriverStr(expected, "ucomisd");
+}
+
+TEST_F(AssemblerX86_64Test, Andq) {
+ GetAssembler()->andq(x86_64::CpuRegister(x86_64::R9),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
+ const char* expected = "andq 0(%RAX), %r9\n";
+ DriverStr(expected, "andq");
+}
+
+TEST_F(AssemblerX86_64Test, Orq) {
+ GetAssembler()->orq(x86_64::CpuRegister(x86_64::R9),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
+ const char* expected = "orq 0(%RAX), %r9\n";
+ DriverStr(expected, "orq");
+}
+
+TEST_F(AssemblerX86_64Test, Xorq) {
+ GetAssembler()->xorq(x86_64::CpuRegister(x86_64::R9),
+ x86_64::Address(x86_64::CpuRegister(x86_64::RAX), 0));
+ const char* expected = "xorq 0(%RAX), %r9\n";
+ DriverStr(expected, "xorq");
+}
+
TEST_F(AssemblerX86_64Test, Movsxd) {
DriverStr(RepeatRr(&x86_64::X86_64Assembler::movsxd, "movsxd %{reg2}, %{reg1}"), "movsxd");
}