aboutsummaryrefslogtreecommitdiffhomepage
path: root/sample/jmp_table.cpp
blob: fb47cac735fdcfe2bd35392de572e981764962d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
	sample of move(reg, LABEL);, L(LABEL), putL(LABEL);
*/
#include <stdio.h>
#define XBYAK_NO_OP_NAMES
#include <xbyak/xbyak.h>

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<int (*)(int)>();
			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());
}