[optimizing compiler] Add support for volatile
- for backends: arm, x86, x86_64
- added necessary instructions to assemblies
- clean up code gen for field set/get
- fixed InstructionDataEquals for some instructions
- fixed comments in compiler_enums
* 003-opcode test verifies basic volatile functionality
Change-Id: I144393efa312dfb2c332cb84056b00edffee338a
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index c86ec4b..87b3813 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -429,6 +429,8 @@
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 8f6d45a..8d1fb60 100644
--- a/compiler/utils/arm/assembler_arm32.cc
+++ b/compiler/utils/arm/assembler_arm32.cc
@@ -778,6 +778,7 @@
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::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 @@
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 6c8d415..b922d66 100644
--- a/compiler/utils/arm/assembler_arm32.h
+++ b/compiler/utils/arm/assembler_arm32.h
@@ -123,6 +123,8 @@
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 951792d..4a0ae0b 100644
--- a/compiler/utils/arm/assembler_arm32_test.cc
+++ b/compiler/utils/arm/assembler_arm32_test.cc
@@ -697,4 +697,28 @@
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 3eaae56..3eccd3f 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -1662,9 +1662,6 @@
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::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::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 48a3a7e..81dd138 100644
--- a/compiler/utils/arm/assembler_thumb2.h
+++ b/compiler/utils/arm/assembler_thumb2.h
@@ -149,6 +149,8 @@
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 6ae95a4..425ccd7 100644
--- a/compiler/utils/arm/assembler_thumb2_test.cc
+++ b/compiler/utils/arm/assembler_thumb2_test.cc
@@ -164,4 +164,32 @@
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 f0353f6..f8c0043 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -443,6 +443,27 @@
}
+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 9fecf1e..6c3d131 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -274,6 +274,9 @@
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 d901673..fccb510 100644
--- a/compiler/utils/x86/assembler_x86_test.cc
+++ b/compiler/utils/x86/assembler_x86_test.cc
@@ -105,6 +105,18 @@
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 =