diff options
Diffstat (limited to 'compiler/utils')
| -rw-r--r-- | compiler/utils/arm/assembler_arm.h | 2 | ||||
| -rw-r--r-- | compiler/utils/arm/assembler_arm32.cc | 42 | ||||
| -rw-r--r-- | compiler/utils/arm/assembler_arm32.h | 2 | ||||
| -rw-r--r-- | compiler/utils/arm/assembler_arm32_test.cc | 24 | ||||
| -rw-r--r-- | compiler/utils/arm/assembler_thumb2.cc | 39 | ||||
| -rw-r--r-- | compiler/utils/arm/assembler_thumb2.h | 2 | ||||
| -rw-r--r-- | compiler/utils/arm/assembler_thumb2_test.cc | 28 | ||||
| -rw-r--r-- | compiler/utils/x86/assembler_x86.cc | 21 | ||||
| -rw-r--r-- | compiler/utils/x86/assembler_x86.h | 3 | ||||
| -rw-r--r-- | compiler/utils/x86/assembler_x86_test.cc | 12 |
10 files changed, 172 insertions, 3 deletions
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h index c86ec4b3d6..87b38133fb 100644 --- a/compiler/utils/arm/assembler_arm.h +++ b/compiler/utils/arm/assembler_arm.h @@ -429,6 +429,8 @@ class ArmAssembler : public Assembler { virtual void ldrex(Register rd, Register rn, Condition cond = AL) = 0; virtual void strex(Register rd, Register rt, Register rn, Condition cond = AL) = 0; + virtual void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) = 0; + virtual void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) = 0; // Miscellaneous instructions. virtual void clrex(Condition cond = AL) = 0; diff --git a/compiler/utils/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc index 8f6d45ab53..8d1fb60725 100644 --- a/compiler/utils/arm/assembler_arm32.cc +++ b/compiler/utils/arm/assembler_arm32.cc @@ -778,6 +778,7 @@ void Arm32Assembler::EmitMulOp(Condition cond, int32_t opcode, Emit(encoding); } + void Arm32Assembler::ldrex(Register rt, Register rn, Condition cond) { CHECK_NE(rn, kNoRegister); CHECK_NE(rt, kNoRegister); @@ -793,6 +794,25 @@ void Arm32Assembler::ldrex(Register rt, Register rn, Condition cond) { } +void Arm32Assembler::ldrexd(Register rt, Register rt2, Register rn, Condition cond) { + CHECK_NE(rn, kNoRegister); + CHECK_NE(rt, kNoRegister); + CHECK_NE(rt2, kNoRegister); + CHECK_NE(rt, R14); + CHECK_EQ(0u, static_cast<uint32_t>(rt) % 2); + CHECK_EQ(static_cast<uint32_t>(rt) + 1, static_cast<uint32_t>(rt2)); + CHECK_NE(cond, kNoCondition); + + int32_t encoding = + (static_cast<uint32_t>(cond) << kConditionShift) | + B24 | B23 | B21 | B20 | + static_cast<uint32_t>(rn) << 16 | + static_cast<uint32_t>(rt) << 12 | + B11 | B10 | B9 | B8 | B7 | B4 | B3 | B2 | B1 | B0; + Emit(encoding); +} + + void Arm32Assembler::strex(Register rd, Register rt, Register rn, @@ -811,6 +831,28 @@ void Arm32Assembler::strex(Register rd, Emit(encoding); } +void Arm32Assembler::strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond) { + CHECK_NE(rd, kNoRegister); + CHECK_NE(rn, kNoRegister); + CHECK_NE(rt, kNoRegister); + CHECK_NE(rt2, kNoRegister); + CHECK_NE(rt, R14); + CHECK_NE(rd, rt); + CHECK_NE(rd, rt2); + CHECK_EQ(0u, static_cast<uint32_t>(rt) % 2); + CHECK_EQ(static_cast<uint32_t>(rt) + 1, static_cast<uint32_t>(rt2)); + CHECK_NE(cond, kNoCondition); + + int32_t encoding = + (static_cast<uint32_t>(cond) << kConditionShift) | + B24 | B23 | B21 | + static_cast<uint32_t>(rn) << 16 | + static_cast<uint32_t>(rd) << 12 | + B11 | B10 | B9 | B8 | B7 | B4 | + static_cast<uint32_t>(rt); + Emit(encoding); +} + void Arm32Assembler::clrex(Condition cond) { CHECK_EQ(cond, AL); // This cannot be conditional on ARM. diff --git a/compiler/utils/arm/assembler_arm32.h b/compiler/utils/arm/assembler_arm32.h index 6c8d41587b..b922d66513 100644 --- a/compiler/utils/arm/assembler_arm32.h +++ b/compiler/utils/arm/assembler_arm32.h @@ -123,6 +123,8 @@ class Arm32Assembler FINAL : public ArmAssembler { void ldrex(Register rd, Register rn, Condition cond = AL) OVERRIDE; void strex(Register rd, Register rt, Register rn, Condition cond = AL) OVERRIDE; + void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE; + void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE; // Miscellaneous instructions. void clrex(Condition cond = AL) OVERRIDE; diff --git a/compiler/utils/arm/assembler_arm32_test.cc b/compiler/utils/arm/assembler_arm32_test.cc index 951792d45b..4a0ae0ba99 100644 --- a/compiler/utils/arm/assembler_arm32_test.cc +++ b/compiler/utils/arm/assembler_arm32_test.cc @@ -697,4 +697,28 @@ TEST_F(AssemblerArm32Test, Vmstat) { DriverStr(expected, "vmrs"); } +TEST_F(AssemblerArm32Test, ldrexd) { + GetAssembler()->ldrexd(arm::R0, arm::R1, arm::R0); + GetAssembler()->ldrexd(arm::R0, arm::R1, arm::R1); + GetAssembler()->ldrexd(arm::R0, arm::R1, arm::R2); + + const char* expected = + "ldrexd r0, r1, [r0]\n" + "ldrexd r0, r1, [r1]\n" + "ldrexd r0, r1, [r2]\n"; + DriverStr(expected, "ldrexd"); +} + +TEST_F(AssemblerArm32Test, strexd) { + GetAssembler()->strexd(arm::R9, arm::R0, arm::R1, arm::R0); + GetAssembler()->strexd(arm::R9, arm::R0, arm::R1, arm::R1); + GetAssembler()->strexd(arm::R9, arm::R0, arm::R1, arm::R2); + + const char* expected = + "strexd r9, r0, r1, [r0]\n" + "strexd r9, r0, r1, [r1]\n" + "strexd r9, r0, r1, [r2]\n"; + DriverStr(expected, "strexd"); +} + } // namespace art diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc index 3eaae56376..3eccd3f9df 100644 --- a/compiler/utils/arm/assembler_thumb2.cc +++ b/compiler/utils/arm/assembler_thumb2.cc @@ -1662,9 +1662,6 @@ void Thumb2Assembler::ldrex(Register rt, Register rn, uint16_t imm, Condition co CHECK_NE(rn, kNoRegister); CHECK_NE(rt, kNoRegister); CheckCondition(cond); - CHECK_NE(rn, kNoRegister); - CHECK_NE(rt, kNoRegister); - CheckCondition(cond); CHECK_LT(imm, (1u << 10)); int32_t encoding = B31 | B30 | B29 | B27 | B22 | B20 | @@ -1701,6 +1698,22 @@ void Thumb2Assembler::strex(Register rd, } +void Thumb2Assembler::ldrexd(Register rt, Register rt2, Register rn, Condition cond) { + CHECK_NE(rn, kNoRegister); + CHECK_NE(rt, kNoRegister); + CHECK_NE(rt2, kNoRegister); + CHECK_NE(rt, rt2); + CheckCondition(cond); + + int32_t encoding = B31 | B30 | B29 | B27 | B23 | B22 | B20 | + static_cast<uint32_t>(rn) << 16 | + static_cast<uint32_t>(rt) << 12 | + static_cast<uint32_t>(rt2) << 8 | + B6 | B5 | B4 | B3 | B2 | B1 | B0; + Emit32(encoding); +} + + void Thumb2Assembler::strex(Register rd, Register rt, Register rn, @@ -1709,6 +1722,26 @@ void Thumb2Assembler::strex(Register rd, } +void Thumb2Assembler::strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond) { + CHECK_NE(rd, kNoRegister); + CHECK_NE(rn, kNoRegister); + CHECK_NE(rt, kNoRegister); + CHECK_NE(rt2, kNoRegister); + CHECK_NE(rt, rt2); + CHECK_NE(rd, rt); + CHECK_NE(rd, rt2); + CheckCondition(cond); + + int32_t encoding = B31 | B30 | B29 | B27 | B23 | B22 | + static_cast<uint32_t>(rn) << 16 | + static_cast<uint32_t>(rt) << 12 | + static_cast<uint32_t>(rt2) << 8 | + B6 | B5 | B4 | + static_cast<uint32_t>(rd); + Emit32(encoding); +} + + void Thumb2Assembler::clrex(Condition cond) { CheckCondition(cond); int32_t encoding = B31 | B30 | B29 | B27 | B28 | B25 | B24 | B23 | diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h index 48a3a7eeb2..81dd13894f 100644 --- a/compiler/utils/arm/assembler_thumb2.h +++ b/compiler/utils/arm/assembler_thumb2.h @@ -149,6 +149,8 @@ class Thumb2Assembler FINAL : public ArmAssembler { void ldrex(Register rd, Register rn, uint16_t imm, Condition cond = AL); void strex(Register rd, Register rt, Register rn, uint16_t imm, Condition cond = AL); + void ldrexd(Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE; + void strexd(Register rd, Register rt, Register rt2, Register rn, Condition cond = AL) OVERRIDE; // Miscellaneous instructions. void clrex(Condition cond = AL) OVERRIDE; diff --git a/compiler/utils/arm/assembler_thumb2_test.cc b/compiler/utils/arm/assembler_thumb2_test.cc index 6ae95a40e6..425ccd7ea3 100644 --- a/compiler/utils/arm/assembler_thumb2_test.cc +++ b/compiler/utils/arm/assembler_thumb2_test.cc @@ -164,4 +164,32 @@ TEST_F(AssemblerThumb2Test, Vmstat) { DriverStr(expected, "vmrs"); } +TEST_F(AssemblerThumb2Test, ldrexd) { + GetAssembler()->ldrexd(arm::R0, arm::R1, arm::R0); + GetAssembler()->ldrexd(arm::R0, arm::R1, arm::R1); + GetAssembler()->ldrexd(arm::R0, arm::R1, arm::R2); + GetAssembler()->ldrexd(arm::R5, arm::R3, arm::R7); + + const char* expected = + "ldrexd r0, r1, [r0]\n" + "ldrexd r0, r1, [r1]\n" + "ldrexd r0, r1, [r2]\n" + "ldrexd r5, r3, [r7]\n"; + DriverStr(expected, "ldrexd"); +} + +TEST_F(AssemblerThumb2Test, strexd) { + GetAssembler()->strexd(arm::R9, arm::R0, arm::R1, arm::R0); + GetAssembler()->strexd(arm::R9, arm::R0, arm::R1, arm::R1); + GetAssembler()->strexd(arm::R9, arm::R0, arm::R1, arm::R2); + GetAssembler()->strexd(arm::R9, arm::R5, arm::R3, arm::R7); + + const char* expected = + "strexd r9, r0, r1, [r0]\n" + "strexd r9, r0, r1, [r1]\n" + "strexd r9, r0, r1, [r2]\n" + "strexd r9, r5, r3, [r7]\n"; + DriverStr(expected, "strexd"); +} + } // namespace art diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc index f0353f6cd2..f8c0043242 100644 --- a/compiler/utils/x86/assembler_x86.cc +++ b/compiler/utils/x86/assembler_x86.cc @@ -443,6 +443,27 @@ void X86Assembler::movsd(XmmRegister dst, XmmRegister src) { } +void X86Assembler::psrlq(XmmRegister reg, const Immediate& shift_count) { + DCHECK(shift_count.is_uint8()); + + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitUint8(0x66); + EmitUint8(0x0F); + EmitUint8(0x73); + EmitXmmRegisterOperand(2, reg); + EmitUint8(shift_count.value()); +} + + +void X86Assembler::punpckldq(XmmRegister dst, XmmRegister src) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitUint8(0x66); + EmitUint8(0x0F); + EmitUint8(0x62); + EmitXmmRegisterOperand(dst, src); +} + + void X86Assembler::addsd(XmmRegister dst, XmmRegister src) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitUint8(0xF2); diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h index 9fecf1edf0..6c3d13122c 100644 --- a/compiler/utils/x86/assembler_x86.h +++ b/compiler/utils/x86/assembler_x86.h @@ -274,6 +274,9 @@ class X86Assembler FINAL : public Assembler { void movsd(const Address& dst, XmmRegister src); void movsd(XmmRegister dst, XmmRegister src); + void psrlq(XmmRegister reg, const Immediate& shift_count); + void punpckldq(XmmRegister dst, XmmRegister src); + void addsd(XmmRegister dst, XmmRegister src); void addsd(XmmRegister dst, const Address& src); void subsd(XmmRegister dst, XmmRegister src); diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc index d901673691..fccb510afb 100644 --- a/compiler/utils/x86/assembler_x86_test.cc +++ b/compiler/utils/x86/assembler_x86_test.cc @@ -105,6 +105,18 @@ TEST_F(AssemblerX86Test, Movl) { DriverStr(expected, "movl"); } +TEST_F(AssemblerX86Test, psrlq) { + GetAssembler()->psrlq(x86::XMM0, CreateImmediate(32)); + const char* expected = "psrlq $0x20, %xmm0\n"; + DriverStr(expected, "psrlq"); +} + +TEST_F(AssemblerX86Test, punpckldq) { + GetAssembler()->punpckldq(x86::XMM0, x86::XMM1); + const char* expected = "punpckldq %xmm1, %xmm0\n"; + DriverStr(expected, "punpckldq"); +} + TEST_F(AssemblerX86Test, LoadLongConstant) { GetAssembler()->LoadLongConstant(x86::XMM0, 51); const char* expected = |