| OLD | NEW |
| (Empty) | |
| 1 //===- subzero/unittest/AssemblerX8664/ControlFlow.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, J) { |
| 17 #define TestJ(C, Near, Dest, Src0, Value0, Src1, Value1) \ |
| 18 do { \ |
| 19 static constexpr char TestString[] = \ |
| 20 "(" #C ", " #Near ", " #Dest ", " #Src0 ", " #Value0 ", " #Src1 \ |
| 21 ", " #Value1 ")"; \ |
| 22 const bool NearJmp = AssemblerX8664::k##Near##Jump; \ |
| 23 Label ShouldBeTaken; \ |
| 24 __ mov(IceType_i32, Encoded_GPR_##Src0(), Immediate(Value0)); \ |
| 25 __ mov(IceType_i32, Encoded_GPR_##Src1(), Immediate(Value1)); \ |
| 26 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(0xBEEF)); \ |
| 27 __ cmp(IceType_i32, Encoded_GPR_##Src0(), Encoded_GPR_##Src1()); \ |
| 28 __ j(Cond::Br_##C, &ShouldBeTaken, NearJmp); \ |
| 29 __ mov(IceType_i32, Encoded_GPR_##Dest(), Immediate(0xC0FFEE)); \ |
| 30 __ bind(&ShouldBeTaken); \ |
| 31 AssembledTest test = assemble(); \ |
| 32 test.run(); \ |
| 33 ASSERT_EQ(Value0, test.Src0()) << TestString; \ |
| 34 ASSERT_EQ(Value1, test.Src1()) << TestString; \ |
| 35 ASSERT_EQ(0xBEEFul, test.Dest()) << TestString; \ |
| 36 reset(); \ |
| 37 } while (0) |
| 38 |
| 39 #define TestImpl(Dst, Src0, Src1) \ |
| 40 do { \ |
| 41 TestJ(o, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 42 TestJ(o, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 43 TestJ(no, Near, Dst, Src0, 0x1ul, Src1, 0x1ul); \ |
| 44 TestJ(no, Far, Dst, Src0, 0x1ul, Src1, 0x1ul); \ |
| 45 TestJ(b, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 46 TestJ(b, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 47 TestJ(ae, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 48 TestJ(ae, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 49 TestJ(e, Near, Dst, Src0, 0x80000000ul, Src1, 0x80000000ul); \ |
| 50 TestJ(e, Far, Dst, Src0, 0x80000000ul, Src1, 0x80000000ul); \ |
| 51 TestJ(ne, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 52 TestJ(ne, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 53 TestJ(be, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 54 TestJ(be, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 55 TestJ(a, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 56 TestJ(a, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 57 TestJ(s, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 58 TestJ(s, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 59 TestJ(ns, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 60 TestJ(ns, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 61 TestJ(p, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 62 TestJ(p, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 63 TestJ(np, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 64 TestJ(np, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 65 TestJ(l, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 66 TestJ(l, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 67 TestJ(ge, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 68 TestJ(ge, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 69 TestJ(le, Near, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 70 TestJ(le, Far, Dst, Src0, 0x80000000ul, Src1, 0x1ul); \ |
| 71 TestJ(g, Near, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 72 TestJ(g, Far, Dst, Src0, 0x1ul, Src1, 0x80000000ul); \ |
| 73 } while (0) |
| 74 |
| 75 TestImpl(r1, r2, r3); |
| 76 TestImpl(r2, r3, r4); |
| 77 TestImpl(r3, r4, r5); |
| 78 TestImpl(r4, r5, r6); |
| 79 TestImpl(r5, r6, r7); |
| 80 TestImpl(r6, r7, r8); |
| 81 TestImpl(r7, r8, r10); |
| 82 TestImpl(r8, r10, r11); |
| 83 TestImpl(r10, r11, r12); |
| 84 TestImpl(r11, r12, r13); |
| 85 TestImpl(r12, r13, r14); |
| 86 TestImpl(r13, r14, r15); |
| 87 TestImpl(r14, r15, r1); |
| 88 TestImpl(r15, r1, r2); |
| 89 |
| 90 #undef TestImpl |
| 91 #undef TestJ |
| 92 } |
| 93 |
| 94 TEST_F(AssemblerX8664Test, CallImm) { |
| 95 __ call(Immediate(16)); |
| 96 __ hlt(); |
| 97 __ hlt(); |
| 98 __ hlt(); |
| 99 __ hlt(); |
| 100 __ hlt(); |
| 101 __ hlt(); |
| 102 __ hlt(); |
| 103 __ hlt(); |
| 104 __ hlt(); |
| 105 __ hlt(); |
| 106 __ hlt(); |
| 107 __ hlt(); |
| 108 __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xf00f)); |
| 109 __ popl(GPRRegister::Encoded_Reg_ebx); |
| 110 |
| 111 AssembledTest test = assemble(); |
| 112 |
| 113 test.run(); |
| 114 |
| 115 EXPECT_EQ(0xF00Fu, test.eax()); |
| 116 } |
| 117 |
| 118 TEST_F(AssemblerX8664Test, CallReg) { |
| 119 #define TestImpl(Dst, Src) \ |
| 120 do { \ |
| 121 __ call(Immediate(16)); \ |
| 122 int CallTargetAddr = codeBytesSize() + 12; \ |
| 123 __ popl(Encoded_GPR_##Dst()); \ |
| 124 __ pushl(Encoded_GPR_##Dst()); \ |
| 125 __ ret(); \ |
| 126 for (int I = codeBytesSize(); I < CallTargetAddr; ++I) { \ |
| 127 __ hlt(); \ |
| 128 } \ |
| 129 __ popl(Encoded_GPR_##Src()); \ |
| 130 __ call(Encoded_GPR_##Src()); \ |
| 131 \ |
| 132 AssembledTest test = assemble(); \ |
| 133 \ |
| 134 test.run(); \ |
| 135 \ |
| 136 ASSERT_LE(15u, test.Dst() - test.Src()) << "(" #Dst ", " #Src ")"; \ |
| 137 reset(); \ |
| 138 } while (0) |
| 139 |
| 140 TestImpl(r1, r2); |
| 141 TestImpl(r2, r3); |
| 142 TestImpl(r3, r4); |
| 143 TestImpl(r4, r5); |
| 144 TestImpl(r5, r6); |
| 145 TestImpl(r6, r7); |
| 146 TestImpl(r7, r8); |
| 147 TestImpl(r8, r10); |
| 148 TestImpl(r10, r11); |
| 149 TestImpl(r11, r12); |
| 150 TestImpl(r12, r13); |
| 151 TestImpl(r13, r14); |
| 152 TestImpl(r14, r15); |
| 153 TestImpl(r15, r1); |
| 154 |
| 155 #undef TestImpl |
| 156 } |
| 157 |
| 158 TEST_F(AssemblerX8664Test, CallAddr) { |
| 159 #define TestImpl(Dst, Src) \ |
| 160 do { \ |
| 161 const uint32_t T0 = allocateQword(); \ |
| 162 const uint64_t V0 = 0xA0C0FFEEBEEFFEEFull; \ |
| 163 __ call(Immediate(16)); \ |
| 164 int CallTargetAddr = codeBytesSize() + 12; \ |
| 165 __ mov(IceType_i8, Encoded_GPR_##Dst##l(), Immediate(0xf4)); \ |
| 166 __ ret(); \ |
| 167 for (int I = codeBytesSize(); I < CallTargetAddr; ++I) { \ |
| 168 __ hlt(); \ |
| 169 } \ |
| 170 __ mov(IceType_i64, Encoded_GPR_##Dst##q(), dwordAddress(T0)); \ |
| 171 __ mov(IceType_i64, Encoded_GPR_##Src##q(), Encoded_GPR_rsp()); \ |
| 172 __ call(Address(Encoded_GPR_##Src##q(), 0)); \ |
| 173 __ popl(Encoded_GPR_##Src##q()); \ |
| 174 \ |
| 175 AssembledTest test = assemble(); \ |
| 176 test.setQwordTo(T0, V0); \ |
| 177 test.run(); \ |
| 178 \ |
| 179 ASSERT_EQ(0xA0C0FFEEBEEFFEF4ull, test.Dst##q()) << "(" #Dst ", " #Src ")"; \ |
| 180 reset(); \ |
| 181 } while (0) |
| 182 |
| 183 TestImpl(r1, r2); |
| 184 TestImpl(r2, r3); |
| 185 TestImpl(r3, r4); |
| 186 TestImpl(r4, r5); |
| 187 TestImpl(r5, r6); |
| 188 TestImpl(r6, r7); |
| 189 TestImpl(r7, r8); |
| 190 TestImpl(r8, r10); |
| 191 TestImpl(r10, r11); |
| 192 TestImpl(r11, r12); |
| 193 TestImpl(r12, r13); |
| 194 TestImpl(r13, r14); |
| 195 TestImpl(r14, r15); |
| 196 TestImpl(r15, r1); |
| 197 |
| 198 #undef TestImpl |
| 199 } |
| 200 |
| 201 TEST_F(AssemblerX8664Test, Jmp) { |
| 202 // TestImplReg uses jmp(Label), so jmp(Label) needs to be tested before it. |
| 203 #define TestImplAddr(Near) \ |
| 204 do { \ |
| 205 Label ForwardJmp; \ |
| 206 Label BackwardJmp; \ |
| 207 Label Done; \ |
| 208 \ |
| 209 __ jmp(&ForwardJmp, AssemblerX8664::k##Near##Jump); \ |
| 210 __ hlt(); \ |
| 211 __ hlt(); \ |
| 212 __ hlt(); \ |
| 213 __ hlt(); \ |
| 214 __ hlt(); \ |
| 215 __ hlt(); \ |
| 216 __ hlt(); \ |
| 217 __ hlt(); \ |
| 218 __ hlt(); \ |
| 219 __ hlt(); \ |
| 220 __ bind(&BackwardJmp); \ |
| 221 __ jmp(&Done, AssemblerX8664::k##Near##Jump); \ |
| 222 __ hlt(); \ |
| 223 __ hlt(); \ |
| 224 __ hlt(); \ |
| 225 __ hlt(); \ |
| 226 __ hlt(); \ |
| 227 __ hlt(); \ |
| 228 __ hlt(); \ |
| 229 __ hlt(); \ |
| 230 __ hlt(); \ |
| 231 __ hlt(); \ |
| 232 __ bind(&ForwardJmp); \ |
| 233 __ jmp(&BackwardJmp, AssemblerX8664::k##NearJump); \ |
| 234 __ hlt(); \ |
| 235 __ hlt(); \ |
| 236 __ hlt(); \ |
| 237 __ hlt(); \ |
| 238 __ hlt(); \ |
| 239 __ hlt(); \ |
| 240 __ hlt(); \ |
| 241 __ hlt(); \ |
| 242 __ hlt(); \ |
| 243 __ hlt(); \ |
| 244 __ bind(&Done); \ |
| 245 } while (0) |
| 246 |
| 247 #define TestImplReg(Dst) \ |
| 248 do { \ |
| 249 __ call(Immediate(16)); \ |
| 250 Label Done; \ |
| 251 __ jmp(&Done, AssemblerX8664::kNearJump); \ |
| 252 __ hlt(); \ |
| 253 __ hlt(); \ |
| 254 __ hlt(); \ |
| 255 __ hlt(); \ |
| 256 __ hlt(); \ |
| 257 __ hlt(); \ |
| 258 __ hlt(); \ |
| 259 __ hlt(); \ |
| 260 __ hlt(); \ |
| 261 __ hlt(); \ |
| 262 __ popl(Encoded_GPR_##Dst()); \ |
| 263 __ jmp(Encoded_GPR_##Dst()); \ |
| 264 __ hlt(); \ |
| 265 __ hlt(); \ |
| 266 __ hlt(); \ |
| 267 __ hlt(); \ |
| 268 __ hlt(); \ |
| 269 __ hlt(); \ |
| 270 __ hlt(); \ |
| 271 __ hlt(); \ |
| 272 __ hlt(); \ |
| 273 __ hlt(); \ |
| 274 __ bind(&Done); \ |
| 275 \ |
| 276 AssembledTest test = assemble(); \ |
| 277 test.run(); \ |
| 278 \ |
| 279 reset(); \ |
| 280 } while (0) |
| 281 |
| 282 TestImplAddr(Near); |
| 283 TestImplAddr(Far); |
| 284 |
| 285 TestImplReg(r1); |
| 286 TestImplReg(r2); |
| 287 TestImplReg(r3); |
| 288 TestImplReg(r4); |
| 289 TestImplReg(r5); |
| 290 TestImplReg(r6); |
| 291 TestImplReg(r7); |
| 292 TestImplReg(r8); |
| 293 TestImplReg(r10); |
| 294 TestImplReg(r11); |
| 295 TestImplReg(r12); |
| 296 TestImplReg(r13); |
| 297 TestImplReg(r14); |
| 298 TestImplReg(r15); |
| 299 |
| 300 #undef TestImplReg |
| 301 #undef TestImplAddr |
| 302 } |
| 303 |
| 304 } // end of anonymous namespace |
| 305 } // end of namespace Test |
| 306 } // end of namespace X8664 |
| 307 } // end of namespace Ice |
| OLD | NEW |