| //===- subzero/unittest/AssemblerX8632/ControleFlow.cpp -------------------===// |
| // |
| // The Subzero Code Generator |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| #include "IceAssemblerX8632.h" |
| #include "AssemblerX8632/TestUtil.h" |
| |
| namespace Ice { |
| namespace X8632 { |
| namespace Test { |
| namespace { |
| |
| TEST_F(AssemblerX8632Test, J) { |
| #define TestJ(C, Near, Src0, Value0, Src1, Value1, Dest) \ |
| do { \ |
| const bool NearJmp = AssemblerX8632::k##Near##Jump; \ |
| Label ShouldBeTaken; \ |
| __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src0, Immediate(Value0)); \ |
| __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Src1, Immediate(Value1)); \ |
| __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(0xBEEF)); \ |
| __ cmp(IceType_i32, GPRRegister::Encoded_Reg_##Src0, \ |
| GPRRegister::Encoded_Reg_##Src1); \ |
| __ j(Cond::Br_##C, &ShouldBeTaken, NearJmp); \ |
| __ mov(IceType_i32, GPRRegister::Encoded_Reg_##Dest, Immediate(0xC0FFEE)); \ |
| __ bind(&ShouldBeTaken); \ |
| AssembledTest test = assemble(); \ |
| test.run(); \ |
| EXPECT_EQ(Value0, test.Src0()) << "Br_" #C ", " #Near; \ |
| EXPECT_EQ(Value1, test.Src1()) << "Br_" #C ", " #Near; \ |
| EXPECT_EQ(0xBEEFul, test.Dest()) << "Br_" #C ", " #Near; \ |
| reset(); \ |
| } while (0) |
| |
| TestJ(o, Near, eax, 0x80000000ul, ebx, 0x1ul, ecx); |
| TestJ(o, Far, ebx, 0x80000000ul, ecx, 0x1ul, edx); |
| TestJ(no, Near, ecx, 0x1ul, edx, 0x1ul, edi); |
| TestJ(no, Far, edx, 0x1ul, edi, 0x1ul, esi); |
| TestJ(b, Near, edi, 0x1ul, esi, 0x80000000ul, eax); |
| TestJ(b, Far, esi, 0x1ul, eax, 0x80000000ul, ebx); |
| TestJ(ae, Near, eax, 0x80000000ul, ebx, 0x1ul, ecx); |
| TestJ(ae, Far, ebx, 0x80000000ul, ecx, 0x1ul, edx); |
| TestJ(e, Near, ecx, 0x80000000ul, edx, 0x80000000ul, edi); |
| TestJ(e, Far, edx, 0x80000000ul, edi, 0x80000000ul, esi); |
| TestJ(ne, Near, edi, 0x80000000ul, esi, 0x1ul, eax); |
| TestJ(ne, Far, esi, 0x80000000ul, eax, 0x1ul, ebx); |
| TestJ(be, Near, eax, 0x1ul, ebx, 0x80000000ul, ecx); |
| TestJ(be, Far, ebx, 0x1ul, ecx, 0x80000000ul, edx); |
| TestJ(a, Near, ecx, 0x80000000ul, edx, 0x1ul, edi); |
| TestJ(a, Far, edx, 0x80000000ul, edi, 0x1ul, esi); |
| TestJ(s, Near, edi, 0x1ul, esi, 0x80000000ul, eax); |
| TestJ(s, Far, esi, 0x1ul, eax, 0x80000000ul, ebx); |
| TestJ(ns, Near, eax, 0x80000000ul, ebx, 0x1ul, ecx); |
| TestJ(ns, Far, ebx, 0x80000000ul, ecx, 0x1ul, edx); |
| TestJ(p, Near, ecx, 0x80000000ul, edx, 0x1ul, edi); |
| TestJ(p, Far, edx, 0x80000000ul, edi, 0x1ul, esi); |
| TestJ(np, Near, edi, 0x1ul, esi, 0x80000000ul, eax); |
| TestJ(np, Far, esi, 0x1ul, eax, 0x80000000ul, ebx); |
| TestJ(l, Near, eax, 0x80000000ul, ebx, 0x1ul, ecx); |
| TestJ(l, Far, ebx, 0x80000000ul, ecx, 0x1ul, edx); |
| TestJ(ge, Near, ecx, 0x1ul, edx, 0x80000000ul, edi); |
| TestJ(ge, Far, edx, 0x1ul, edi, 0x80000000ul, esi); |
| TestJ(le, Near, edi, 0x80000000ul, esi, 0x1ul, eax); |
| TestJ(le, Far, esi, 0x80000000ul, eax, 0x1ul, ebx); |
| TestJ(g, Near, eax, 0x1ul, ebx, 0x80000000ul, ecx); |
| TestJ(g, Far, ebx, 0x1ul, ecx, 0x80000000ul, edx); |
| |
| #undef TestJ |
| } |
| |
| TEST_F(AssemblerX8632Test, CallImm) { |
| __ call(Immediate(16)); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xf00f)); |
| __ popl(GPRRegister::Encoded_Reg_ebx); |
| |
| AssembledTest test = assemble(); |
| |
| test.run(); |
| |
| EXPECT_EQ(0xF00Fu, test.eax()); |
| } |
| |
| TEST_F(AssemblerX8632Test, CallReg) { |
| __ call(Immediate(16)); |
| __ popl(GPRRegister::Encoded_Reg_edx); |
| __ pushl(GPRRegister::Encoded_Reg_edx); |
| __ ret(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ popl(GPRRegister::Encoded_Reg_ebx); |
| __ call(GPRRegister::Encoded_Reg_ebx); |
| |
| AssembledTest test = assemble(); |
| |
| test.run(); |
| |
| EXPECT_EQ(15u, test.edx() - test.ebx()); |
| } |
| |
| TEST_F(AssemblerX8632Test, CallAddr) { |
| __ call(Immediate(16)); |
| __ mov(IceType_i8, GPRRegister::Encoded_Reg_eax, Immediate(0xf4)); |
| __ ret(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ hlt(); |
| __ mov(IceType_i32, GPRRegister::Encoded_Reg_eax, Immediate(0xf1f2f300)); |
| __ call(Address(GPRRegister::Encoded_Reg_esp, 0, AssemblerFixup::NoFixup)); |
| __ popl(GPRRegister::Encoded_Reg_edx); |
| |
| AssembledTest test = assemble(); |
| |
| test.run(); |
| |
| EXPECT_EQ(0xf1f2f3f4, test.eax()); |
| } |
| |
| TEST_F(AssemblerX8632Test, Jmp) { |
| // TestImplReg uses jmp(Label), so jmp(Label) needs to be tested before it. |
| #define TestImplAddr(Near) \ |
| do { \ |
| Label ForwardJmp; \ |
| Label BackwardJmp; \ |
| Label Done; \ |
| \ |
| __ jmp(&ForwardJmp, AssemblerX8632::k##Near##Jump); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ bind(&BackwardJmp); \ |
| __ jmp(&Done, AssemblerX8632::k##Near##Jump); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ bind(&ForwardJmp); \ |
| __ jmp(&BackwardJmp, AssemblerX8632::k##NearJump); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ bind(&Done); \ |
| } while (0) |
| |
| #define TestImplReg(Dst) \ |
| do { \ |
| __ call(Immediate(16)); \ |
| Label Done; \ |
| __ jmp(&Done, AssemblerX8632::kNearJump); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ popl(GPRRegister::Encoded_Reg_##Dst); \ |
| __ jmp(GPRRegister::Encoded_Reg_##Dst); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ hlt(); \ |
| __ bind(&Done); \ |
| \ |
| AssembledTest test = assemble(); \ |
| test.run(); \ |
| \ |
| reset(); \ |
| } while (0) |
| |
| TestImplAddr(Near); |
| TestImplAddr(Far); |
| |
| TestImplReg(eax); |
| TestImplReg(ebx); |
| TestImplReg(ecx); |
| TestImplReg(edx); |
| TestImplReg(esi); |
| TestImplReg(edi); |
| |
| #undef TestImplReg |
| #undef TestImplAddr |
| } |
| |
| } // end of anonymous namespace |
| } // end of namespace Test |
| } // end of namespace X8632 |
| } // end of namespace Ice |