1 //===- subzero/unittest/AssemblerX8632/GPRArith.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, PushalPopal) { 17 // These are invalid in x86-64, so we can't write tests which will execute 18 // these instructions. 19 __ pushal(); 20 __ popal(); 21 22 constexpr size_t ByteCount = 2; 23 ASSERT_EQ(ByteCount, codeBytesSize()); 24 25 constexpr uint8_t Pushal = 0x60; 26 constexpr uint8_t Popal = 0x61; 27 28 verifyBytes<ByteCount>(codeBytes(), Pushal, Popal); 29 } 30 31 TEST_F(AssemblerX8632Test, PopAddr) { 32 const uint32_t T0 = allocateDword(); 33 constexpr uint32_t V0 = 0xEFAB; 34 35 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xC0FFEE)); 36 __ pushl(GPRRegister::Encoded_Reg_eax); 37 __ popl(dwordAddress(T0)); 38 39 AssembledTest test = assemble(); 40 test.setDwordTo(T0, V0); 41 42 test.run(); 43 44 ASSERT_EQ(0xC0FFEEul, test.contentsOfDword(T0)); 45 } 46 47 TEST_F(AssemblerX8632Test, SetCC) { 48 #define TestSetCC(C, Src0, Value0, Src1, Value1, Dest, IsTrue) \ 49 do { \ 50 const uint32_t T0 = allocateDword(); \ 51 constexpr uint32_t V0 = 0xF00F00; \ 52 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src0, Immediate(Value0)); \ 53 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src1, Immediate(Value1)); \ 54 __ cmp(IceType_i32, GPRRegister::Encoded_Reg_##Src0, \ 55 GPRRegister::Encoded_Reg_##Src1); \ 56 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(0)); \ 57 __ setcc(Cond::Br_##C, ByteRegister(GPRRegister::Encoded_Reg_##Dest)); \ 58 __ setcc(Cond::Br_##C, dwordAddress(T0)); \ 59 \ 60 AssembledTest test = assemble(); \ 61 test.setDwordTo(T0, V0); \ 62 \ 63 test.run(); \ 64 \ 65 EXPECT_EQ(IsTrue, test.Dest()) \ 66 << "(" #C ", " #Src0 ", " #Value0 ", " #Src1 ", " #Value1 ", " #Dest \ 67 ", " #IsTrue ")"; \ 68 EXPECT_EQ((0xF00F00 | IsTrue), test.contentsOfDword(T0)) \ 69 << "(" #C ", " #Src0 ", " #Value0 ", " #Src1 ", " #Value1 ", " #Dest \ 70 ", " #IsTrue ")"; \ 71 \ 72 reset(); \ 73 } while (0) 74 75 TestSetCC(o, eax, 0x80000000u, ebx, 0x1u, ecx, 1u); 76 TestSetCC(o, eax, 0x1u, ebx, 0x10000000u, ecx, 0u); 77 78 TestSetCC(no, ebx, 0x1u, ecx, 0x10000000u, edx, 1u); 79 TestSetCC(no, ebx, 0x80000000u, ecx, 0x1u, edx, 0u); 80 81 TestSetCC(b, ecx, 0x1, edx, 0x80000000u, eax, 1u); 82 TestSetCC(b, ecx, 0x80000000u, edx, 0x1u, eax, 0u); 83 84 TestSetCC(ae, edx, 0x80000000u, edi, 0x1u, ebx, 1u); 85 TestSetCC(ae, edx, 0x1u, edi, 0x80000000u, ebx, 0u); 86 87 TestSetCC(e, edi, 0x1u, esi, 0x1u, ecx, 1u); 88 TestSetCC(e, edi, 0x1u, esi, 0x11111u, ecx, 0u); 89 90 TestSetCC(ne, esi, 0x80000000u, eax, 0x1u, edx, 1u); 91 TestSetCC(ne, esi, 0x1u, eax, 0x1u, edx, 0u); 92 93 TestSetCC(be, eax, 0x1u, ebx, 0x80000000u, eax, 1u); 94 TestSetCC(be, eax, 0x80000000u, ebx, 0x1u, eax, 0u); 95 96 TestSetCC(a, ebx, 0x80000000u, ecx, 0x1u, ebx, 1u); 97 TestSetCC(a, ebx, 0x1u, ecx, 0x80000000u, ebx, 0u); 98 99 TestSetCC(s, ecx, 0x1u, edx, 0x80000000u, ecx, 1u); 100 TestSetCC(s, ecx, 0x80000000u, edx, 0x1u, ecx, 0u); 101 102 TestSetCC(ns, edx, 0x80000000u, edi, 0x1u, ecx, 1u); 103 TestSetCC(ns, edx, 0x1u, edi, 0x80000000u, ecx, 0u); 104 105 TestSetCC(p, edi, 0x80000000u, esi, 0x1u, edx, 1u); 106 TestSetCC(p, edi, 0x1u, esi, 0x80000000u, edx, 0u); 107 108 TestSetCC(np, esi, 0x1u, edi, 0x80000000u, eax, 1u); 109 TestSetCC(np, esi, 0x80000000u, edi, 0x1u, eax, 0u); 110 111 TestSetCC(l, edi, 0x80000000u, eax, 0x1u, ebx, 1u); 112 TestSetCC(l, edi, 0x1u, eax, 0x80000000u, ebx, 0u); 113 114 TestSetCC(ge, eax, 0x1u, ebx, 0x80000000u, ecx, 1u); 115 TestSetCC(ge, eax, 0x80000000u, ebx, 0x1u, ecx, 0u); 116 117 TestSetCC(le, ebx, 0x80000000u, ecx, 0x1u, edx, 1u); 118 TestSetCC(le, ebx, 0x1u, ecx, 0x80000000u, edx, 0u); 119 120 #undef TestSetCC 121 } 122 123 TEST_F(AssemblerX8632Test, Lea) { 124 #define TestLeaBaseDisp(Base, BaseValue, Disp, Dst) \ 125 do { \ 126 static constexpr char TestString[] = \ 127 "(" #Base ", " #BaseValue ", " #Dst ")"; \ 128 if (GPRRegister::Encoded_Reg_##Base != GPRRegister::Encoded_Reg_esp && \ 129 GPRRegister::Encoded_Reg_##Base != GPRRegister::Encoded_Reg_ebp) { \ 130 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Base, \ 131 Immediate(BaseValue)); \ 132 } \ 133 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \ 134 Address(GPRRegister::Encoded_Reg_##Base, Disp, \ 135 AssemblerFixup::NoFixup)); \ 136 AssembledTest test = assemble(); \ 137 test.run(); \ 138 ASSERT_EQ(test.Base() + (Disp), test.Dst()) << TestString << " with Disp " \ 139 << Disp; \ 140 reset(); \ 141 } while (0) 142 143 #define TestLeaIndex32bitDisp(Index, IndexValue, Disp, Dst0, Dst1, Dst2, Dst3) \ 144 do { \ 145 static constexpr char TestString[] = \ 146 "(" #Index ", " #IndexValue ", " #Dst0 ", " #Dst1 ", " #Dst2 \ 147 ", " #Dst3 ")"; \ 148 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Index, \ 149 Immediate(IndexValue)); \ 150 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst0, \ 151 Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_1, Disp, \ 152 AssemblerFixup::NoFixup)); \ 153 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst1, \ 154 Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_2, Disp, \ 155 AssemblerFixup::NoFixup)); \ 156 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst2, \ 157 Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_4, Disp, \ 158 AssemblerFixup::NoFixup)); \ 159 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst3, \ 160 Address(GPRRegister::Encoded_Reg_##Index, Traits::TIMES_8, Disp, \ 161 AssemblerFixup::NoFixup)); \ 162 AssembledTest test = assemble(); \ 163 test.run(); \ 164 ASSERT_EQ((test.Index() << Traits::TIMES_1) + (Disp), test.Dst0()) \ 165 << TestString << " " << Disp; \ 166 ASSERT_EQ((test.Index() << Traits::TIMES_2) + (Disp), test.Dst1()) \ 167 << TestString << " " << Disp; \ 168 ASSERT_EQ((test.Index() << Traits::TIMES_4) + (Disp), test.Dst2()) \ 169 << TestString << " " << Disp; \ 170 ASSERT_EQ((test.Index() << Traits::TIMES_8) + (Disp), test.Dst3()) \ 171 << TestString << " " << Disp; \ 172 reset(); \ 173 } while (0) 174 175 #define TestLeaBaseIndexDisp(Base, BaseValue, Index, IndexValue, Disp, Dst0, \ 176 Dst1, Dst2, Dst3) \ 177 do { \ 178 static constexpr char TestString[] = \ 179 "(" #Base ", " #BaseValue ", " #Index ", " #IndexValue ", " #Dst0 \ 180 ", " #Dst1 ", " #Dst2 ", " #Dst3 ")"; \ 181 if (GPRRegister::Encoded_Reg_##Base != GPRRegister::Encoded_Reg_esp && \ 182 GPRRegister::Encoded_Reg_##Base != GPRRegister::Encoded_Reg_ebp) { \ 183 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Base, \ 184 Immediate(BaseValue)); \ 185 } \ 186 /* esp is not a valid index register. */ \ 187 if (GPRRegister::Encoded_Reg_##Index != GPRRegister::Encoded_Reg_ebp) { \ 188 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Index, \ 189 Immediate(IndexValue)); \ 190 } \ 191 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst0, \ 192 Address(GPRRegister::Encoded_Reg_##Base, \ 193 GPRRegister::Encoded_Reg_##Index, Traits::TIMES_1, Disp, \ 194 AssemblerFixup::NoFixup)); \ 195 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst1, \ 196 Address(GPRRegister::Encoded_Reg_##Base, \ 197 GPRRegister::Encoded_Reg_##Index, Traits::TIMES_2, Disp, \ 198 AssemblerFixup::NoFixup)); \ 199 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst2, \ 200 Address(GPRRegister::Encoded_Reg_##Base, \ 201 GPRRegister::Encoded_Reg_##Index, Traits::TIMES_4, Disp, \ 202 AssemblerFixup::NoFixup)); \ 203 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst3, \ 204 Address(GPRRegister::Encoded_Reg_##Base, \ 205 GPRRegister::Encoded_Reg_##Index, Traits::TIMES_8, Disp, \ 206 AssemblerFixup::NoFixup)); \ 207 AssembledTest test = assemble(); \ 208 test.run(); \ 209 uint32_t ExpectedIndexValue = test.Index(); \ 210 if (GPRRegister::Encoded_Reg_##Index == GPRRegister::Encoded_Reg_esp) { \ 211 ExpectedIndexValue = 0; \ 212 } \ 213 ASSERT_EQ(test.Base() + (ExpectedIndexValue << Traits::TIMES_1) + (Disp), \ 214 test.Dst0()) \ 215 << TestString << " " << Disp; \ 216 ASSERT_EQ(test.Base() + (ExpectedIndexValue << Traits::TIMES_2) + (Disp), \ 217 test.Dst1()) \ 218 << TestString << " " << Disp; \ 219 ASSERT_EQ(test.Base() + (ExpectedIndexValue << Traits::TIMES_4) + (Disp), \ 220 test.Dst2()) \ 221 << TestString << " " << Disp; \ 222 ASSERT_EQ(test.Base() + (ExpectedIndexValue << Traits::TIMES_8) + (Disp), \ 223 test.Dst3()) \ 224 << TestString << " " << Disp; \ 225 reset(); \ 226 } while (0) 227 228 for (const int32_t Disp : 229 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) { 230 TestLeaBaseDisp(eax, 0x10000Fu, Disp, ebx); 231 TestLeaBaseDisp(ebx, 0x20000Fu, Disp, ecx); 232 TestLeaBaseDisp(ecx, 0x30000Fu, Disp, edx); 233 TestLeaBaseDisp(edx, 0x40000Fu, Disp, esi); 234 TestLeaBaseDisp(esi, 0x50000Fu, Disp, edi); 235 TestLeaBaseDisp(edi, 0x60000Fu, Disp, eax); 236 TestLeaBaseDisp(esp, 0x11000Fu, Disp, eax); 237 TestLeaBaseDisp(ebp, 0x22000Fu, Disp, ecx); 238 } 239 240 // esp is not a valid index register. 241 // ebp is not valid in this addressing mode (rm = 0). 242 for (const int32_t Disp : 243 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) { 244 TestLeaIndex32bitDisp(eax, 0x2000u, Disp, ebx, ecx, edx, esi); 245 TestLeaIndex32bitDisp(ebx, 0x4000u, Disp, ecx, edx, esi, edi); 246 TestLeaIndex32bitDisp(ecx, 0x6000u, Disp, edx, esi, edi, eax); 247 TestLeaIndex32bitDisp(edx, 0x8000u, Disp, esi, edi, eax, ebx); 248 TestLeaIndex32bitDisp(esi, 0xA000u, Disp, edi, eax, ebx, ecx); 249 TestLeaIndex32bitDisp(edi, 0xC000u, Disp, eax, ebx, ecx, edx); 250 } 251 252 for (const int32_t Disp : 253 {0x00, 0x06, -0x06, 0x0600, -0x6000, 0x6000000, -0x6000000}) { 254 TestLeaBaseIndexDisp(eax, 0x100000u, ebx, 0x600u, Disp, ecx, edx, esi, edi); 255 TestLeaBaseIndexDisp(ebx, 0x200000u, ecx, 0x500u, Disp, edx, esi, edi, eax); 256 TestLeaBaseIndexDisp(ecx, 0x300000u, edx, 0x400u, Disp, esi, edi, eax, ebx); 257 TestLeaBaseIndexDisp(edx, 0x400000u, esi, 0x300u, Disp, edi, eax, ebx, ecx); 258 TestLeaBaseIndexDisp(esi, 0x500000u, edi, 0x200u, Disp, eax, ebx, ecx, edx); 259 TestLeaBaseIndexDisp(edi, 0x600000u, eax, 0x100u, Disp, ebx, ecx, edx, esi); 260 261 /* Initializers are ignored when Src[01] is ebp/esp. */ 262 TestLeaBaseIndexDisp(esp, 0, ebx, 0x6000u, Disp, ecx, edx, esi, edi); 263 TestLeaBaseIndexDisp(esp, 0, ecx, 0x5000u, Disp, edx, esi, edi, eax); 264 TestLeaBaseIndexDisp(esp, 0, edx, 0x4000u, Disp, esi, edi, eax, ebx); 265 TestLeaBaseIndexDisp(esp, 0, esi, 0x3000u, Disp, edi, eax, ebx, ecx); 266 TestLeaBaseIndexDisp(esp, 0, edi, 0x2000u, Disp, eax, ebx, ecx, edx); 267 TestLeaBaseIndexDisp(esp, 0, eax, 0x1000u, Disp, ebx, ecx, edx, esi); 268 269 TestLeaBaseIndexDisp(ebp, 0, ebx, 0x6000u, Disp, ecx, edx, esi, edi); 270 TestLeaBaseIndexDisp(ebp, 0, ecx, 0x5000u, Disp, edx, esi, edi, eax); 271 TestLeaBaseIndexDisp(ebp, 0, edx, 0x4000u, Disp, esi, edi, eax, ebx); 272 TestLeaBaseIndexDisp(ebp, 0, esi, 0x3000u, Disp, edi, eax, ebx, ecx); 273 TestLeaBaseIndexDisp(ebp, 0, edi, 0x2000u, Disp, eax, ebx, ecx, edx); 274 TestLeaBaseIndexDisp(ebp, 0, eax, 0x1000u, Disp, ebx, ecx, edx, esi); 275 276 TestLeaBaseIndexDisp(eax, 0x1000000u, ebp, 0, Disp, ecx, edx, esi, edi); 277 TestLeaBaseIndexDisp(ebx, 0x2000000u, ebp, 0, Disp, edx, esi, edi, eax); 278 TestLeaBaseIndexDisp(ecx, 0x3000000u, ebp, 0, Disp, esi, edi, eax, ebx); 279 TestLeaBaseIndexDisp(edx, 0x4000000u, ebp, 0, Disp, edi, eax, ebx, ecx); 280 TestLeaBaseIndexDisp(esi, 0x5000000u, ebp, 0, Disp, eax, ebx, ecx, edx); 281 TestLeaBaseIndexDisp(edi, 0x6000000u, ebp, 0, Disp, ebx, ecx, edx, esi); 282 283 TestLeaBaseIndexDisp(esp, 0, ebp, 0, Disp, ebx, ecx, edx, esi); 284 } 285 286 // Absolute addressing mode is tested in the Low Level tests. The encoding used 287 // by the assembler has different meanings in x86-32 and x86-64. 288 #undef TestLeaBaseIndexDisp 289 #undef TestLeaScaled32bitDisp 290 #undef TestLeaBaseDisp 291 } 292 293 TEST_F(AssemblerX8632LowLevelTest, LeaAbsolute) { 294 #define TestLeaAbsolute(Dst, Value) \ 295 do { \ 296 static constexpr char TestString[] = "(" #Dst ", " #Value ")"; \ 297 __ lea(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \ 298 Address(Value, AssemblerFixup::NoFixup)); \ 299 static constexpr uint32_t ByteCount = 6; \ 300 ASSERT_EQ(ByteCount, codeBytesSize()) << TestString; \ 301 static constexpr uint8_t Opcode = 0x8D; \ 302 static constexpr uint8_t ModRM = \ 303 /*mod=*/0x00 | /*reg*/ (GPRRegister::Encoded_Reg_##Dst << 3) | \ 304 /*rm*/ GPRRegister::Encoded_Reg_ebp; \ 305 verifyBytes<ByteCount>(codeBytes(), Opcode, ModRM, (Value)&0xFF, \ 306 (Value >> 8) & 0xFF, (Value >> 16) & 0xFF, \ 307 (Value >> 24) & 0xFF); \ 308 reset(); \ 309 } while (0) 310 311 TestLeaAbsolute(eax, 0x11BEEF22); 312 TestLeaAbsolute(ebx, 0x33BEEF44); 313 TestLeaAbsolute(ecx, 0x55BEEF66); 314 TestLeaAbsolute(edx, 0x77BEEF88); 315 TestLeaAbsolute(esi, 0x99BEEFAA); 316 TestLeaAbsolute(edi, 0xBBBEEFBB); 317 318 #undef TesLeaAbsolute 319 } 320 321 TEST_F(AssemblerX8632Test, Test) { 322 static constexpr uint32_t Mask8 = 0xFF; 323 static constexpr uint32_t Mask16 = 0xFFFF; 324 static constexpr uint32_t Mask32 = 0xFFFFFFFF; 325 326 #define TestImplRegReg(Dst, Value0, Src, Value1, Size) \ 327 do { \ 328 static constexpr bool NearJump = true; \ 329 static constexpr char TestString[] = \ 330 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \ 331 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \ 332 static constexpr uint32_t ValueIfFalse = 0x11111111; \ 333 \ 334 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 335 Immediate(Value0)); \ 336 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 337 Immediate(Value1)); \ 338 __ test(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 339 GPRRegister::Encoded_Reg_##Src); \ 340 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \ 341 Immediate(ValueIfFalse)); \ 342 Label Done; \ 343 __ j(Cond::Br_e, &Done, NearJump); \ 344 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \ 345 Immediate(ValueIfTrue)); \ 346 __ bind(&Done); \ 347 \ 348 AssembledTest test = assemble(); \ 349 test.run(); \ 350 \ 351 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \ 352 : ValueIfFalse, \ 353 test.Dst()) \ 354 << TestString; \ 355 reset(); \ 356 } while (0) 357 358 #define TestImplRegImm(Dst, Value0, Imm, Size) \ 359 do { \ 360 static constexpr bool NearJump = true; \ 361 static constexpr char TestString[] = \ 362 "(" #Dst ", " #Value0 ", " #Imm ", " #Size ")"; \ 363 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \ 364 static constexpr uint32_t ValueIfFalse = 0x11111111; \ 365 \ 366 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 367 Immediate(Value0)); \ 368 __ test(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 369 Immediate((Imm)&Mask##Size)); \ 370 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \ 371 Immediate(ValueIfFalse)); \ 372 Label Done; \ 373 __ j(Cond::Br_e, &Done, NearJump); \ 374 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dst, \ 375 Immediate(ValueIfTrue)); \ 376 __ bind(&Done); \ 377 \ 378 AssembledTest test = assemble(); \ 379 test.run(); \ 380 \ 381 ASSERT_EQ(((Value0)&Mask##Size) & ((Imm)&Mask##Size) ? ValueIfTrue \ 382 : ValueIfFalse, \ 383 test.Dst()) \ 384 << TestString; \ 385 reset(); \ 386 } while (0) 387 388 #define TestImplAddrReg(Value0, Src, Value1, Size) \ 389 do { \ 390 static constexpr bool NearJump = true; \ 391 static constexpr char TestString[] = \ 392 "(Addr, " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \ 393 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \ 394 static constexpr uint32_t ValueIfFalse = 0x11111111; \ 395 const uint32_t T0 = allocateDword(); \ 396 \ 397 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 398 Immediate(Value1)); \ 399 __ test(IceType_i##Size, dwordAddress(T0), \ 400 GPRRegister::Encoded_Reg_##Src); \ 401 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfFalse)); \ 402 Label Done; \ 403 __ j(Cond::Br_e, &Done, NearJump); \ 404 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfTrue)); \ 405 __ bind(&Done); \ 406 \ 407 AssembledTest test = assemble(); \ 408 test.setDwordTo(T0, uint32_t(Value0)); \ 409 test.run(); \ 410 \ 411 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \ 412 : ValueIfFalse, \ 413 test.contentsOfDword(T0)) \ 414 << TestString; \ 415 reset(); \ 416 } while (0) 417 418 #define TestImplAddrImm(Value0, Value1, Size) \ 419 do { \ 420 static constexpr bool NearJump = true; \ 421 static constexpr char TestString[] = \ 422 "(Addr, " #Value0 ", " #Value1 ", " #Size ")"; \ 423 static constexpr uint32_t ValueIfTrue = 0xBEEFFEEB; \ 424 static constexpr uint32_t ValueIfFalse = 0x11111111; \ 425 const uint32_t T0 = allocateDword(); \ 426 \ 427 __ test(IceType_i##Size, dwordAddress(T0), \ 428 Immediate((Value1)&Mask##Size)); \ 429 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfFalse)); \ 430 Label Done; \ 431 __ j(Cond::Br_e, &Done, NearJump); \ 432 __ mov(IceType_i32, dwordAddress(T0), Immediate(ValueIfTrue)); \ 433 __ bind(&Done); \ 434 \ 435 AssembledTest test = assemble(); \ 436 test.setDwordTo(T0, uint32_t(Value0)); \ 437 test.run(); \ 438 \ 439 ASSERT_EQ(((Value0)&Mask##Size) & ((Value1)&Mask##Size) ? ValueIfTrue \ 440 : ValueIfFalse, \ 441 test.contentsOfDword(T0)) \ 442 << TestString; \ 443 reset(); \ 444 } while (0) 445 446 #define TestImplValues(Dst, Value0, Src, Value1, Size) \ 447 do { \ 448 TestImplRegReg(Dst, Value0, Src, Value1, Size); \ 449 TestImplRegImm(Dst, Value0, Value1, Size); \ 450 TestImplAddrReg(Value0, Src, Value1, Size); \ 451 TestImplAddrImm(Value0, Value1, Size); \ 452 } while (0) 453 454 #define TestImplSize(Dst, Src, Size) \ 455 do { \ 456 TestImplValues(Dst, 0xF0F12101, Src, 0x00000000, Size); \ 457 TestImplValues(Dst, 0xF0000000, Src, 0xF0000000, Size); \ 458 TestImplValues(Dst, 0x0F00000F, Src, 0xF00000F0, Size); \ 459 } while (0) 460 461 #define TestImpl(Dst, Src) \ 462 do { \ 463 TestImplSize(Dst, Src, 8); \ 464 TestImplSize(Dst, Src, 16); \ 465 TestImplSize(Dst, Src, 32); \ 466 } while (0) 467 468 TestImpl(eax, ebx); 469 TestImpl(ebx, ecx); 470 TestImpl(ecx, edx); 471 TestImpl(edx, esi); 472 TestImpl(esi, edi); 473 TestImpl(edi, eax); 474 475 #undef TestImpl 476 #undef TestImplSize 477 #undef TestImplValues 478 #undef TestImplAddrImm 479 #undef TestImplAddrReg 480 #undef TestImplRegImm 481 #undef TestImplRegReg 482 } 483 484 // No mull/div because x86. 485 // No shift because x86. 486 TEST_F(AssemblerX8632Test, Arith_most) { 487 static constexpr uint32_t Mask8 = 0xFF; 488 static constexpr uint32_t Mask16 = 0xFFFF; 489 static constexpr uint32_t Mask32 = 0xFFFFFFFF; 490 491 #define TestImplRegReg(Inst, Dst, Value0, Src, Value1, Type, Size, Op) \ 492 do { \ 493 static constexpr char TestString[] = \ 494 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 \ 495 ", " #Type #Size "_t, " #Op ")"; \ 496 \ 497 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 498 Immediate(Value0)); \ 499 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 500 Immediate(Value1)); \ 501 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 502 GPRRegister::Encoded_Reg_##Src); \ 503 \ 504 AssembledTest test = assemble(); \ 505 test.run(); \ 506 \ 507 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \ 508 static_cast<Type##Size##_t>((Value0)&Mask##Size) \ 509 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \ 510 Mask##Size &test.Dst()) \ 511 << TestString; \ 512 reset(); \ 513 } while (0) 514 515 #define TestImplRegAddr(Inst, Dst, Value0, Value1, Type, Size, Op) \ 516 do { \ 517 static constexpr char TestString[] = \ 518 "(" #Inst ", " #Dst ", " #Value0 ", Addr, " #Value1 ", " #Type #Size \ 519 "_t, " #Op ")"; \ 520 const uint32_t T0 = allocateDword(); \ 521 const uint32_t V0 = Value1; \ 522 \ 523 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 524 Immediate(Value0)); \ 525 __ mov(IceType_i##Size, dwordAddress(T0), Immediate(Value1)); \ 526 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 527 dwordAddress(T0)); \ 528 \ 529 AssembledTest test = assemble(); \ 530 test.setDwordTo(T0, V0); \ 531 test.run(); \ 532 \ 533 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \ 534 static_cast<Type##Size##_t>((Value0)&Mask##Size) \ 535 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \ 536 Mask##Size &test.Dst()) \ 537 << TestString; \ 538 reset(); \ 539 } while (0) 540 541 #define TestImplRegImm(Inst, Dst, Value0, Imm, Type, Size, Op) \ 542 do { \ 543 static constexpr char TestString[] = \ 544 "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Type #Size \ 545 "_t, " #Op ")"; \ 546 \ 547 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 548 Immediate(Value0)); \ 549 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 550 Immediate((Imm)&Mask##Size)); \ 551 \ 552 AssembledTest test = assemble(); \ 553 test.run(); \ 554 \ 555 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \ 556 static_cast<Type##Size##_t>((Value0)&Mask##Size) \ 557 Op static_cast<Type##Size##_t>((Imm)&Mask##Size)), \ 558 Mask##Size &test.Dst()) \ 559 << TestString; \ 560 reset(); \ 561 } while (0) 562 563 #define TestImplAddrReg(Inst, Value0, Src, Value1, Type, Size, Op) \ 564 do { \ 565 static constexpr char TestString[] = \ 566 "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Type #Size \ 567 "_t, " #Op ")"; \ 568 const uint32_t T0 = allocateDword(); \ 569 const uint32_t V0 = Value0; \ 570 \ 571 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 572 Immediate(Value1)); \ 573 __ Inst(IceType_i##Size, dwordAddress(T0), \ 574 GPRRegister::Encoded_Reg_##Src); \ 575 \ 576 AssembledTest test = assemble(); \ 577 test.setDwordTo(T0, V0); \ 578 test.run(); \ 579 \ 580 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \ 581 static_cast<Type##Size##_t>((Value0)&Mask##Size) \ 582 Op static_cast<Type##Size##_t>((Value1)&Mask##Size)), \ 583 Mask##Size &test.contentsOfDword(T0)) \ 584 << TestString; \ 585 reset(); \ 586 } while (0) 587 588 #define TestImplAddrImm(Inst, Value0, Imm, Type, Size, Op) \ 589 do { \ 590 static constexpr char TestString[] = \ 591 "(" #Inst ", Addr, " #Value0 ", Imm, " #Imm ", " #Type #Size \ 592 "_t, " #Op ")"; \ 593 const uint32_t T0 = allocateDword(); \ 594 const uint32_t V0 = Value0; \ 595 \ 596 __ Inst(IceType_i##Size, dwordAddress(T0), Immediate((Imm)&Mask##Size)); \ 597 \ 598 AssembledTest test = assemble(); \ 599 test.setDwordTo(T0, V0); \ 600 test.run(); \ 601 \ 602 ASSERT_EQ(Mask##Size &static_cast<uint32_t>( \ 603 static_cast<Type##Size##_t>((Value0)&Mask##Size) \ 604 Op static_cast<Type##Size##_t>((Imm)&Mask##Size)), \ 605 Mask##Size &test.contentsOfDword(T0)) \ 606 << TestString; \ 607 reset(); \ 608 } while (0) 609 610 #define TestImplOp(Inst, Dst, Value0, Src, Value1, Type, Size, Op) \ 611 do { \ 612 TestImplRegReg(Inst, Dst, Value0, Src, Value1, Type, Size, Op); \ 613 TestImplRegAddr(Inst, Dst, Value0, Value1, Type, Size, Op); \ 614 TestImplRegImm(Inst, Dst, Value0, Value1, Type, Size, Op); \ 615 TestImplAddrReg(Inst, Value0, Src, Value1, Type, Size, Op); \ 616 TestImplAddrImm(Inst, Value0, Value1, Type, Size, Op); \ 617 } while (0) 618 619 #define TestImplValues(Dst, Value0, Src, Value1, Size) \ 620 do { \ 621 TestImplOp(And, Dst, Value0, Src, Value1, int, Size, &); \ 622 TestImplOp(And, Dst, Value0, Src, Value1, uint, Size, &); \ 623 TestImplOp(Or, Dst, Value0, Src, Value1, int, Size, | ); \ 624 TestImplOp(Or, Dst, Value0, Src, Value1, uint, Size, | ); \ 625 TestImplOp(Xor, Dst, Value0, Src, Value1, int, Size, ^); \ 626 TestImplOp(Xor, Dst, Value0, Src, Value1, uint, Size, ^); \ 627 TestImplOp(add, Dst, Value0, Src, Value1, int, Size, +); \ 628 TestImplOp(add, Dst, Value0, Src, Value1, uint, Size, +); \ 629 TestImplOp(sub, Dst, Value0, Src, Value1, int, Size, -); \ 630 TestImplOp(sub, Dst, Value0, Src, Value1, uint, Size, -); \ 631 } while (0) 632 633 #define TestImplSize(Dst, Src, Size) \ 634 do { \ 635 TestImplValues(Dst, 0xF0F12101, Src, 0x00000000, Size); \ 636 TestImplValues(Dst, 0xF0000000, Src, 0xF0000000, Size); \ 637 TestImplValues(Dst, 0x0F00000F, Src, 0xF0000070, Size); \ 638 TestImplValues(Dst, 0x0F00F00F, Src, 0xF000F070, Size); \ 639 } while (0) 640 641 #define TestImpl(Dst, Src) \ 642 do { \ 643 if (GPRRegister::Encoded_Reg_##Src <= 3 && \ 644 GPRRegister::Encoded_Reg_##Dst <= 3) { \ 645 TestImplSize(Dst, Src, 8); \ 646 } \ 647 TestImplSize(Dst, Src, 16); \ 648 TestImplSize(Dst, Src, 32); \ 649 } while (0) 650 651 TestImpl(eax, ebx); 652 TestImpl(ebx, ecx); 653 TestImpl(ecx, edx); 654 TestImpl(edx, esi); 655 TestImpl(esi, edi); 656 TestImpl(edi, eax); 657 658 #undef TestImpl 659 #undef TestImplSize 660 #undef TestImplValues 661 #undef TestImplOp 662 #undef TestImplAddrImm 663 #undef TestImplAddrReg 664 #undef TestImplRegImm 665 #undef TestImplRegAddr 666 #undef TestImplRegReg 667 } 668 669 TEST_F(AssemblerX8632Test, Arith_BorrowNCarry) { 670 const uint32_t Mask8 = 0x000000FF; 671 const uint32_t Mask16 = 0x0000FFFF; 672 const uint32_t Mask32 = 0xFFFFFFFF; 673 674 const uint64_t ResultMask8 = 0x000000000000FFFFull; 675 const uint64_t ResultMask16 = 0x00000000FFFFFFFFull; 676 const uint64_t ResultMask32 = 0xFFFFFFFFFFFFFFFFull; 677 678 #define TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, \ 679 Op, Size) \ 680 do { \ 681 static_assert(Size == 8 || Size == 16 || Size == 32, \ 682 "Invalid size " #Size); \ 683 static constexpr char TestString[] = \ 684 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 ", " #Src0 \ 685 ", " #Src1 ", " #Value1 ", " #Op ", " #Size ")"; \ 686 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst0, \ 687 Immediate(uint64_t(Value0) & Mask##Size)); \ 688 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst1, \ 689 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \ 690 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src0, \ 691 Immediate(uint64_t(Value1) & Mask##Size)); \ 692 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src1, \ 693 Immediate((uint64_t(Value1) >> Size) & Mask##Size)); \ 694 __ Inst0(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst0, \ 695 GPRRegister::Encoded_Reg_##Src0); \ 696 __ Inst1(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst1, \ 697 GPRRegister::Encoded_Reg_##Src1); \ 698 \ 699 AssembledTest test = assemble(); \ 700 test.run(); \ 701 \ 702 static constexpr uint64_t Result = \ 703 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \ 704 ResultMask##Size); \ 705 static constexpr uint32_t Expected0 = Result & Mask##Size; \ 706 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \ 707 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \ 708 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \ 709 reset(); \ 710 } while (0) 711 712 #define TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size) \ 713 do { \ 714 static_assert(Size == 8 || Size == 16 || Size == 32, \ 715 "Invalid size " #Size); \ 716 static constexpr char TestString[] = \ 717 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 \ 718 ", Addr, " #Value1 ", " #Op ", " #Size ")"; \ 719 const uint32_t T0 = allocateDword(); \ 720 const uint32_t V0 = uint64_t(Value1) & Mask##Size; \ 721 const uint32_t T1 = allocateDword(); \ 722 const uint32_t V1 = (uint64_t(Value1) >> Size) & Mask##Size; \ 723 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst0, \ 724 Immediate(uint64_t(Value0) & Mask##Size)); \ 725 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst1, \ 726 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \ 727 __ Inst0(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst0, \ 728 dwordAddress(T0)); \ 729 __ Inst1(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst1, \ 730 dwordAddress(T1)); \ 731 \ 732 AssembledTest test = assemble(); \ 733 test.setDwordTo(T0, V0); \ 734 test.setDwordTo(T1, V1); \ 735 test.run(); \ 736 \ 737 static constexpr uint64_t Result = \ 738 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \ 739 ResultMask##Size); \ 740 static constexpr uint32_t Expected0 = Result & Mask##Size; \ 741 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \ 742 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \ 743 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \ 744 reset(); \ 745 } while (0) 746 747 #define TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Imm, Op, Size) \ 748 do { \ 749 static_assert(Size == 8 || Size == 16 || Size == 32, \ 750 "Invalid size " #Size); \ 751 static constexpr char TestString[] = \ 752 "(" #Inst0 ", " #Inst1 ", " #Dst0 ", " #Dst1 ", " #Value0 \ 753 ", Imm(" #Imm "), " #Op ", " #Size ")"; \ 754 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst0, \ 755 Immediate(uint64_t(Value0) & Mask##Size)); \ 756 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst1, \ 757 Immediate((uint64_t(Value0) >> Size) & Mask##Size)); \ 758 __ Inst0(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst0, \ 759 Immediate(uint64_t(Imm) & Mask##Size)); \ 760 __ Inst1(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst1, \ 761 Immediate((uint64_t(Imm) >> Size) & Mask##Size)); \ 762 \ 763 AssembledTest test = assemble(); \ 764 test.run(); \ 765 \ 766 static constexpr uint64_t Result = \ 767 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Imm) & \ 768 ResultMask##Size); \ 769 static constexpr uint32_t Expected0 = Result & Mask##Size; \ 770 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \ 771 ASSERT_EQ(Expected0, test.Dst0()) << TestString << ": 0"; \ 772 ASSERT_EQ(Expected1, test.Dst1()) << TestString << ": 1"; \ 773 reset(); \ 774 } while (0) 775 776 #define TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size) \ 777 do { \ 778 static_assert(Size == 8 || Size == 16 || Size == 32, \ 779 "Invalid size " #Size); \ 780 static constexpr char TestString[] = \ 781 "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", " #Src0 ", " #Src1 \ 782 ", " #Value1 ", " #Op ", " #Size ")"; \ 783 const uint32_t T0 = allocateDword(); \ 784 const uint32_t V0 = uint64_t(Value0) & Mask##Size; \ 785 const uint32_t T1 = allocateDword(); \ 786 const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size; \ 787 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src0, \ 788 Immediate(uint64_t(Value1) & Mask##Size)); \ 789 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src1, \ 790 Immediate((uint64_t(Value1) >> Size) & Mask##Size)); \ 791 __ Inst0(IceType_i##Size, dwordAddress(T0), \ 792 GPRRegister::Encoded_Reg_##Src0); \ 793 __ Inst1(IceType_i##Size, dwordAddress(T1), \ 794 GPRRegister::Encoded_Reg_##Src1); \ 795 \ 796 AssembledTest test = assemble(); \ 797 test.setDwordTo(T0, V0); \ 798 test.setDwordTo(T1, V1); \ 799 test.run(); \ 800 \ 801 static constexpr uint64_t Result = \ 802 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Value1) & \ 803 ResultMask##Size); \ 804 static constexpr uint32_t Expected0 = Result & Mask##Size; \ 805 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \ 806 ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0"; \ 807 ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1"; \ 808 reset(); \ 809 } while (0) 810 811 #define TestImplAddrImm(Inst0, Inst1, Value0, Imm, Op, Size) \ 812 do { \ 813 static_assert(Size == 8 || Size == 16 || Size == 32, \ 814 "Invalid size " #Size); \ 815 static constexpr char TestString[] = \ 816 "(" #Inst0 ", " #Inst1 ", Addr, " #Value0 ", Imm(" #Imm "), " #Op \ 817 ", " #Size ")"; \ 818 const uint32_t T0 = allocateDword(); \ 819 const uint32_t V0 = uint64_t(Value0) & Mask##Size; \ 820 const uint32_t T1 = allocateDword(); \ 821 const uint32_t V1 = (uint64_t(Value0) >> Size) & Mask##Size; \ 822 __ Inst0(IceType_i##Size, dwordAddress(T0), \ 823 Immediate(uint64_t(Imm) & Mask##Size)); \ 824 __ Inst1(IceType_i##Size, dwordAddress(T1), \ 825 Immediate((uint64_t(Imm) >> Size) & Mask##Size)); \ 826 \ 827 AssembledTest test = assemble(); \ 828 test.setDwordTo(T0, V0); \ 829 test.setDwordTo(T1, V1); \ 830 test.run(); \ 831 \ 832 static constexpr uint64_t Result = \ 833 (uint64_t(Value0) & ResultMask##Size)Op(uint64_t(Imm) & \ 834 ResultMask##Size); \ 835 static constexpr uint32_t Expected0 = Result & Mask##Size; \ 836 static constexpr uint32_t Expected1 = (Result >> Size) & Mask##Size; \ 837 ASSERT_EQ(Expected0, test.contentsOfDword(T0)) << TestString << ": 0"; \ 838 ASSERT_EQ(Expected1, test.contentsOfDword(T1)) << TestString << ": 1"; \ 839 reset(); \ 840 } while (0) 841 842 #define TestImplOp(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op, \ 843 Size) \ 844 do { \ 845 TestImplRegReg(Inst0, Inst1, Dst0, Dst1, Value0, Src0, Src1, Value1, Op, \ 846 Size); \ 847 TestImplRegAddr(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size); \ 848 TestImplRegImm(Inst0, Inst1, Dst0, Dst1, Value0, Value1, Op, Size); \ 849 TestImplAddrReg(Inst0, Inst1, Value0, Src0, Src1, Value1, Op, Size); \ 850 TestImplAddrImm(Inst0, Inst1, Value0, Value1, Op, Size); \ 851 } while (0) 852 853 #define TestImplValues(Dst0, Dst1, Value0, Src0, Src1, Value1, Size) \ 854 do { \ 855 TestImplOp(add, adc, Dst0, Dst1, Value0, Src0, Src1, Value1, +, Size); \ 856 TestImplOp(sub, sbb, Dst0, Dst1, Value0, Src0, Src1, Value1, -, Size); \ 857 } while (0) 858 859 #define TestImplSize(Dst0, Dst1, Src0, Src1, Size) \ 860 do { \ 861 TestImplValues(Dst0, Dst1, 0xFFFFFFFFFFFFFF00ull, Src0, Src1, \ 862 0xFFFFFFFF0000017Full, Size); \ 863 } while (0) 864 865 #define TestImpl(Dst0, Dst1, Src0, Src1) \ 866 do { \ 867 if (GPRRegister::Encoded_Reg_##Dst0 <= 3 && \ 868 GPRRegister::Encoded_Reg_##Dst1 <= 3 && \ 869 GPRRegister::Encoded_Reg_##Src0 <= 3 && \ 870 GPRRegister::Encoded_Reg_##Src1 <= 3) { \ 871 TestImplSize(Dst0, Dst1, Src0, Src1, 8); \ 872 } \ 873 TestImplSize(Dst0, Dst1, Src0, Src1, 16); \ 874 TestImplSize(Dst0, Dst1, Src0, Src1, 32); \ 875 } while (0) 876 877 TestImpl(eax, ebx, ecx, edx); 878 TestImpl(ebx, ecx, edx, esi); 879 TestImpl(ecx, edx, esi, edi); 880 TestImpl(edx, esi, edi, eax); 881 TestImpl(esi, edi, eax, ebx); 882 TestImpl(edi, eax, ebx, ecx); 883 884 #undef TestImpl 885 #undef TestImplSize 886 #undef TestImplValues 887 #undef TestImplOp 888 #undef TestImplAddrImm 889 #undef TestImplAddrReg 890 #undef TestImplRegImm 891 #undef TestImplRegAddr 892 #undef TestImplRegReg 893 } 894 895 TEST_F(AssemblerX8632LowLevelTest, Cbw_Cwd_Cdq) { 896 #define TestImpl(Inst, BytesSize, ...) \ 897 do { \ 898 __ Inst(); \ 899 ASSERT_EQ(BytesSize, codeBytesSize()) << #Inst; \ 900 verifyBytes<BytesSize>(codeBytes(), __VA_ARGS__); \ 901 reset(); \ 902 } while (0) 903 904 TestImpl(cbw, 2u, 0x66, 0x98); 905 TestImpl(cwd, 2u, 0x66, 0x99); 906 TestImpl(cdq, 1u, 0x99); 907 908 #undef TestImpl 909 } 910 911 TEST_F(AssemblerX8632Test, SingleOperandMul) { 912 static constexpr uint32_t Mask8 = 0x000000FF; 913 static constexpr uint32_t Mask16 = 0x0000FFFF; 914 static constexpr uint32_t Mask32 = 0xFFFFFFFF; 915 916 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size) \ 917 do { \ 918 static_assert(GPRRegister::Encoded_Reg_eax != \ 919 GPRRegister::Encoded_Reg_##Src, \ 920 "eax can not be src1."); \ 921 \ 922 static constexpr char TestString[] = \ 923 "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size \ 924 ")"; \ 925 static constexpr Type##64_t OperandEax = \ 926 static_cast<Type##Size##_t>((Value0)&Mask##Size); \ 927 static constexpr Type##64_t OperandOther = \ 928 static_cast<Type##Size##_t>((Value1)&Mask##Size); \ 929 static constexpr uint32_t ExpectedEax = \ 930 Mask##Size & (OperandEax * OperandOther); \ 931 static constexpr uint32_t ExpectedEdx = \ 932 Mask##Size & ((OperandEax * OperandOther) >> Size); \ 933 \ 934 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_eax, \ 935 Immediate((Value0)&Mask##Size)); \ 936 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 937 Immediate((Value1)&Mask##Size)); \ 938 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Src); \ 939 \ 940 if (Size == 8) { \ 941 /* mov %ah, %dl */ \ 942 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_edx, \ 943 GPRRegister::Encoded_Reg_esp); \ 944 __ And(IceType_i16, GPRRegister::Encoded_Reg_eax, Immediate(0x00FF)); \ 945 if (GPRRegister::Encoded_Reg_##Src == GPRRegister::Encoded_Reg_esi) { \ 946 /* src == dh; clear dx's upper 8 bits. */ \ 947 __ And(IceType_i16, GPRRegister::Encoded_Reg_edx, Immediate(0x00FF)); \ 948 } \ 949 } \ 950 \ 951 AssembledTest test = assemble(); \ 952 test.run(); \ 953 \ 954 ASSERT_EQ(ExpectedEax, test.eax()) << TestString; \ 955 ASSERT_EQ(ExpectedEdx, test.edx()) << TestString; \ 956 reset(); \ 957 } while (0) 958 959 #define TestImplAddr(Inst, Value0, Value1, Type, Size) \ 960 do { \ 961 static constexpr char TestString[] = \ 962 "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")"; \ 963 static const uint32_t T0 = allocateDword(); \ 964 static constexpr uint32_t V0 = Value1; \ 965 static constexpr Type##64_t OperandEax = \ 966 static_cast<Type##Size##_t>((Value0)&Mask##Size); \ 967 static constexpr Type##64_t OperandOther = \ 968 static_cast<Type##Size##_t>((Value1)&Mask##Size); \ 969 static constexpr uint32_t ExpectedEax = \ 970 Mask##Size & (OperandEax * OperandOther); \ 971 static constexpr uint32_t ExpectedEdx = \ 972 Mask##Size & ((OperandEax * OperandOther) >> Size); \ 973 \ 974 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_eax, \ 975 Immediate((Value0)&Mask##Size)); \ 976 __ Inst(IceType_i##Size, dwordAddress(T0)); \ 977 \ 978 if (Size == 8) { \ 979 /* mov %ah, %dl */ \ 980 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_edx, \ 981 GPRRegister::Encoded_Reg_esp); \ 982 __ And(IceType_i16, GPRRegister::Encoded_Reg_eax, Immediate(0x00FF)); \ 983 } \ 984 \ 985 AssembledTest test = assemble(); \ 986 test.setDwordTo(T0, V0); \ 987 test.run(); \ 988 \ 989 ASSERT_EQ(ExpectedEax, test.eax()) << TestString; \ 990 ASSERT_EQ(ExpectedEdx, test.edx()) << TestString; \ 991 reset(); \ 992 } while (0) 993 994 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size) \ 995 do { \ 996 TestImplReg(Inst, Value0, Src, Value1, Type, Size); \ 997 TestImplAddr(Inst, Value0, Value1, Type, Size); \ 998 } while (0) 999 1000 #define TestImplValue(Value0, Src, Value1, Size) \ 1001 do { \ 1002 TestImplOp(mul, Value0, Src, Value1, uint, Size); \ 1003 TestImplOp(imul, Value0, Src, Value1, int, Size); \ 1004 } while (0) 1005 1006 #define TestImplSize(Src, Size) \ 1007 do { \ 1008 TestImplValue(10, Src, 1, Size); \ 1009 TestImplValue(10, Src, -1, Size); \ 1010 TestImplValue(-10, Src, 37, Size); \ 1011 TestImplValue(-10, Src, -15, Size); \ 1012 } while (0) 1013 1014 #define TestImpl(Src) \ 1015 do { \ 1016 TestImplSize(Src, 8); \ 1017 TestImplSize(Src, 16); \ 1018 TestImplSize(Src, 32); \ 1019 } while (0) 1020 1021 TestImpl(ebx); 1022 TestImpl(ecx); 1023 TestImpl(edx); 1024 TestImpl(esi); 1025 TestImpl(edi); 1026 1027 #undef TestImpl 1028 #undef TestImplSize 1029 #undef TestImplValue 1030 #undef TestImplOp 1031 #undef TestImplAddr 1032 #undef TestImplReg 1033 } 1034 1035 TEST_F(AssemblerX8632Test, TwoOperandImul) { 1036 static constexpr uint32_t Mask16 = 0x0000FFFF; 1037 static constexpr uint32_t Mask32 = 0xFFFFFFFF; 1038 1039 #define TestImplRegReg(Dst, Value0, Src, Value1, Size) \ 1040 do { \ 1041 static constexpr char TestString[] = \ 1042 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Size ")"; \ 1043 static constexpr int64_t Operand0 = \ 1044 static_cast<int##Size##_t>((Value0)&Mask##Size); \ 1045 static constexpr int64_t Operand1 = \ 1046 static_cast<int##Size##_t>((Value1)&Mask##Size); \ 1047 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \ 1048 \ 1049 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1050 Immediate((Value0)&Mask##Size)); \ 1051 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 1052 Immediate((Value1)&Mask##Size)); \ 1053 __ imul(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1054 GPRRegister::Encoded_Reg_##Src); \ 1055 \ 1056 if (Size == 8) { \ 1057 /* mov %ah, %dl */ \ 1058 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_edx, \ 1059 GPRRegister::Encoded_Reg_esp); \ 1060 __ And(IceType_i16, GPRRegister::Encoded_Reg_eax, Immediate(0x00FF)); \ 1061 if (GPRRegister::Encoded_Reg_##Src == GPRRegister::Encoded_Reg_esi) { \ 1062 /* src == dh; clear dx's upper 8 bits. */ \ 1063 __ And(IceType_i16, GPRRegister::Encoded_Reg_edx, Immediate(0x00FF)); \ 1064 } \ 1065 } \ 1066 \ 1067 AssembledTest test = assemble(); \ 1068 test.run(); \ 1069 \ 1070 ASSERT_EQ(Expected, test.Dst()) << TestString; \ 1071 reset(); \ 1072 } while (0) 1073 1074 #define TestImplRegImm(Dst, Value0, Imm, Size) \ 1075 do { \ 1076 static constexpr char TestString[] = \ 1077 "(" #Dst ", " #Value0 ", Imm(" #Imm "), " #Size ")"; \ 1078 static constexpr int64_t Operand0 = \ 1079 static_cast<int##Size##_t>((Value0)&Mask##Size); \ 1080 static constexpr int64_t Operand1 = \ 1081 static_cast<int##Size##_t>((Imm)&Mask##Size); \ 1082 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \ 1083 \ 1084 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1085 Immediate((Value0)&Mask##Size)); \ 1086 __ imul(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, Immediate(Imm)); \ 1087 \ 1088 if (Size == 8) { \ 1089 /* mov %ah, %dl */ \ 1090 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_edx, \ 1091 GPRRegister::Encoded_Reg_esp); \ 1092 __ And(IceType_i16, GPRRegister::Encoded_Reg_eax, Immediate(0x00FF)); \ 1093 } \ 1094 \ 1095 AssembledTest test = assemble(); \ 1096 test.run(); \ 1097 \ 1098 ASSERT_EQ(Expected, test.Dst()) << TestString; \ 1099 reset(); \ 1100 } while (0) 1101 1102 #define TestImplRegAddr(Dst, Value0, Value1, Size) \ 1103 do { \ 1104 static constexpr char TestString[] = \ 1105 "(" #Dst ", " #Value0 ", Addr," #Value1 ", " #Size ")"; \ 1106 static constexpr int64_t Operand0 = \ 1107 static_cast<int##Size##_t>((Value0)&Mask##Size); \ 1108 static constexpr int64_t Operand1 = \ 1109 static_cast<int##Size##_t>((Value1)&Mask##Size); \ 1110 static constexpr uint32_t Expected = Mask##Size & (Operand0 * Operand1); \ 1111 const uint32_t T0 = allocateDword(); \ 1112 \ 1113 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1114 Immediate((Value0)&Mask##Size)); \ 1115 __ imul(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1116 dwordAddress(T0)); \ 1117 \ 1118 if (Size == 8) { \ 1119 /* mov %ah, %dl */ \ 1120 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_edx, \ 1121 GPRRegister::Encoded_Reg_esp); \ 1122 __ And(IceType_i16, GPRRegister::Encoded_Reg_eax, Immediate(0x00FF)); \ 1123 } \ 1124 \ 1125 AssembledTest test = assemble(); \ 1126 test.setDwordTo(T0, static_cast<uint32_t>(Operand1)); \ 1127 test.run(); \ 1128 \ 1129 ASSERT_EQ(Expected, test.Dst()) << TestString; \ 1130 reset(); \ 1131 } while (0) 1132 1133 #define TestImplValue(Dst, Value0, Src, Value1, Size) \ 1134 do { \ 1135 TestImplRegReg(Dst, Value0, Src, Value1, Size); \ 1136 TestImplRegImm(Dst, Value0, Value1, Size); \ 1137 TestImplRegAddr(Dst, Value0, Value1, Size); \ 1138 } while (0) 1139 1140 #define TestImplSize(Dst, Src, Size) \ 1141 do { \ 1142 TestImplValue(Dst, 1, Src, 1, Size); \ 1143 TestImplValue(Dst, -10, Src, 0x4050AA20, Size); \ 1144 TestImplValue(Dst, -2, Src, -55, Size); \ 1145 } while (0) 1146 1147 #define TestImpl(Dst, Src) \ 1148 do { \ 1149 TestImplSize(Dst, Src, 16); \ 1150 TestImplSize(Dst, Src, 32); \ 1151 } while (0) 1152 1153 TestImpl(eax, ebx); 1154 TestImpl(ebx, ecx); 1155 TestImpl(ecx, edx); 1156 TestImpl(edx, esi); 1157 TestImpl(esi, edi); 1158 TestImpl(edi, eax); 1159 1160 #undef TestImpl 1161 #undef TestImplSize 1162 #undef TestImplValue 1163 #undef TestImplRegAddr 1164 #undef TestImplRegImm 1165 #undef TestImplRegReg 1166 } 1167 1168 TEST_F(AssemblerX8632Test, Div) { 1169 static constexpr uint32_t Mask8 = 0x000000FF; 1170 static constexpr uint32_t Mask16 = 0x0000FFFF; 1171 static constexpr uint32_t Mask32 = 0xFFFFFFFF; 1172 1173 static constexpr uint64_t Operand0Mask8 = 0x00000000000000FFull; 1174 static constexpr uint64_t Operand0Mask16 = 0x00000000FFFFFFFFull; 1175 static constexpr uint64_t Operand0Mask32 = 0xFFFFFFFFFFFFFFFFull; 1176 1177 using Operand0Type_int8 = int16_t; 1178 using Operand0Type_uint8 = uint16_t; 1179 using Operand0Type_int16 = int32_t; 1180 using Operand0Type_uint16 = uint32_t; 1181 using Operand0Type_int32 = int64_t; 1182 using Operand0Type_uint32 = uint64_t; 1183 1184 #define TestImplReg(Inst, Value0, Src, Value1, Type, Size) \ 1185 do { \ 1186 static_assert(GPRRegister::Encoded_Reg_eax != \ 1187 GPRRegister::Encoded_Reg_##Src, \ 1188 "eax can not be src1."); \ 1189 static_assert(GPRRegister::Encoded_Reg_edx != \ 1190 GPRRegister::Encoded_Reg_##Src, \ 1191 "edx can not be src1."); \ 1192 \ 1193 static constexpr char TestString[] = \ 1194 "(" #Inst ", " #Value0 ", " #Src ", " #Value1 ", " #Type ", " #Size \ 1195 ")"; \ 1196 static constexpr Operand0Type_##Type##Size Operand0 = \ 1197 static_cast<Type##64_t>(Value0) & Operand0Mask##Size; \ 1198 static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size; \ 1199 static constexpr Type##Size##_t Operand0Hi = \ 1200 (Operand0 >> Size) & Mask##Size; \ 1201 static constexpr Type##Size##_t Operand1 = \ 1202 static_cast<Type##Size##_t>(Value1) & Mask##Size; \ 1203 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_eax, \ 1204 Immediate(Operand0Lo)); \ 1205 if (Size == 8) { \ 1206 /* mov Operand0Hi, %ah */ \ 1207 __ mov(IceType_i8, GPRRegister::Encoded_Reg_esp, Immediate(Operand0Hi)); \ 1208 } else { \ 1209 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_edx, \ 1210 Immediate(Operand0Hi)); \ 1211 } \ 1212 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 1213 Immediate(Operand1)); \ 1214 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Src); \ 1215 if (Size == 8) { \ 1216 /* mov %ah, %dl */ \ 1217 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_edx, \ 1218 GPRRegister::Encoded_Reg_esp); \ 1219 __ And(IceType_i16, GPRRegister::Encoded_Reg_eax, Immediate(0x00FF)); \ 1220 if (GPRRegister::Encoded_Reg_##Src == GPRRegister::Encoded_Reg_esi) { \ 1221 __ And(IceType_i16, GPRRegister::Encoded_Reg_edx, Immediate(0x00FF)); \ 1222 } \ 1223 } \ 1224 \ 1225 AssembledTest test = assemble(); \ 1226 test.run(); \ 1227 \ 1228 static constexpr uint32_t Quocient = (Operand0 / Operand1) & Mask##Size; \ 1229 static constexpr uint32_t Reminder = (Operand0 % Operand1) & Mask##Size; \ 1230 EXPECT_EQ(Quocient, test.eax()) << TestString; \ 1231 EXPECT_EQ(Reminder, test.edx()) << TestString; \ 1232 reset(); \ 1233 } while (0) 1234 1235 #define TestImplAddr(Inst, Value0, Value1, Type, Size) \ 1236 do { \ 1237 static constexpr char TestString[] = \ 1238 "(" #Inst ", " #Value0 ", Addr, " #Value1 ", " #Type ", " #Size ")"; \ 1239 static constexpr Operand0Type_##Type##Size Operand0 = \ 1240 static_cast<Type##64_t>(Value0) & Operand0Mask##Size; \ 1241 static constexpr Type##Size##_t Operand0Lo = Operand0 & Mask##Size; \ 1242 static constexpr Type##Size##_t Operand0Hi = \ 1243 (Operand0 >> Size) & Mask##Size; \ 1244 const uint32_t T0 = allocateDword(); \ 1245 static constexpr Type##Size##_t V0 = \ 1246 static_cast<Type##Size##_t>(Value1) & Mask##Size; \ 1247 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_eax, \ 1248 Immediate(Operand0Lo)); \ 1249 if (Size == 8) { \ 1250 /* mov Operand0Hi, %ah */ \ 1251 __ mov(IceType_i8, GPRRegister::Encoded_Reg_esp, Immediate(Operand0Hi)); \ 1252 } else { \ 1253 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_edx, \ 1254 Immediate(Operand0Hi)); \ 1255 } \ 1256 __ Inst(IceType_i##Size, dwordAddress(T0)); \ 1257 if (Size == 8) { \ 1258 /* mov %ah, %dl */ \ 1259 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_edx, \ 1260 GPRRegister::Encoded_Reg_esp); \ 1261 __ And(IceType_i16, GPRRegister::Encoded_Reg_eax, Immediate(0x00FF)); \ 1262 } \ 1263 \ 1264 AssembledTest test = assemble(); \ 1265 test.setDwordTo(T0, static_cast<uint32_t>(V0)); \ 1266 test.run(); \ 1267 \ 1268 static constexpr uint32_t Quocient = (Operand0 / V0) & Mask##Size; \ 1269 static constexpr uint32_t Reminder = (Operand0 % V0) & Mask##Size; \ 1270 EXPECT_EQ(Quocient, test.eax()) << TestString; \ 1271 EXPECT_EQ(Reminder, test.edx()) << TestString; \ 1272 reset(); \ 1273 } while (0) 1274 1275 #define TestImplOp(Inst, Value0, Src, Value1, Type, Size) \ 1276 do { \ 1277 TestImplReg(Inst, Value0, Src, Value1, Type, Size); \ 1278 TestImplAddr(Inst, Value0, Value1, Type, Size); \ 1279 } while (0) 1280 1281 #define TestImplValue(Value0, Src, Value1, Size) \ 1282 do { \ 1283 TestImplOp(div, Value0, Src, Value1, uint, Size); \ 1284 TestImplOp(idiv, Value0, Src, Value1, int, Size); \ 1285 } while (0) 1286 1287 #define TestImplSize(Src, Size) \ 1288 do { \ 1289 TestImplValue(10, Src, 1, Size); \ 1290 TestImplValue(10, Src, -1, Size); \ 1291 } while (0) 1292 1293 #define TestImpl(Src) \ 1294 do { \ 1295 TestImplSize(Src, 8); \ 1296 TestImplSize(Src, 16); \ 1297 TestImplSize(Src, 32); \ 1298 } while (0) 1299 1300 TestImpl(ebx); 1301 TestImpl(ecx); 1302 TestImpl(esi); 1303 TestImpl(edi); 1304 1305 #undef TestImpl 1306 #undef TestImplSize 1307 #undef TestImplValue 1308 #undef TestImplOp 1309 #undef TestImplAddr 1310 #undef TestImplReg 1311 } 1312 1313 // This is not executable in x86-64 because the one byte inc/dec instructions 1314 // became the REX prefixes. Therefore, these are tested with the low-level test 1315 // infrastructure. 1316 TEST_F(AssemblerX8632LowLevelTest, Incl_Decl_Reg) { 1317 #define TestImpl(Inst, Dst, BaseOpcode) \ 1318 do { \ 1319 __ Inst(GPRRegister::Encoded_Reg_##Dst); \ 1320 static constexpr uint8_t ByteCount = 1; \ 1321 ASSERT_EQ(ByteCount, codeBytesSize()); \ 1322 verifyBytes<ByteCount>(codeBytes(), \ 1323 BaseOpcode | GPRRegister::Encoded_Reg_##Dst); \ 1324 reset(); \ 1325 } while (0) 1326 1327 #define TestInc(Dst) \ 1328 do { \ 1329 constexpr uint8_t InclOpcode = 0x40; \ 1330 TestImpl(incl, Dst, InclOpcode); \ 1331 } while (0) 1332 1333 #define TestDec(Dst) \ 1334 do { \ 1335 constexpr uint8_t DeclOpcode = 0x48; \ 1336 TestImpl(decl, Dst, DeclOpcode); \ 1337 } while (0) 1338 1339 TestInc(eax); 1340 TestInc(ecx); 1341 TestInc(edx); 1342 TestInc(ebx); 1343 TestInc(esp); 1344 TestInc(ebp); 1345 TestInc(esi); 1346 TestInc(esi); 1347 1348 TestDec(eax); 1349 TestDec(ecx); 1350 TestDec(edx); 1351 TestDec(ebx); 1352 TestDec(esp); 1353 TestDec(ebp); 1354 TestDec(esi); 1355 TestDec(esi); 1356 1357 #undef TestInc 1358 #undef TestDec 1359 #undef TestImpl 1360 } 1361 1362 TEST_F(AssemblerX8632Test, Incl_Decl_Addr) { 1363 #define TestImpl(Inst, Value0) \ 1364 do { \ 1365 const bool IsInc = std::string(#Inst).find("incl") != std::string::npos; \ 1366 const uint32_t T0 = allocateDword(); \ 1367 const uint32_t V0 = Value0; \ 1368 \ 1369 __ Inst(dwordAddress(T0)); \ 1370 \ 1371 AssembledTest test = assemble(); \ 1372 test.setDwordTo(T0, V0); \ 1373 test.run(); \ 1374 \ 1375 ASSERT_EQ(static_cast<uint32_t>(Value0 + (IsInc ? 1 : -1)), \ 1376 test.contentsOfDword(T0)); \ 1377 reset(); \ 1378 } while (0) 1379 1380 #define TestInc(Value0) \ 1381 do { \ 1382 TestImpl(incl, Value0); \ 1383 } while (0) 1384 1385 #define TestDec(Value0) \ 1386 do { \ 1387 TestImpl(decl, Value0); \ 1388 } while (0) 1389 1390 TestInc(230); 1391 1392 TestDec(30); 1393 1394 #undef TestInc 1395 #undef TestDec 1396 #undef TestImpl 1397 } 1398 1399 TEST_F(AssemblerX8632Test, Shifts) { 1400 static constexpr uint32_t Mask8 = 0x000000FF; 1401 static constexpr uint32_t Mask16 = 0x0000FFFF; 1402 static constexpr uint32_t Mask32 = 0xFFFFFFFF; 1403 1404 #define TestImplRegImm(Inst, Dst, Value0, Imm, Op, Type, Size) \ 1405 do { \ 1406 static constexpr char TestString[] = \ 1407 "(" #Inst ", " #Dst ", " #Value0 ", Imm(" #Imm "), " #Op ", " #Type \ 1408 ", " #Size ")"; \ 1409 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \ 1410 const uint##Size##_t Expected = \ 1411 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Imm) | \ 1412 (!IsRol ? 0 : (Value0) >> (Size - Imm))); \ 1413 \ 1414 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1415 Immediate((Value0)&Mask##Size)); \ 1416 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1417 Immediate((Imm)&Mask##Size)); \ 1418 \ 1419 AssembledTest test = assemble(); \ 1420 test.run(); \ 1421 \ 1422 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \ 1423 reset(); \ 1424 } while (0) 1425 1426 #define TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, \ 1427 Type, Size) \ 1428 do { \ 1429 static constexpr char TestString[] = \ 1430 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 \ 1431 ", Imm(" #Count "), " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \ 1432 const uint##Size##_t Expected = \ 1433 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \ 1434 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \ 1435 \ 1436 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1437 Immediate((Value0)&Mask##Size)); \ 1438 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 1439 Immediate((Value1)&Mask##Size)); \ 1440 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1441 GPRRegister::Encoded_Reg_##Src, Immediate(Count)); \ 1442 \ 1443 AssembledTest test = assemble(); \ 1444 test.run(); \ 1445 \ 1446 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \ 1447 reset(); \ 1448 } while (0) 1449 1450 #define TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size) \ 1451 do { \ 1452 static constexpr char TestString[] = \ 1453 "(" #Inst ", " #Dst ", " #Value0 ", " #Count ", " #Op ", " #Type \ 1454 ", " #Size ")"; \ 1455 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \ 1456 const uint##Size##_t Expected = \ 1457 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) | \ 1458 (!IsRol ? 0 : Value0 >> (Size - Count))); \ 1459 \ 1460 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1461 Immediate((Value0)&Mask##Size)); \ 1462 __ mov(IceType_i8, GPRRegister::Encoded_Reg_ecx, \ 1463 Immediate((Count)&Mask##Size)); \ 1464 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1465 GPRRegister::Encoded_Reg_ecx); \ 1466 \ 1467 AssembledTest test = assemble(); \ 1468 test.run(); \ 1469 \ 1470 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \ 1471 reset(); \ 1472 } while (0) 1473 1474 #define TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, \ 1475 Type, Size) \ 1476 do { \ 1477 static constexpr char TestString[] = \ 1478 "(" #Inst ", " #Dst ", " #Value0 ", " #Src ", " #Value1 ", " #Count \ 1479 ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \ 1480 const uint##Size##_t Expected = \ 1481 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \ 1482 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \ 1483 \ 1484 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1485 Immediate((Value0)&Mask##Size)); \ 1486 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 1487 Immediate((Value1)&Mask##Size)); \ 1488 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_ecx, \ 1489 Immediate((Count)&0x7F)); \ 1490 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1491 GPRRegister::Encoded_Reg_##Src); \ 1492 \ 1493 AssembledTest test = assemble(); \ 1494 test.run(); \ 1495 \ 1496 ASSERT_EQ(static_cast<uint32_t>(Expected), test.Dst()) << TestString; \ 1497 reset(); \ 1498 } while (0) 1499 1500 #define TestImplAddrCl(Inst, Value0, Count, Op, Type, Size) \ 1501 do { \ 1502 static constexpr char TestString[] = \ 1503 "(" #Inst ", Addr, " #Value0 ", " #Count ", " #Op ", " #Type \ 1504 ", " #Size ")"; \ 1505 const bool IsRol = std::string(#Inst).find("rol") != std::string::npos; \ 1506 const uint##Size##_t Expected = \ 1507 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op(Count) | \ 1508 (!IsRol ? 0 : Value0 >> (Size - Count))); \ 1509 const uint32_t T0 = allocateDword(); \ 1510 const uint32_t V0 = Value0; \ 1511 \ 1512 __ mov(IceType_i8, GPRRegister::Encoded_Reg_ecx, \ 1513 Immediate((Count)&Mask##Size)); \ 1514 __ Inst(IceType_i##Size, dwordAddress(T0), GPRRegister::Encoded_Reg_ecx); \ 1515 \ 1516 AssembledTest test = assemble(); \ 1517 test.setDwordTo(T0, V0); \ 1518 test.run(); \ 1519 \ 1520 ASSERT_EQ(static_cast<uint32_t>(Expected), \ 1521 Mask##Size &test.contentsOfDword(T0)) \ 1522 << TestString; \ 1523 reset(); \ 1524 } while (0) 1525 1526 #define TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, \ 1527 Size) \ 1528 do { \ 1529 static constexpr char TestString[] = \ 1530 "(" #Inst ", Addr, " #Value0 ", " #Src ", " #Value1 ", " #Count \ 1531 ", " #Op0 ", " #Op1 ", " #Type ", " #Size ")"; \ 1532 const uint##Size##_t Expected = \ 1533 Mask##Size & (static_cast<Type##Size##_t>(Value0) Op0(Count) | \ 1534 (static_cast<Type##64_t>(Value1) Op1(Size - Count))); \ 1535 const uint32_t T0 = allocateDword(); \ 1536 \ 1537 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 1538 Immediate((Value1)&Mask##Size)); \ 1539 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_ecx, \ 1540 Immediate((Count)&0x7F)); \ 1541 __ Inst(IceType_i##Size, dwordAddress(T0), \ 1542 GPRRegister::Encoded_Reg_##Src); \ 1543 \ 1544 AssembledTest test = assemble(); \ 1545 test.setDwordTo(T0, static_cast<uint32_t>(Value0)); \ 1546 test.run(); \ 1547 \ 1548 ASSERT_EQ(static_cast<uint32_t>(Expected), test.contentsOfDword(T0)) \ 1549 << TestString; \ 1550 reset(); \ 1551 } while (0) 1552 1553 #define TestImplOp(Inst, Dst, Value0, Count, Op, Type, Size) \ 1554 do { \ 1555 static_assert(GPRRegister::Encoded_Reg_##Dst != \ 1556 GPRRegister::Encoded_Reg_ecx, \ 1557 "ecx should not be specified as Dst"); \ 1558 TestImplRegImm(Inst, Dst, Value0, Count, Op, Type, Size); \ 1559 TestImplRegImm(Inst, ecx, Value0, Count, Op, Type, Size); \ 1560 TestImplRegCl(Inst, Dst, Value0, Count, Op, Type, Size); \ 1561 TestImplAddrCl(Inst, Value0, Count, Op, Type, Size); \ 1562 } while (0) 1563 1564 #define TestImplThreeOperandOp(Inst, Dst, Value0, Src, Value1, Count, Op0, \ 1565 Op1, Type, Size) \ 1566 do { \ 1567 static_assert(GPRRegister::Encoded_Reg_##Dst != \ 1568 GPRRegister::Encoded_Reg_ecx, \ 1569 "ecx should not be specified as Dst"); \ 1570 static_assert(GPRRegister::Encoded_Reg_##Src != \ 1571 GPRRegister::Encoded_Reg_ecx, \ 1572 "ecx should not be specified as Src"); \ 1573 TestImplRegRegImm(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type, \ 1574 Size); \ 1575 TestImplRegRegCl(Inst, Dst, Value0, Src, Value1, Count, Op0, Op1, Type, \ 1576 Size); \ 1577 TestImplAddrRegCl(Inst, Value0, Src, Value1, Count, Op0, Op1, Type, Size); \ 1578 } while (0) 1579 1580 #define TestImplValue(Dst, Value0, Count, Size) \ 1581 do { \ 1582 TestImplOp(rol, Dst, Value0, Count, <<, uint, Size); \ 1583 TestImplOp(shl, Dst, Value0, Count, <<, uint, Size); \ 1584 TestImplOp(shr, Dst, Value0, Count, >>, uint, Size); \ 1585 TestImplOp(sar, Dst, Value0, Count, >>, int, Size); \ 1586 } while (0) 1587 1588 #define TestImplThreeOperandValue(Dst, Value0, Src, Value1, Count, Size) \ 1589 do { \ 1590 TestImplThreeOperandOp(shld, Dst, Value0, Src, Value1, Count, <<, >>, \ 1591 uint, Size); \ 1592 TestImplThreeOperandOp(shrd, Dst, Value0, Src, Value1, Count, >>, <<, \ 1593 uint, Size); \ 1594 } while (0) 1595 1596 #define TestImplSize(Dst, Size) \ 1597 do { \ 1598 TestImplValue(Dst, 0x8F, 3, Size); \ 1599 TestImplValue(Dst, 0x8FFF, 7, Size); \ 1600 TestImplValue(Dst, 0x8FFFF, 7, Size); \ 1601 } while (0) 1602 1603 #define TestImplThreeOperandSize(Dst, Src, Size) \ 1604 do { \ 1605 TestImplThreeOperandValue(Dst, 0xFFF3, Src, 0xA000, 8, Size); \ 1606 } while (0) 1607 1608 #define TestImpl(Dst, Src) \ 1609 do { \ 1610 if (GPRRegister::Encoded_Reg_##Dst < 4) { \ 1611 TestImplSize(Dst, 8); \ 1612 } \ 1613 TestImplSize(Dst, 16); \ 1614 TestImplThreeOperandSize(Dst, Src, 16); \ 1615 TestImplSize(Dst, 32); \ 1616 TestImplThreeOperandSize(Dst, Src, 32); \ 1617 } while (0) 1618 1619 TestImpl(eax, ebx); 1620 TestImpl(ebx, edx); 1621 TestImpl(edx, esi); 1622 TestImpl(esi, edi); 1623 TestImpl(edi, eax); 1624 1625 #undef TestImpl 1626 #undef TestImplThreeOperandSize 1627 #undef TestImplSize 1628 #undef TestImplValue 1629 #undef TestImplThreeOperandValue 1630 #undef TestImplOp 1631 #undef TestImplThreeOperandOp 1632 #undef TestImplAddrCl 1633 #undef TestImplRegRegCl 1634 #undef TestImplRegCl 1635 #undef TestImplRegRegImm 1636 #undef TestImplRegImm 1637 } 1638 1639 TEST_F(AssemblerX8632Test, Neg) { 1640 static constexpr uint32_t Mask8 = 0x000000ff; 1641 static constexpr uint32_t Mask16 = 0x0000ffff; 1642 static constexpr uint32_t Mask32 = 0xffffffff; 1643 1644 #define TestImplReg(Dst, Size) \ 1645 do { \ 1646 static constexpr int32_t Value = 0xFF00A543; \ 1647 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1648 Immediate(static_cast<int##Size##_t>(Value) & Mask##Size)); \ 1649 __ neg(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst); \ 1650 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_eax, \ 1651 GPRRegister::Encoded_Reg_##Dst); \ 1652 __ And(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(Mask##Size)); \ 1653 \ 1654 AssembledTest test = assemble(); \ 1655 test.run(); \ 1656 \ 1657 ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size), \ 1658 test.eax()) \ 1659 << "(" #Dst ", " #Size ")"; \ 1660 reset(); \ 1661 } while (0) 1662 1663 #define TestImplAddr(Size) \ 1664 do { \ 1665 static constexpr int32_t Value = 0xFF00A543; \ 1666 const uint32_t T0 = allocateDword(); \ 1667 __ neg(IceType_i##Size, dwordAddress(T0)); \ 1668 \ 1669 AssembledTest test = assemble(); \ 1670 test.setDwordTo(T0, Value &Mask##Size); \ 1671 test.run(); \ 1672 \ 1673 ASSERT_EQ(1 + (~static_cast<int##Size##_t>(Value) & Mask##Size), \ 1674 test.contentsOfDword(T0)) \ 1675 << "(Addr, " #Size ")"; \ 1676 reset(); \ 1677 } while (0) 1678 1679 #define TestImpl(Size) \ 1680 do { \ 1681 TestImplAddr(Size); \ 1682 TestImplReg(eax, Size); \ 1683 TestImplReg(ebx, Size); \ 1684 TestImplReg(ecx, Size); \ 1685 TestImplReg(edx, Size); \ 1686 TestImplReg(esi, Size); \ 1687 TestImplReg(edi, Size); \ 1688 } while (0) 1689 1690 TestImpl(8); 1691 TestImpl(16); 1692 TestImpl(32); 1693 1694 #undef TestImpl 1695 #undef TestImplAddr 1696 #undef TestImplReg 1697 } 1698 1699 TEST_F(AssemblerX8632Test, Not) { 1700 #define TestImpl(Dst) \ 1701 do { \ 1702 static constexpr uint32_t Value = 0xFF00A543; \ 1703 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dst, Immediate(Value)); \ 1704 __ notl(GPRRegister::Encoded_Reg_##Dst); \ 1705 \ 1706 AssembledTest test = assemble(); \ 1707 test.run(); \ 1708 \ 1709 ASSERT_EQ(~Value, test.Dst()) << "(" #Dst ")"; \ 1710 reset(); \ 1711 } while (0) 1712 1713 TestImpl(eax); 1714 TestImpl(ebx); 1715 TestImpl(ecx); 1716 TestImpl(edx); 1717 TestImpl(esi); 1718 TestImpl(edi); 1719 1720 #undef TestImpl 1721 } 1722 1723 TEST_F(AssemblerX8632Test, Bswap) { 1724 #define TestImpl(Dst) \ 1725 do { \ 1726 static constexpr uint32_t Value = 0xFF00A543; \ 1727 static constexpr uint32_t Expected = 0x43A500FF; \ 1728 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dst, Immediate(Value)); \ 1729 __ bswap(IceType_i32, GPRRegister::Encoded_Reg_##Dst); \ 1730 \ 1731 AssembledTest test = assemble(); \ 1732 test.run(); \ 1733 \ 1734 ASSERT_EQ(Expected, test.Dst()) << "(" #Dst ")"; \ 1735 reset(); \ 1736 } while (0) 1737 1738 TestImpl(eax); 1739 TestImpl(ebx); 1740 TestImpl(ecx); 1741 TestImpl(edx); 1742 TestImpl(esi); 1743 TestImpl(edi); 1744 1745 #undef TestImpl 1746 } 1747 1748 TEST_F(AssemblerX8632Test, Bt) { 1749 #define TestImpl(Dst, Value0, Src, Value1) \ 1750 do { \ 1751 static constexpr char TestString[] = \ 1752 "(" #Dst ", " #Value0 ", " #Src ", " #Value1 ")"; \ 1753 static constexpr uint32_t Expected = ((Value0) & (1u << (Value1))) != 0; \ 1754 \ 1755 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dst, Immediate(Value0)); \ 1756 __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src, Immediate(Value1)); \ 1757 __ bt(GPRRegister::Encoded_Reg_##Dst, GPRRegister::Encoded_Reg_##Src); \ 1758 __ setcc(Cond::Br_b, ByteRegister::Encoded_8_Reg_al); \ 1759 __ And(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xFFu)); \ 1760 \ 1761 AssembledTest test = assemble(); \ 1762 test.run(); \ 1763 \ 1764 ASSERT_EQ(Expected, test.eax()) << TestString; \ 1765 reset(); \ 1766 } while (0) 1767 1768 TestImpl(eax, 0x08000000, ebx, 27u); 1769 TestImpl(ebx, 0x08000000, ecx, 23u); 1770 TestImpl(ecx, 0x00000000, edx, 1u); 1771 TestImpl(edx, 0x08000300, esi, 9u); 1772 TestImpl(esi, 0x08000300, edi, 10u); 1773 TestImpl(edi, 0x7FFFEFFF, eax, 13u); 1774 1775 #undef TestImpl 1776 } 1777 1778 template <uint32_t Value, uint32_t Bits> class BitScanHelper { 1779 BitScanHelper() = delete; 1780 1781 public: 1782 static_assert(Bits == 16 || Bits == 32, "Bits must be 16 or 32"); 1783 using ValueType = 1784 typename std::conditional<Bits == 16, uint16_t, uint32_t>::type; 1785 1786 private: 1787 static constexpr ValueType BitIndex(bool Forward, ValueType Index) { 1788 return (Value == 0) 1789 ? BitScanHelper<Value, Bits>::NoBitSet 1790 : (Value & (1u << Index) 1791 ? Index 1792 : BitIndex(Forward, (Forward ? Index + 1 : Index - 1))); 1793 } 1794 1795 public: 1796 static constexpr ValueType NoBitSet = static_cast<ValueType>(-1); 1797 static constexpr ValueType bsf = BitIndex(/*Forward*/ true, /*Index=*/0); 1798 static constexpr ValueType bsr = 1799 BitIndex(/*Forward*/ false, /*Index=*/Bits - 1); 1800 }; 1801 1802 TEST_F(AssemblerX8632Test, BitScanOperations) { 1803 #define TestImplRegReg(Inst, Dst, Src, Value1, Size) \ 1804 do { \ 1805 static constexpr char TestString[] = \ 1806 "(" #Inst ", " #Dst ", " #Src ", " #Value1 ", " #Size ")"; \ 1807 static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst; \ 1808 const uint32_t ZeroFlag = allocateDword(); \ 1809 __ mov(IceType_i##Size, GPRRegister::Encoded_Reg_##Src, \ 1810 Immediate(Value1)); \ 1811 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1812 GPRRegister::Encoded_Reg_##Src); \ 1813 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \ 1814 \ 1815 AssembledTest test = assemble(); \ 1816 test.setDwordTo(ZeroFlag, 0u); \ 1817 test.run(); \ 1818 \ 1819 ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet), \ 1820 test.contentsOfDword(ZeroFlag)) \ 1821 << TestString; \ 1822 if ((Expected != BitScanHelper<Value1, Size>::NoBitSet)) { \ 1823 ASSERT_EQ(Expected, test.Dst()) << TestString; \ 1824 } \ 1825 reset(); \ 1826 } while (0) 1827 1828 #define TestImplRegAddr(Inst, Dst, Value1, Size) \ 1829 do { \ 1830 static constexpr char TestString[] = \ 1831 "(" #Inst ", " #Dst ", Addr, " #Value1 ", " #Size ")"; \ 1832 static constexpr uint32_t Expected = BitScanHelper<Value1, Size>::Inst; \ 1833 const uint32_t T0 = allocateDword(); \ 1834 const uint32_t ZeroFlag = allocateDword(); \ 1835 __ Inst(IceType_i##Size, GPRRegister::Encoded_Reg_##Dst, \ 1836 dwordAddress(T0)); \ 1837 __ setcc(Cond::Br_e, dwordAddress(ZeroFlag)); \ 1838 \ 1839 AssembledTest test = assemble(); \ 1840 test.setDwordTo(T0, Value1); \ 1841 test.setDwordTo(ZeroFlag, 0u); \ 1842 test.run(); \ 1843 \ 1844 ASSERT_EQ((Expected == BitScanHelper<Value1, Size>::NoBitSet), \ 1845 test.contentsOfDword(ZeroFlag)) \ 1846 << TestString; \ 1847 if (Expected != BitScanHelper<Value1, Size>::NoBitSet) { \ 1848 ASSERT_EQ(Expected, test.Dst()) << TestString; \ 1849 } \ 1850 reset(); \ 1851 } while (0) 1852 1853 #define TestImplSize(Dst, Src, Value1, Size) \ 1854 do { \ 1855 TestImplRegReg(bsf, Dst, Src, Value1, Size); \ 1856 TestImplRegAddr(bsf, Dst, Value1, Size); \ 1857 TestImplRegReg(bsr, Dst, Src, Value1, Size); \ 1858 TestImplRegAddr(bsf, Dst, Value1, Size); \ 1859 } while (0) 1860 1861 #define TestImplValue(Dst, Src, Value1) \ 1862 do { \ 1863 TestImplSize(Dst, Src, Value1, 16); \ 1864 TestImplSize(Dst, Src, Value1, 32); \ 1865 } while (0) 1866 1867 #define TestImpl(Dst, Src) \ 1868 do { \ 1869 TestImplValue(Dst, Src, 0x80000001); \ 1870 TestImplValue(Dst, Src, 0x00000000); \ 1871 TestImplValue(Dst, Src, 0x80001000); \ 1872 TestImplValue(Dst, Src, 0x00FFFF00); \ 1873 } while (0) 1874 1875 TestImpl(eax, ebx); 1876 TestImpl(ebx, ecx); 1877 TestImpl(ecx, edx); 1878 TestImpl(edx, esi); 1879 TestImpl(esi, edi); 1880 TestImpl(edi, eax); 1881 1882 #undef TestImpl 1883 #undef TestImplValue 1884 #undef TestImplSize 1885 #undef TestImplRegAddr 1886 #undef TestImplRegReg 1887 } 1888 1889 } // end of anonymous namespace 1890 } // end of namespace Test 1891 } // end of namespace X8632 1892 } // end of namespace Ice 1893