//===- 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