Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(519)

Unified Diff: unittest/AssemblerX8632/Locked.cpp

Issue 1224173006: Adds the x86-64 assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments; make format Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « unittest/AssemblerX8632/GPRArith.cpp ('k') | unittest/AssemblerX8632/LowLevel.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: unittest/AssemblerX8632/Locked.cpp
diff --git a/unittest/AssemblerX8632/Locked.cpp b/unittest/AssemblerX8632/Locked.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..82c1e140eed847b9fbd2ff72fdadb1a88fd7397e
--- /dev/null
+++ b/unittest/AssemblerX8632/Locked.cpp
@@ -0,0 +1,409 @@
+//===- subzero/unittest/AssemblerX8632/Locked.cpp -------------------------===//
+//
+// The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "AssemblerX8632/TestUtil.h"
+
+namespace Ice {
+namespace X8632 {
+namespace Test {
+namespace {
+
+TEST_F(AssemblerX8632LowLevelTest, Mfence) {
+ __ mfence();
+
+ static constexpr uint8_t ByteCount = 3;
+ ASSERT_EQ(ByteCount, codeBytesSize());
+ verifyBytes<ByteCount>(codeBytes(), 0x0F, 0xAE, 0xF0);
+}
+
+TEST_F(AssemblerX8632LowLevelTest, Lock) {
+ __ lock();
+
+ static constexpr uint8_t ByteCount = 1;
+ ASSERT_EQ(ByteCount, codeBytesSize());
+ verifyBytes<ByteCount>(codeBytes(), 0xF0);
+}
+
+TEST_F(AssemblerX8632Test, Xchg) {
+ static constexpr uint32_t Mask8 = 0x000000FF;
+ static constexpr uint32_t Mask16 = 0x0000FFFF;
+ static constexpr uint32_t Mask32 = 0xFFFFFFFF;
+
+#define TestImplAddrReg(Value0, Dst1, Value1, Size) \
+ do { \
+ static constexpr char TestString[] = \
+ "(" #Value0 ", " #Dst1 ", " #Value1 ", " #Size ")"; \
+ const uint32_t T0 = allocateDword(); \
+ const uint32_t V0 = (Value0)&Mask##Size; \
+ const uint32_t V1 = (Value1)&Mask##Size; \
+ \
+ __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst1, \
+ Immediate(Value1)); \
+ __ xchg(IceType_i##Size, dwordAddress(T0), \
+ GPRRegister::Encoded_Reg_##Dst1); \
+ __ And(IceType_i32, GPRRegister::Encoded_Reg_##Dst1, \
+ Immediate(Mask##Size)); \
+ \
+ AssembledTest test = assemble(); \
+ test.setDwordTo(T0, V0); \
+ test.run(); \
+ \
+ ASSERT_EQ(V0, test.Dst1()) << TestString; \
+ ASSERT_EQ(V1, test.contentsOfDword(T0)) << TestString; \
+ reset(); \
+ } while (0)
+
+#define TestImplSize(Dst1, Size) \
+ do { \
+ TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, Size); \
+ } while (0)
+
+#define TestImpl(Dst1) \
+ do { \
+ if (GPRRegister::Encoded_Reg_##Dst1 < 4) { \
+ TestImplSize(Dst1, 8); \
+ } \
+ TestImplSize(Dst1, 16); \
+ TestImplSize(Dst1, 32); \
+ } while (0)
+
+ TestImpl(eax);
+ TestImpl(ebx);
+ TestImpl(ecx);
+ TestImpl(edx);
+ TestImpl(esi);
+ TestImpl(edi);
+
+#undef TestImpl
+#undef TestImplSize
+#undef TestImplAddrReg
+}
+
+TEST_F(AssemblerX8632Test, Xadd) {
+ static constexpr bool NotLocked = false;
+ static constexpr bool Locked = true;
+
+ static constexpr uint32_t Mask8 = 0x000000FF;
+ static constexpr uint32_t Mask16 = 0x0000FFFF;
+ static constexpr uint32_t Mask32 = 0xFFFFFFFF;
+
+#define TestImplAddrReg(Value0, Dst1, Value1, LockedOrNot, Size) \
+ do { \
+ static constexpr char TestString[] = \
+ "(" #Value0 ", " #Dst1 ", " #Value1 ", " #Size ")"; \
+ const uint32_t T0 = allocateDword(); \
+ const uint32_t V0 = (Value0)&Mask##Size; \
+ const uint32_t V1 = (Value1)&Mask##Size; \
+ \
+ __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst1, \
+ Immediate(Value1)); \
+ __ xadd(IceType_i##Size, dwordAddress(T0), \
+ GPRRegister::Encoded_Reg_##Dst1, LockedOrNot); \
+ __ And(IceType_i32, GPRRegister::Encoded_Reg_##Dst1, \
+ Immediate(Mask##Size)); \
+ \
+ AssembledTest test = assemble(); \
+ test.setDwordTo(T0, V0); \
+ test.run(); \
+ \
+ ASSERT_EQ(V0, test.Dst1()) << TestString; \
+ ASSERT_EQ(Mask##Size &(V1 + V0), test.contentsOfDword(T0)) << TestString; \
+ reset(); \
+ } while (0)
+
+#define TestImplSize(Dst1, Size) \
+ do { \
+ TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, NotLocked, Size); \
+ TestImplAddrReg(0xa2b34567, Dst1, 0x0507ddee, Locked, Size); \
+ } while (0)
+
+#define TestImpl(Dst1) \
+ do { \
+ if (GPRRegister::Encoded_Reg_##Dst1 < 4) { \
+ TestImplSize(Dst1, 8); \
+ } \
+ TestImplSize(Dst1, 16); \
+ TestImplSize(Dst1, 32); \
+ } while (0)
+
+ TestImpl(eax);
+ TestImpl(ebx);
+ TestImpl(ecx);
+ TestImpl(edx);
+ TestImpl(esi);
+ TestImpl(edi);
+
+#undef TestImpl
+#undef TestImplSize
+#undef TestImplAddrReg
+}
+
+TEST_F(AssemblerX8632LowLevelTest, Xadd) {
+ static constexpr bool NotLocked = false;
+ static constexpr bool Locked = true;
+
+ // Ensures that xadd emits a lock prefix accordingly.
+ {
+ __ xadd(IceType_i8, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, NotLocked);
+ static constexpr uint8_t ByteCountNotLocked8 = 7;
+ ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
+ verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x0F, 0xC0, 0x35, 0x00, 0xFF,
+ 0x01, 0x00);
+ reset();
+
+ __ xadd(IceType_i8, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, Locked);
+ static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
+ ASSERT_EQ(ByteCountLocked8, codeBytesSize());
+ verifyBytes<ByteCountLocked8>(codeBytes(), 0xF0, 0x0F, 0xC0, 0x35, 0x00,
+ 0xFF, 0x01, 0x00);
+ reset();
+ }
+
+ {
+ __ xadd(IceType_i16, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, NotLocked);
+ static constexpr uint8_t ByteCountNotLocked16 = 8;
+ ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
+ verifyBytes<ByteCountNotLocked16>(codeBytes(), 0x66, 0x0F, 0xC1, 0x35, 0x00,
+ 0xFF, 0x01, 0x00);
+ reset();
+
+ __ xadd(IceType_i16, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, Locked);
+ static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
+ ASSERT_EQ(ByteCountLocked16, codeBytesSize());
+ verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x0F, 0xC1, 0x35,
+ 0x00, 0xFF, 0x01, 0x00);
+ reset();
+ }
+
+ {
+ __ xadd(IceType_i32, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, NotLocked);
+ static constexpr uint8_t ByteCountNotLocked32 = 7;
+ ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
+ verifyBytes<ByteCountNotLocked32>(codeBytes(), 0x0F, 0xC1, 0x35, 0x00, 0xFF,
+ 0x01, 0x00);
+ reset();
+
+ __ xadd(IceType_i32, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, Locked);
+ static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
+ ASSERT_EQ(ByteCountLocked32, codeBytesSize());
+ verifyBytes<ByteCountLocked32>(codeBytes(), 0xF0, 0x0F, 0xC1, 0x35, 0x00,
+ 0xFF, 0x01, 0x00);
+ reset();
+ }
+}
+
+TEST_F(AssemblerX8632Test, Cmpxchg8b) {
+ static constexpr bool NotLocked = false;
+ static constexpr bool Locked = true;
+
+#define TestImpl(Value0, Value1, ValueMem, LockedOrNot) \
+ do { \
+ static constexpr char TestString[] = \
+ "(" #Value0 ", " #Value1 ", " #ValueMem ", " #LockedOrNot ")"; \
+ const uint32_t T0 = allocateQword(); \
+ static constexpr uint64_t V0 = ValueMem; \
+ const uint32_t ZeroFlag = allocateDword(); \
+ \
+ __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, \
+ Immediate(uint64_t(Value0) & 0xFFFFFFFF)); \
+ __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, \
+ Immediate(uint64_t(Value0) >> 32)); \
+ __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, \
+ Immediate(uint64_t(Value1) & 0xFFFFFFFF)); \
+ __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, \
+ Immediate(uint64_t(Value1) >> 32)); \
+ __ cmpxchg8b(dwordAddress(T0), LockedOrNot); \
+ __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
+ \
+ AssembledTest test = assemble(); \
+ test.setQwordTo(T0, V0); \
+ test.setDwordTo(ZeroFlag, uint32_t(0xFF)); \
+ test.run(); \
+ \
+ if (V0 == (Value0)) { \
+ ASSERT_EQ(uint64_t(Value1), test.contentsOfQword(T0)) << TestString; \
+ ASSERT_EQ(1u, test.contentsOfDword(ZeroFlag)) << TestString; \
+ } else { \
+ ASSERT_EQ(uint64_t(ValueMem) & 0xFFFFFFFF, test.eax()) << TestString; \
+ ASSERT_EQ((uint64_t(ValueMem) >> 32) & 0xFFFFFFFF, test.edx()) \
+ << TestString; \
+ ASSERT_EQ(0u, test.contentsOfDword(ZeroFlag)) << TestString; \
+ } \
+ reset(); \
+ } while (0)
+
+ TestImpl(0x98987676543210ull, 0x1, 0x98987676543210ull, NotLocked);
+ TestImpl(0x98987676543210ull, 0x1, 0x98987676543210ull, Locked);
+ TestImpl(0x98987676543210ull, 0x1, 0x98987676543211ull, NotLocked);
+ TestImpl(0x98987676543210ull, 0x1, 0x98987676543211ull, Locked);
+
+#undef TestImpl
+}
+
+TEST_F(AssemblerX8632LowLevelTest, Cmpxchg8b) {
+ static constexpr bool NotLocked = false;
+ static constexpr bool Locked = true;
+
+ // Ensures that cmpxchg8b emits a lock prefix accordingly.
+ __ cmpxchg8b(Address::Absolute(0x1FF00), NotLocked);
+ static constexpr uint8_t ByteCountNotLocked = 7;
+ ASSERT_EQ(ByteCountNotLocked, codeBytesSize());
+ verifyBytes<ByteCountNotLocked>(codeBytes(), 0x0F, 0xC7, 0x0D, 0x00, 0xFF,
+ 0x01, 0x00);
+ reset();
+
+ __ cmpxchg8b(Address::Absolute(0x1FF00), Locked);
+ static constexpr uint8_t ByteCountLocked = 1 + ByteCountNotLocked;
+ ASSERT_EQ(ByteCountLocked, codeBytesSize());
+ verifyBytes<ByteCountLocked>(codeBytes(), 0xF0, 0x0F, 0xC7, 0x0D, 0x00, 0xFF,
+ 0x01, 0x00);
+ reset();
+}
+
+TEST_F(AssemblerX8632Test, Cmpxchg) {
+ static constexpr bool NotLocked = false;
+ static constexpr bool Locked = true;
+
+ static constexpr uint32_t Mask8 = 0x000000FF;
+ static constexpr uint32_t Mask16 = 0x0000FFFF;
+ static constexpr uint32_t Mask32 = 0xFFFFFFFF;
+
+#define TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, Size) \
+ do { \
+ static constexpr char TestString[] = \
+ "(" #Value0 ", " #Src ", " #Value1 ", " #ValueMem ", " #LockedOrNot \
+ ", " #Size ")"; \
+ const uint32_t T0 = allocateDword(); \
+ static constexpr uint32_t V0 = (ValueMem)&Mask##Size; \
+ const uint32_t ZeroFlag = allocateDword(); \
+ \
+ __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_eax, \
+ Immediate((Value0)&Mask##Size)); \
+ __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \
+ Immediate((Value1)&Mask##Size)); \
+ __ cmpxchg(IceType_i##Size, dwordAddress(T0), \
+ GPRRegister::Encoded_Reg_##Src, LockedOrNot); \
+ __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \
+ \
+ AssembledTest test = assemble(); \
+ test.setDwordTo(T0, V0); \
+ test.setDwordTo(ZeroFlag, uint32_t(0xFF)); \
+ test.run(); \
+ \
+ if (V0 == (Mask##Size & (Value0))) { \
+ ASSERT_EQ(uint32_t((Value1)&Mask##Size), test.contentsOfDword(T0)) \
+ << TestString; \
+ ASSERT_EQ(1u, test.contentsOfDword(ZeroFlag)) << TestString; \
+ } else { \
+ ASSERT_EQ(uint32_t((ValueMem)&Mask##Size), test.eax()) << TestString; \
+ ASSERT_EQ(0u, test.contentsOfDword(ZeroFlag)) << TestString; \
+ } \
+ reset(); \
+ } while (0)
+
+#define TestImplValue(Value0, Src, Value1, ValueMem, LockedOrNot) \
+ do { \
+ if (GPRRegister::Encoded_Reg_##Src < 4) { \
+ TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 8); \
+ } \
+ TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 16); \
+ TestImplAddrReg(Value0, Src, Value1, ValueMem, LockedOrNot, 32); \
+ } while (0)
+
+#define TestImpl(Src, LockedOrNot) \
+ do { \
+ TestImplValue(0xFFFFFFFF, Src, 0x1, 0xFFFFFFFF, LockedOrNot); \
+ TestImplValue(0x0FFF0F0F, Src, 0x1, 0xFFFFFFFF, LockedOrNot); \
+ } while (0)
+
+ TestImpl(ebx, Locked);
+ TestImpl(edx, NotLocked);
+ TestImpl(ecx, Locked);
+ TestImpl(ecx, NotLocked);
+ TestImpl(edx, Locked);
+ TestImpl(edx, NotLocked);
+ TestImpl(esi, Locked);
+ TestImpl(esi, NotLocked);
+ TestImpl(edi, Locked);
+ TestImpl(edi, NotLocked);
+
+#undef TestImpl
+#undef TestImplValue
+#undef TestImplAddrReg
+}
+
+TEST_F(AssemblerX8632LowLevelTest, Cmpxchg) {
+ static constexpr bool NotLocked = false;
+ static constexpr bool Locked = true;
+
+ // Ensures that cmpxchg emits a lock prefix accordingly.
+ {
+ __ cmpxchg(IceType_i8, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, NotLocked);
+ static constexpr uint8_t ByteCountNotLocked8 = 7;
+ ASSERT_EQ(ByteCountNotLocked8, codeBytesSize());
+ verifyBytes<ByteCountNotLocked8>(codeBytes(), 0x0F, 0xB0, 0x35, 0x00, 0xFF,
+ 0x01, 0x00);
+ reset();
+
+ __ cmpxchg(IceType_i8, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, Locked);
+ static constexpr uint8_t ByteCountLocked8 = 1 + ByteCountNotLocked8;
+ ASSERT_EQ(ByteCountLocked8, codeBytesSize());
+ verifyBytes<ByteCountLocked8>(codeBytes(), 0xF0, 0x0F, 0xB0, 0x35, 0x00,
+ 0xFF, 0x01, 0x00);
+ reset();
+ }
+
+ {
+ __ cmpxchg(IceType_i16, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, NotLocked);
+ static constexpr uint8_t ByteCountNotLocked16 = 8;
+ ASSERT_EQ(ByteCountNotLocked16, codeBytesSize());
+ verifyBytes<ByteCountNotLocked16>(codeBytes(), 0x66, 0x0F, 0xB1, 0x35, 0x00,
+ 0xFF, 0x01, 0x00);
+ reset();
+
+ __ cmpxchg(IceType_i16, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, Locked);
+ static constexpr uint8_t ByteCountLocked16 = 1 + ByteCountNotLocked16;
+ ASSERT_EQ(ByteCountLocked16, codeBytesSize());
+ verifyBytes<ByteCountLocked16>(codeBytes(), 0x66, 0xF0, 0x0F, 0xB1, 0x35,
+ 0x00, 0xFF, 0x01, 0x00);
+ reset();
+ }
+
+ {
+ __ cmpxchg(IceType_i32, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, NotLocked);
+ static constexpr uint8_t ByteCountNotLocked32 = 7;
+ ASSERT_EQ(ByteCountNotLocked32, codeBytesSize());
+ verifyBytes<ByteCountNotLocked32>(codeBytes(), 0x0F, 0xB1, 0x35, 0x00, 0xFF,
+ 0x01, 0x00);
+ reset();
+
+ __ cmpxchg(IceType_i32, Address::Absolute(0x1FF00),
+ GPRRegister::Encoded_Reg_esi, Locked);
+ static constexpr uint8_t ByteCountLocked32 = 1 + ByteCountNotLocked32;
+ ASSERT_EQ(ByteCountLocked32, codeBytesSize());
+ verifyBytes<ByteCountLocked32>(codeBytes(), 0xF0, 0x0F, 0xB1, 0x35, 0x00,
+ 0xFF, 0x01, 0x00);
+ reset();
+ }
+}
+
+} // end of anonymous namespace
+} // end of namespace Test
+} // end of namespace X8632
+} // end of namespace Ice
« no previous file with comments | « unittest/AssemblerX8632/GPRArith.cpp ('k') | unittest/AssemblerX8632/LowLevel.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698