Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
jmp.cpp
Go to the documentation of this file.
1#include <stdio.h>
2#include <string.h>
3#include <string>
4#define XBYAK_NO_OP_NAMES
5#include <xbyak/xbyak.h>
6#include <cybozu/inttype.hpp>
7#include <cybozu/test.hpp>
8
9using namespace Xbyak;
10
12{
13 for (int i = 0; i < n; i++) {
14 gen->nop();
15 }
16}
17
18void diff(const std::string& a, const std::string& b)
19{
20 if (a == b) return;
21 if (a.size() != b.size()) printf("size diff %d %d\n", (int)a.size(), (int)b.size());
22 for (size_t i = 0; i < (std::min)(a.size(), b.size()); i++) {
23 if (a[i] != b[i]) {
24 printf("diff %d(%04x) %02x %02x\n", (int)i, (int)i, (unsigned char)a[i], (unsigned char)b[i]);
25 }
26 }
27}
28
29void dump(const std::string& m)
30{
31 printf("size=%d\n ", (int)m.size());
32 for (int i = 0; i < 16; i++) {
33 printf("%02x ", i);
34 }
35 printf("\n ");
36 for (int i = 0; i < 16; i++) {
37 printf("---");
38 }
39 printf("\n");
40 for (size_t i = 0; i < m.size(); i++) {
41 if ((i % 16) == 0) printf("%04x ", (int)(i / 16));
42 printf("%02x ", (unsigned char)m[i]);
43 if ((i % 16) == 15) putchar('\n');
44 }
45 putchar('\n');
46}
47
49{
50 struct TestJmp : public Xbyak::CodeGenerator {
51 /*
52 4 X0:
53 5 00000004 EBFE jmp short X0
54 6
55 7 X1:
56 8 00000006 <res 00000001> dummyX1 resb 1
57 9 00000007 EBFD jmp short X1
58 10
59 11 X126:
60 12 00000009 <res 0000007E> dummyX126 resb 126
61 13 00000087 EB80 jmp short X126
62 14
63 15 X127:
64 16 00000089 <res 0000007F> dummyX127 resb 127
65 17 00000108 E97CFFFFFF jmp near X127
66 18
67 19 0000010D EB00 jmp short Y0
68 20 Y0:
69 21
70 22 0000010F EB01 jmp short Y1
71 23 00000111 <res 00000001> dummyY1 resb 1
72 24 Y1:
73 25
74 26 00000112 EB7F jmp short Y127
75 27 00000114 <res 0000007F> dummyY127 resb 127
76 28 Y127:
77 29
78 30 00000193 E980000000 jmp near Y128
79 31 00000198 <res 00000080> dummyY128 resb 128
80 32 Y128:
81 */
82 TestJmp(int offset, bool isBack, bool isShort, bool useNewLabel)
83 {
84 if (useNewLabel) {
86 if (isBack) {
87 L(label);
88 putNop(this, offset);
89 jmp(label);
90 } else {
91 if (isShort) {
92 jmp(label);
93 } else {
94 jmp(label, T_NEAR);
95 }
96 putNop(this, offset);
97 L(label);
98 }
99 } else {
100 if (isBack) {
101 L("@@");
102 putNop(this, offset);
103 jmp("@b");
104 } else {
105 if (isShort) {
106 jmp("@f");
107 } else {
108 jmp("@f", T_NEAR);
109 }
110 putNop(this, offset);
111 L("@@");
112 }
113 }
114 }
115 };
116 static const struct Tbl {
117 int offset;
118 bool isBack;
119 bool isShort;
120 uint8 result[6];
121 int size;
122 } tbl[] = {
123 { 0, true, true, { 0xeb, 0xfe }, 2 },
124 { 1, true, true, { 0xeb, 0xfd }, 2 },
125 { 126, true, true, { 0xeb, 0x80 }, 2 },
126 { 127, true, false, {0xe9, 0x7c, 0xff, 0xff, 0xff }, 5 },
127 { 0, false, true, { 0xeb, 0x00 }, 2 },
128 { 1, false, true, { 0xeb, 0x01 }, 2 },
129 { 127, false, true, { 0xeb, 0x7f }, 2 },
130 { 128, false, false, { 0xe9, 0x80, 0x00, 0x00, 0x00 }, 5 },
131 };
132 for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
133 const Tbl *p = &tbl[i];
134 for (int k = 0; k < 2; k++) {
135 TestJmp jmp(p->offset, p->isBack, p->isShort, k == 0);
136 const uint8 *q = (const uint8*)jmp.getCode();
137 if (p->isBack) q += p->offset; /* skip nop */
138 for (int j = 0; j < p->size; j++) {
139 CYBOZU_TEST_EQUAL(q[j], p->result[j]);
140 }
141 }
142 }
143}
144
146{
147 struct TestJmpCx : public CodeGenerator {
148 explicit TestJmpCx(void *p, bool useNewLabel)
150 {
151 if (useNewLabel) {
152 Label lp;
153 L(lp);
154#ifdef XBYAK64
155 /*
156 67 E3 FD ; jecxz lp
157 E3 FB ; jrcxz lp
158 */
159 jecxz(lp);
160 jrcxz(lp);
161#else
162 /*
163 E3FE ; jecxz lp
164 67E3FB ; jcxz lp
165 */
166 jecxz(lp);
167 jcxz(lp);
168#endif
169 } else {
170 inLocalLabel();
171 L(".lp");
172#ifdef XBYAK64
173 /*
174 67 E3 FD ; jecxz lp
175 E3 FB ; jrcxz lp
176 */
177 jecxz(".lp");
178 jrcxz(".lp");
179#else
180 /*
181 E3FE ; jecxz lp
182 67E3FB ; jcxz lp
183 */
184 jecxz(".lp");
185 jcxz(".lp");
186#endif
188 }
189 }
190 };
191 const struct {
192 const char *p;
193 size_t len;
194 } tbl = {
195#ifdef XBYAK64
196 "\x67\xe3\xfd\xe3\xfb", 5
197#else
198 "\xe3\xfe\x67\xe3\xfb", 5
199#endif
200 };
201 for (int j = 0; j < 2; j++) {
202 char buf[16] = {};
203 TestJmpCx code(buf, j == 0);
204 CYBOZU_TEST_EQUAL(memcmp(buf, tbl.p, tbl.len), 0);
205 }
206}
207
208#ifdef _MSC_VER
209 #pragma warning(disable : 4310)
210#endif
212{
213 struct TestJmp2 : public CodeGenerator {
214 /*
215 1 00000000 90 nop
216 2 00000001 90 nop
217 3 f1:
218 4 00000002 <res 0000007E> dummyX1 resb 126
219 6 00000080 EB80 jmp f1
220 7
221 8 f2:
222 9 00000082 <res 0000007F> dummyX2 resb 127
223 11 00000101 E97CFFFFFF jmp f2
224 12
225 13
226 14 00000106 EB7F jmp f3
227 15 00000108 <res 0000007F> dummyX3 resb 127
228 17 f3:
229 18
230 19 00000187 E980000000 jmp f4
231 20 0000018C <res 00000080> dummyX4 resb 128
232 22 f4:
233 */
234 TestJmp2(void *p, bool useNewLabel)
235 : Xbyak::CodeGenerator(8192, p)
236 {
237 if (useNewLabel) {
238 inLocalLabel();
239 nop();
240 nop();
241 L(".f1");
242 putNop(this, 126);
243 jmp(".f1");
244 L(".f2");
245 putNop(this, 127);
246 jmp(".f2", T_NEAR);
247
248 jmp(".f3");
249 putNop(this, 127);
250 L(".f3");
251 jmp(".f4", T_NEAR);
252 putNop(this, 128);
253 L(".f4");
255 } else {
256 nop();
257 nop();
258 Label f1, f2, f3, f4;
259 L(f1);
260 putNop(this, 126);
261 jmp(f1);
262 L(f2);
263 putNop(this, 127);
264 jmp(f2, T_NEAR);
265
266 jmp(f3);
267 putNop(this, 127);
268 L(f3);
269 jmp(f4, T_NEAR);
270 putNop(this, 128);
271 L(f4);
272 }
273 }
274 };
275
276 std::string ok;
277 ok.resize(0x18C + 128, (char)0x90);
278 ok[0x080] = (char)0xeb;
279 ok[0x081] = (char)0x80;
280
281 ok[0x101] = (char)0xe9;
282 ok[0x102] = (char)0x7c;
283 ok[0x103] = (char)0xff;
284 ok[0x104] = (char)0xff;
285 ok[0x105] = (char)0xff;
286
287 ok[0x106] = (char)0xeb;
288 ok[0x107] = (char)0x7f;
289
290 ok[0x187] = (char)0xe9;
291 ok[0x188] = (char)0x80;
292 ok[0x189] = (char)0x00;
293 ok[0x18a] = (char)0x00;
294 ok[0x18b] = (char)0x00;
295 for (int i = 0; i < 2; i++) {
296 for (int j = 0; j < 2; j++) {
297 TestJmp2 c(i == 0 ? 0 : Xbyak::AutoGrow, j == 0);
298 c.ready();
299 std::string m((const char*)c.getCode(), c.getSize());
300 CYBOZU_TEST_EQUAL(m, ok);
301 }
302 }
303}
304
305#ifdef XBYAK32
306int add5(int x) { return x + 5; }
307int add2(int x) { return x + 2; }
308
310{
311 struct Grow : Xbyak::CodeGenerator {
312 Grow(int dummySize)
314 {
315 mov(eax, 100);
316 push(eax);
317 call((void*)add5);
318 add(esp, 4);
319 push(eax);
320 call((void*)add2);
321 add(esp, 4);
322 ret();
323 for (int i = 0; i < dummySize; i++) {
324 db(0);
325 }
326 }
327 };
328 for (int dummySize = 0; dummySize < 40000; dummySize += 10000) {
329 printf("dummySize=%d\n", dummySize);
330 Grow g(dummySize);
331 g.ready();
332 int (*f)() = (int (*)())g.getCode();
333 int x = f();
334 const int ok = 107;
335 CYBOZU_TEST_EQUAL(x, ok);
336 }
337}
338#endif
339
340Xbyak::uint8 bufL[4096 * 32];
341Xbyak::uint8 bufS[4096 * 2];
342
344 Xbyak::uint8 *alloc(size_t size)
345 {
346 if (size < sizeof(bufS)) {
347 printf("test use bufS(%d)\n", (int)size);
348 return bufS;
349 }
350 if (size < sizeof(bufL)) {
351 printf("test use bufL(%d)\n", (int)size);
352 return bufL;
353 }
354 fprintf(stderr, "no memory %d\n", (int)size);
355 exit(1);
356 }
357 void free(Xbyak::uint8 *)
358 {
359 }
361
363{
364 struct Test4 : Xbyak::CodeGenerator {
365 Test4(int size, void *mode, bool useNewLabel)
366 : CodeGenerator(size, mode)
367 {
368 if (useNewLabel) {
369 Label x;
370 jmp(x);
371 putNop(this, 10);
372 L(x);
373 ret();
374 } else {
375 inLocalLabel();
376 jmp(".x");
377 putNop(this, 10);
378 L(".x");
379 ret();
381 }
382 }
383 };
384 for (int i = 0; i < 2; i++) {
385 const bool useNewLabel = i == 0;
386 std::string fm, gm;
387 Test4 fc(1024, 0, useNewLabel);
388 Test4 gc(5, Xbyak::AutoGrow, !useNewLabel);
389 gc.ready();
390 fm.assign((const char*)fc.getCode(), fc.getSize());
391 gm.assign((const char*)gc.getCode(), gc.getSize());
392 CYBOZU_TEST_EQUAL(fm, gm);
393 }
394}
395
397{
398 struct Test5 : Xbyak::CodeGenerator {
399 explicit Test5(int size, int count, void *mode)
400 : CodeGenerator(size, mode, &myAlloc)
401 {
402 using namespace Xbyak;
403 inLocalLabel();
404 mov(ecx, count);
405 xor_(eax, eax);
406 L(".lp");
407 for (int i = 0; i < count; i++) {
408 L(Label::toStr(i));
409 add(eax, 1);
410 int to = 0;
411 if (i < count / 2) {
412 to = count - 1 - i;
413 } else {
414 to = count - i;
415 }
416 if (i == count / 2) {
417 jmp(".exit", T_NEAR);
418 } else {
419 jmp(Label::toStr(to), T_NEAR);
420 }
421 }
422 L(".exit");
423 sub(ecx, 1);
424 jnz(".lp", T_NEAR);
425 ret();
427 }
428 };
429 std::string fm, gm;
430 const int count = 50;
431 int ret;
432 Test5 fc(1024 * 64, count, 0);
433 ret = ((int (*)())fc.getCode())();
435 fm.assign((const char*)fc.getCode(), fc.getSize());
436 Test5 gc(10, count, Xbyak::AutoGrow);
437 gc.ready();
438 ret = ((int (*)())gc.getCode())();
440 gm.assign((const char*)gc.getCode(), gc.getSize());
441 CYBOZU_TEST_EQUAL(fm, gm);
442}
443
444size_t getValue(const uint8* p)
445{
446 size_t v = 0;
447 for (size_t i = 0; i < sizeof(size_t); i++) {
448 v |= size_t(p[i]) << (i * 8);
449 }
450 return v;
451}
452
453void checkAddr(const uint8 *p, size_t offset, size_t expect)
454{
455 size_t v = getValue(p + offset);
456 CYBOZU_TEST_EQUAL(v, size_t(p) + expect);
457}
458
460{
461 struct MovLabelCode : Xbyak::CodeGenerator {
462 MovLabelCode(bool grow, bool useNewLabel)
463 : Xbyak::CodeGenerator(grow ? 128 : 4096, grow ? Xbyak::AutoGrow : 0)
464 {
465#ifdef XBYAK64
466 const Reg64& a = rax;
467#else
468 const Reg32& a = eax;
469#endif
470 if (useNewLabel) {
471 nop(); // 0x90
472 Label lp1, lp2;
473 L(lp1);
474 nop();
475 mov(a, lp1); // 0xb8 + <4byte> / 0x48bb + <8byte>
476 nop();
477 mov(a, lp2); // 0xb8
478 // force realloc if AutoGrow
479 putNop(this, 256);
480 nop();
481 L(lp2);
482 } else {
483 inLocalLabel();
484 nop(); // 0x90
485 L(".lp1");
486 nop();
487 mov(a, ".lp1"); // 0xb8 + <4byte> / 0x48bb + <8byte>
488 nop();
489 mov(a, ".lp2"); // 0xb8
490 // force realloc if AutoGrow
491 putNop(this, 256);
492 nop();
493 L(".lp2");
495 }
496 }
497 };
498
499 const struct {
500 int pos;
501 uint8 ok;
502 } tbl[] = {
503#ifdef XBYAK32
504 { 0x00, 0x90 },
505 // lp1:0x001
506 { 0x001, 0x90 },
507 { 0x002, 0xb8 },
508 // 0x003
509 { 0x007, 0x90 },
510 { 0x008, 0xb8 },
511 // 0x009
512 { 0x10d, 0x90 },
513 // lp2:0x10e
514#else
515 { 0x000, 0x90 },
516 // lp1:0x001
517 { 0x001, 0x90 },
518 { 0x002, 0x48 },
519 { 0x003, 0xb8 },
520 // 0x004
521 { 0x00c, 0x90 },
522 { 0x00d, 0x48 },
523 { 0x00e, 0xb8 },
524 // 0x00f
525 { 0x117, 0x90 },
526 // lp2:0x118
527#endif
528 };
529 for (int j = 0; j < 2; j++) {
530 const bool grow = j == 0;
531 for (int k = 0; k < 2; k++) {
532 const bool useNewLabel = k == 0;
533 MovLabelCode code(grow, useNewLabel);
534 if (grow) code.ready();
535 const uint8* const p = code.getCode();
536 for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
537 int pos = tbl[i].pos;
538 uint8 x = p[pos];
539 uint8 ok = tbl[i].ok;
540 CYBOZU_TEST_EQUAL(x, ok);
541 }
542#ifdef XBYAK32
543 checkAddr(p, 0x03, 0x001);
544 checkAddr(p, 0x09, 0x10e);
545#else
546 checkAddr(p, 0x04, 0x001);
547 checkAddr(p, 0x0f, 0x118);
548#endif
549 }
550 }
551}
552
553CYBOZU_TEST_AUTO(testMovLabel2)
554{
555 struct MovLabel2Code : Xbyak::CodeGenerator {
556 MovLabel2Code()
557 {
558#ifdef XBYAK64
559 const Reg64& a = rax;
560 const Reg64& c = rcx;
561#else
562 const Reg32& a = eax;
563 const Reg32& c = ecx;
564#endif
565 xor_(a, a);
566 xor_(c, c);
567 jmp("in");
568 ud2();
569 L("@@"); // L1
570 add(a, 2);
571 mov(c, "@f");
572 jmp(c); // goto L2
573 ud2();
574 L("in");
575 mov(c, "@b");
576 add(a, 1);
577 jmp(c); // goto L1
578 ud2();
579 L("@@"); // L2
580 add(a, 4);
581 ret();
582 }
583 };
584 MovLabel2Code code;
585 int ret = code.getCode<int (*)()>()();
587}
588
590{
591 struct Code : Xbyak::CodeGenerator {
592 Code(int type)
593 {
594 inLocalLabel();
595 xor_(eax, eax);
596 switch (type) {
597 case 0:
598 L("@@");
599 inc(eax);
600 cmp(eax, 1);
601 je("@b");
602 break;
603 case 1:
604 test(eax, eax);
605 jz("@f");
606 ud2();
607 L("@@");
608 break;
609 case 2:
610 L("@@");
611 inc(eax);
612 cmp(eax, 1); // 1, 2
613 je("@b");
614 cmp(eax, 2); // 2, 3
615 je("@b");
616 break;
617 case 3:
618 L("@@");
619 inc(eax);
620 cmp(eax, 1); // 1, 2
621 je("@b");
622 cmp(eax, 2); // 2, 3
623 je("@b");
624 jmp("@f");
625 ud2();
626 L("@@");
627 break;
628 case 4:
629 L("@@");
630 inc(eax);
631 cmp(eax, 1); // 1, 2
632 je("@b");
633 cmp(eax, 2); // 2, 3
634 je("@b");
635 jmp("@f");
636 ud2();
637 L("@@");
638 inc(eax); // 4, 5
639 cmp(eax, 4);
640 je("@b");
641 break;
642 case 5:
643 L("@@");
644 L("@@");
645 inc(eax);
646 cmp(eax, 1);
647 je("@b");
648 break;
649 case 6:
650 L("@@");
651 L("@@");
652 L("@@");
653 inc(eax);
654 cmp(eax, 1);
655 je("@b");
656 break;
657 case 7:
658 jmp("@f");
659 L("@@");
660 inc(eax); // 1, 2
661 cmp(eax, 1);
662 je("@b");
663 cmp(eax, 2);
664 jne("@f"); // not jmp
665 inc(eax); // 3
666 L("@@");
667 inc(eax); // 4, 5, 6
668 cmp(eax, 4);
669 je("@b");
670 cmp(eax, 5);
671 je("@b");
672 jmp("@f");
673 jmp("@f");
674 jmp("@b");
675 L("@@");
676 break;
677 }
678 ret();
680 }
681 };
682 const int expectedTbl[] = {
683 2, 0, 3, 3, 5, 2, 2, 6
684 };
685 for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(expectedTbl); i++) {
686 Code code((int)i);
687 int ret = code.getCode<int (*)()>()();
688 CYBOZU_TEST_EQUAL(ret, expectedTbl[i]);
689 }
690}
691
693{
694 struct TestLocal : public Xbyak::CodeGenerator {
695 TestLocal(bool grow)
696 : Xbyak::CodeGenerator(grow ? 128 : 4096, grow ? Xbyak::AutoGrow : 0)
697 {
698 xor_(eax, eax);
699 inLocalLabel();
700 jmp("start0", T_NEAR);
701 L(".back");
702 inc(eax); // 8
703 jmp(".next", T_NEAR);
704 L("start2");
705 inc(eax); // 7
706 jmp(".back", T_NEAR);
707 inLocalLabel();
708 L(".back");
709 inc(eax); // 5
710 putNop(this, 128);
711 jmp(".next", T_NEAR);
712 L("start1");
713 inc(eax); // 4
714 jmp(".back", T_NEAR);
715 inLocalLabel();
716 L(".back");
717 inc(eax); // 2
718 jmp(".next", T_NEAR);
719 L("start0");
720 inc(eax); // 1
721 jmp(".back", T_NEAR);
722 L(".next");
723 inc(eax); // 3
724 jmp("start1", T_NEAR);
726 L(".next");
727 inc(eax); // 6
728 jmp("start2", T_NEAR);
730 L(".next");
731 inc(eax); // 9
732 jmp("start3", T_NEAR);
733 inLocalLabel();
734 L(".back");
735 inc(eax); // 14
736 jmp("exit", T_NEAR);
737 L("start4");
738 inc(eax); // 13
739 jmp(".back", T_NEAR);
741 L("start3");
742 inc(eax); // 10
743 inLocalLabel();
744 jmp(".next", T_NEAR);
745 L(".back");
746 inc(eax); // 12
747 jmp("start4", T_NEAR);
748 L(".next");
749 inc(eax); // 11
750 jmp(".back", T_NEAR);
753 L("exit");
754 inc(eax); // 15
755 ret();
756 }
757 };
758
759 for (int i = 0; i < 2; i++) {
760 const bool grow = i == 1;
761 printf("test6 grow=%d\n", i);
762 TestLocal code(grow);
763 if (grow) code.ready();
764 int (*f)() = code.getCode<int (*)()>();
765 int a = f();
766 CYBOZU_TEST_EQUAL(a, 15);
767 }
768}
769
771{
772 struct A : Xbyak::CodeGenerator {
773 A()
774 {
775 add(eax, 5);
776 ret();
777 }
778 };
779 struct B : Xbyak::CodeGenerator {
780 B(bool grow, const void *p) : Xbyak::CodeGenerator(grow ? 0 : 4096, grow ? Xbyak::AutoGrow : 0)
781 {
782 mov(eax, 1);
783 add(eax, 2);
784 jnz(p);
785 }
786 };
787 A a;
788 const void *p = a.getCode<const void*>();
789 for (int i = 0; i < 2; i++) {
790 bool grow = i == 1;
791 B b(grow, p);
792 if (grow) {
793 b.ready();
794 }
795 int (*f)() = b.getCode<int (*)()>();
796 CYBOZU_TEST_EQUAL(f(), 8);
797 }
798}
799
800CYBOZU_TEST_AUTO(testNewLabel)
801{
802 struct Code : Xbyak::CodeGenerator {
803 Code(bool grow)
804 : Xbyak::CodeGenerator(grow ? 128 : 4096, grow ? Xbyak::AutoGrow : 0)
805 {
806 xor_(eax, eax);
807 {
808 Label label1;
809 Label label2;
810 Label label3;
811 Label label4;
812 Label exit;
813 jmp(label1, T_NEAR);
814 L(label2);
815 inc(eax); // 2
816 jmp(label3, T_NEAR);
817 L(label4);
818 inc(eax); // 4
819 jmp(exit, T_NEAR);
820 putNop(this, 128);
821 L(label3);
822 inc(eax); // 3
823 jmp(label4, T_NEAR);
824 L(label1);
825 inc(eax); // 1
826 jmp(label2, T_NEAR);
827 L(exit);
828 }
829 {
830 Label label1;
831 Label label2;
832 Label label3;
833 Label label4;
834 Label exit;
835 jmp(label1);
836 L(label2);
837 inc(eax); // 6
838 jmp(label3);
839 L(label4);
840 inc(eax); // 8
841 jmp(exit);
842 L(label3);
843 inc(eax); // 7
844 jmp(label4);
845 L(label1);
846 inc(eax); // 5
847 jmp(label2);
848 L(exit);
849 }
850 Label callLabel;
851 { // eax == 8
852 Label label1;
853 Label label2;
854 L(label1);
855 inc(eax); // 9, 10, 11, 13
856 cmp(eax, 9);
857 je(label1);
858 // 10, 11, 13
859 inc(eax); // 11, 12, 13
860 cmp(eax, 11);
861 je(label1);
862 // 12, 13
863 cmp(eax, 12);
864 je(label2);
865 inc(eax); // 14
866 cmp(eax, 14);
867 je(label2);
868 ud2();
869 L(label2); // 14
870 inc(eax); // 13, 15
871 cmp(eax, 13);
872 je(label1);
873 }
874 call(callLabel);
875 ret();
876 L(callLabel);
877 inc(eax); // 16
878 ret();
879 }
880 };
881 for (int i = 0; i < 2; i++) {
882 const bool grow = i == 1;
883 printf("testNewLabel grow=%d\n", grow);
884 Code code(grow);
885 if (grow) code.ready();
886 int (*f)() = code.getCode<int (*)()>();
887 int r = f();
888 CYBOZU_TEST_EQUAL(r, 16);
889 }
890}
891
893{
894 struct Code : Xbyak::CodeGenerator {
895 Code(bool grow)
896 : Xbyak::CodeGenerator(grow ? 128 : 4096, grow ? Xbyak::AutoGrow : 0)
897 {
898 xor_(eax, eax);
899 Label dst, src;
900 L(src);
901 inc(eax);
902 cmp(eax, 1);
903 je(dst);
904 inc(eax); // 2, 3, 5
905 cmp(eax, 5);
906 putNop(this, 128);
907 jne(dst, T_NEAR);
908 ret();
909 assignL(dst, src);
910 // test of copy label
911 {
912 Label sss(dst);
913 {
914 Label ttt;
915 ttt = src;
916 }
917 }
918 }
919 };
920 for (int i = 0; i < 2; i++) {
921 const bool grow = i == 0;
922 printf("testAssign grow=%d\n", grow);
923 Code code(grow);
924 if (grow) code.ready();
925 int (*f)() = code.getCode<int (*)()>();
926 int ret = f();
928 }
929}
930
931CYBOZU_TEST_AUTO(doubleDefine)
932{
933 struct Code : Xbyak::CodeGenerator {
934 Code()
935 {
936 {
937 Label label;
938 L(label);
939 // forbitten double L()
941 }
942 {
943 Label label;
944 jmp(label);
946 }
947 {
948 Label label1, label2;
949 L(label1);
950 jmp(label2);
951 assignL(label2, label1);
952 // forbitten double assignL
954 }
955 {
956 Label label1, label2;
957 L(label1);
958 jmp(label2);
959 // forbitten assignment to label1 set by L()
961 }
962 }
963 } code;
964}
965
967 void test()
968 {
969 Xbyak::Label L1, L2, L3;
970 nop();
971 L(L1);
972 const uint8_t *p1 = getCurr();
974
975 nop();
976 jmp(L2);
977 nop();
978 jmp(L3);
979 L(L2);
981 // L3 is not defined
983
984 // L3 is set by L1
985 assignL(L3, L1);
987 }
988};
989
991{
993 c.test();
994}
995
998 size_t a1;
999 size_t a3;
1000 explicit GetAddressCode2(int size)
1001 : Xbyak::CodeGenerator(size, size == 4096 ? 0 : Xbyak::AutoGrow)
1002 , a1(0)
1003 , a3(0)
1004 {
1005 bool autoGrow = size != 4096;
1006 nop();
1007 L(L1);
1008 if (autoGrow) {
1010 }
1011 a1 = getSize();
1012 nop();
1013 jmp(L2);
1014 if (autoGrow) {
1016 }
1017 L(L3);
1018 a3 = getSize();
1019 if (autoGrow) {
1021 }
1022 nop();
1023 assignL(L2, L1);
1024 if (autoGrow) {
1026 }
1027 }
1028};
1029
1031{
1032 const int sizeTbl[] = {
1033 2, 128, // grow
1034 4096 // not grow
1035 };
1036 for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(sizeTbl); i++) {
1037 int size = sizeTbl[i];
1038 GetAddressCode2 c(size);
1039 c.ready();
1040 const uint8_t *p = c.getCode();
1044 }
1045}
1046
1047#ifdef XBYAK64
1049{
1050 int a[] = { 1, 10 };
1051 int b[] = { 100, 1000 };
1052 struct Code : Xbyak::CodeGenerator {
1053 Code(const int *a, const int *b)
1054 {
1055 Label label1, label2;
1056 jmp("@f");
1057 L(label1);
1058 db(a[0], 4);
1059 db(a[1], 4);
1060 L("@@");
1061 mov(eax, ptr [rip + label1]); // a[0]
1062 mov(ecx, ptr [rip + label1+4]); // a[1]
1063 mov(edx, ptr [rip + label2-8+2+6]); // b[0]
1064 add(ecx, ptr [rip + 16+label2-12]); // b[1]
1065 add(eax, ecx);
1066 add(eax, edx);
1067 ret();
1068 L(label2);
1069 db(b[0], 4);
1070 db(b[1], 4);
1071
1072 // error
1073 CYBOZU_TEST_EXCEPTION(rip + label1 + label2, Xbyak::Error);
1074 }
1075 } code(a, b);
1076 int ret = code.getCode<int (*)()>()();
1077 CYBOZU_TEST_EQUAL(ret, a[0] + a[1] + b[0] + b[1]);
1078}
1079
1080int ret1234()
1081{
1082 return 1234;
1083}
1084
1085int ret9999()
1086{
1087 return 9999;
1088}
1089
1090CYBOZU_TEST_AUTO(rip_jmp)
1091{
1092 struct Code : Xbyak::CodeGenerator {
1093 Code()
1094 {
1095 Label label;
1096 xor_(eax, eax);
1097 call(ptr [rip + label]);
1098 mov(ecx, eax);
1099 call(ptr [rip + label + 8]);
1100 add(eax, ecx);
1101 ret();
1102 L(label);
1103 db((size_t)ret1234, 8);
1104 db((size_t)ret9999, 8);
1105 }
1106 } code;
1107 int ret = code.getCode<int (*)()>()();
1108 CYBOZU_TEST_EQUAL(ret, ret1234() + ret9999());
1109}
1110
1111#ifdef XBYAK64_GCC
1112CYBOZU_TEST_AUTO(rip_addr)
1113{
1114 /*
1115 assume |&x - &code| < 2GiB
1116 */
1117 static int x = 5;
1118 struct Code : Xbyak::CodeGenerator {
1119 Code()
1120 {
1121 mov(eax, 123);
1122 mov(ptr[rip + &x], eax);
1123 ret();
1124 }
1125 } code;
1126 code.getCode<void (*)()>()();
1127 CYBOZU_TEST_EQUAL(x, 123);
1128}
1129#endif
1130CYBOZU_TEST_AUTO(rip_addr_with_fixed_buf)
1131{
1132 MIE_ALIGN(4096) static char buf[8192];
1133 static char *p = buf + 4096;
1134 static int *x0 = (int*)buf;
1135 static int *x1 = x0 + 1;
1136 struct Code : Xbyak::CodeGenerator {
1137 Code() : Xbyak::CodeGenerator(4096, p)
1138 {
1139 mov(eax, 123);
1140 mov(ptr[rip + x0], eax);
1141 mov(dword[rip + x1], 456);
1142 mov(byte[rip + 1 + x1 + 3], 99);
1143 ret();
1144 }
1145 } code;
1146 Xbyak::CodeArray::protect(p, 4096, true);
1147 code.getCode<void (*)()>()();
1148 CYBOZU_TEST_EQUAL(*x0, 123);
1149 CYBOZU_TEST_EQUAL(*x1, 456);
1150 CYBOZU_TEST_EQUAL(buf[8], 99);
1151}
1152#endif
void test2()
void test1()
void test3()
#define CYBOZU_NUM_OF_ARRAY(x)
Definition inttype.hpp:58
#define CYBOZU_TEST_ASSERT(x)
Definition test.hpp:192
#define CYBOZU_TEST_EXCEPTION(statement, Exception)
Definition test.hpp:285
#define CYBOZU_TEST_EQUAL_POINTER(x, y)
Definition test.hpp:221
#define CYBOZU_TEST_EQUAL(x, y)
Definition test.hpp:199
#define CYBOZU_TEST_AUTO(name)
Definition test.hpp:322
const mie::Vuint & p
Definition bn.cpp:27
const mie::Vuint & r
Definition bn.cpp:28
size_t getSize() const
Definition xbyak.h:911
const uint8 * getCode() const
Definition xbyak.h:905
static bool protect(const void *addr, size_t size, bool canExec)
Definition xbyak.h:966
const uint8 * getCurr() const
Definition xbyak.h:908
void jecxz(std::string label)
Definition xbyak.h:1564
void call(const Operand &op)
Definition xbyak.h:2150
void xor_(const Operand &op, uint32 imm)
Definition xbyak.h:1279
CodeGenerator(size_t maxSize=DEFAULT_MAX_CODE_SIZE, void *userPtr=0, Allocator *allocator=0)
Definition xbyak.h:2351
void jcxz(std::string label)
Definition xbyak.h:1562
void cmp(const Operand &op, uint32 imm)
Definition xbyak.h:94
const Reg32 eax
Definition xbyak.h:2087
void jmp(const Operand &op)
Definition xbyak.h:2144
void inc(const Operand &op)
Definition xbyak.h:307
void jne(const Label &label, LabelType type=T_AUTO)
Definition xbyak.h:369
const Reg32 ecx
Definition xbyak.h:2087
void test(const Operand &op, const Reg &reg)
Definition xbyak.h:2162
bool hasUndefinedLabel() const
Definition xbyak.h:2411
void add(const Operand &op, uint32 imm)
Definition xbyak.h:6
void sub(const Operand &op, uint32 imm)
Definition xbyak.h:746
void je(const Label &label, LabelType type=T_AUTO)
Definition xbyak.h:329
void db(int code)
Definition xbyak.h:882
void nop(size_t size=1, bool useMultiByteNop=true)
Definition xbyak.h:2436
void jz(const Label &label, LabelType type=T_AUTO)
Definition xbyak.h:425
const Reg32 edx
Definition xbyak.h:2087
void mov(const Operand &reg1, const Operand &reg2)
Definition xbyak.h:2210
void assignL(Label &dst, const Label &src)
Definition xbyak.h:2136
void jnz(const Label &label, LabelType type=T_AUTO)
Definition xbyak.h:401
void L(const std::string &label)
Definition xbyak.h:2126
void push(const Operand &op)
Definition xbyak.h:2189
const AddressFrame ptr
Definition xbyak.h:2090
static std::string toStr(int num)
Definition xbyak.h:1103
const uint8 * getAddress() const
Definition xbyak.h:1331
const struct Ptn tbl[]
int * count
MyAllocator myAlloc
Xbyak::uint8 bufL[4096 *32]
Definition jmp.cpp:340
void dump(const std::string &m)
Definition jmp.cpp:29
size_t getValue(const uint8 *p)
Definition jmp.cpp:444
void putNop(Xbyak::CodeGenerator *gen, int n)
Definition jmp.cpp:11
void diff(const std::string &a, const std::string &b)
Definition jmp.cpp:18
Xbyak::uint8 bufS[4096 *2]
Definition jmp.cpp:341
void checkAddr(const uint8 *p, size_t offset, size_t expect)
Definition jmp.cpp:453
const char * expect
Definition minitest.cpp:5
LOGGING_API void printf(Category category, const char *format,...)
Definition Logging.cpp:30
Definition xbyak.h:104
void *const AutoGrow
Definition xbyak.h:788
namespace sysio::chain
Definition authority.cpp:3
unsigned char uint8
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
int add(int a, int b)
unsigned char uint8_t
Definition stdint.h:124
Definition bench.cpp:18
Code()
Definition memfunc.cpp:19
void test()
Definition jmp.cpp:967
Xbyak::Label L1
Definition jmp.cpp:997
GetAddressCode2(int size)
Definition jmp.cpp:1000
size_t a3
Definition jmp.cpp:999
Xbyak::Label L3
Definition jmp.cpp:997
size_t a1
Definition jmp.cpp:998
Xbyak::Label L2
Definition jmp.cpp:997
Xbyak::uint8 * alloc(size_t size)
Definition jmp.cpp:344
void free(Xbyak::uint8 *)
Definition jmp.cpp:357
size_t size() const
Definition zm.h:519
#define A
int type definition and macros Copyright (C) 2008 Cybozu Labs, Inc., all rights reserved.
unit test class
Xbyak ; JIT assembler for x86(IA32)/x64 by C++.
void jnz(const Label &label, LabelType type=T_AUTO)
char * label
CK_RV ret
uint16_t j
size_t len
uint8_t buf[2048]
#define MIE_ALIGN(x)
Definition zm.h:50