1 //===- subzero/unittest/AssemblerX8632/X87.cpp ----------------------------===// 2 // 3 // The Subzero Code Generator 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include "AssemblerX8632/TestUtil.h" 10 11 namespace Ice { 12 namespace X8632 { 13 namespace Test { 14 namespace { 15 16 TEST_F(AssemblerX8632LowLevelTest, Fld) { 17 __ fld(IceType_f32, 18 Address(GPRRegister::Encoded_Reg_ebp, 1, AssemblerFixup::NoFixup)); 19 __ fld(IceType_f64, Address(GPRRegister::Encoded_Reg_ebp, 0x10000, 20 AssemblerFixup::NoFixup)); 21 22 constexpr size_t ByteCount = 9; 23 ASSERT_EQ(ByteCount, codeBytesSize()); 24 25 constexpr uint8_t Fld32Opcode = 0xd9; 26 constexpr uint8_t Fld32ModRM = (/*mod*/ 1 << 6) | (/*reg*/ 0 << 3) | 27 (/*rm*/ GPRRegister::Encoded_Reg_ebp); 28 constexpr uint8_t Fld64Opcode = 0xdd; 29 constexpr uint8_t Fld64ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 0 << 3) | 30 (/*rm*/ GPRRegister::Encoded_Reg_ebp); 31 verifyBytes<ByteCount>(codeBytes(), Fld32Opcode, Fld32ModRM, 0x01, 32 Fld64Opcode, Fld64ModRM, 0x00, 0x00, 0x01, 0x00); 33 } 34 35 TEST_F(AssemblerX8632LowLevelTest, FstpAddr) { 36 __ fstp(IceType_f32, 37 Address(GPRRegister::Encoded_Reg_ebp, 1, AssemblerFixup::NoFixup)); 38 __ fstp(IceType_f64, Address(GPRRegister::Encoded_Reg_ebp, 0x10000, 39 AssemblerFixup::NoFixup)); 40 41 constexpr size_t ByteCount = 9; 42 ASSERT_EQ(ByteCount, codeBytesSize()); 43 44 constexpr uint8_t Fld32Opcode = 0xd9; 45 constexpr uint8_t Fld32ModRM = (/*mod*/ 1 << 6) | (/*reg*/ 3 << 3) | 46 (/*rm*/ GPRRegister::Encoded_Reg_ebp); 47 constexpr uint8_t Fld64Opcode = 0xdd; 48 constexpr uint8_t Fld64ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 3 << 3) | 49 (/*rm*/ GPRRegister::Encoded_Reg_ebp); 50 verifyBytes<ByteCount>(codeBytes(), Fld32Opcode, Fld32ModRM, 0x01, 51 Fld64Opcode, Fld64ModRM, 0x00, 0x00, 0x01, 0x00); 52 } 53 54 TEST_F(AssemblerX8632LowLevelTest, Fincstp) { 55 __ fincstp(); 56 57 constexpr size_t ByteCount = 2; 58 ASSERT_EQ(ByteCount, codeBytesSize()); 59 60 verifyBytes<ByteCount>(codeBytes(), 0xD9, 0XF7); 61 } 62 63 TEST_F(AssemblerX8632LowLevelTest, FnstcwAddr) { 64 __ fnstcw( 65 Address(GPRRegister::Encoded_Reg_ebp, 0x12345, AssemblerFixup::NoFixup)); 66 67 constexpr size_t ByteCount = 6; 68 ASSERT_EQ(ByteCount, codeBytesSize()); 69 70 constexpr uint8_t Opcode = 0xd9; 71 constexpr uint8_t ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 7 << 3) | 72 (/*rm*/ GPRRegister::Encoded_Reg_ebp); 73 verifyBytes<ByteCount>(codeBytes(), Opcode, ModRM, 0x45, 0x23, 0x01, 0x00); 74 } 75 76 TEST_F(AssemblerX8632LowLevelTest, FldcwAddr) { 77 __ fldcw( 78 Address(GPRRegister::Encoded_Reg_ebp, 0x12345, AssemblerFixup::NoFixup)); 79 80 constexpr size_t ByteCount = 6; 81 ASSERT_EQ(ByteCount, codeBytesSize()); 82 83 constexpr uint8_t Opcode = 0xd9; 84 constexpr uint8_t ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 5 << 3) | 85 (/*rm*/ GPRRegister::Encoded_Reg_ebp); 86 verifyBytes<ByteCount>(codeBytes(), Opcode, ModRM, 0x45, 0x23, 0x01, 0x00); 87 } 88 89 TEST_F(AssemblerX8632Test, FstpSt) { 90 #define TestFstpSt(Size, MemorySize, Type) \ 91 do { \ 92 const uint32_t T1 = allocate##MemorySize(); \ 93 const Type OldValue1 = -1.0f; \ 94 const uint32_t T2 = allocate##MemorySize(); \ 95 const Type OldValue2 = -2.0f; \ 96 const uint32_t T3 = allocate##MemorySize(); \ 97 const Type OldValue3 = -3.0f; \ 98 const uint32_t T4 = allocate##MemorySize(); \ 99 const Type OldValue4 = -4.0f; \ 100 const uint32_t T5 = allocate##MemorySize(); \ 101 const Type OldValue5 = -5.0f; \ 102 const uint32_t T6 = allocate##MemorySize(); \ 103 const Type OldValue6 = -6.0f; \ 104 const uint32_t T7 = allocate##MemorySize(); \ 105 const Type OldValue7 = -7.0f; \ 106 \ 107 const uint32_t N7 = allocate##MemorySize(); \ 108 constexpr Type NewValue7 = 777.77f; \ 109 const uint32_t N6 = allocate##MemorySize(); \ 110 constexpr Type NewValue6 = 666.66f; \ 111 const uint32_t N5 = allocate##MemorySize(); \ 112 constexpr Type NewValue5 = 555.55f; \ 113 const uint32_t N4 = allocate##MemorySize(); \ 114 constexpr Type NewValue4 = 444.44f; \ 115 const uint32_t N3 = allocate##MemorySize(); \ 116 constexpr Type NewValue3 = 333.33f; \ 117 const uint32_t N2 = allocate##MemorySize(); \ 118 constexpr Type NewValue2 = 222.22f; \ 119 const uint32_t N1 = allocate##MemorySize(); \ 120 constexpr Type NewValue1 = 111.11f; \ 121 \ 122 __ fincstp(); \ 123 __ fincstp(); \ 124 __ fincstp(); \ 125 __ fincstp(); \ 126 __ fincstp(); \ 127 __ fincstp(); \ 128 __ fincstp(); \ 129 \ 130 __ fld(IceType_f##Size, dwordAddress(N7)); \ 131 __ fstp(X87STRegister::Encoded_X87ST_7); \ 132 __ fld(IceType_f##Size, dwordAddress(N6)); \ 133 __ fstp(X87STRegister::Encoded_X87ST_6); \ 134 __ fld(IceType_f##Size, dwordAddress(N5)); \ 135 __ fstp(X87STRegister::Encoded_X87ST_5); \ 136 __ fld(IceType_f##Size, dwordAddress(N4)); \ 137 __ fstp(X87STRegister::Encoded_X87ST_4); \ 138 __ fld(IceType_f##Size, dwordAddress(N3)); \ 139 __ fstp(X87STRegister::Encoded_X87ST_3); \ 140 __ fld(IceType_f##Size, dwordAddress(N2)); \ 141 __ fstp(X87STRegister::Encoded_X87ST_2); \ 142 __ fld(IceType_f##Size, dwordAddress(N1)); \ 143 __ fstp(X87STRegister::Encoded_X87ST_1); \ 144 \ 145 __ fstp(IceType_f##Size, dwordAddress(T1)); \ 146 __ fstp(IceType_f##Size, dwordAddress(T2)); \ 147 __ fstp(IceType_f##Size, dwordAddress(T3)); \ 148 __ fstp(IceType_f##Size, dwordAddress(T4)); \ 149 __ fstp(IceType_f##Size, dwordAddress(T5)); \ 150 __ fstp(IceType_f##Size, dwordAddress(T6)); \ 151 __ fstp(IceType_f##Size, dwordAddress(T7)); \ 152 \ 153 AssembledTest test = assemble(); \ 154 test.set##MemorySize##To(T1, OldValue1); \ 155 test.set##MemorySize##To(N1, NewValue1); \ 156 test.set##MemorySize##To(T2, OldValue2); \ 157 test.set##MemorySize##To(N2, NewValue2); \ 158 test.set##MemorySize##To(T3, OldValue3); \ 159 test.set##MemorySize##To(N3, NewValue3); \ 160 test.set##MemorySize##To(T4, OldValue4); \ 161 test.set##MemorySize##To(N4, NewValue4); \ 162 test.set##MemorySize##To(T5, OldValue5); \ 163 test.set##MemorySize##To(N5, NewValue5); \ 164 test.set##MemorySize##To(T6, OldValue6); \ 165 test.set##MemorySize##To(N6, NewValue6); \ 166 test.set##MemorySize##To(T7, OldValue7); \ 167 test.set##MemorySize##To(N7, NewValue7); \ 168 \ 169 test.run(); \ 170 \ 171 ASSERT_FLOAT_EQ(NewValue1, test.contentsOf##MemorySize<Type>(T1)) \ 172 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 173 ASSERT_FLOAT_EQ(NewValue1, test.contentsOf##MemorySize<Type>(N1)) \ 174 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 175 ASSERT_FLOAT_EQ(NewValue2, test.contentsOf##MemorySize<Type>(T2)) \ 176 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 177 ASSERT_FLOAT_EQ(NewValue2, test.contentsOf##MemorySize<Type>(N2)) \ 178 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 179 ASSERT_FLOAT_EQ(NewValue3, test.contentsOf##MemorySize<Type>(T3)) \ 180 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 181 ASSERT_FLOAT_EQ(NewValue3, test.contentsOf##MemorySize<Type>(N3)) \ 182 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 183 ASSERT_FLOAT_EQ(NewValue4, test.contentsOf##MemorySize<Type>(T4)) \ 184 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 185 ASSERT_FLOAT_EQ(NewValue4, test.contentsOf##MemorySize<Type>(N4)) \ 186 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 187 ASSERT_FLOAT_EQ(NewValue5, test.contentsOf##MemorySize<Type>(T5)) \ 188 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 189 ASSERT_FLOAT_EQ(NewValue5, test.contentsOf##MemorySize<Type>(N5)) \ 190 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 191 ASSERT_FLOAT_EQ(NewValue6, test.contentsOf##MemorySize<Type>(T6)) \ 192 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 193 ASSERT_FLOAT_EQ(NewValue6, test.contentsOf##MemorySize<Type>(N6)) \ 194 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 195 ASSERT_FLOAT_EQ(NewValue7, test.contentsOf##MemorySize<Type>(T7)) \ 196 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 197 ASSERT_FLOAT_EQ(NewValue7, test.contentsOf##MemorySize<Type>(N7)) \ 198 << "(" #Size ", " #MemorySize ", " #Type ")"; \ 199 \ 200 reset(); \ 201 } while (0) 202 203 TestFstpSt(32, Dword, float); 204 TestFstpSt(64, Qword, double); 205 206 #undef TestFstpSt 207 } 208 209 TEST_F(AssemblerX8632Test, Fild) { 210 #define TestFild(OperandType, Size, MemorySize, FpType, IntType) \ 211 do { \ 212 const uint32_t T0 = allocate##MemorySize(); \ 213 constexpr IntType V0 = 0x1234; \ 214 \ 215 __ fild##OperandType(dwordAddress(T0)); \ 216 __ fstp(IceType_f##Size, dwordAddress(T0)); \ 217 \ 218 AssembledTest test = assemble(); \ 219 \ 220 test.set##MemorySize##To(T0, V0); \ 221 test.run(); \ 222 \ 223 ASSERT_FLOAT_EQ(static_cast<FpType>(V0), \ 224 test.contentsOf##MemorySize<FpType>(T0)) \ 225 << "(" #OperandType ", " #Size ", " #MemorySize ", " #FpType \ 226 ", " #IntType ")"; \ 227 \ 228 reset(); \ 229 } while (0) 230 231 TestFild(s, 32, Dword, float, uint32_t); 232 TestFild(l, 64, Qword, double, uint64_t); 233 #undef TestFild 234 } 235 236 TEST_F(AssemblerX8632Test, Fistp) { 237 #define TestFistp(OperandType, Size, MemorySize, FpType, IntType) \ 238 do { \ 239 const uint32_t T0 = allocate##MemorySize(); \ 240 constexpr IntType V0 = 0x1234; \ 241 const uint32_t T1 = allocate##MemorySize(); \ 242 constexpr IntType V1 = 0xFFFF; \ 243 \ 244 __ fild##OperandType(dwordAddress(T0)); \ 245 __ fistp##OperandType(dwordAddress(T1)); \ 246 \ 247 AssembledTest test = assemble(); \ 248 \ 249 test.set##MemorySize##To(T0, V0); \ 250 test.set##MemorySize##To(T1, V1); \ 251 test.run(); \ 252 \ 253 ASSERT_EQ(static_cast<IntType>(V0), \ 254 test.contentsOf##MemorySize<IntType>(T0)) \ 255 << "(" #OperandType ", " #Size ", " #MemorySize ", " #FpType \ 256 ", " #IntType ")"; \ 257 ASSERT_EQ(static_cast<IntType>(V0), \ 258 test.contentsOf##MemorySize<IntType>(T1)) \ 259 << "(" #OperandType ", " #Size ", " #MemorySize ", " #FpType \ 260 ", " #IntType ")"; \ 261 \ 262 reset(); \ 263 } while (0) 264 265 TestFistp(s, 32, Dword, float, uint32_t); 266 TestFistp(l, 64, Qword, double, uint64_t); 267 #undef TestFistp 268 } 269 270 } // end of anonymous namespace 271 } // end of namespace Test 272 } // end of namespace X8632 273 } // end of namespace Ice 274