/* sample of move(reg, LABEL);, L(LABEL), putL(LABEL); */ #include #define XBYAK_NO_OP_NAMES #include const int expectTbl[] = { 5, 9, 12 }; struct Code : Xbyak::CodeGenerator { explicit Code(int mode, size_t size, void *p) : Xbyak::CodeGenerator(size, p) { inLocalLabel(); #ifdef XBYAK64 const Xbyak::Reg64& a = rax; const Xbyak::Reg64& c = rcx; #ifdef XBYAK64_WIN mov(rax, rcx); #else mov(rax, rdi); #endif #else const Xbyak::Reg32& a = eax; const Xbyak::Reg32& c = ecx; mov(a, ptr [esp + 4]); #endif switch (mode) { case 0: mov(c, ".jmp_table"); lea(c, ptr [c + a * 8]); jmp(c); align(8); L(".jmp_table"); mov(a, expectTbl[0]); ret(); align(8); mov(a, expectTbl[1]); ret(); align(8); mov(a, expectTbl[2]); ret(); break; case 1: /* the label for putL is defined when called */ mov(c, ".jmp_table"); jmp(ptr [c + a * (int)sizeof(size_t)]); L(".label1"); mov(a, expectTbl[0]); jmp(".end"); L(".label2"); mov(a, expectTbl[1]); jmp(".end"); L(".label3"); mov(a, expectTbl[2]); jmp(".end"); L(".end"); ret(); ud2(); align(8); L(".jmp_table"); putL(".label1"); putL(".label2"); putL(".label3"); break; case 2: /* the label for putL is not defined when called */ jmp(".in"); ud2(); align(8); L(".jmp_table"); putL(".label1"); putL(".label2"); putL(".label3"); L(".in"); mov(c, ".jmp_table"); jmp(ptr [c + a * (int)sizeof(size_t)]); L(".label1"); mov(a, expectTbl[0]); jmp(".end"); L(".label2"); mov(a, expectTbl[1]); jmp(".end"); L(".label3"); mov(a, expectTbl[2]); jmp(".end"); L(".end"); ret(); break; } outLocalLabel(); } }; int main() try { for (int mode = 0; mode < 3; mode++) { printf("mode=%d\n", mode); for (int grow = 0; grow < 2; grow++) { printf("auto grow=%s\n", grow ? "on" : "off"); Code c(mode, grow ? 30 : 4096, grow ? Xbyak::AutoGrow : 0); int (*f)(int) = c.getCode(); c.ready(); for (int i = 0; i < 3; i++) { const int a = expectTbl[i]; const int b = f(i); if (a != b) { printf("ERR i=%d, a=%d, b=%d\n", i, a, b); exit(1); } } } } puts("ok"); } catch (std::exception& e) { printf("ERR %s\n", e.what()); }