summaryrefslogtreecommitdiff
path: root/compiler/utils
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/utils')
-rw-r--r--compiler/utils/arm/assembler_arm.h4
-rw-r--r--compiler/utils/arm/assembler_thumb2.cc35
-rw-r--r--compiler/utils/arm/assembler_thumb2_test.cc10
-rw-r--r--compiler/utils/x86/assembler_x86.cc30
-rw-r--r--compiler/utils/x86/assembler_x86.h5
5 files changed, 69 insertions, 15 deletions
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index 8730f52eca..dd0dba2df4 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -100,6 +100,10 @@ class ShifterOperand {
return rm_;
}
+ Register GetSecondRegister() const {
+ return rs_;
+ }
+
enum Type {
kUnknown = -1,
kRegister,
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index 6d0571e263..e8eb019af3 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -826,7 +826,9 @@ void Thumb2Assembler::Emit32BitDataProcessing(Condition cond ATTRIBUTE_UNUSED,
// Check special cases.
if ((opcode == SUB || opcode == ADD) && (so.GetImmediate() < (1u << 12))) {
if (opcode == SUB) {
- thumb_opcode = 5U /* 0b0101 */;
+ if (!set_cc) {
+ thumb_opcode = 5U /* 0b0101 */;
+ }
} else {
thumb_opcode = 0;
}
@@ -836,13 +838,14 @@ void Thumb2Assembler::Emit32BitDataProcessing(Condition cond ATTRIBUTE_UNUSED,
uint32_t imm3 = (imm >> 8) & 7U /* 0b111 */;
uint32_t imm8 = imm & 0xff;
- encoding = B31 | B30 | B29 | B28 | B25 |
- thumb_opcode << 21 |
- rn << 16 |
- rd << 8 |
- i << 26 |
- imm3 << 12 |
- imm8;
+ encoding = B31 | B30 | B29 | B28 |
+ (set_cc ? B20 : B25) |
+ thumb_opcode << 21 |
+ rn << 16 |
+ rd << 8 |
+ i << 26 |
+ imm3 << 12 |
+ imm8;
} else {
// Modified immediate.
uint32_t imm = ModifiedImmediate(so.encodingThumb());
@@ -858,13 +861,13 @@ void Thumb2Assembler::Emit32BitDataProcessing(Condition cond ATTRIBUTE_UNUSED,
imm;
}
} else if (so.IsRegister()) {
- // Register (possibly shifted)
- encoding = B31 | B30 | B29 | B27 | B25 |
- thumb_opcode << 21 |
- (set_cc ? 1 : 0) << 20 |
- rn << 16 |
- rd << 8 |
- so.encodingThumb();
+ // Register (possibly shifted)
+ encoding = B31 | B30 | B29 | B27 | B25 |
+ thumb_opcode << 21 |
+ (set_cc ? 1 : 0) << 20 |
+ rn << 16 |
+ rd << 8 |
+ so.encodingThumb();
}
Emit32(encoding);
}
@@ -921,6 +924,8 @@ void Thumb2Assembler::Emit16BitDataProcessing(Condition cond,
use_immediate = true;
immediate = so.GetImmediate();
} else {
+ CHECK(!(so.IsRegister() && so.IsShift() && so.GetSecondRegister() != kNoRegister))
+ << "No register-shifted register instruction available in thumb";
// Adjust rn and rd: only two registers will be emitted.
switch (opcode) {
case AND:
diff --git a/compiler/utils/arm/assembler_thumb2_test.cc b/compiler/utils/arm/assembler_thumb2_test.cc
index ebea9d4262..d802852caf 100644
--- a/compiler/utils/arm/assembler_thumb2_test.cc
+++ b/compiler/utils/arm/assembler_thumb2_test.cc
@@ -227,4 +227,14 @@ TEST_F(AssemblerThumb2Test, eor) {
DriverStr(expected, "abs");
}
+TEST_F(AssemblerThumb2Test, sub) {
+ __ subs(arm::R1, arm::R0, arm::ShifterOperand(42));
+ __ sub(arm::R1, arm::R0, arm::ShifterOperand(42));
+
+ const char* expected =
+ "subs r1, r0, #42\n"
+ "subw r1, r0, #42\n";
+ DriverStr(expected, "sub");
+}
+
} // namespace art
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index 8f4208b417..90170ceed5 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -451,6 +451,36 @@ void X86Assembler::movsd(XmmRegister dst, XmmRegister src) {
}
+void X86Assembler::movhpd(XmmRegister dst, const Address& src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0x66);
+ EmitUint8(0x0F);
+ EmitUint8(0x16);
+ EmitOperand(dst, src);
+}
+
+
+void X86Assembler::movhpd(const Address& dst, XmmRegister src) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0x66);
+ EmitUint8(0x0F);
+ EmitUint8(0x17);
+ EmitOperand(src, dst);
+}
+
+
+void X86Assembler::psrldq(XmmRegister reg, const Immediate& shift_count) {
+ DCHECK(shift_count.is_uint8());
+
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitUint8(0x66);
+ EmitUint8(0x0F);
+ EmitUint8(0x73);
+ EmitXmmRegisterOperand(3, reg);
+ EmitUint8(shift_count.value());
+}
+
+
void X86Assembler::psrlq(XmmRegister reg, const Immediate& shift_count) {
DCHECK(shift_count.is_uint8());
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 2dde90744e..4d20db03a9 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -277,6 +277,11 @@ class X86Assembler FINAL : public Assembler {
void psrlq(XmmRegister reg, const Immediate& shift_count);
void punpckldq(XmmRegister dst, XmmRegister src);
+ void movhpd(XmmRegister dst, const Address& src);
+ void movhpd(const Address& dst, XmmRegister src);
+
+ void psrldq(XmmRegister reg, const Immediate& shift_count);
+
void addsd(XmmRegister dst, XmmRegister src);
void addsd(XmmRegister dst, const Address& src);
void subsd(XmmRegister dst, XmmRegister src);