| //===- subzero/unittest/AssemblerX8632/X87.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, Fld) { |
| __ fld(IceType_f32, |
| Address(GPRRegister::Encoded_Reg_ebp, 1, AssemblerFixup::NoFixup)); |
| __ fld(IceType_f64, Address(GPRRegister::Encoded_Reg_ebp, 0x10000, |
| AssemblerFixup::NoFixup)); |
| |
| constexpr size_t ByteCount = 9; |
| ASSERT_EQ(ByteCount, codeBytesSize()); |
| |
| constexpr uint8_t Fld32Opcode = 0xd9; |
| constexpr uint8_t Fld32ModRM = (/*mod*/ 1 << 6) | (/*reg*/ 0 << 3) | |
| (/*rm*/ GPRRegister::Encoded_Reg_ebp); |
| constexpr uint8_t Fld64Opcode = 0xdd; |
| constexpr uint8_t Fld64ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 0 << 3) | |
| (/*rm*/ GPRRegister::Encoded_Reg_ebp); |
| verifyBytes<ByteCount>(codeBytes(), Fld32Opcode, Fld32ModRM, 0x01, |
| Fld64Opcode, Fld64ModRM, 0x00, 0x00, 0x01, 0x00); |
| } |
| |
| TEST_F(AssemblerX8632LowLevelTest, FstpAddr) { |
| __ fstp(IceType_f32, |
| Address(GPRRegister::Encoded_Reg_ebp, 1, AssemblerFixup::NoFixup)); |
| __ fstp(IceType_f64, Address(GPRRegister::Encoded_Reg_ebp, 0x10000, |
| AssemblerFixup::NoFixup)); |
| |
| constexpr size_t ByteCount = 9; |
| ASSERT_EQ(ByteCount, codeBytesSize()); |
| |
| constexpr uint8_t Fld32Opcode = 0xd9; |
| constexpr uint8_t Fld32ModRM = (/*mod*/ 1 << 6) | (/*reg*/ 3 << 3) | |
| (/*rm*/ GPRRegister::Encoded_Reg_ebp); |
| constexpr uint8_t Fld64Opcode = 0xdd; |
| constexpr uint8_t Fld64ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 3 << 3) | |
| (/*rm*/ GPRRegister::Encoded_Reg_ebp); |
| verifyBytes<ByteCount>(codeBytes(), Fld32Opcode, Fld32ModRM, 0x01, |
| Fld64Opcode, Fld64ModRM, 0x00, 0x00, 0x01, 0x00); |
| } |
| |
| TEST_F(AssemblerX8632LowLevelTest, Fincstp) { |
| __ fincstp(); |
| |
| constexpr size_t ByteCount = 2; |
| ASSERT_EQ(ByteCount, codeBytesSize()); |
| |
| verifyBytes<ByteCount>(codeBytes(), 0xD9, 0XF7); |
| } |
| |
| TEST_F(AssemblerX8632LowLevelTest, FnstcwAddr) { |
| __ fnstcw( |
| Address(GPRRegister::Encoded_Reg_ebp, 0x12345, AssemblerFixup::NoFixup)); |
| |
| constexpr size_t ByteCount = 6; |
| ASSERT_EQ(ByteCount, codeBytesSize()); |
| |
| constexpr uint8_t Opcode = 0xd9; |
| constexpr uint8_t ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 7 << 3) | |
| (/*rm*/ GPRRegister::Encoded_Reg_ebp); |
| verifyBytes<ByteCount>(codeBytes(), Opcode, ModRM, 0x45, 0x23, 0x01, 0x00); |
| } |
| |
| TEST_F(AssemblerX8632LowLevelTest, FldcwAddr) { |
| __ fldcw( |
| Address(GPRRegister::Encoded_Reg_ebp, 0x12345, AssemblerFixup::NoFixup)); |
| |
| constexpr size_t ByteCount = 6; |
| ASSERT_EQ(ByteCount, codeBytesSize()); |
| |
| constexpr uint8_t Opcode = 0xd9; |
| constexpr uint8_t ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 5 << 3) | |
| (/*rm*/ GPRRegister::Encoded_Reg_ebp); |
| verifyBytes<ByteCount>(codeBytes(), Opcode, ModRM, 0x45, 0x23, 0x01, 0x00); |
| } |
| |
| TEST_F(AssemblerX8632Test, FstpSt) { |
| #define TestFstpSt(Size, MemorySize, Type) \ |
| do { \ |
| const uint32_t T1 = allocate##MemorySize(); \ |
| const Type OldValue1 = -1.0f; \ |
| const uint32_t T2 = allocate##MemorySize(); \ |
| const Type OldValue2 = -2.0f; \ |
| const uint32_t T3 = allocate##MemorySize(); \ |
| const Type OldValue3 = -3.0f; \ |
| const uint32_t T4 = allocate##MemorySize(); \ |
| const Type OldValue4 = -4.0f; \ |
| const uint32_t T5 = allocate##MemorySize(); \ |
| const Type OldValue5 = -5.0f; \ |
| const uint32_t T6 = allocate##MemorySize(); \ |
| const Type OldValue6 = -6.0f; \ |
| const uint32_t T7 = allocate##MemorySize(); \ |
| const Type OldValue7 = -7.0f; \ |
| \ |
| const uint32_t N7 = allocate##MemorySize(); \ |
| constexpr Type NewValue7 = 777.77f; \ |
| const uint32_t N6 = allocate##MemorySize(); \ |
| constexpr Type NewValue6 = 666.66f; \ |
| const uint32_t N5 = allocate##MemorySize(); \ |
| constexpr Type NewValue5 = 555.55f; \ |
| const uint32_t N4 = allocate##MemorySize(); \ |
| constexpr Type NewValue4 = 444.44f; \ |
| const uint32_t N3 = allocate##MemorySize(); \ |
| constexpr Type NewValue3 = 333.33f; \ |
| const uint32_t N2 = allocate##MemorySize(); \ |
| constexpr Type NewValue2 = 222.22f; \ |
| const uint32_t N1 = allocate##MemorySize(); \ |
| constexpr Type NewValue1 = 111.11f; \ |
| \ |
| __ fincstp(); \ |
| __ fincstp(); \ |
| __ fincstp(); \ |
| __ fincstp(); \ |
| __ fincstp(); \ |
| __ fincstp(); \ |
| __ fincstp(); \ |
| \ |
| __ fld(IceType_f##Size, dwordAddress(N7)); \ |
| __ fstp(X87STRegister::Encoded_X87ST_7); \ |
| __ fld(IceType_f##Size, dwordAddress(N6)); \ |
| __ fstp(X87STRegister::Encoded_X87ST_6); \ |
| __ fld(IceType_f##Size, dwordAddress(N5)); \ |
| __ fstp(X87STRegister::Encoded_X87ST_5); \ |
| __ fld(IceType_f##Size, dwordAddress(N4)); \ |
| __ fstp(X87STRegister::Encoded_X87ST_4); \ |
| __ fld(IceType_f##Size, dwordAddress(N3)); \ |
| __ fstp(X87STRegister::Encoded_X87ST_3); \ |
| __ fld(IceType_f##Size, dwordAddress(N2)); \ |
| __ fstp(X87STRegister::Encoded_X87ST_2); \ |
| __ fld(IceType_f##Size, dwordAddress(N1)); \ |
| __ fstp(X87STRegister::Encoded_X87ST_1); \ |
| \ |
| __ fstp(IceType_f##Size, dwordAddress(T1)); \ |
| __ fstp(IceType_f##Size, dwordAddress(T2)); \ |
| __ fstp(IceType_f##Size, dwordAddress(T3)); \ |
| __ fstp(IceType_f##Size, dwordAddress(T4)); \ |
| __ fstp(IceType_f##Size, dwordAddress(T5)); \ |
| __ fstp(IceType_f##Size, dwordAddress(T6)); \ |
| __ fstp(IceType_f##Size, dwordAddress(T7)); \ |
| \ |
| AssembledTest test = assemble(); \ |
| test.set##MemorySize##To(T1, OldValue1); \ |
| test.set##MemorySize##To(N1, NewValue1); \ |
| test.set##MemorySize##To(T2, OldValue2); \ |
| test.set##MemorySize##To(N2, NewValue2); \ |
| test.set##MemorySize##To(T3, OldValue3); \ |
| test.set##MemorySize##To(N3, NewValue3); \ |
| test.set##MemorySize##To(T4, OldValue4); \ |
| test.set##MemorySize##To(N4, NewValue4); \ |
| test.set##MemorySize##To(T5, OldValue5); \ |
| test.set##MemorySize##To(N5, NewValue5); \ |
| test.set##MemorySize##To(T6, OldValue6); \ |
| test.set##MemorySize##To(N6, NewValue6); \ |
| test.set##MemorySize##To(T7, OldValue7); \ |
| test.set##MemorySize##To(N7, NewValue7); \ |
| \ |
| test.run(); \ |
| \ |
| ASSERT_FLOAT_EQ(NewValue1, test.contentsOf##MemorySize<Type>(T1)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue1, test.contentsOf##MemorySize<Type>(N1)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue2, test.contentsOf##MemorySize<Type>(T2)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue2, test.contentsOf##MemorySize<Type>(N2)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue3, test.contentsOf##MemorySize<Type>(T3)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue3, test.contentsOf##MemorySize<Type>(N3)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue4, test.contentsOf##MemorySize<Type>(T4)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue4, test.contentsOf##MemorySize<Type>(N4)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue5, test.contentsOf##MemorySize<Type>(T5)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue5, test.contentsOf##MemorySize<Type>(N5)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue6, test.contentsOf##MemorySize<Type>(T6)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue6, test.contentsOf##MemorySize<Type>(N6)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue7, test.contentsOf##MemorySize<Type>(T7)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| ASSERT_FLOAT_EQ(NewValue7, test.contentsOf##MemorySize<Type>(N7)) \ |
| << "(" #Size ", " #MemorySize ", " #Type ")"; \ |
| \ |
| reset(); \ |
| } while (0) |
| |
| TestFstpSt(32, Dword, float); |
| TestFstpSt(64, Qword, double); |
| |
| #undef TestFstpSt |
| } |
| |
| TEST_F(AssemblerX8632Test, Fild) { |
| #define TestFild(OperandType, Size, MemorySize, FpType, IntType) \ |
| do { \ |
| const uint32_t T0 = allocate##MemorySize(); \ |
| constexpr IntType V0 = 0x1234; \ |
| \ |
| __ fild##OperandType(dwordAddress(T0)); \ |
| __ fstp(IceType_f##Size, dwordAddress(T0)); \ |
| \ |
| AssembledTest test = assemble(); \ |
| \ |
| test.set##MemorySize##To(T0, V0); \ |
| test.run(); \ |
| \ |
| ASSERT_FLOAT_EQ(static_cast<FpType>(V0), \ |
| test.contentsOf##MemorySize<FpType>(T0)) \ |
| << "(" #OperandType ", " #Size ", " #MemorySize ", " #FpType \ |
| ", " #IntType ")"; \ |
| \ |
| reset(); \ |
| } while (0) |
| |
| TestFild(s, 32, Dword, float, uint32_t); |
| TestFild(l, 64, Qword, double, uint64_t); |
| #undef TestFild |
| } |
| |
| TEST_F(AssemblerX8632Test, Fistp) { |
| #define TestFistp(OperandType, Size, MemorySize, FpType, IntType) \ |
| do { \ |
| const uint32_t T0 = allocate##MemorySize(); \ |
| constexpr IntType V0 = 0x1234; \ |
| const uint32_t T1 = allocate##MemorySize(); \ |
| constexpr IntType V1 = 0xFFFF; \ |
| \ |
| __ fild##OperandType(dwordAddress(T0)); \ |
| __ fistp##OperandType(dwordAddress(T1)); \ |
| \ |
| AssembledTest test = assemble(); \ |
| \ |
| test.set##MemorySize##To(T0, V0); \ |
| test.set##MemorySize##To(T1, V1); \ |
| test.run(); \ |
| \ |
| ASSERT_EQ(static_cast<IntType>(V0), \ |
| test.contentsOf##MemorySize<IntType>(T0)) \ |
| << "(" #OperandType ", " #Size ", " #MemorySize ", " #FpType \ |
| ", " #IntType ")"; \ |
| ASSERT_EQ(static_cast<IntType>(V0), \ |
| test.contentsOf##MemorySize<IntType>(T1)) \ |
| << "(" #OperandType ", " #Size ", " #MemorySize ", " #FpType \ |
| ", " #IntType ")"; \ |
| \ |
| reset(); \ |
| } while (0) |
| |
| TestFistp(s, 32, Dword, float, uint32_t); |
| TestFistp(l, 64, Qword, double, uint64_t); |
| #undef TestFistp |
| } |
| |
| } // end of anonymous namespace |
| } // end of namespace Test |
| } // end of namespace X8632 |
| } // end of namespace Ice |