ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp
Revision: 1.1
Committed: 2004-11-01T15:30:46Z (19 years, 8 months ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-19, nigel-build-17
Log Message:
add dumb but handy brute-force runtime assembler verifier, someone will
probably want to rewrite it to use BFD/opcodes internals for checks

File Contents

# Content
1 /******************** -*- mode: C; tab-width: 8 -*- ********************
2 *
3 * Dumb and Brute Force Run-time assembler verifier for IA-32 and AMD64
4 *
5 ***********************************************************************/
6
7
8 /***********************************************************************
9 *
10 * Copyright 2004 Gwenole Beauchesne
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 ***********************************************************************/
27
28 /*
29 * STATUS: 5.5M variations covering unary register based operations,
30 * reg/reg operations, imm/reg operations.
31 *
32 * TODO:
33 * - Rewrite to use internal BFD/opcodes format instead of string compares
34 * - Add reg/mem, imm/mem variations
35 */
36
37 #define _BSD_SOURCE 1
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include <errno.h>
44
45 #include "sysdeps.h"
46
47 #undef abort
48 #define abort() do { \
49 fprintf(stderr, "ABORT: %s, line %d\n", __FILE__, __LINE__); \
50 (abort)(); \
51 } while (0)
52
53 #define X86_TARGET_64BIT 1
54 #define X86_FLAT_REGISTERS 0
55 #define X86_OPTIMIZE_ALU 1
56 #define X86_OPTIMIZE_ROTSHI 1
57 #include "compiler/codegen_x86.h"
58
59 #define x86_emit_byte(B) emit_byte(B)
60 #define x86_emit_word(W) emit_word(W)
61 #define x86_emit_long(L) emit_long(L)
62 #define x86_emit_quad(Q) emit_quad(Q)
63 #define x86_get_target() get_target()
64 #define x86_emit_failure(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__)
65
66 static void jit_fail(const char *msg, const char *file, int line, const char *function)
67 {
68 fprintf(stderr, "JIT failure in function %s from file %s at line %d: %s\n",
69 function, file, line, msg);
70 abort();
71 }
72
73 static uint8 *target;
74
75 static inline void emit_byte(uint8 x)
76 {
77 *target++ = x;
78 }
79
80 static inline void emit_word(uint16 x)
81 {
82 *((uint16 *)target) = x;
83 target += 2;
84 }
85
86 static inline void emit_long(uint32 x)
87 {
88 *((uint32 *)target) = x;
89 target += 4;
90 }
91
92 static inline void emit_quad(uint64 x)
93 {
94 *((uint64 *)target) = x;
95 target += 8;
96 }
97
98 static inline void set_target(uint8 *t)
99 {
100 target = t;
101 }
102
103 static inline uint8 *get_target(void)
104 {
105 return target;
106 }
107
108 static uint32 mon_read_byte(uintptr addr)
109 {
110 uint8 *m = (uint8 *)addr;
111 return (uint32)(*m);
112 }
113
114 extern "C" {
115 #include "disass/dis-asm.h"
116
117 int buffer_read_memory(bfd_vma from, bfd_byte *to, unsigned int length, struct disassemble_info *info)
118 {
119 while (length--)
120 *to++ = mon_read_byte(from++);
121 return 0;
122 }
123
124 void perror_memory(int status, bfd_vma memaddr, struct disassemble_info *info)
125 {
126 info->fprintf_func(info->stream, "Unknown error %d\n", status);
127 }
128
129 void generic_print_address(bfd_vma addr, struct disassemble_info *info)
130 {
131 if (addr >= UVAL64(0x100000000))
132 info->fprintf_func(info->stream, "$%08x%08x", (uint32)(addr >> 32), (uint32)addr);
133 else
134 info->fprintf_func(info->stream, "$%08x", (uint32)addr);
135 }
136
137 int generic_symbol_at_address(bfd_vma addr, struct disassemble_info *info)
138 {
139 return 0;
140 }
141 }
142
143 struct SFILE {
144 char *buffer;
145 char *current;
146 };
147
148 static int mon_sprintf(SFILE *f, const char *format, ...)
149 {
150 int n;
151 va_list args;
152 va_start(args, format);
153 vsprintf(f->current, format, args);
154 f->current += n = strlen(f->current);
155 va_end(args);
156 return n;
157 }
158
159 static int disass_x86(char *buf, uintptr adr)
160 {
161 disassemble_info info;
162 SFILE sfile;
163 sfile.buffer = buf;
164 sfile.current = buf;
165 INIT_DISASSEMBLE_INFO(info, (FILE *)&sfile, (fprintf_ftype)mon_sprintf);
166 info.mach = bfd_mach_x86_64;
167 info.disassembler_options = "suffix";
168 return print_insn_i386(adr, &info);
169 }
170
171 enum {
172 op_disp,
173 op_reg,
174 op_base,
175 op_index,
176 op_scale,
177 op_imm,
178 };
179 struct operand_t {
180 int32 disp;
181 int8 reg;
182 int8 base;
183 int8 index;
184 int8 scale;
185 int64 imm;
186
187 void clear() {
188 disp = imm = 0;
189 reg = base = index = -1;
190 scale = 1;
191 }
192
193 void fill(int optype, int value) {
194 switch (optype) {
195 case op_disp: disp = value; break;
196 case op_reg: reg = value; break;
197 case op_base: base = value; break;
198 case op_index: index = value; break;
199 case op_scale: scale = value; break;
200 case op_imm: imm = value; break;
201 default: abort();
202 }
203 }
204 };
205
206 struct insn_t {
207 char name[16];
208 int n_operands;
209 #define MAX_OPERANDS 3
210 operand_t operands[MAX_OPERANDS];
211
212 void clear() {
213 memset(name, 0, sizeof(name));
214 n_operands = 0;
215 for (int i = 0; i < MAX_OPERANDS; i++)
216 operands[i].clear();
217 }
218
219 void pretty_print() {
220 printf("%s, %d operands\n", name, n_operands);
221 for (int i = 0; i < n_operands; i++) {
222 operand_t *op = &operands[i];
223 if (op->reg != -1)
224 printf(" reg r%d\n", op->reg);
225 else {
226 printf(" mem 0x%08x(", op->disp);
227 if (op->base != -1)
228 printf("r%d", op->base);
229 printf(",");
230 if (op->index != -1)
231 printf("r%d", op->index);
232 printf(",");
233 if (op->base != -1 || op->index != -1)
234 printf("%d", op->scale);
235 printf(")\n");
236 }
237 }
238 }
239 };
240
241 static const struct {
242 const char *name;
243 int reg;
244 }
245 regnames[] = {
246 #define _(REG) { #REG, X86_##REG }
247
248 _(AL), _(CL), _(DL), _(BL),
249 _(AH), _(CH), _(DH), _(BH),
250 _(SPL), _(BPL), _(SIL), _(DIL),
251 _(R8B), _(R9B), _(R10B), _(R11B), _(R12B), _(R13B), _(R14B), _(R15B),
252
253 _(AX), _(CX), _(DX), _(BX), _(SP), _(BP), _(SI), _(DI),
254 _(R8W), _(R9W), _(R10W), _(R11W), _(R12W), _(R13W), _(R14W), _(R15W),
255
256 _(EAX), _(ECX), _(EDX), _(EBX), _(ESP), _(EBP), _(ESI), _(EDI),
257 _(R8D), _(R9D), _(R10D), _(R11D), _(R12D), _(R13D), _(R14D), _(R15D),
258
259 _(RAX), _(RCX), _(RDX), _(RBX), _(RSP), _(RBP), _(RSI), _(RDI),
260 _(R8), _(R9), _(R10), _(R11), _(R12), _(R13), _(R14), _(R15),
261
262 { NULL, -1 }
263 #undef _
264 };
265
266 static int parse_reg(operand_t *op, int optype, char *buf)
267 {
268 for (int i = 0; regnames[i].name; i++) {
269 int len = strlen(regnames[i].name);
270 if (strncasecmp(regnames[i].name, buf, len) == 0) {
271 op->fill(optype, regnames[i].reg);
272 return len;
273 }
274 }
275 return 0;
276 }
277
278 static int parse_mem(operand_t *op, char *buf)
279 {
280 char *p = buf;
281
282 if (strncmp(buf, "0x", 2) == 0) {
283 unsigned long val = strtoul(buf, &p, 16);
284 if (val == 0 && errno == EINVAL)
285 abort();
286 op->disp = val;
287 }
288
289 if (*p == '(') {
290 p++;
291
292 if (*p == '%') {
293 p++;
294
295 int n = parse_reg(op, op_base, p);
296 if (n <= 0)
297 return -3;
298 p += n;
299 }
300
301 if (*p == ',') {
302 p++;
303
304 if (*p == '%') {
305 int n = parse_reg(op, op_index, ++p);
306 if (n <= 0)
307 return -4;
308 p += n;
309
310 if (*p != ',')
311 return -5;
312 p++;
313
314 goto do_parse_scale;
315 }
316 else if (isdigit(*p)) {
317 do_parse_scale:
318 long val = strtol(p, &p, 10);
319 if (val == 0 && errno == EINVAL)
320 abort();
321 op->scale = val;
322 }
323 }
324
325 if (*p != ')')
326 return -6;
327 p++;
328 }
329
330 return p - buf;
331 }
332
333 static void parse_insn(insn_t *ii, char *buf)
334 {
335 char *p = buf;
336 ii->clear();
337
338 for (int i = 0; !isspace(*p); i++)
339 ii->name[i] = *p++;
340
341 while (*p && isspace(*p))
342 p++;
343 if (*p == '\0')
344 return;
345
346 int n_operands = 0;
347 int optype = op_reg;
348 bool done = false;
349 while (!done) {
350 int n;
351 switch (*p) {
352 case '%':
353 n = parse_reg(&ii->operands[n_operands], optype, ++p);
354 if (n <= 0) {
355 fprintf(stderr, "parse_reg(%s) error %d\n", p, n);
356 abort();
357 }
358 p += n;
359 break;
360 case '0': case '(':
361 n = parse_mem(&ii->operands[n_operands], p);
362 if (n <= 0) {
363 fprintf(stderr, "parse_mem(%s) error %d\n", p, n);
364 abort();
365 }
366 p += n;
367 break;
368 case '$': {
369 unsigned long val = strtoul(++p, &p, 16);
370 if (val == 0 && errno == EINVAL)
371 abort();
372 ii->operands[n_operands].imm = val;
373 break;
374 }
375 case '*':
376 p++;
377 break;
378 case ',':
379 n_operands++;
380 p++;
381 break;
382 case ' ': case '\t':
383 p++;
384 break;
385 case '\0':
386 done = true;
387 break;
388 default:
389 fprintf(stderr, "parse error> %s\n", p);
390 abort();
391 }
392 }
393 ii->n_operands = n_operands + 1;
394 }
395
396 static long n_tests, n_failures;
397 static long n_all_tests, n_all_failures;
398
399 static bool check_reg(insn_t *ii, const char *name, int r)
400 {
401 if (strcasecmp(ii->name, name) != 0) {
402 fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
403 return false;
404 }
405
406 if (ii->n_operands != 1) {
407 fprintf(stderr, "ERROR: instruction expected 1 operand, got %d\n", ii->n_operands);
408 return false;
409 }
410
411 int reg = ii->operands[0].reg;
412
413 if (reg != r) {
414 fprintf(stderr, "ERROR: instruction expected r%d as source, got ", r);
415 if (reg == -1)
416 fprintf(stderr, "nothing\n");
417 else
418 fprintf(stderr, "%d\n", reg);
419 return false;
420 }
421
422 return true;
423 }
424
425 static bool check_reg_reg(insn_t *ii, const char *name, int s, int d)
426 {
427 if (strcasecmp(ii->name, name) != 0) {
428 fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
429 return false;
430 }
431
432 if (ii->n_operands != 2) {
433 fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands);
434 return false;
435 }
436
437 int srcreg = ii->operands[0].reg;
438 int dstreg = ii->operands[1].reg;
439
440 if (srcreg != s) {
441 fprintf(stderr, "ERROR: instruction expected r%d as source, got ", s);
442 if (srcreg == -1)
443 fprintf(stderr, "nothing\n");
444 else
445 fprintf(stderr, "%d\n", srcreg);
446 return false;
447 }
448
449 if (dstreg != d) {
450 fprintf(stderr, "ERROR: instruction expected r%d as destination, got ", d);
451 if (dstreg == -1)
452 fprintf(stderr, "nothing\n");
453 else
454 fprintf(stderr, "%d\n", dstreg);
455 return false;
456 }
457
458 return true;
459 }
460
461 static bool check_imm_reg(insn_t *ii, const char *name, uint32 v, int d, int mode = -1)
462 {
463 if (strcasecmp(ii->name, name) != 0) {
464 fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
465 return false;
466 }
467
468 if (ii->n_operands != 2) {
469 fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands);
470 return false;
471 }
472
473 uint32 imm = ii->operands[0].imm;
474 int dstreg = ii->operands[1].reg;
475
476 if (mode == -1) {
477 char suffix = name[strlen(name) - 1];
478 switch (suffix) {
479 case 'b': mode = 1; break;
480 case 'w': mode = 2; break;
481 case 'l': mode = 4; break;
482 case 'q': mode = 8; break;
483 }
484 }
485 switch (mode) {
486 case 1: v &= 0xff; break;
487 case 2: v &= 0xffff; break;
488 }
489
490 if (imm != v) {
491 fprintf(stderr, "ERROR: instruction expected 0x%08x as immediate, got ", v);
492 if (imm == -1)
493 fprintf(stderr, "nothing\n");
494 else
495 fprintf(stderr, "0x%08x\n", imm);
496 return false;
497 }
498
499 if (dstreg != d) {
500 fprintf(stderr, "ERROR: instruction expected r%d as destination, got ", d);
501 if (dstreg == -1)
502 fprintf(stderr, "nothing\n");
503 else
504 fprintf(stderr, "%d\n", dstreg);
505 return false;
506 }
507
508 return true;
509 }
510
511 static bool check_mem_reg(insn_t *ii, const char *name, uint32 D, int B, int I, int S, int R)
512 {
513 if (strcasecmp(ii->name, name) != 0) {
514 fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
515 return false;
516 }
517
518 if (ii->n_operands != 2) {
519 fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands);
520 return false;
521 }
522
523 operand_t *mem = &ii->operands[0];
524 operand_t *reg = &ii->operands[1];
525
526 uint32 d = mem->disp;
527 int b = mem->base;
528 int i = mem->index;
529 int s = mem->scale;
530 int r = reg->reg;
531
532 if (d != D) {
533 fprintf(stderr, "ERROR: instruction expected 0x%08x as displacement, got 0x%08x\n", D, d);
534 return false;
535 }
536
537 if (b != B) {
538 fprintf(stderr, "ERROR: instruction expected r%d as base, got r%d\n", B, b);
539 return false;
540 }
541
542 if (i != I) {
543 fprintf(stderr, "ERROR: instruction expected r%d as index, got r%d\n", I, i);
544 return false;
545 }
546
547 if (s != S) {
548 fprintf(stderr, "ERROR: instruction expected %d as scale factor, got %d\n", S, s);
549 return false;
550 }
551
552 if (r != R) {
553 fprintf(stderr, "ERROR: instruction expected r%d as reg operand, got r%d\n", R, r);
554 return false;
555 }
556
557 return true;
558 }
559
560 static int verbose = 2;
561
562 int main(void)
563 {
564 static char buffer[1024];
565 #define MAX_INSN_LENGTH 16
566 #define MAX_INSNS 1024
567 static uint8 block[MAX_INSNS * MAX_INSN_LENGTH];
568 static char *insns[MAX_INSNS];
569 static int modes[MAX_INSNS];
570 n_all_tests = n_all_failures = 0;
571
572 printf("Testing reg forms\n");
573 n_tests = n_failures = 0;
574 for (int r = 0; r < 16; r++) {
575 set_target(block);
576 uint8 *b = get_target();
577 int i = 0;
578 #define GEN(INSN, GENOP) do { \
579 insns[i++] = INSN; \
580 GENOP##r(r); \
581 } while (0)
582 #define GENA(INSN, GENOP) do { \
583 GEN(INSN "b", GENOP##B); \
584 GEN(INSN "w", GENOP##W); \
585 GEN(INSN "l", GENOP##L); \
586 GEN(INSN "q", GENOP##Q); \
587 } while (0)
588 GENA("not", NOT);
589 GENA("neg", NEG);
590 GENA("mul", MUL);
591 GENA("imul", IMUL);
592 GENA("div", DIV);
593 GENA("idiv", IDIV);
594 GENA("dec", DEC);
595 GENA("inc", INC);
596 GEN("callq", CALLs);
597 GEN("jmpq", JMPs);
598 GEN("pushl", PUSHQ); // FIXME: disass bug? wrong suffix
599 GEN("popl", POPQ); // FIXME: disass bug? wrong suffix
600 GEN("bswap", BSWAPL); // FIXME: disass bug? no suffix
601 GEN("bswap", BSWAPQ); // FIXME: disass bug? no suffix
602 GEN("seto", SETO);
603 GEN("setno", SETNO);
604 GEN("setb", SETB);
605 GEN("setae", SETAE);
606 GEN("sete", SETE);
607 GEN("setne", SETNE);
608 GEN("setbe", SETBE);
609 GEN("seta", SETA);
610 GEN("sets", SETS);
611 GEN("setns", SETNS);
612 GEN("setp", SETP);
613 GEN("setnp", SETNP);
614 GEN("setl", SETL);
615 GEN("setge", SETGE);
616 GEN("setle", SETLE);
617 GEN("setg", SETG);
618 #undef GENA
619 #undef GEN
620 int last_insn = i;
621 uint8 *e = get_target();
622
623 uint8 *p = b;
624 i = 0;
625 while (p < e) {
626 int n = disass_x86(buffer, (uintptr)p);
627 insn_t ii;
628 parse_insn(&ii, buffer);
629
630 if (!check_reg(&ii, insns[i], r)) {
631 if (verbose > 1)
632 fprintf(stderr, "%s\n", buffer);
633 n_failures++;
634 }
635
636 p += n;
637 i += 1;
638 n_tests++;
639 }
640 if (i != last_insn)
641 abort();
642 }
643 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
644 n_all_tests += n_tests;
645 n_all_failures += n_failures;
646
647 printf("Testing reg,reg forms\n");
648 n_tests = n_failures = 0;
649 for (int s = 0; s < 16; s++) {
650 for (int d = 0; d < 16; d++) {
651 set_target(block);
652 uint8 *b = get_target();
653 int i = 0;
654 #define GEN(INSN, GENOP) do { \
655 insns[i++] = INSN; \
656 GENOP##rr(s, d); \
657 } while (0)
658 #define GEN1(INSN, GENOP, OP) do { \
659 insns[i++] = INSN; \
660 GENOP##rr(OP, s, d); \
661 } while (0)
662 #define GENA(INSN, GENOP) do { \
663 GEN(INSN "b", GENOP##B); \
664 GEN(INSN "w", GENOP##W); \
665 GEN(INSN "l", GENOP##L); \
666 GEN(INSN "q", GENOP##Q); \
667 } while (0)
668 GENA("adc", ADC);
669 GENA("add", ADD);
670 GENA("and", AND);
671 GENA("cmp", CMP);
672 GENA("or", OR);
673 GENA("sbb", SBB);
674 GENA("sub", SUB);
675 GENA("xor", XOR);
676 GENA("mov", MOV);
677 GEN("btw", BTW);
678 GEN("btl", BTL);
679 GEN("btq", BTQ);
680 GEN("btcw", BTCW);
681 GEN("btcl", BTCL);
682 GEN("btcq", BTCQ);
683 GEN("btrw", BTRW);
684 GEN("btrl", BTRL);
685 GEN("btrq", BTRQ);
686 GEN("btsw", BTSW);
687 GEN("btsl", BTSL);
688 GEN("btsq", BTSQ);
689 GEN("imulw", IMULW);
690 GEN("imull", IMULL);
691 GEN("imulq", IMULQ);
692 GEN1("cmove", CMOVW, X86_CC_Z);
693 GEN1("cmove", CMOVL, X86_CC_Z);
694 GEN1("cmove", CMOVQ, X86_CC_Z);
695 GENA("test", TEST);
696 GENA("cmpxchg", CMPXCHG);
697 GENA("xadd", XADD);
698 GENA("xchg", XCHG);
699 GEN("bsfw", BSFW);
700 GEN("bsfl", BSFL);
701 GEN("bsfq", BSFQ);
702 GEN("bsrw", BSRW);
703 GEN("bsrl", BSRL);
704 GEN("bsrq", BSRQ);
705 GEN("movsbw", MOVSBW);
706 GEN("movsbl", MOVSBL);
707 GEN("movsbq", MOVSBQ);
708 GEN("movzbw", MOVZBW);
709 GEN("movzbl", MOVZBL);
710 GEN("movzbq", MOVZBQ);
711 GEN("movswl", MOVSWL);
712 GEN("movswq", MOVSWQ);
713 GEN("movzwl", MOVZWL);
714 GEN("movzwq", MOVZWQ);
715 GEN("movslq", MOVSLQ);
716 #undef GENA
717 #undef GEN1
718 #undef GEN
719 int last_insn = i;
720 uint8 *e = get_target();
721
722 uint8 *p = b;
723 i = 0;
724 while (p < e) {
725 int n = disass_x86(buffer, (uintptr)p);
726 insn_t ii;
727 parse_insn(&ii, buffer);
728
729 if (!check_reg_reg(&ii, insns[i], s, d)) {
730 if (verbose > 1)
731 fprintf(stderr, "%s\n", buffer);
732 n_failures++;
733 }
734
735 p += n;
736 i += 1;
737 n_tests++;
738 }
739 if (i != last_insn)
740 abort();
741 }
742 }
743 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
744 n_all_tests += n_tests;
745 n_all_failures += n_failures;
746
747 printf("Testing cl,reg forms\n");
748 n_tests = n_failures = 0;
749 for (int d = 0; d < 16; d++) {
750 set_target(block);
751 uint8 *b = get_target();
752 int i = 0;
753 #define GEN(INSN, GENOP) do { \
754 insns[i++] = INSN; \
755 GENOP##rr(X86_CL, d); \
756 } while (0)
757 #define GENA(INSN, GENOP) do { \
758 GEN(INSN "b", GENOP##B); \
759 GEN(INSN "w", GENOP##W); \
760 GEN(INSN "l", GENOP##L); \
761 GEN(INSN "q", GENOP##Q); \
762 } while (0)
763 GENA("rol", ROL);
764 GENA("ror", ROR);
765 GENA("rcl", RCL);
766 GENA("rcr", RCR);
767 GENA("shl", SHL);
768 GENA("shr", SHR);
769 GENA("sar", SAR);
770 #undef GENA
771 #undef GEN
772 int last_insn = i;
773 uint8 *e = get_target();
774
775 uint8 *p = b;
776 i = 0;
777 while (p < e) {
778 int n = disass_x86(buffer, (uintptr)p);
779 insn_t ii;
780 parse_insn(&ii, buffer);
781
782 if (!check_reg_reg(&ii, insns[i], X86_CL, d)) {
783 if (verbose > 1)
784 fprintf(stderr, "%s\n", buffer);
785 n_failures++;
786 }
787
788 p += n;
789 i += 1;
790 n_tests++;
791 }
792 if (i != last_insn)
793 abort();
794 }
795 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
796 n_all_tests += n_tests;
797 n_all_failures += n_failures;
798
799 printf("Testing imm,reg forms\n");
800 static const uint32 imm_table[] = {
801 0x00000000, 0x00000001, 0x00000002, 0x00000004,
802 0x00000008, 0x00000010, 0x00000020, 0x00000040,
803 0x00000080, 0x000000fe, 0x000000ff, 0x00000100,
804 0x00000101, 0x00000102, 0xfffffffe, 0xffffffff,
805 0x00000000, 0x10000000, 0x20000000, 0x30000000,
806 0x40000000, 0x50000000, 0x60000000, 0x70000000,
807 0x80000000, 0x90000000, 0xa0000000, 0xb0000000,
808 0xc0000000, 0xd0000000, 0xe0000000, 0xf0000000,
809 0xfffffffd, 0xfffffffe, 0xffffffff, 0x00000001,
810 0x00000002, 0x00000003, 0x11111111, 0x22222222,
811 0x33333333, 0x44444444, 0x55555555, 0x66666666,
812 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa,
813 0xbbbbbbbb, 0xcccccccc, 0xdddddddd, 0xeeeeeeee,
814 };
815 const int n_imm_tab_count = sizeof(imm_table)/sizeof(imm_table[0]);
816 n_tests = n_failures = 0;
817 for (int j = 0; j < n_imm_tab_count; j++) {
818 const uint32 value = imm_table[j];
819 for (int d = 0; d < 16; d++) {
820 set_target(block);
821 uint8 *b = get_target();
822 int i = 0;
823 #define GEN(INSN, GENOP) do { \
824 insns[i] = INSN; \
825 modes[i] = -1; \
826 i++; GENOP##ir(value, d); \
827 } while (0)
828 #define GENM(INSN, GENOP, MODE) do { \
829 insns[i] = INSN; \
830 modes[i] = MODE; \
831 i++; GENOP##ir(value, d); \
832 } while (0)
833 #define GENA(INSN, GENOP) do { \
834 GEN(INSN "b", GENOP##B); \
835 GEN(INSN "w", GENOP##W); \
836 GEN(INSN "l", GENOP##L); \
837 GEN(INSN "q", GENOP##Q); \
838 } while (0)
839 #define GENAM(INSN, GENOP, MODE) do { \
840 GENM(INSN "b", GENOP##B, MODE); \
841 GENM(INSN "w", GENOP##W, MODE); \
842 GENM(INSN "l", GENOP##L, MODE); \
843 GENM(INSN "q", GENOP##Q, MODE); \
844 } while (0)
845 GENA("adc", ADC);
846 GENA("add", ADD);
847 GENA("and", AND);
848 GENA("cmp", CMP);
849 GENA("or", OR);
850 GENA("sbb", SBB);
851 GENA("sub", SUB);
852 GENA("xor", XOR);
853 GENA("mov", MOV);
854 GENM("btw", BTW, 1);
855 GENM("btl", BTL, 1);
856 GENM("btq", BTQ, 1);
857 GENM("btcw", BTCW, 1);
858 GENM("btcl", BTCL, 1);
859 GENM("btcq", BTCQ, 1);
860 GENM("btrw", BTRW, 1);
861 GENM("btrl", BTRL, 1);
862 GENM("btrq", BTRQ, 1);
863 GENM("btsw", BTSW, 1);
864 GENM("btsl", BTSL, 1);
865 GENM("btsq", BTSQ, 1);
866 if (value != 1) {
867 GENAM("rol", ROL, 1);
868 GENAM("ror", ROR, 1);
869 GENAM("rcl", RCL, 1);
870 GENAM("rcr", RCR, 1);
871 GENAM("shl", SHL, 1);
872 GENAM("shr", SHR, 1);
873 GENAM("sar", SAR, 1);
874 }
875 GENA("test", TEST);
876 #undef GENAM
877 #undef GENA
878 #undef GENM
879 #undef GEN
880 int last_insn = i;
881 uint8 *e = get_target();
882
883 uint8 *p = b;
884 i = 0;
885 while (p < e) {
886 int n = disass_x86(buffer, (uintptr)p);
887 insn_t ii;
888 parse_insn(&ii, buffer);
889
890 if (!check_imm_reg(&ii, insns[i], value, d, modes[i])) {
891 if (verbose > 1)
892 fprintf(stderr, "%s\n", buffer);
893 n_failures++;
894 }
895
896 p += n;
897 i += 1;
898 n_tests++;
899 }
900 if (i != last_insn)
901 abort();
902 }
903 }
904 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
905 n_all_tests += n_tests;
906 n_all_failures += n_failures;
907
908 printf("Testing mem,reg forms\n");
909 n_tests = n_failures = 0;
910 static const uint32 off_table[] = {
911 0x00000000,
912 0x00000001,
913 0x00000040,
914 0x00000080,
915 0x000000ff,
916 0x00000100,
917 0xfffffffe,
918 0xffffffff,
919 };
920 const int off_table_count = sizeof(off_table) / sizeof(off_table[0]);
921 for (int d = 0; d < off_table_count; d++) {
922 const uint32 D = off_table[d];
923 for (int B = -1; B < 16; B++) {
924 for (int I = -1; I < 16; I++) {
925 if (I == X86_RSP)
926 continue;
927 for (int S = 1; S < 8; S *= 2) {
928 if (I == -1)
929 continue;
930 for (int r = 0; r < 16; r++) {
931 set_target(block);
932 uint8 *b = get_target();
933 int i = 0;
934 #define GEN(INSN, GENOP) do { \
935 insns[i++] = INSN; \
936 GENOP##mr(D, B, I, S, r); \
937 } while (0)
938 #define GENA(INSN, GENOP) do { \
939 GEN(INSN "b", GENOP##B); \
940 GEN(INSN "w", GENOP##W); \
941 GEN(INSN "l", GENOP##L); \
942 GEN(INSN "q", GENOP##Q); \
943 } while (0)
944 GENA("adc", ADC);
945 GENA("add", ADD);
946 GENA("and", AND);
947 GENA("cmp", CMP);
948 GENA("or", OR);
949 GENA("sbb", SBB);
950 GENA("sub", SUB);
951 GENA("xor", XOR);
952 GENA("mov", MOV);
953 GEN("imulw", IMULW);
954 GEN("imull", IMULL);
955 GEN("imulq", IMULQ);
956 GEN("bsfw", BSFW);
957 GEN("bsfl", BSFL);
958 GEN("bsfq", BSFQ);
959 GEN("bsrw", BSRW);
960 GEN("bsrl", BSRL);
961 GEN("bsrq", BSRQ);
962 GEN("movsbw", MOVSBW);
963 GEN("movsbl", MOVSBL);
964 GEN("movsbq", MOVSBQ);
965 GEN("movzbw", MOVZBW);
966 GEN("movzbl", MOVZBL);
967 GEN("movzbq", MOVZBQ);
968 GEN("movswl", MOVSWL);
969 GEN("movswq", MOVSWQ);
970 GEN("movzwl", MOVZWL);
971 GEN("movzwq", MOVZWQ);
972 GEN("movslq", MOVSLQ);
973 #undef GENA
974 #undef GEN
975 int last_insn = i;
976 uint8 *e = get_target();
977
978 uint8 *p = b;
979 i = 0;
980 while (p < e) {
981 int n = disass_x86(buffer, (uintptr)p);
982 insn_t ii;
983 parse_insn(&ii, buffer);
984
985 if (!check_mem_reg(&ii, insns[i], D, B, I, S, r)) {
986 if (verbose > 1)
987 fprintf(stderr, "%s\n", buffer);
988 n_failures++;
989 }
990
991 p += n;
992 i += 1;
993 n_tests++;
994 }
995 if (i != last_insn)
996 abort();
997 }
998 }
999 }
1000 }
1001 }
1002 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1003 n_all_tests += n_tests;
1004 n_all_failures += n_failures;
1005
1006 printf("\n");
1007 printf("All %ld tests run, %ld failures\n", n_all_tests, n_all_failures);
1008 }