summaryrefslogtreecommitdiff
path: root/compiler/utils/x86/assembler_x86.cc
diff options
context:
space:
mode:
author Ulya Trafimovich <skvadrik@google.com> 2021-07-12 14:20:16 +0100
committer Ulyana Trafimovich <skvadrik@google.com> 2021-07-12 16:24:37 +0000
commitb50ceebb814f28a6ade94974d3e8614c8585760e (patch)
tree8297534745f75989ddf6b6c124ccc623a8eee71f /compiler/utils/x86/assembler_x86.cc
parent38837d44f47a14ccd07e9de3c26d3e40b9768d0d (diff)
x86: Add missing variants for XCHG and tests for this instruction.
Add XCHG variants when both operands are registers. Handle the special case when at least one of the register operands is EAX/AX. Add tests for the new variants and for other variants that previously weren't tested. Bug: 65872996 Test: m test-art-host-gtest Change-Id: I1e80d1b86f3d2e804b90c2a181e4eabded30d8ae
Diffstat (limited to 'compiler/utils/x86/assembler_x86.cc')
-rw-r--r--compiler/utils/x86/assembler_x86.cc47
1 files changed, 44 insertions, 3 deletions
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index adc7bcc0f4..b6708de81c 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -2887,9 +2887,22 @@ void X86Assembler::fprem() {
}
-void X86Assembler::xchgb(Register reg, const Address& address) {
- // For testing purpose
- xchgb(static_cast<ByteRegister>(reg), address);
+bool X86Assembler::try_xchg_eax(Register dst, Register src) {
+ if (src != EAX && dst != EAX) {
+ return false;
+ }
+ if (dst == EAX) {
+ std::swap(src, dst);
+ }
+ EmitUint8(0x90 + dst);
+ return true;
+}
+
+
+void X86Assembler::xchgb(ByteRegister dst, ByteRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0x86);
+ EmitRegisterOperand(dst, src);
}
@@ -2900,6 +2913,29 @@ void X86Assembler::xchgb(ByteRegister reg, const Address& address) {
}
+void X86Assembler::xchgb(Register dst, Register src) {
+ xchgb(static_cast<ByteRegister>(dst), static_cast<ByteRegister>(src));
+}
+
+
+void X86Assembler::xchgb(Register reg, const Address& address) {
+ xchgb(static_cast<ByteRegister>(reg), address);
+}
+
+
+void X86Assembler::xchgw(Register dst, Register src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitOperandSizeOverride();
+ if (try_xchg_eax(dst, src)) {
+ // A short version for AX.
+ return;
+ }
+ // General case.
+ EmitUint8(0x87);
+ EmitRegisterOperand(dst, src);
+}
+
+
void X86Assembler::xchgw(Register reg, const Address& address) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitOperandSizeOverride();
@@ -2910,6 +2946,11 @@ void X86Assembler::xchgw(Register reg, const Address& address) {
void X86Assembler::xchgl(Register dst, Register src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ if (try_xchg_eax(dst, src)) {
+ // A short version for EAX.
+ return;
+ }
+ // General case.
EmitUint8(0x87);
EmitRegisterOperand(dst, src);
}