diff --git a/src/app/test/testx86.cpp b/src/app/test/testx86.cpp index ff5c06b..034fdb9 100644 --- a/src/app/test/testx86.cpp +++ b/src/app/test/testx86.cpp @@ -231,14 +231,14 @@ struct X86Test_JumpCross : public X86Test { }; // ============================================================================ -// [X86Test_JumpUnreachable] +// [X86Test_JumpUnreachable1] // ============================================================================ -struct X86Test_JumpUnreachable : public X86Test { - X86Test_JumpUnreachable() : X86Test("[Jump] Unreachable code") {} +struct X86Test_JumpUnreachable1 : public X86Test { + X86Test_JumpUnreachable1() : X86Test("[Jump] Unreachable #1") {} static void add(PodVector& tests) { - tests.append(new X86Test_JumpUnreachable()); + tests.append(new X86Test_JumpUnreachable1()); } virtual void compile(Compiler& c) { @@ -291,6 +291,52 @@ struct X86Test_JumpUnreachable : public X86Test { } }; +// ============================================================================ +// [X86Test_JumpUnreachable2] +// ============================================================================ + +struct X86Test_JumpUnreachable2 : public X86Test { + X86Test_JumpUnreachable2() : X86Test("[Jump] Unreachable #2") {} + + static void add(PodVector& tests) { + tests.append(new X86Test_JumpUnreachable2()); + } + + virtual void compile(Compiler& c) { + c.addFunc(kFuncConvHost, FuncBuilder0()); + + Label L_1(c); + Label L_2(c); + + GpVar v0(c, kVarTypeUInt32, "v0"); + GpVar v1(c, kVarTypeUInt32, "v1"); + + c.jmp(L_1); + c.bind(L_2); + c.mov(v0, 1); + c.mov(v1, 2); + c.cmp(v0, v1); + c.jz(L_2); + c.jmp(L_1); + + c.bind(L_1); + c.ret(); + c.endFunc(); + } + + virtual bool run(void* _func, StringBuilder& result, StringBuilder& expect) { + typedef void (*Func)(void); + Func func = asmjit_cast(_func); + + func(); + + result.appendString("ret={}"); + expect.appendString("ret={}"); + + return true; + } +}; + // ============================================================================ // [X86Test_AllocBase] // ============================================================================ @@ -2331,7 +2377,8 @@ X86TestSuite::X86TestSuite() : // Jump. ADD_TEST(X86Test_JumpCross); - ADD_TEST(X86Test_JumpUnreachable); + ADD_TEST(X86Test_JumpUnreachable1); + ADD_TEST(X86Test_JumpUnreachable2); // Alloc. ADD_TEST(X86Test_AllocBase); diff --git a/src/asmjit/base/context.cpp b/src/asmjit/base/context.cpp index c0f620d..fc2a42e 100644 --- a/src/asmjit/base/context.cpp +++ b/src/asmjit/base/context.cpp @@ -270,11 +270,11 @@ Error BaseContext::removeUnreachableCode() { while (link != NULL) { BaseNode* node = link->getValue(); - if (node != NULL) { + if (node != NULL && node->getPrev() != NULL) { // Locate all unreachable nodes. BaseNode* first = node; do { - if (node->isFetched() || (node->getType() == kNodeTypeTarget && static_cast(node)->getNumRefs() > 0)) + if (node->isFetched()) break; node = node->getNext(); } while (node != stop); diff --git a/src/asmjit/x86/x86assembler.cpp b/src/asmjit/x86/x86assembler.cpp index 363307e..9ce86b9 100644 --- a/src/asmjit/x86/x86assembler.cpp +++ b/src/asmjit/x86/x86assembler.cpp @@ -2021,9 +2021,20 @@ _GroupPop_Gp: opReg = static_cast(o1)->getRegIndex(); rmReg = static_cast(o0)->getRegIndex(); - // Special opcode for AX/EAX/RAX. - if (o0->getSize() > 1 && (opReg == 0 || rmReg == 0)) { - opCode = 0x90 + opReg + rmReg; // One of them is zero. + // Special opcode for 'xchg ?ax, reg'. + if (code == kInstXchg && o0->getSize() > 1 && (opReg == 0 || rmReg == 0)) { + // One of them is zero, it doesn't matter if the instruction's form is + // 'xchg ?ax, reg' or 'xchg reg, ?ax'. + opReg += rmReg; + + // Rex.B (0x01). + if (Arch == kArchX64) { + opX += opReg >> 3; + opReg &= 0x7; + } + + opCode = 0x90 + opReg; + ADD_66H_P(o0->getSize() == 2); ADD_REX_W(o0->getSize() == 8); goto _EmitX86Op;