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