| OLD | NEW |
| (Empty) | |
| 1 //===- subzero/unittest/AssemblerX8632/DataMov.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(AssemblerX8632Test, MovRegImm) { |
| 17 constexpr uint32_t ExpectedEax = 0x000000FFul; |
| 18 constexpr uint32_t ExpectedEbx = 0x0000FF00ul; |
| 19 constexpr uint32_t ExpectedEcx = 0x00FF0000ul; |
| 20 constexpr uint32_t ExpectedEdx = 0xFF000000ul; |
| 21 constexpr uint32_t ExpectedEdi = 0x6AAA0006ul; |
| 22 constexpr uint32_t ExpectedEsi = 0x6000AAA6ul; |
| 23 |
| 24 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ExpectedEax)); |
| 25 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, Immediate(ExpectedEbx)); |
| 26 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, Immediate(ExpectedEcx)); |
| 27 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, Immediate(ExpectedEdx)); |
| 28 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, Immediate(ExpectedEdi)); |
| 29 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(ExpectedEsi)); |
| 30 |
| 31 AssembledTest test = assemble(); |
| 32 test.run(); |
| 33 EXPECT_EQ(ExpectedEax, test.eax()); |
| 34 EXPECT_EQ(ExpectedEbx, test.ebx()); |
| 35 EXPECT_EQ(ExpectedEcx, test.ecx()); |
| 36 EXPECT_EQ(ExpectedEdx, test.edx()); |
| 37 EXPECT_EQ(ExpectedEdi, test.edi()); |
| 38 EXPECT_EQ(ExpectedEsi, test.esi()); |
| 39 } |
| 40 |
| 41 TEST_F(AssemblerX8632Test, MovMemImm) { |
| 42 const uint32_t T0 = allocateDword(); |
| 43 constexpr uint32_t ExpectedT0 = 0x00111100ul; |
| 44 const uint32_t T1 = allocateDword(); |
| 45 constexpr uint32_t ExpectedT1 = 0x00222200ul; |
| 46 const uint32_t T2 = allocateDword(); |
| 47 constexpr uint32_t ExpectedT2 = 0x03333000ul; |
| 48 const uint32_t T3 = allocateDword(); |
| 49 constexpr uint32_t ExpectedT3 = 0x00444400ul; |
| 50 |
| 51 __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0)); |
| 52 __ mov(IceType_i32, dwordAddress(T1), Immediate(ExpectedT1)); |
| 53 __ mov(IceType_i32, dwordAddress(T2), Immediate(ExpectedT2)); |
| 54 __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3)); |
| 55 |
| 56 AssembledTest test = assemble(); |
| 57 test.run(); |
| 58 EXPECT_EQ(0ul, test.eax()); |
| 59 EXPECT_EQ(0ul, test.ebx()); |
| 60 EXPECT_EQ(0ul, test.ecx()); |
| 61 EXPECT_EQ(0ul, test.edx()); |
| 62 EXPECT_EQ(0ul, test.edi()); |
| 63 EXPECT_EQ(0ul, test.esi()); |
| 64 EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0)); |
| 65 EXPECT_EQ(ExpectedT1, test.contentsOfDword(T1)); |
| 66 EXPECT_EQ(ExpectedT2, test.contentsOfDword(T2)); |
| 67 EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3)); |
| 68 } |
| 69 |
| 70 TEST_F(AssemblerX8632Test, MovMemReg) { |
| 71 const uint32_t T0 = allocateDword(); |
| 72 constexpr uint32_t ExpectedT0 = 0x00111100ul; |
| 73 const uint32_t T1 = allocateDword(); |
| 74 constexpr uint32_t ExpectedT1 = 0x00222200ul; |
| 75 const uint32_t T2 = allocateDword(); |
| 76 constexpr uint32_t ExpectedT2 = 0x00333300ul; |
| 77 const uint32_t T3 = allocateDword(); |
| 78 constexpr uint32_t ExpectedT3 = 0x00444400ul; |
| 79 const uint32_t T4 = allocateDword(); |
| 80 constexpr uint32_t ExpectedT4 = 0x00555500ul; |
| 81 const uint32_t T5 = allocateDword(); |
| 82 constexpr uint32_t ExpectedT5 = 0x00666600ul; |
| 83 |
| 84 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(ExpectedT0)); |
| 85 __ mov(IceType_i32, dwordAddress(T0), GPRRegister::Encoded_Reg_eax); |
| 86 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, Immediate(ExpectedT1)); |
| 87 __ mov(IceType_i32, dwordAddress(T1), GPRRegister::Encoded_Reg_ebx); |
| 88 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, Immediate(ExpectedT2)); |
| 89 __ mov(IceType_i32, dwordAddress(T2), GPRRegister::Encoded_Reg_ecx); |
| 90 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, Immediate(ExpectedT3)); |
| 91 __ mov(IceType_i32, dwordAddress(T3), GPRRegister::Encoded_Reg_edx); |
| 92 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, Immediate(ExpectedT4)); |
| 93 __ mov(IceType_i32, dwordAddress(T4), GPRRegister::Encoded_Reg_edi); |
| 94 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(ExpectedT5)); |
| 95 __ mov(IceType_i32, dwordAddress(T5), GPRRegister::Encoded_Reg_esi); |
| 96 |
| 97 AssembledTest test = assemble(); |
| 98 test.run(); |
| 99 EXPECT_EQ(ExpectedT0, test.contentsOfDword(T0)); |
| 100 EXPECT_EQ(ExpectedT1, test.contentsOfDword(T1)); |
| 101 EXPECT_EQ(ExpectedT2, test.contentsOfDword(T2)); |
| 102 EXPECT_EQ(ExpectedT3, test.contentsOfDword(T3)); |
| 103 EXPECT_EQ(ExpectedT4, test.contentsOfDword(T4)); |
| 104 EXPECT_EQ(ExpectedT5, test.contentsOfDword(T5)); |
| 105 } |
| 106 |
| 107 TEST_F(AssemblerX8632Test, MovRegReg) { |
| 108 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0x20)); |
| 109 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, |
| 110 GPRRegister::Encoded_Reg_eax); |
| 111 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, |
| 112 GPRRegister::Encoded_Reg_ebx); |
| 113 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, |
| 114 GPRRegister::Encoded_Reg_ecx); |
| 115 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, |
| 116 GPRRegister::Encoded_Reg_edx); |
| 117 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, |
| 118 GPRRegister::Encoded_Reg_edi); |
| 119 |
| 120 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, Immediate(0x55000000ul)); |
| 121 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, |
| 122 GPRRegister::Encoded_Reg_esi); |
| 123 |
| 124 AssembledTest test = assemble(); |
| 125 test.run(); |
| 126 EXPECT_EQ(0x55000000ul, test.eax()); |
| 127 EXPECT_EQ(0x20ul, test.ebx()); |
| 128 EXPECT_EQ(0x20ul, test.ecx()); |
| 129 EXPECT_EQ(0x20ul, test.edx()); |
| 130 EXPECT_EQ(0x20ul, test.edi()); |
| 131 EXPECT_EQ(0x55000000ul, test.esi()); |
| 132 } |
| 133 |
| 134 TEST_F(AssemblerX8632Test, MovRegMem) { |
| 135 const uint32_t T0 = allocateDword(); |
| 136 constexpr uint32_t ExpectedT0 = 0x00111100ul; |
| 137 const uint32_t T1 = allocateDword(); |
| 138 constexpr uint32_t ExpectedT1 = 0x00222200ul; |
| 139 const uint32_t T2 = allocateDword(); |
| 140 constexpr uint32_t ExpectedT2 = 0x00333300ul; |
| 141 const uint32_t T3 = allocateDword(); |
| 142 constexpr uint32_t ExpectedT3 = 0x00444400ul; |
| 143 const uint32_t T4 = allocateDword(); |
| 144 constexpr uint32_t ExpectedT4 = 0x00555500ul; |
| 145 const uint32_t T5 = allocateDword(); |
| 146 constexpr uint32_t ExpectedT5 = 0x00666600ul; |
| 147 |
| 148 __ mov(IceType_i32, dwordAddress(T0), Immediate(ExpectedT0)); |
| 149 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, dwordAddress(T0)); |
| 150 |
| 151 __ mov(IceType_i32, dwordAddress(T1), Immediate(ExpectedT1)); |
| 152 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ebx, dwordAddress(T1)); |
| 153 |
| 154 __ mov(IceType_i32, dwordAddress(T2), Immediate(ExpectedT2)); |
| 155 __ mov(IceType_i32, GPRRegister::Encoded_Reg_ecx, dwordAddress(T2)); |
| 156 |
| 157 __ mov(IceType_i32, dwordAddress(T3), Immediate(ExpectedT3)); |
| 158 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edx, dwordAddress(T3)); |
| 159 |
| 160 __ mov(IceType_i32, dwordAddress(T4), Immediate(ExpectedT4)); |
| 161 __ mov(IceType_i32, GPRRegister::Encoded_Reg_edi, dwordAddress(T4)); |
| 162 |
| 163 __ mov(IceType_i32, dwordAddress(T5), Immediate(ExpectedT5)); |
| 164 __ mov(IceType_i32, GPRRegister::Encoded_Reg_esi, dwordAddress(T5)); |
| 165 |
| 166 AssembledTest test = assemble(); |
| 167 test.run(); |
| 168 EXPECT_EQ(ExpectedT0, test.eax()); |
| 169 EXPECT_EQ(ExpectedT1, test.ebx()); |
| 170 EXPECT_EQ(ExpectedT2, test.ecx()); |
| 171 EXPECT_EQ(ExpectedT3, test.edx()); |
| 172 EXPECT_EQ(ExpectedT4, test.edi()); |
| 173 EXPECT_EQ(ExpectedT5, test.esi()); |
| 174 } |
| 175 |
| 176 TEST_F(AssemblerX8632Test, Movzx) { |
| 177 #define TestMovzx8bitWithRegDest(Src, Dst, Imm) \ |
| 178 do { \ |
| 179 static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate"); \ |
| 180 __ mov(IceType_i8, GPRRegister::Encoded_Reg_##Src, Immediate(Imm)); \ |
| 181 __ movzx(IceType_i8, GPRRegister::Encoded_Reg_##Dst, \ |
| 182 GPRRegister::Encoded_Reg_##Src); \ |
| 183 AssembledTest test = assemble(); \ |
| 184 test.run(); \ |
| 185 ASSERT_EQ(Imm, test.Dst()) << "(" #Src ", " #Dst ", " #Imm ")"; \ |
| 186 reset(); \ |
| 187 } while (0) |
| 188 |
| 189 #define TestMovzx16bitWithRegDest(Src, Dst, Imm) \ |
| 190 do { \ |
| 191 static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate"); \ |
| 192 __ mov(IceType_i16, GPRRegister::Encoded_Reg_##Src, Immediate(Imm)); \ |
| 193 __ movzx(IceType_i16, GPRRegister::Encoded_Reg_##Dst, \ |
| 194 GPRRegister::Encoded_Reg_##Src); \ |
| 195 AssembledTest test = assemble(); \ |
| 196 test.run(); \ |
| 197 ASSERT_EQ(Imm, test.Dst()) << "(" #Src ", " #Dst ", " #Imm ")"; \ |
| 198 reset(); \ |
| 199 } while (0) |
| 200 |
| 201 #define TestMovzx8bitWithAddrSrc(Dst, Imm) \ |
| 202 do { \ |
| 203 static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate"); \ |
| 204 const uint32_t T0 = allocateDword(); \ |
| 205 const uint32_t V0 = Imm; \ |
| 206 __ movzx(IceType_i8, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 207 AssembledTest test = assemble(); \ |
| 208 test.setDwordTo(T0, V0); \ |
| 209 test.run(); \ |
| 210 ASSERT_EQ(Imm, test.Dst()) << "(Addr, " #Dst ", " #Imm ")"; \ |
| 211 reset(); \ |
| 212 } while (0) |
| 213 |
| 214 #define TestMovzx16bitWithAddrSrc(Dst, Imm) \ |
| 215 do { \ |
| 216 static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate"); \ |
| 217 const uint32_t T0 = allocateDword(); \ |
| 218 const uint32_t V0 = Imm; \ |
| 219 __ movzx(IceType_i16, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 220 AssembledTest test = assemble(); \ |
| 221 test.setDwordTo(T0, V0); \ |
| 222 test.run(); \ |
| 223 ASSERT_EQ(Imm, test.Dst()) << "(Addr, " #Dst ", " #Imm ")"; \ |
| 224 reset(); \ |
| 225 } while (0) |
| 226 |
| 227 #define TestMovzx(Dst) \ |
| 228 do { \ |
| 229 TestMovzx8bitWithRegDest(eax, Dst, 0x81u); \ |
| 230 TestMovzx8bitWithRegDest(ebx, Dst, 0x82u); \ |
| 231 TestMovzx8bitWithRegDest(ecx, Dst, 0x83u); \ |
| 232 TestMovzx8bitWithRegDest(edx, Dst, 0x84u); \ |
| 233 /* esi is encoded as dh */ \ |
| 234 TestMovzx8bitWithRegDest(esi, Dst, 0x85u); \ |
| 235 /* edi is encoded as bh */ \ |
| 236 TestMovzx8bitWithRegDest(edi, Dst, 0x86u); \ |
| 237 /* ebp is encoded as ch */ \ |
| 238 TestMovzx8bitWithRegDest(ebp, Dst, 0x87u); \ |
| 239 /* esp is encoded as ah */ \ |
| 240 TestMovzx8bitWithRegDest(esp, Dst, 0x88u); \ |
| 241 TestMovzx8bitWithAddrSrc(Dst, 0x8Fu); \ |
| 242 \ |
| 243 TestMovzx16bitWithRegDest(eax, Dst, 0x8118u); \ |
| 244 TestMovzx16bitWithRegDest(ebx, Dst, 0x8228u); \ |
| 245 TestMovzx16bitWithRegDest(ecx, Dst, 0x8338u); \ |
| 246 TestMovzx16bitWithRegDest(edx, Dst, 0x8448u); \ |
| 247 TestMovzx16bitWithAddrSrc(Dst, 0x8FF8u); \ |
| 248 } while (0) |
| 249 |
| 250 TestMovzx(eax); |
| 251 TestMovzx(ebx); |
| 252 TestMovzx(ecx); |
| 253 TestMovzx(edx); |
| 254 TestMovzx(esi); |
| 255 TestMovzx(edi); |
| 256 |
| 257 #undef TestMovzx |
| 258 #undef TestMovzx16bitWithAddrDest |
| 259 #undef TestMovzx8bitWithAddrDest |
| 260 #undef TestMovzx16bitWithRegDest |
| 261 #undef TestMovzx8bitWithRegDest |
| 262 } |
| 263 |
| 264 TEST_F(AssemblerX8632Test, Movsx) { |
| 265 #define TestMovsx8bitWithRegDest(Src, Dst, Imm) \ |
| 266 do { \ |
| 267 static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate"); \ |
| 268 __ mov(IceType_i8, GPRRegister::Encoded_Reg_##Src, Immediate(Imm)); \ |
| 269 __ movsx(IceType_i8, GPRRegister::Encoded_Reg_##Dst, \ |
| 270 GPRRegister::Encoded_Reg_##Src); \ |
| 271 AssembledTest test = assemble(); \ |
| 272 test.run(); \ |
| 273 ASSERT_EQ((0xFFFFFF00 | (Imm)), test.Dst()) \ |
| 274 << "(" #Src ", " #Dst ", " #Imm ")"; \ |
| 275 reset(); \ |
| 276 } while (0) |
| 277 |
| 278 #define TestMovsx16bitWithRegDest(Src, Dst, Imm) \ |
| 279 do { \ |
| 280 static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate"); \ |
| 281 __ mov(IceType_i16, GPRRegister::Encoded_Reg_##Src, Immediate(Imm)); \ |
| 282 __ movsx(IceType_i16, GPRRegister::Encoded_Reg_##Dst, \ |
| 283 GPRRegister::Encoded_Reg_##Src); \ |
| 284 AssembledTest test = assemble(); \ |
| 285 test.run(); \ |
| 286 ASSERT_EQ((0xFFFF0000 | (Imm)), test.Dst()) \ |
| 287 << "(" #Src ", " #Dst ", " #Imm ")"; \ |
| 288 reset(); \ |
| 289 } while (0) |
| 290 |
| 291 #define TestMovsx8bitWithAddrSrc(Dst, Imm) \ |
| 292 do { \ |
| 293 static_assert(((Imm)&0xFF) == (Imm), #Imm " is not an 8bit immediate"); \ |
| 294 const uint32_t T0 = allocateDword(); \ |
| 295 const uint32_t V0 = Imm; \ |
| 296 __ movsx(IceType_i8, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 297 AssembledTest test = assemble(); \ |
| 298 test.setDwordTo(T0, V0); \ |
| 299 test.run(); \ |
| 300 ASSERT_EQ((0xFFFFFF00 | (Imm)), test.Dst()) \ |
| 301 << "(Addr, " #Dst ", " #Imm ")"; \ |
| 302 reset(); \ |
| 303 } while (0) |
| 304 |
| 305 #define TestMovsx16bitWithAddrSrc(Dst, Imm) \ |
| 306 do { \ |
| 307 static_assert(((Imm)&0xFFFF) == (Imm), #Imm " is not a 16bit immediate"); \ |
| 308 const uint32_t T0 = allocateDword(); \ |
| 309 const uint32_t V0 = Imm; \ |
| 310 __ movsx(IceType_i16, GPRRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 311 AssembledTest test = assemble(); \ |
| 312 test.setDwordTo(T0, V0); \ |
| 313 test.run(); \ |
| 314 ASSERT_EQ((0xFFFF0000 | (Imm)), test.Dst()) \ |
| 315 << "(Addr, " #Dst ", " #Imm ")"; \ |
| 316 reset(); \ |
| 317 } while (0) |
| 318 |
| 319 #define TestMovsx(Dst) \ |
| 320 do { \ |
| 321 TestMovsx8bitWithRegDest(eax, Dst, 0x81u); \ |
| 322 TestMovsx8bitWithRegDest(ebx, Dst, 0x82u); \ |
| 323 TestMovsx8bitWithRegDest(ecx, Dst, 0x83u); \ |
| 324 TestMovsx8bitWithRegDest(edx, Dst, 0x84u); \ |
| 325 /* esi is encoded as dh */ \ |
| 326 TestMovsx8bitWithRegDest(esi, Dst, 0x85u); \ |
| 327 /* edi is encoded as bh */ \ |
| 328 TestMovsx8bitWithRegDest(edi, Dst, 0x86u); \ |
| 329 /* ebp is encoded as ch */ \ |
| 330 TestMovsx8bitWithRegDest(ebp, Dst, 0x87u); \ |
| 331 /* esp is encoded as ah */ \ |
| 332 TestMovsx8bitWithRegDest(esp, Dst, 0x88u); \ |
| 333 TestMovsx8bitWithAddrSrc(Dst, 0x8Fu); \ |
| 334 \ |
| 335 TestMovsx16bitWithRegDest(eax, Dst, 0x8118u); \ |
| 336 TestMovsx16bitWithRegDest(ebx, Dst, 0x8228u); \ |
| 337 TestMovsx16bitWithRegDest(ecx, Dst, 0x8338u); \ |
| 338 TestMovsx16bitWithRegDest(edx, Dst, 0x8448u); \ |
| 339 TestMovsx16bitWithAddrSrc(Dst, 0x8FF8u); \ |
| 340 } while (0) |
| 341 |
| 342 TestMovsx(eax); |
| 343 TestMovsx(ebx); |
| 344 TestMovsx(ecx); |
| 345 TestMovsx(edx); |
| 346 TestMovsx(esi); |
| 347 TestMovsx(edi); |
| 348 |
| 349 #undef TestMovsx |
| 350 #undef TestMovsx16bitWithAddrDest |
| 351 #undef TestMovsx8bitWithAddrDest |
| 352 #undef TestMovsx16bitWithRegDest |
| 353 #undef TestMovsx8bitWithRegDest |
| 354 } |
| 355 |
| 356 TEST_F(AssemblerX8632LowLevelTest, RepMovsb) { |
| 357 __ rep_movsb(); |
| 358 |
| 359 static constexpr uint32_t ByteCount = 2; |
| 360 static constexpr uint8_t Prefix = 0xF3; |
| 361 static constexpr uint8_t Opcode = 0xA4; |
| 362 |
| 363 ASSERT_EQ(ByteCount, codeBytesSize()); |
| 364 verifyBytes<ByteCount>(codeBytes(), Prefix, Opcode); |
| 365 } |
| 366 |
| 367 TEST_F(AssemblerX8632Test, MovssXmmAddr) { |
| 368 #define TestMovssXmmAddrFloatLength(FloatLength, Xmm, Value) \ |
| 369 do { \ |
| 370 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ |
| 371 "Invalid fp length #FloatLength"); \ |
| 372 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 373 \ |
| 374 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \ |
| 375 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ |
| 376 const uint32_t T0 = allocateQword(); \ |
| 377 const Type V0 = Value; \ |
| 378 \ |
| 379 __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Xmm, \ |
| 380 dwordAddress(T0)); \ |
| 381 \ |
| 382 AssembledTest test = assemble(); \ |
| 383 if (IsDouble) { \ |
| 384 test.setQwordTo(T0, static_cast<double>(V0)); \ |
| 385 } else { \ |
| 386 test.setDwordTo(T0, static_cast<float>(V0)); \ |
| 387 } \ |
| 388 test.run(); \ |
| 389 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \ |
| 390 << Value; \ |
| 391 reset(); \ |
| 392 } while (0) |
| 393 |
| 394 #define TestMovssXmmAddr(FloatLength) \ |
| 395 do { \ |
| 396 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 397 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ |
| 398 TestMovssXmmAddrFloatLength(FloatLength, xmm0, Value); \ |
| 399 TestMovssXmmAddrFloatLength(FloatLength, xmm1, Value); \ |
| 400 TestMovssXmmAddrFloatLength(FloatLength, xmm2, Value); \ |
| 401 TestMovssXmmAddrFloatLength(FloatLength, xmm3, Value); \ |
| 402 TestMovssXmmAddrFloatLength(FloatLength, xmm4, Value); \ |
| 403 TestMovssXmmAddrFloatLength(FloatLength, xmm5, Value); \ |
| 404 TestMovssXmmAddrFloatLength(FloatLength, xmm6, Value); \ |
| 405 TestMovssXmmAddrFloatLength(FloatLength, xmm7, Value); \ |
| 406 } \ |
| 407 } while (0) |
| 408 |
| 409 TestMovssXmmAddr(32); |
| 410 TestMovssXmmAddr(64); |
| 411 |
| 412 #undef TestMovssXmmAddr |
| 413 #undef TestMovssXmmAddrType |
| 414 } |
| 415 |
| 416 TEST_F(AssemblerX8632Test, MovssAddrXmm) { |
| 417 #define TestMovssAddrXmmFloatLength(FloatLength, Xmm, Value) \ |
| 418 do { \ |
| 419 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ |
| 420 "Invalid fp length #FloatLength"); \ |
| 421 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 422 \ |
| 423 static constexpr char TestString[] = "(" #FloatLength ", " #Xmm ")"; \ |
| 424 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ |
| 425 const uint32_t T0 = allocateQword(); \ |
| 426 const Type V0 = Value; \ |
| 427 const uint32_t T1 = allocateQword(); \ |
| 428 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \ |
| 429 "f" #FloatLength " does not have quiet nan."); \ |
| 430 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \ |
| 431 \ |
| 432 __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Xmm, \ |
| 433 dwordAddress(T0)); \ |
| 434 \ |
| 435 AssembledTest test = assemble(); \ |
| 436 if (IsDouble) { \ |
| 437 test.setQwordTo(T0, static_cast<double>(V0)); \ |
| 438 test.setQwordTo(T1, static_cast<double>(V1)); \ |
| 439 } else { \ |
| 440 test.setDwordTo(T0, static_cast<float>(V0)); \ |
| 441 test.setDwordTo(T1, static_cast<float>(V1)); \ |
| 442 } \ |
| 443 test.run(); \ |
| 444 ASSERT_DOUBLE_EQ(Value, test.Xmm<Type>()) << TestString << " value is " \ |
| 445 << Value; \ |
| 446 reset(); \ |
| 447 } while (0) |
| 448 |
| 449 #define TestMovssAddrXmm(FloatLength) \ |
| 450 do { \ |
| 451 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 452 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ |
| 453 TestMovssAddrXmmFloatLength(FloatLength, xmm0, Value); \ |
| 454 TestMovssAddrXmmFloatLength(FloatLength, xmm1, Value); \ |
| 455 TestMovssAddrXmmFloatLength(FloatLength, xmm2, Value); \ |
| 456 TestMovssAddrXmmFloatLength(FloatLength, xmm3, Value); \ |
| 457 TestMovssAddrXmmFloatLength(FloatLength, xmm4, Value); \ |
| 458 TestMovssAddrXmmFloatLength(FloatLength, xmm5, Value); \ |
| 459 TestMovssAddrXmmFloatLength(FloatLength, xmm6, Value); \ |
| 460 TestMovssAddrXmmFloatLength(FloatLength, xmm7, Value); \ |
| 461 } \ |
| 462 } while (0) |
| 463 |
| 464 TestMovssAddrXmm(32); |
| 465 TestMovssAddrXmm(64); |
| 466 |
| 467 #undef TestMovssAddrXmm |
| 468 #undef TestMovssAddrXmmType |
| 469 } |
| 470 |
| 471 TEST_F(AssemblerX8632Test, MovssXmmXmm) { |
| 472 #define TestMovssXmmXmmFloatLength(FloatLength, Src, Dst, Value) \ |
| 473 do { \ |
| 474 static_assert((FloatLength) == 32 || (FloatLength) == 64, \ |
| 475 "Invalid fp length #FloatLength"); \ |
| 476 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 477 \ |
| 478 static constexpr char TestString[] = \ |
| 479 "(" #FloatLength ", " #Src ", " #Dst ")"; \ |
| 480 static constexpr bool IsDouble = std::is_same<Type, double>::value; \ |
| 481 const uint32_t T0 = allocateQword(); \ |
| 482 const Type V0 = Value; \ |
| 483 const uint32_t T1 = allocateQword(); \ |
| 484 static_assert(std::numeric_limits<Type>::has_quiet_NaN, \ |
| 485 "f" #FloatLength " does not have quiet nan."); \ |
| 486 const Type V1 = std::numeric_limits<Type>::quiet_NaN(); \ |
| 487 \ |
| 488 __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Src, \ |
| 489 dwordAddress(T0)); \ |
| 490 __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Dst, \ |
| 491 dwordAddress(T1)); \ |
| 492 __ movss(IceType_f##FloatLength, XmmRegister::Encoded_Reg_##Dst, \ |
| 493 XmmRegister::Encoded_Reg_##Src); \ |
| 494 \ |
| 495 AssembledTest test = assemble(); \ |
| 496 if (IsDouble) { \ |
| 497 test.setQwordTo(T0, static_cast<double>(V0)); \ |
| 498 test.setQwordTo(T1, static_cast<double>(V1)); \ |
| 499 } else { \ |
| 500 test.setDwordTo(T0, static_cast<float>(V0)); \ |
| 501 test.setDwordTo(T1, static_cast<float>(V1)); \ |
| 502 } \ |
| 503 test.run(); \ |
| 504 ASSERT_DOUBLE_EQ(Value, test.Dst<Type>()) << TestString << " value is " \ |
| 505 << Value; \ |
| 506 reset(); \ |
| 507 } while (0) |
| 508 |
| 509 #define TestMovssXmmXmm(FloatLength) \ |
| 510 do { \ |
| 511 using Type = std::conditional<FloatLength == 32, float, double>::type; \ |
| 512 for (const Type Value : {0.0, -0.0, 1.0, -1.0, 3.14, 99999.9999}) { \ |
| 513 TestMovssXmmXmmFloatLength(FloatLength, xmm0, xmm1, Value); \ |
| 514 TestMovssXmmXmmFloatLength(FloatLength, xmm1, xmm2, Value); \ |
| 515 TestMovssXmmXmmFloatLength(FloatLength, xmm2, xmm3, Value); \ |
| 516 TestMovssXmmXmmFloatLength(FloatLength, xmm3, xmm4, Value); \ |
| 517 TestMovssXmmXmmFloatLength(FloatLength, xmm4, xmm5, Value); \ |
| 518 TestMovssXmmXmmFloatLength(FloatLength, xmm5, xmm6, Value); \ |
| 519 TestMovssXmmXmmFloatLength(FloatLength, xmm6, xmm7, Value); \ |
| 520 TestMovssXmmXmmFloatLength(FloatLength, xmm7, xmm0, Value); \ |
| 521 } \ |
| 522 } while (0) |
| 523 |
| 524 TestMovssXmmXmm(32); |
| 525 TestMovssXmmXmm(64); |
| 526 |
| 527 #undef TestMovssXmmXmm |
| 528 #undef TestMovssXmmXmmType |
| 529 } |
| 530 |
| 531 TEST_F(AssemblerX8632Test, MovdToXmm) { |
| 532 #define TestMovdXmmReg(Src, Dst, Value) \ |
| 533 do { \ |
| 534 assert(((Value)&0xFFFFFFFF) == (Value)); \ |
| 535 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ |
| 536 const uint32_t T0 = allocateQword(); \ |
| 537 const uint64_t V0 = 0xFFFFFFFF00000000ull; \ |
| 538 \ |
| 539 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src, Immediate(Value)); \ |
| 540 __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 541 __ movd(XmmRegister::Encoded_Reg_##Dst, GPRRegister::Encoded_Reg_##Src); \ |
| 542 \ |
| 543 AssembledTest test = assemble(); \ |
| 544 \ |
| 545 test.setQwordTo(T0, V0); \ |
| 546 test.run(); \ |
| 547 \ |
| 548 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ |
| 549 << Value; \ |
| 550 reset(); \ |
| 551 } while (0) |
| 552 |
| 553 #define TestMovdXmmAddr(Dst, Value) \ |
| 554 do { \ |
| 555 assert(((Value)&0xFFFFFFFF) == (Value)); \ |
| 556 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ |
| 557 const uint32_t T0 = allocateQword(); \ |
| 558 const uint32_t V0 = Value; \ |
| 559 const uint32_t T1 = allocateQword(); \ |
| 560 const uint64_t V1 = 0xFFFFFFFF00000000ull; \ |
| 561 \ |
| 562 __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 563 __ movd(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 564 \ |
| 565 AssembledTest test = assemble(); \ |
| 566 \ |
| 567 test.setDwordTo(T0, V0); \ |
| 568 test.setQwordTo(T1, V1); \ |
| 569 test.run(); \ |
| 570 \ |
| 571 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ |
| 572 << Value; \ |
| 573 reset(); \ |
| 574 } while (0) |
| 575 |
| 576 #define TestMovd(Dst) \ |
| 577 do { \ |
| 578 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \ |
| 579 TestMovdXmmReg(eax, Dst, Value); \ |
| 580 TestMovdXmmReg(ebx, Dst, Value); \ |
| 581 TestMovdXmmReg(ecx, Dst, Value); \ |
| 582 TestMovdXmmReg(edx, Dst, Value); \ |
| 583 TestMovdXmmReg(esi, Dst, Value); \ |
| 584 TestMovdXmmReg(edi, Dst, Value); \ |
| 585 TestMovdXmmAddr(Dst, Value); \ |
| 586 } \ |
| 587 } while (0) |
| 588 |
| 589 TestMovd(xmm0); |
| 590 TestMovd(xmm1); |
| 591 TestMovd(xmm2); |
| 592 TestMovd(xmm3); |
| 593 TestMovd(xmm4); |
| 594 TestMovd(xmm5); |
| 595 TestMovd(xmm6); |
| 596 TestMovd(xmm7); |
| 597 |
| 598 #undef TestMovdXmmAddr |
| 599 #undef TestMovdXmmReg |
| 600 #undef TestMovd |
| 601 } |
| 602 |
| 603 TEST_F(AssemblerX8632Test, MovdFromXmm) { |
| 604 #define TestMovdRegXmm(Src, Dst, Value) \ |
| 605 do { \ |
| 606 assert(((Value)&0xFFFFFFFF) == (Value)); \ |
| 607 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ |
| 608 const uint32_t T0 = allocateDword(); \ |
| 609 const uint32_t V0 = Value; \ |
| 610 \ |
| 611 __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 612 __ movd(GPRRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ |
| 613 \ |
| 614 AssembledTest test = assemble(); \ |
| 615 \ |
| 616 test.setDwordTo(T0, V0); \ |
| 617 test.run(); \ |
| 618 \ |
| 619 ASSERT_EQ(Value, test.contentsOfDword(T0)) << TestString << " value is " \ |
| 620 << Value; \ |
| 621 reset(); \ |
| 622 } while (0) |
| 623 |
| 624 #define TestMovdAddrXmm(Src, Value) \ |
| 625 do { \ |
| 626 assert(((Value)&0xFFFFFFFF) == (Value)); \ |
| 627 static constexpr char TestString[] = "(" #Src ", Addr)"; \ |
| 628 const uint32_t T0 = allocateDword(); \ |
| 629 const uint32_t V0 = Value; \ |
| 630 const uint32_t T1 = allocateDword(); \ |
| 631 const uint32_t V1 = ~(Value); \ |
| 632 \ |
| 633 __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 634 __ movd(dwordAddress(T1), XmmRegister::Encoded_Reg_##Src); \ |
| 635 \ |
| 636 AssembledTest test = assemble(); \ |
| 637 \ |
| 638 test.setDwordTo(T0, V0); \ |
| 639 test.setDwordTo(T1, V1); \ |
| 640 test.run(); \ |
| 641 \ |
| 642 ASSERT_EQ(Value, test.contentsOfDword(T1)) << TestString << " value is " \ |
| 643 << Value; \ |
| 644 reset(); \ |
| 645 } while (0) |
| 646 |
| 647 #define TestMovd(Src) \ |
| 648 do { \ |
| 649 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { \ |
| 650 TestMovdRegXmm(Src, eax, Value); \ |
| 651 TestMovdRegXmm(Src, ebx, Value); \ |
| 652 TestMovdRegXmm(Src, ecx, Value); \ |
| 653 TestMovdRegXmm(Src, edx, Value); \ |
| 654 TestMovdRegXmm(Src, esi, Value); \ |
| 655 TestMovdRegXmm(Src, edi, Value); \ |
| 656 TestMovdAddrXmm(Src, Value); \ |
| 657 } \ |
| 658 } while (0) |
| 659 |
| 660 TestMovd(xmm0); |
| 661 TestMovd(xmm1); |
| 662 TestMovd(xmm2); |
| 663 TestMovd(xmm3); |
| 664 TestMovd(xmm4); |
| 665 TestMovd(xmm5); |
| 666 TestMovd(xmm6); |
| 667 TestMovd(xmm7); |
| 668 |
| 669 #undef TestMovdAddrXmm |
| 670 #undef TestMovdRegXmm |
| 671 #undef TestMovd |
| 672 } |
| 673 |
| 674 TEST_F(AssemblerX8632Test, MovqXmmAddr) { |
| 675 #define TestMovd(Dst, Value) \ |
| 676 do { \ |
| 677 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ |
| 678 const uint32_t T0 = allocateQword(); \ |
| 679 const uint64_t V0 = Value; \ |
| 680 const uint32_t T1 = allocateQword(); \ |
| 681 const uint64_t V1 = ~(Value); \ |
| 682 \ |
| 683 __ movss(IceType_f64, XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 684 __ movq(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 685 \ |
| 686 AssembledTest test = assemble(); \ |
| 687 \ |
| 688 test.setQwordTo(T0, V0); \ |
| 689 test.setQwordTo(T1, V1); \ |
| 690 test.run(); \ |
| 691 \ |
| 692 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ |
| 693 << Value; \ |
| 694 reset(); \ |
| 695 } while (0) |
| 696 |
| 697 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { |
| 698 TestMovd(xmm0, Value); |
| 699 TestMovd(xmm1, Value); |
| 700 TestMovd(xmm2, Value); |
| 701 TestMovd(xmm3, Value); |
| 702 TestMovd(xmm4, Value); |
| 703 TestMovd(xmm5, Value); |
| 704 TestMovd(xmm6, Value); |
| 705 TestMovd(xmm7, Value); |
| 706 } |
| 707 |
| 708 #undef TestMovd |
| 709 } |
| 710 |
| 711 TEST_F(AssemblerX8632Test, MovqAddrXmm) { |
| 712 #define TestMovd(Dst, Value) \ |
| 713 do { \ |
| 714 static constexpr char TestString[] = "(" #Dst ", Addr)"; \ |
| 715 const uint32_t T0 = allocateQword(); \ |
| 716 const uint64_t V0 = Value; \ |
| 717 const uint32_t T1 = allocateQword(); \ |
| 718 const uint64_t V1 = ~(Value); \ |
| 719 \ |
| 720 __ movq(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 721 __ movq(dwordAddress(T1), XmmRegister::Encoded_Reg_##Dst); \ |
| 722 \ |
| 723 AssembledTest test = assemble(); \ |
| 724 \ |
| 725 test.setQwordTo(T0, V0); \ |
| 726 test.setQwordTo(T1, V1); \ |
| 727 test.run(); \ |
| 728 \ |
| 729 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ |
| 730 << Value; \ |
| 731 reset(); \ |
| 732 } while (0) |
| 733 |
| 734 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { |
| 735 TestMovd(xmm0, Value); |
| 736 TestMovd(xmm1, Value); |
| 737 TestMovd(xmm2, Value); |
| 738 TestMovd(xmm3, Value); |
| 739 TestMovd(xmm4, Value); |
| 740 TestMovd(xmm5, Value); |
| 741 TestMovd(xmm6, Value); |
| 742 TestMovd(xmm7, Value); |
| 743 } |
| 744 |
| 745 #undef TestMovd |
| 746 } |
| 747 |
| 748 TEST_F(AssemblerX8632Test, MovqXmmXmm) { |
| 749 #define TestMovd(Src, Dst, Value) \ |
| 750 do { \ |
| 751 static constexpr char TestString[] = "(" #Src ", " #Dst ")"; \ |
| 752 const uint32_t T0 = allocateQword(); \ |
| 753 const uint64_t V0 = Value; \ |
| 754 const uint32_t T1 = allocateQword(); \ |
| 755 const uint64_t V1 = ~(Value); \ |
| 756 \ |
| 757 __ movq(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 758 __ movq(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 759 __ movq(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ |
| 760 \ |
| 761 AssembledTest test = assemble(); \ |
| 762 \ |
| 763 test.setQwordTo(T0, V0); \ |
| 764 test.setQwordTo(T1, V1); \ |
| 765 test.run(); \ |
| 766 \ |
| 767 ASSERT_EQ(Value, test.Dst<uint64_t>()) << TestString << " value is " \ |
| 768 << Value; \ |
| 769 reset(); \ |
| 770 } while (0) |
| 771 |
| 772 for (uint32_t Value : {0u, 1u, 0x7FFFFFFFu, 0x80000000u, 0xFFFFFFFFu}) { |
| 773 TestMovd(xmm0, xmm1, Value); |
| 774 TestMovd(xmm1, xmm2, Value); |
| 775 TestMovd(xmm2, xmm3, Value); |
| 776 TestMovd(xmm3, xmm4, Value); |
| 777 TestMovd(xmm4, xmm5, Value); |
| 778 TestMovd(xmm5, xmm6, Value); |
| 779 TestMovd(xmm6, xmm7, Value); |
| 780 TestMovd(xmm7, xmm0, Value); |
| 781 } |
| 782 |
| 783 #undef TestMovd |
| 784 } |
| 785 |
| 786 TEST_F(AssemblerX8632Test, MovupsXmmAddr) { |
| 787 #define TestMovups(Dst) \ |
| 788 do { \ |
| 789 static constexpr char TestString[] = "(" #Dst ")"; \ |
| 790 const uint32_t T0 = allocateDqword(); \ |
| 791 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ |
| 792 std::numeric_limits<float>::infinity()); \ |
| 793 \ |
| 794 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 795 \ |
| 796 AssembledTest test = assemble(); \ |
| 797 test.setDqwordTo(T0, V0); \ |
| 798 test.run(); \ |
| 799 \ |
| 800 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ |
| 801 reset(); \ |
| 802 } while (0) |
| 803 |
| 804 TestMovups(xmm0); |
| 805 TestMovups(xmm1); |
| 806 TestMovups(xmm2); |
| 807 TestMovups(xmm3); |
| 808 TestMovups(xmm4); |
| 809 TestMovups(xmm5); |
| 810 TestMovups(xmm6); |
| 811 TestMovups(xmm7); |
| 812 |
| 813 #undef TestMovups |
| 814 } |
| 815 |
| 816 TEST_F(AssemblerX8632Test, MovupsAddrXmm) { |
| 817 #define TestMovups(Src) \ |
| 818 do { \ |
| 819 static constexpr char TestString[] = "(" #Src ")"; \ |
| 820 const uint32_t T0 = allocateDqword(); \ |
| 821 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ |
| 822 std::numeric_limits<float>::infinity()); \ |
| 823 const uint32_t T1 = allocateDqword(); \ |
| 824 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ |
| 825 \ |
| 826 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 827 __ movups(dwordAddress(T1), XmmRegister::Encoded_Reg_##Src); \ |
| 828 \ |
| 829 AssembledTest test = assemble(); \ |
| 830 test.setDqwordTo(T0, V0); \ |
| 831 test.setDqwordTo(T1, V1); \ |
| 832 test.run(); \ |
| 833 \ |
| 834 ASSERT_EQ(V0, test.contentsOfDqword(T1)) << TestString; \ |
| 835 reset(); \ |
| 836 } while (0) |
| 837 |
| 838 TestMovups(xmm0); |
| 839 TestMovups(xmm1); |
| 840 TestMovups(xmm2); |
| 841 TestMovups(xmm3); |
| 842 TestMovups(xmm4); |
| 843 TestMovups(xmm5); |
| 844 TestMovups(xmm6); |
| 845 TestMovups(xmm7); |
| 846 |
| 847 #undef TestMovups |
| 848 } |
| 849 |
| 850 TEST_F(AssemblerX8632Test, MovupsXmmXmm) { |
| 851 #define TestMovups(Dst, Src) \ |
| 852 do { \ |
| 853 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \ |
| 854 const uint32_t T0 = allocateDqword(); \ |
| 855 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ |
| 856 std::numeric_limits<float>::infinity()); \ |
| 857 const uint32_t T1 = allocateDqword(); \ |
| 858 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ |
| 859 \ |
| 860 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 861 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 862 __ movups(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ |
| 863 \ |
| 864 AssembledTest test = assemble(); \ |
| 865 test.setDqwordTo(T0, V0); \ |
| 866 test.setDqwordTo(T1, V1); \ |
| 867 test.run(); \ |
| 868 \ |
| 869 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ |
| 870 reset(); \ |
| 871 } while (0) |
| 872 |
| 873 TestMovups(xmm0, xmm1); |
| 874 TestMovups(xmm1, xmm2); |
| 875 TestMovups(xmm2, xmm3); |
| 876 TestMovups(xmm3, xmm4); |
| 877 TestMovups(xmm4, xmm5); |
| 878 TestMovups(xmm5, xmm6); |
| 879 TestMovups(xmm6, xmm7); |
| 880 TestMovups(xmm7, xmm0); |
| 881 |
| 882 #undef TestMovups |
| 883 } |
| 884 |
| 885 TEST_F(AssemblerX8632Test, MovapsXmmXmm) { |
| 886 #define TestMovaps(Dst, Src) \ |
| 887 do { \ |
| 888 static constexpr char TestString[] = "(" #Dst ", " #Src ")"; \ |
| 889 const uint32_t T0 = allocateDqword(); \ |
| 890 const Dqword V0(1.0f, -1.0, std::numeric_limits<float>::quiet_NaN(), \ |
| 891 std::numeric_limits<float>::infinity()); \ |
| 892 const uint32_t T1 = allocateDqword(); \ |
| 893 const Dqword V1(0.0, 0.0, 0.0, 0.0); \ |
| 894 \ |
| 895 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 896 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 897 __ movaps(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ |
| 898 \ |
| 899 AssembledTest test = assemble(); \ |
| 900 test.setDqwordTo(T0, V0); \ |
| 901 test.setDqwordTo(T1, V1); \ |
| 902 test.run(); \ |
| 903 \ |
| 904 ASSERT_EQ(V0, test.Dst<Dqword>()) << TestString; \ |
| 905 reset(); \ |
| 906 } while (0) |
| 907 |
| 908 TestMovaps(xmm0, xmm1); |
| 909 TestMovaps(xmm1, xmm2); |
| 910 TestMovaps(xmm2, xmm3); |
| 911 TestMovaps(xmm3, xmm4); |
| 912 TestMovaps(xmm4, xmm5); |
| 913 TestMovaps(xmm5, xmm6); |
| 914 TestMovaps(xmm6, xmm7); |
| 915 TestMovaps(xmm7, xmm0); |
| 916 |
| 917 #undef TestMovaps |
| 918 } |
| 919 |
| 920 TEST_F(AssemblerX8632Test, Movhlps_Movlhps) { |
| 921 #define TestImplSingle(Dst, Src, Inst, Expect) \ |
| 922 do { \ |
| 923 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Inst ")"; \ |
| 924 const uint32_t T0 = allocateDqword(); \ |
| 925 const Dqword V0(uint64_t(0xAAAAAAAABBBBBBBBull), \ |
| 926 uint64_t(0xCCCCCCCCDDDDDDDDull)); \ |
| 927 const uint32_t T1 = allocateDqword(); \ |
| 928 const Dqword V1(uint64_t(0xEEEEEEEEFFFFFFFFull), \ |
| 929 uint64_t(0x9999999988888888ull)); \ |
| 930 \ |
| 931 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T0)); \ |
| 932 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T1)); \ |
| 933 __ Inst(XmmRegister::Encoded_Reg_##Dst, XmmRegister::Encoded_Reg_##Src); \ |
| 934 \ |
| 935 AssembledTest test = assemble(); \ |
| 936 test.setDqwordTo(T0, V0); \ |
| 937 test.setDqwordTo(T1, V1); \ |
| 938 test.run(); \ |
| 939 \ |
| 940 ASSERT_EQ(Dqword Expect, test.Dst<Dqword>()) << TestString; \ |
| 941 reset(); \ |
| 942 } while (0) |
| 943 |
| 944 #define TestImpl(Dst, Src) \ |
| 945 do { \ |
| 946 TestImplSingle(Dst, Src, movhlps, (uint64_t(0x9999999988888888ull), \ |
| 947 uint64_t(0xCCCCCCCCDDDDDDDDull))); \ |
| 948 TestImplSingle(Dst, Src, movlhps, (uint64_t(0xAAAAAAAABBBBBBBBull), \ |
| 949 uint64_t(0xEEEEEEEEFFFFFFFFull))); \ |
| 950 } while (0) |
| 951 |
| 952 TestImpl(xmm0, xmm1); |
| 953 TestImpl(xmm1, xmm2); |
| 954 TestImpl(xmm2, xmm3); |
| 955 TestImpl(xmm3, xmm4); |
| 956 TestImpl(xmm4, xmm5); |
| 957 TestImpl(xmm5, xmm6); |
| 958 TestImpl(xmm6, xmm7); |
| 959 TestImpl(xmm7, xmm0); |
| 960 |
| 961 #undef TestImpl |
| 962 #undef TestImplSingle |
| 963 } |
| 964 |
| 965 TEST_F(AssemblerX8632Test, Movmsk) { |
| 966 #define TestMovmskGPRXmm(GPR, Src, Value1, Expected, Inst) \ |
| 967 do { \ |
| 968 static constexpr char TestString[] = \ |
| 969 "(" #GPR ", " #Src ", " #Value1 ", " #Expected ", " #Inst ")"; \ |
| 970 const uint32_t T0 = allocateDqword(); \ |
| 971 const Dqword V0 Value1; \ |
| 972 \ |
| 973 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 974 __ Inst(GPRRegister::Encoded_Reg_##GPR, XmmRegister::Encoded_Reg_##Src); \ |
| 975 \ |
| 976 AssembledTest test = assemble(); \ |
| 977 test.setDqwordTo(T0, V0); \ |
| 978 test.run(); \ |
| 979 \ |
| 980 ASSERT_EQ(Expected, test.GPR()) << TestString; \ |
| 981 reset(); \ |
| 982 } while (0) |
| 983 |
| 984 #define TestMovmsk(GPR, Src) \ |
| 985 do { \ |
| 986 TestMovmskGPRXmm(GPR, Src, (-1.0, 1.0, -1.0, 1.0), 0x05ul, movmskps); \ |
| 987 TestMovmskGPRXmm(GPR, Src, (1.0, -1.0), 0x02ul, movmskpd); \ |
| 988 } while (0) |
| 989 |
| 990 TestMovmsk(eax, xmm0); |
| 991 TestMovmsk(ebx, xmm1); |
| 992 TestMovmsk(ecx, xmm2); |
| 993 TestMovmsk(edx, xmm3); |
| 994 TestMovmsk(esi, xmm4); |
| 995 TestMovmsk(edi, xmm5); |
| 996 TestMovmsk(eax, xmm6); |
| 997 TestMovmsk(ebx, xmm7); |
| 998 |
| 999 #undef TestMovmskGPRXmm |
| 1000 #undef TestMovmsk |
| 1001 } |
| 1002 |
| 1003 TEST_F(AssemblerX8632Test, Pmovsxdq) { |
| 1004 #define TestPmovsxdqXmmXmm(Dst, Src, Value1) \ |
| 1005 do { \ |
| 1006 static constexpr char TestString[] = "(" #Dst ", " #Src ", " #Value1 ")"; \ |
| 1007 const uint32_t T0 = allocateDqword(); \ |
| 1008 const Dqword V0 Value1; \ |
| 1009 const uint32_t T1 = allocateDqword(); \ |
| 1010 const Dqword V1(uint64_t(0), uint64_t(0)); \ |
| 1011 \ |
| 1012 __ movups(XmmRegister::Encoded_Reg_##Src, dwordAddress(T0)); \ |
| 1013 __ movups(XmmRegister::Encoded_Reg_##Dst, dwordAddress(T1)); \ |
| 1014 __ pmovsxdq(XmmRegister::Encoded_Reg_##Dst, \ |
| 1015 XmmRegister::Encoded_Reg_##Src); \ |
| 1016 \ |
| 1017 AssembledTest test = assemble(); \ |
| 1018 test.setDqwordTo(T0, V0); \ |
| 1019 test.setDqwordTo(T1, V1); \ |
| 1020 test.run(); \ |
| 1021 \ |
| 1022 const Dqword Expected(uint64_t(V0.I32[0]), uint64_t(V0.I32[1])); \ |
| 1023 ASSERT_EQ(Expected, test.Dst<Dqword>()) << TestString; \ |
| 1024 reset(); \ |
| 1025 } while (0) |
| 1026 |
| 1027 #define TestPmovsxdq(Dst, Src) \ |
| 1028 do { \ |
| 1029 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x700000007FFFFFFFull), \ |
| 1030 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ |
| 1031 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x800000007FFFFFFFull), \ |
| 1032 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ |
| 1033 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x70000000FFFFFFFFull), \ |
| 1034 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ |
| 1035 TestPmovsxdqXmmXmm(Dst, Src, (uint64_t(0x80000000FFFFFFFFull), \ |
| 1036 uint64_t(0xAAAAAAAAEEEEEEEEull))); \ |
| 1037 } while (0) |
| 1038 |
| 1039 TestPmovsxdq(xmm0, xmm1); |
| 1040 TestPmovsxdq(xmm1, xmm2); |
| 1041 TestPmovsxdq(xmm2, xmm3); |
| 1042 TestPmovsxdq(xmm3, xmm4); |
| 1043 TestPmovsxdq(xmm4, xmm5); |
| 1044 TestPmovsxdq(xmm5, xmm6); |
| 1045 TestPmovsxdq(xmm6, xmm7); |
| 1046 TestPmovsxdq(xmm7, xmm0); |
| 1047 |
| 1048 #undef TestPmovsxdq |
| 1049 #undef TestPmovsxdqXmmXmm |
| 1050 } |
| 1051 |
| 1052 TEST_F(AssemblerX8632Test, CmovRegReg) { |
| 1053 #define TestCmovRegReg(C, Src0, Value0, Src1, Value1, Dest, IsTrue) \ |
| 1054 do { \ |
| 1055 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src0, Immediate(Value0)); \ |
| 1056 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src1, Immediate(Value1)); \ |
| 1057 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(Value0)); \ |
| 1058 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_##Src0, \ |
| 1059 GPRRegister::Encoded_Reg_##Src1); \ |
| 1060 __ cmov(IceType_i32, Cond::Br_##C, GPRRegister::Encoded_Reg_##Dest, \ |
| 1061 GPRRegister::Encoded_Reg_##Src1); \ |
| 1062 \ |
| 1063 AssembledTest test = assemble(); \ |
| 1064 test.run(); \ |
| 1065 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) \ |
| 1066 << "(" #C ", " #Src0 ", " #Value0 ", " #Src1 ", " #Value1 ", " #Dest \ |
| 1067 ", " #IsTrue ")"; \ |
| 1068 \ |
| 1069 reset(); \ |
| 1070 } while (0) |
| 1071 |
| 1072 TestCmovRegReg(o, eax, 0x80000000u, ebx, 0x1u, ecx, 1u); |
| 1073 TestCmovRegReg(o, eax, 0x1u, ebx, 0x10000000u, ecx, 0u); |
| 1074 |
| 1075 TestCmovRegReg(no, ebx, 0x1u, ecx, 0x10000000u, edx, 1u); |
| 1076 TestCmovRegReg(no, ebx, 0x80000000u, ecx, 0x1u, edx, 0u); |
| 1077 |
| 1078 TestCmovRegReg(b, ecx, 0x1, edx, 0x80000000u, eax, 1u); |
| 1079 TestCmovRegReg(b, ecx, 0x80000000u, edx, 0x1u, eax, 0u); |
| 1080 |
| 1081 TestCmovRegReg(ae, edx, 0x80000000u, edi, 0x1u, ebx, 1u); |
| 1082 TestCmovRegReg(ae, edx, 0x1u, edi, 0x80000000u, ebx, 0u); |
| 1083 |
| 1084 TestCmovRegReg(e, edi, 0x1u, esi, 0x1u, ecx, 1u); |
| 1085 TestCmovRegReg(e, edi, 0x1u, esi, 0x11111u, ecx, 0u); |
| 1086 |
| 1087 TestCmovRegReg(ne, esi, 0x80000000u, eax, 0x1u, edx, 1u); |
| 1088 TestCmovRegReg(ne, esi, 0x1u, eax, 0x1u, edx, 0u); |
| 1089 |
| 1090 TestCmovRegReg(be, eax, 0x1u, ebx, 0x80000000u, eax, 1u); |
| 1091 TestCmovRegReg(be, eax, 0x80000000u, ebx, 0x1u, eax, 0u); |
| 1092 |
| 1093 TestCmovRegReg(a, ebx, 0x80000000u, ecx, 0x1u, ebx, 1u); |
| 1094 TestCmovRegReg(a, ebx, 0x1u, ecx, 0x80000000u, ebx, 0u); |
| 1095 |
| 1096 TestCmovRegReg(s, ecx, 0x1u, edx, 0x80000000u, ecx, 1u); |
| 1097 TestCmovRegReg(s, ecx, 0x80000000u, edx, 0x1u, ecx, 0u); |
| 1098 |
| 1099 TestCmovRegReg(ns, edx, 0x80000000u, edi, 0x1u, ecx, 1u); |
| 1100 TestCmovRegReg(ns, edx, 0x1u, edi, 0x80000000u, ecx, 0u); |
| 1101 |
| 1102 TestCmovRegReg(p, edi, 0x80000000u, esi, 0x1u, edx, 1u); |
| 1103 TestCmovRegReg(p, edi, 0x1u, esi, 0x80000000u, edx, 0u); |
| 1104 |
| 1105 TestCmovRegReg(np, esi, 0x1u, edi, 0x80000000u, eax, 1u); |
| 1106 TestCmovRegReg(np, esi, 0x80000000u, edi, 0x1u, eax, 0u); |
| 1107 |
| 1108 TestCmovRegReg(l, edi, 0x80000000u, eax, 0x1u, ebx, 1u); |
| 1109 TestCmovRegReg(l, edi, 0x1u, eax, 0x80000000u, ebx, 0u); |
| 1110 |
| 1111 TestCmovRegReg(ge, eax, 0x1u, ebx, 0x80000000u, ecx, 1u); |
| 1112 TestCmovRegReg(ge, eax, 0x80000000u, ebx, 0x1u, ecx, 0u); |
| 1113 |
| 1114 TestCmovRegReg(le, ebx, 0x80000000u, ecx, 0x1u, edx, 1u); |
| 1115 TestCmovRegReg(le, ebx, 0x1u, ecx, 0x80000000u, edx, 0u); |
| 1116 |
| 1117 #undef TestCmovRegReg |
| 1118 } |
| 1119 |
| 1120 TEST_F(AssemblerX8632Test, CmovRegAddr) { |
| 1121 #define TestCmovRegAddr(C, Src0, Value0, Value1, Dest, IsTrue) \ |
| 1122 do { \ |
| 1123 const uint32_t T0 = allocateDword(); \ |
| 1124 const uint32_t V0 = Value1; \ |
| 1125 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src0, Immediate(Value0)); \ |
| 1126 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(Value0)); \ |
| 1127 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_##Src0, dwordAddress(T0)); \ |
| 1128 __ cmov(IceType_i32, Cond::Br_##C, GPRRegister::Encoded_Reg_##Dest, \ |
| 1129 dwordAddress(T0)); \ |
| 1130 \ |
| 1131 AssembledTest test = assemble(); \ |
| 1132 test.setDwordTo(T0, V0); \ |
| 1133 test.run(); \ |
| 1134 ASSERT_EQ((IsTrue) ? (Value1) : (Value0), test.Dest()) \ |
| 1135 << "(" #C ", " #Src0 ", " #Value0 ", " #Value1 ", " #Dest ", " #IsTrue \ |
| 1136 ")"; \ |
| 1137 \ |
| 1138 reset(); \ |
| 1139 } while (0) |
| 1140 |
| 1141 TestCmovRegAddr(o, eax, 0x80000000u, 0x1u, ecx, 1u); |
| 1142 TestCmovRegAddr(o, eax, 0x1u, 0x10000000u, ecx, 0u); |
| 1143 |
| 1144 TestCmovRegAddr(no, ebx, 0x1u, 0x10000000u, edx, 1u); |
| 1145 TestCmovRegAddr(no, ebx, 0x80000000u, 0x1u, edx, 0u); |
| 1146 |
| 1147 TestCmovRegAddr(b, ecx, 0x1, 0x80000000u, eax, 1u); |
| 1148 TestCmovRegAddr(b, ecx, 0x80000000u, 0x1u, eax, 0u); |
| 1149 |
| 1150 TestCmovRegAddr(ae, edx, 0x80000000u, 0x1u, ebx, 1u); |
| 1151 TestCmovRegAddr(ae, edx, 0x1u, 0x80000000u, ebx, 0u); |
| 1152 |
| 1153 TestCmovRegAddr(e, edi, 0x1u, 0x1u, ecx, 1u); |
| 1154 TestCmovRegAddr(e, edi, 0x1u, 0x11111u, ecx, 0u); |
| 1155 |
| 1156 TestCmovRegAddr(ne, esi, 0x80000000u, 0x1u, edx, 1u); |
| 1157 TestCmovRegAddr(ne, esi, 0x1u, 0x1u, edx, 0u); |
| 1158 |
| 1159 TestCmovRegAddr(be, eax, 0x1u, 0x80000000u, eax, 1u); |
| 1160 TestCmovRegAddr(be, eax, 0x80000000u, 0x1u, eax, 0u); |
| 1161 |
| 1162 TestCmovRegAddr(a, ebx, 0x80000000u, 0x1u, ebx, 1u); |
| 1163 TestCmovRegAddr(a, ebx, 0x1u, 0x80000000u, ebx, 0u); |
| 1164 |
| 1165 TestCmovRegAddr(s, ecx, 0x1u, 0x80000000u, ecx, 1u); |
| 1166 TestCmovRegAddr(s, ecx, 0x80000000u, 0x1u, ecx, 0u); |
| 1167 |
| 1168 TestCmovRegAddr(ns, edx, 0x80000000u, 0x1u, ecx, 1u); |
| 1169 TestCmovRegAddr(ns, edx, 0x1u, 0x80000000u, ecx, 0u); |
| 1170 |
| 1171 TestCmovRegAddr(p, edi, 0x80000000u, 0x1u, edx, 1u); |
| 1172 TestCmovRegAddr(p, edi, 0x1u, 0x80000000u, edx, 0u); |
| 1173 |
| 1174 TestCmovRegAddr(np, esi, 0x1u, 0x80000000u, eax, 1u); |
| 1175 TestCmovRegAddr(np, esi, 0x80000000u, 0x1u, eax, 0u); |
| 1176 |
| 1177 TestCmovRegAddr(l, edi, 0x80000000u, 0x1u, ebx, 1u); |
| 1178 TestCmovRegAddr(l, edi, 0x1u, 0x80000000u, ebx, 0u); |
| 1179 |
| 1180 TestCmovRegAddr(ge, eax, 0x1u, 0x80000000u, ecx, 1u); |
| 1181 TestCmovRegAddr(ge, eax, 0x80000000u, 0x1u, ecx, 0u); |
| 1182 |
| 1183 TestCmovRegAddr(le, ebx, 0x80000000u, 0x1u, edx, 1u); |
| 1184 TestCmovRegAddr(le, ebx, 0x1u, 0x80000000u, edx, 0u); |
| 1185 |
| 1186 #undef TestCmovRegAddr |
| 1187 } |
| 1188 |
| 1189 } // end of anonymous namespace |
| 1190 } // end of namespace Test |
| 1191 } // end of namespace X8632 |
| 1192 } // end of namespace Ice |
| OLD | NEW |