diff --git a/gen/gen_code.cpp b/gen/gen_code.cpp index fa6618d..348f828 100644 --- a/gen/gen_code.cpp +++ b/gen/gen_code.cpp @@ -49,6 +49,7 @@ std::string type2String(int type) void put_jREGz(const char *reg, bool prefix) { printf("void j%sz(const std::string& label) { %sopJmp(label, T_SHORT, 0xe3, 0, 0); }\n", reg, prefix ? "db(0x67); " : ""); + printf("void j%sz(Label& label) { %sopJmp(label, T_SHORT, 0xe3, 0, 0); }\n", reg, prefix ? "db(0x67); " : ""); } void put() diff --git a/test/jmp.cpp b/test/jmp.cpp index cca4139..c5ab4b8 100644 --- a/test/jmp.cpp +++ b/test/jmp.cpp @@ -16,59 +16,76 @@ void putNop(Xbyak::CodeGenerator *gen, int n) gen->nop(); } } -struct TestJmp : public Xbyak::CodeGenerator { -/* - 4 X0: - 5 00000004 EBFE jmp short X0 - 6 - 7 X1: - 8 00000006 dummyX1 resb 1 - 9 00000007 EBFD jmp short X1 - 10 - 11 X126: - 12 00000009 dummyX126 resb 126 - 13 00000087 EB80 jmp short X126 - 14 - 15 X127: - 16 00000089 dummyX127 resb 127 - 17 00000108 E97CFFFFFF jmp near X127 - 18 - 19 0000010D EB00 jmp short Y0 - 20 Y0: - 21 - 22 0000010F EB01 jmp short Y1 - 23 00000111 dummyY1 resb 1 - 24 Y1: - 25 - 26 00000112 EB7F jmp short Y127 - 27 00000114 dummyY127 resb 127 - 28 Y127: - 29 - 30 00000193 E980000000 jmp near Y128 - 31 00000198 dummyY128 resb 128 - 32 Y128: -*/ - TestJmp(int offset, bool isBack, bool isShort) - { - if (isBack) { - L("@@"); - putNop(this, offset); - jmp("@b"); - } else { - if (isShort) { - jmp("@f"); - } else { - jmp("@f", T_NEAR); - } - putNop(this, offset); - L("@@"); - } - } -}; void test1() { puts("test1"); + struct TestJmp : public Xbyak::CodeGenerator { + /* + 4 X0: + 5 00000004 EBFE jmp short X0 + 6 + 7 X1: + 8 00000006 dummyX1 resb 1 + 9 00000007 EBFD jmp short X1 + 10 + 11 X126: + 12 00000009 dummyX126 resb 126 + 13 00000087 EB80 jmp short X126 + 14 + 15 X127: + 16 00000089 dummyX127 resb 127 + 17 00000108 E97CFFFFFF jmp near X127 + 18 + 19 0000010D EB00 jmp short Y0 + 20 Y0: + 21 + 22 0000010F EB01 jmp short Y1 + 23 00000111 dummyY1 resb 1 + 24 Y1: + 25 + 26 00000112 EB7F jmp short Y127 + 27 00000114 dummyY127 resb 127 + 28 Y127: + 29 + 30 00000193 E980000000 jmp near Y128 + 31 00000198 dummyY128 resb 128 + 32 Y128: + */ + TestJmp(int offset, bool isBack, bool isShort, bool useNewLabel) + { + if (useNewLabel) { + Label label; + if (isBack) { + L(label); + putNop(this, offset); + jmp(label); + } else { + if (isShort) { + jmp(label); + } else { + jmp(label, T_NEAR); + } + putNop(this, offset); + L(label); + } + } else { + if (isBack) { + L("@@"); + putNop(this, offset); + jmp("@b"); + } else { + if (isShort) { + jmp("@f"); + } else { + jmp("@f", T_NEAR); + } + putNop(this, offset); + L("@@"); + } + } + } + }; static const struct Tbl { int offset; bool isBack; @@ -87,91 +104,70 @@ void test1() }; for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) { const Tbl *p = &tbl[i]; - TestJmp jmp(p->offset, p->isBack, p->isShort); - const uint8 *q = (const uint8*)jmp.getCode(); - if (p->isBack) q += p->offset; /* skip nop */ - for (int j = 0; j < p->size; j++) { - if (q[j] != p->result[j]) { - printf("err (%d,%d) %02x assume=%02x\n", (int)i, j, q[j], p->result[j]); + for (int k = 0; k < 2; k++) { + TestJmp jmp(p->offset, p->isBack, p->isShort, k == 0); + const uint8 *q = (const uint8*)jmp.getCode(); + if (p->isBack) q += p->offset; /* skip nop */ + for (int j = 0; j < p->size; j++) { + if (q[j] != p->result[j]) { + printf("err (%d, %d, %d) %02x assume=%02x\n", (int)i, k, j, q[j], p->result[j]); + } } } } } -struct TestJmp2 : public CodeGenerator { -/* - 1 00000000 90 nop - 2 00000001 90 nop - 3 f1: - 4 00000002 dummyX1 resb 126 - 6 00000080 EB80 jmp f1 - 7 - 8 f2: - 9 00000082 dummyX2 resb 127 - 11 00000101 E97CFFFFFF jmp f2 - 12 - 13 - 14 00000106 EB7F jmp f3 - 15 00000108 dummyX3 resb 127 - 17 f3: - 18 - 19 00000187 E980000000 jmp f4 - 20 0000018C dummyX4 resb 128 - 22 f4: -*/ - explicit TestJmp2(void *p) - : Xbyak::CodeGenerator(8192, p) - { - inLocalLabel(); - nop(); - nop(); - L(".f1"); - putNop(this, 126); - jmp(".f1"); - L(".f2"); - putNop(this, 127); - jmp(".f2", T_NEAR); - - jmp(".f3"); - putNop(this, 127); - L(".f3"); - jmp(".f4", T_NEAR); - putNop(this, 128); - L(".f4"); - outLocalLabel(); - } -}; - -struct TestJmpCx : public CodeGenerator { - explicit TestJmpCx(void *p) - : Xbyak::CodeGenerator(16, p) - { - inLocalLabel(); - L(".lp"); -#ifdef XBYAK64 - puts("TestJmpCx 64bit"); - /* - 67 E3 FD ; jecxz lp - E3 FB ; jrcxz lp - */ - jecxz(".lp"); - jrcxz(".lp"); -#else - puts("TestJmpCx 32bit"); - /* - E3FE ; jecxz lp - 67E3FB ; jcxz lp - */ - jecxz(".lp"); - jcxz(".lp"); -#endif - outLocalLabel(); - } -}; - void testJmpCx() { puts("testJmpCx"); + struct TestJmpCx : public CodeGenerator { + explicit TestJmpCx(void *p, bool useNewLabel) + : Xbyak::CodeGenerator(16, p) + { + if (useNewLabel) { + Label lp; + L(lp); +#ifdef XBYAK64 + puts("TestJmpCx 64bit"); + /* + 67 E3 FD ; jecxz lp + E3 FB ; jrcxz lp + */ + jecxz(lp); + jrcxz(lp); +#else + puts("TestJmpCx 32bit"); + /* + E3FE ; jecxz lp + 67E3FB ; jcxz lp + */ + jecxz(lp); + jcxz(lp); +#endif + } else { + inLocalLabel(); + L(".lp"); +#ifdef XBYAK64 + puts("TestJmpCx 64bit"); + /* + 67 E3 FD ; jecxz lp + E3 FB ; jrcxz lp + */ + jecxz(".lp"); + jrcxz(".lp"); +#else + puts("TestJmpCx 32bit"); + /* + E3FE ; jecxz lp + 67E3FB ; jcxz lp + */ + jecxz(".lp"); + jcxz(".lp"); +#endif + outLocalLabel(); + } + } + }; const struct { const char *p; size_t len; @@ -182,15 +178,17 @@ void testJmpCx() "\xe3\xfe\x67\xe3\xfb", 5 #endif }; - char buf[16] = {}; - TestJmpCx code(buf); - if (memcmp(buf, tbl.p, tbl.len) == 0) { - } else { - puts("ng"); - for (int i = 0; i < 8; i++) { - printf("%02x ", (unsigned char)buf[i]); + for (int j = 0; j < 2; j++) { + char buf[16] = {}; + TestJmpCx code(buf, j == 0); + if (memcmp(buf, tbl.p, tbl.len) == 0) { + } else { + printf("err %d\n", j); + for (int i = 0; i < 8; i++) { + printf("%02x ", (unsigned char)buf[i]); + } + printf("\n"); } - printf("\n"); } } @@ -200,6 +198,50 @@ void testJmpCx() void test2() { puts("test2"); + struct TestJmp2 : public CodeGenerator { + /* + 1 00000000 90 nop + 2 00000001 90 nop + 3 f1: + 4 00000002 dummyX1 resb 126 + 6 00000080 EB80 jmp f1 + 7 + 8 f2: + 9 00000082 dummyX2 resb 127 + 11 00000101 E97CFFFFFF jmp f2 + 12 + 13 + 14 00000106 EB7F jmp f3 + 15 00000108 dummyX3 resb 127 + 17 f3: + 18 + 19 00000187 E980000000 jmp f4 + 20 0000018C dummyX4 resb 128 + 22 f4: + */ + explicit TestJmp2(void *p) + : Xbyak::CodeGenerator(8192, p) + { + inLocalLabel(); + nop(); + nop(); + L(".f1"); + putNop(this, 126); + jmp(".f1"); + L(".f2"); + putNop(this, 127); + jmp(".f2", T_NEAR); + + jmp(".f3"); + putNop(this, 127); + L(".f3"); + jmp(".f4", T_NEAR); + putNop(this, 128); + L(".f4"); + outLocalLabel(); + } + }; + std::string ok; ok.resize(0x18C + 128, (char)0x90); ok[0x080] = (char)0xeb; @@ -241,27 +283,26 @@ void test2() int add5(int x) { return x + 5; } int add2(int x) { return x + 2; } -struct Grow : Xbyak::CodeGenerator { - Grow(int dummySize) - : Xbyak::CodeGenerator(128, Xbyak::AutoGrow) - { - mov(eax, 100); - push(eax); - call((void*)add5); - add(esp, 4); - push(eax); - call((void*)add2); - add(esp, 4); - ret(); - for (int i = 0; i < dummySize; i++) { - db(0); - } - } -}; - void test3() { puts("test3"); + struct Grow : Xbyak::CodeGenerator { + Grow(int dummySize) + : Xbyak::CodeGenerator(128, Xbyak::AutoGrow) + { + mov(eax, 100); + push(eax); + call((void*)add5); + add(esp, 4); + push(eax); + call((void*)add2); + add(esp, 4); + ret(); + for (int i = 0; i < dummySize; i++) { + db(0); + } + } + }; for (int dummySize = 0; dummySize < 40000; dummySize += 10000) { printf("dummySize=%d\n", dummySize); Grow g(dummySize); @@ -327,24 +368,24 @@ void diff(const std::string& a, const std::string& b) } } -struct Test4 : Xbyak::CodeGenerator { - explicit Test4(int size, void *mode) - : CodeGenerator(size, mode) - { - using namespace Xbyak; - inLocalLabel(); - outLocalLabel(); - jmp(".x"); - for (int i = 0; i < 10; i++) { - nop(); - } - L(".x"); - ret(); - } -}; void test4() { puts("test4"); + struct Test4 : Xbyak::CodeGenerator { + explicit Test4(int size, void *mode) + : CodeGenerator(size, mode) + { + using namespace Xbyak; + inLocalLabel(); + outLocalLabel(); + jmp(".x"); + for (int i = 0; i < 10; i++) { + nop(); + } + L(".x"); + ret(); + } + }; std::string fm, gm; Test4 fc(1024, 0); Test4 gc(5, Xbyak::AutoGrow); @@ -356,41 +397,40 @@ void test4() diff(gm, gm); } -struct Test5 : Xbyak::CodeGenerator { - explicit Test5(int size, int count, void *mode) - : CodeGenerator(size, mode, &myAlloc) - { - using namespace Xbyak; - inLocalLabel(); - mov(ecx, count); - xor(eax, eax); - L(".lp"); - for (int i = 0; i < count; i++) { - L(Label::toStr(i)); - add(eax, 1); - int to = 0; - if (i < count / 2) { - to = count - 1 - i; - } else { - to = count - i; - } - if (i == count / 2) { - jmp(".exit", T_NEAR); - } else { - jmp(Label::toStr(to), T_NEAR); - } - } - L(".exit"); - sub(ecx, 1); - jnz(".lp", T_NEAR); - ret(); - outLocalLabel(); - } -}; - void test5() { puts("test5"); + struct Test5 : Xbyak::CodeGenerator { + explicit Test5(int size, int count, void *mode) + : CodeGenerator(size, mode, &myAlloc) + { + using namespace Xbyak; + inLocalLabel(); + mov(ecx, count); + xor(eax, eax); + L(".lp"); + for (int i = 0; i < count; i++) { + L(Label::toStr(i)); + add(eax, 1); + int to = 0; + if (i < count / 2) { + to = count - 1 - i; + } else { + to = count - i; + } + if (i == count / 2) { + jmp(".exit", T_NEAR); + } else { + jmp(Label::toStr(to), T_NEAR); + } + } + L(".exit"); + sub(ecx, 1); + jnz(".lp", T_NEAR); + ret(); + outLocalLabel(); + } + }; std::string fm, gm; const int count = 50; int ret; @@ -509,111 +549,110 @@ void testMovLabel(bool grow) #endif } -struct MovLabel2Code : Xbyak::CodeGenerator { - MovLabel2Code() - { -#ifdef XBYAK64 - const Reg64& a = rax; - const Reg64& c = rcx; -#else - const Reg32& a = eax; - const Reg32& c = ecx; -#endif - xor(a, a); - xor(c, c); - jmp("in"); - ud2(); - L("@@"); // L1 - add(a, 2); - mov(c, "@f"); - jmp(c); // goto L2 - ud2(); - L("in"); - mov(c, "@b"); - add(a, 1); - jmp(c); // goto L1 - ud2(); - L("@@"); // L2 - add(a, 4); - ret(); - } -}; - void testMovLabel2() { puts("tsetMovLabel2"); + struct MovLabel2Code : Xbyak::CodeGenerator { + MovLabel2Code() + { + #ifdef XBYAK64 + const Reg64& a = rax; + const Reg64& c = rcx; + #else + const Reg32& a = eax; + const Reg32& c = ecx; + #endif + xor(a, a); + xor(c, c); + jmp("in"); + ud2(); + L("@@"); // L1 + add(a, 2); + mov(c, "@f"); + jmp(c); // goto L2 + ud2(); + L("in"); + mov(c, "@b"); + add(a, 1); + jmp(c); // goto L1 + ud2(); + L("@@"); // L2 + add(a, 4); + ret(); + } + }; MovLabel2Code code; int ret = code.getCode()(); if (ret != 7) printf("ERR=%d\n", ret); } -struct TestLocal : public Xbyak::CodeGenerator { - TestLocal(bool grow) - : Xbyak::CodeGenerator(grow ? 128 : 4096, grow ? Xbyak::AutoGrow : 0) - { - xor_(eax, eax); - inLocalLabel(); - jmp("start0", T_NEAR); - L(".back"); - inc(eax); // 8 - jmp(".next", T_NEAR); - L("start2"); - inc(eax); // 7 - jmp(".back", T_NEAR); +void test6() +{ + struct TestLocal : public Xbyak::CodeGenerator { + TestLocal(bool grow) + : Xbyak::CodeGenerator(grow ? 128 : 4096, grow ? Xbyak::AutoGrow : 0) + { + xor_(eax, eax); inLocalLabel(); + jmp("start0", T_NEAR); L(".back"); - inc(eax); // 5 - putNop(this, 128); + inc(eax); // 8 jmp(".next", T_NEAR); - L("start1"); - inc(eax); // 4 + L("start2"); + inc(eax); // 7 jmp(".back", T_NEAR); inLocalLabel(); L(".back"); - inc(eax); // 2 + inc(eax); // 5 + putNop(this, 128); jmp(".next", T_NEAR); - L("start0"); - inc(eax); // 1 + L("start1"); + inc(eax); // 4 jmp(".back", T_NEAR); + inLocalLabel(); + L(".back"); + inc(eax); // 2 + jmp(".next", T_NEAR); + L("start0"); + inc(eax); // 1 + jmp(".back", T_NEAR); + L(".next"); + inc(eax); // 3 + jmp("start1", T_NEAR); + outLocalLabel(); L(".next"); - inc(eax); // 3 - jmp("start1", T_NEAR); + inc(eax); // 6 + jmp("start2", T_NEAR); outLocalLabel(); L(".next"); - inc(eax); // 6 - jmp("start2", T_NEAR); + inc(eax); // 9 + jmp("start3", T_NEAR); + inLocalLabel(); + L(".back"); + inc(eax); // 14 + jmp("exit", T_NEAR); + L("start4"); + inc(eax); // 13 + jmp(".back", T_NEAR); + outLocalLabel(); + L("start3"); + inc(eax); // 10 + inLocalLabel(); + jmp(".next", T_NEAR); + L(".back"); + inc(eax); // 12 + jmp("start4", T_NEAR); + L(".next"); + inc(eax); // 11 + jmp(".back", T_NEAR); + outLocalLabel(); outLocalLabel(); - L(".next"); - inc(eax); // 9 - jmp("start3", T_NEAR); - inLocalLabel(); - L(".back"); - inc(eax); // 14 - jmp("exit", T_NEAR); - L("start4"); - inc(eax); // 13 - jmp(".back", T_NEAR); - outLocalLabel(); - L("start3"); - inc(eax); // 10 - inLocalLabel(); - jmp(".next", T_NEAR); - L(".back"); - inc(eax); // 12 - jmp("start4", T_NEAR); - L(".next"); - inc(eax); // 11 - jmp(".back", T_NEAR); - outLocalLabel(); - outLocalLabel(); - L("exit"); - inc(eax); // 15 - ret(); - } -}; + L("exit"); + inc(eax); // 15 + ret(); + } + }; -void test6() -{ for (int i = 0; i < 2; i++) { const bool grow = i == 1; printf("test6 grow=%d\n", i); @@ -695,7 +734,6 @@ void testNewLabel() int main() try { -#if 0 test1(); test2(); #ifdef ONLY_32BIT @@ -708,7 +746,6 @@ try { testMovLabel(false); testMovLabel(true); testMovLabel2(); -#endif testNewLabel(); } catch (std::exception& e) { printf("ERR:%s\n", e.what()); diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h index b1bd482..a511ef2 100644 --- a/xbyak/xbyak_mnemonic.h +++ b/xbyak/xbyak_mnemonic.h @@ -304,10 +304,14 @@ void jg(Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, void setg(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 15); } #ifdef XBYAK32 void jcxz(const std::string& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jcxz(Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } void jecxz(const std::string& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jecxz(Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } #else void jecxz(const std::string& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jecxz(Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } void jrcxz(const std::string& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jrcxz(Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } #endif #ifdef XBYAK64 void cdqe() { db(0x48); db(0x98); }