diff options
author | Mark Mendell <mark.p.mendell@intel.com> | 2015-04-20 22:10:34 -0400 |
---|---|---|
committer | Mark Mendell <mark.p.mendell@intel.com> | 2015-04-21 16:23:15 -0400 |
commit | 40741f394b2737e503f2c08be0ae9dd490fb106b (patch) | |
tree | d5d9e6d51168e36154de408e2b5d77371bd8c86d /compiler/utils | |
parent | dac1a694e4fd79fd5d5ba95319197a1e42f9f054 (diff) | |
download | android_art-40741f394b2737e503f2c08be0ae9dd490fb106b.tar.gz android_art-40741f394b2737e503f2c08be0ae9dd490fb106b.tar.bz2 android_art-40741f394b2737e503f2c08be0ae9dd490fb106b.zip |
[optimizing] Use more X86_64 addressing modes
Allow constant and memory addresses to more X86_64 instructions.
Add memory formats to X86_64 instructions to match.
Fix a bug in cmpq(CpuRegister, const Address&).
Allow mov <addr>,immediate (instruction 0xC7) to be a valid faulting
instruction.
Change-Id: I5b8a409444426633920cd08e09f687a7afc88a39
Signed-off-by: Mark Mendell <mark.p.mendell@intel.com>
Diffstat (limited to 'compiler/utils')
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.cc | 135 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.h | 13 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64_test.cc | 101 |
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"); } |