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.11
Committed: 2008-02-16T22:14:41Z (16 years, 5 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.10: +2 -2 lines
Log Message:
Use D suffix for 64-bit real, even though L is the actual GNU assembler suffix.

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-2008 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: 26M 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 static int verbose = 2;
48
49 #define TEST_INST_ALU 1
50 #define TEST_INST_FPU 1
51 #define TEST_INST_MMX 1
52 #define TEST_INST_SSE 1
53 #if TEST_INST_ALU
54 #define TEST_INST_ALU_REG 1
55 #define TEST_INST_ALU_REG_REG 1
56 #define TEST_INST_ALU_CNT_REG 1
57 #define TEST_INST_ALU_IMM_REG 1
58 #define TEST_INST_ALU_MEM_REG 1
59 #endif
60 #if TEST_INST_FPU
61 #define TEST_INST_FPU_UNARY 1
62 #define TEST_INST_FPU_REG 1
63 #define TEST_INST_FPU_MEM 1
64 #endif
65 #if TEST_INST_MMX
66 #define TEST_INST_MMX_REG_REG 1
67 #define TEST_INST_MMX_IMM_REG 1
68 #define TEST_INST_MMX_MEM_REG 1
69 #endif
70 #if TEST_INST_SSE
71 #define TEST_INST_SSE_REG 1
72 #define TEST_INST_SSE_REG_REG 1
73 #define TEST_INST_SSE_MEM_REG 1
74 #endif
75
76 #undef abort
77 #define abort() do { \
78 fprintf(stderr, "ABORT: %s, line %d\n", __FILE__, __LINE__); \
79 (abort)(); \
80 } while (0)
81
82 #define X86_TARGET_64BIT 1
83 #define X86_FLAT_REGISTERS 0
84 #define X86_OPTIMIZE_ALU 1
85 #define X86_OPTIMIZE_ROTSHI 1
86 #define X86_RIP_RELATIVE_ADDR 0
87 #include "compiler/codegen_x86.h"
88
89 #if X86_TARGET_64BIT
90 #define X86_MAX_ALU_REGS 16
91 #define X86_MAX_SSE_REGS 16
92 #else
93 #define X86_MAX_ALU_REGS 8
94 #define X86_MAX_SSE_REGS 8
95 #endif
96 #define X86_MAX_FPU_REGS 8
97 #define X86_MAX_MMX_REGS 8
98
99 #define VALID_REG(r, b, n) (((unsigned)((r) - X86_##b)) < (n))
100 #if X86_TARGET_64BIT
101 #define VALID_REG8(r) (VALID_REG(r, AL, 16) || VALID_REG(r, AH, 4))
102 #define VALID_REG64(r) VALID_REG(r, RAX, X86_MAX_ALU_REGS)
103 #else
104 #define VALID_REG8(r) (VALID_REG(r, AL, 4) || VALID_REG(r, AH, 4))
105 #define VALID_REG64(r) (0)
106 #endif
107 #define VALID_REG16(r) VALID_REG(r, AX, X86_MAX_ALU_REGS)
108 #define VALID_REG32(r) VALID_REG(r, EAX, X86_MAX_ALU_REGS)
109
110 #define x86_emit_byte(B) emit_byte(B)
111 #define x86_emit_word(W) emit_word(W)
112 #define x86_emit_long(L) emit_long(L)
113 #define x86_emit_quad(Q) emit_quad(Q)
114 #define x86_get_target() get_target()
115 #define x86_emit_failure(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__)
116
117 static void jit_fail(const char *msg, const char *file, int line, const char *function)
118 {
119 fprintf(stderr, "JIT failure in function %s from file %s at line %d: %s\n",
120 function, file, line, msg);
121 abort();
122 }
123
124 static uint8 *target;
125
126 static inline void emit_byte(uint8 x)
127 {
128 *target++ = x;
129 }
130
131 static inline void emit_word(uint16 x)
132 {
133 *((uint16 *)target) = x;
134 target += 2;
135 }
136
137 static inline void emit_long(uint32 x)
138 {
139 *((uint32 *)target) = x;
140 target += 4;
141 }
142
143 static inline void emit_quad(uint64 x)
144 {
145 *((uint64 *)target) = x;
146 target += 8;
147 }
148
149 static inline void set_target(uint8 *t)
150 {
151 target = t;
152 }
153
154 static inline uint8 *get_target(void)
155 {
156 return target;
157 }
158
159 static uint32 mon_read_byte(uintptr addr)
160 {
161 uint8 *m = (uint8 *)addr;
162 return (uint32)(*m);
163 }
164
165 extern "C" {
166 #include "disass/dis-asm.h"
167
168 int buffer_read_memory(bfd_vma from, bfd_byte *to, unsigned int length, struct disassemble_info *info)
169 {
170 while (length--)
171 *to++ = mon_read_byte(from++);
172 return 0;
173 }
174
175 void perror_memory(int status, bfd_vma memaddr, struct disassemble_info *info)
176 {
177 info->fprintf_func(info->stream, "Unknown error %d\n", status);
178 }
179
180 void generic_print_address(bfd_vma addr, struct disassemble_info *info)
181 {
182 if (addr >= UVAL64(0x100000000))
183 info->fprintf_func(info->stream, "$%08x%08x", (uint32)(addr >> 32), (uint32)addr);
184 else
185 info->fprintf_func(info->stream, "$%08x", (uint32)addr);
186 }
187
188 int generic_symbol_at_address(bfd_vma addr, struct disassemble_info *info)
189 {
190 return 0;
191 }
192 }
193
194 struct SFILE {
195 char *buffer;
196 char *current;
197 };
198
199 static int mon_sprintf(SFILE *f, const char *format, ...)
200 {
201 int n;
202 va_list args;
203 va_start(args, format);
204 vsprintf(f->current, format, args);
205 f->current += n = strlen(f->current);
206 va_end(args);
207 return n;
208 }
209
210 static int disass_x86(char *buf, uintptr adr)
211 {
212 disassemble_info info;
213 SFILE sfile;
214 sfile.buffer = buf;
215 sfile.current = buf;
216 INIT_DISASSEMBLE_INFO(info, (FILE *)&sfile, (fprintf_ftype)mon_sprintf);
217 info.mach = X86_TARGET_64BIT ? bfd_mach_x86_64 : bfd_mach_i386_i386;
218 info.disassembler_options = "suffix";
219 return print_insn_i386(adr, &info);
220 }
221
222 enum {
223 op_disp,
224 op_reg,
225 op_base,
226 op_index,
227 op_scale,
228 op_imm,
229 };
230 struct operand_t {
231 int32 disp;
232 int8 reg;
233 int8 base;
234 int8 index;
235 int8 scale;
236 int64 imm;
237
238 void clear() {
239 disp = imm = 0;
240 reg = base = index = -1;
241 scale = 1;
242 }
243
244 void fill(int optype, int value) {
245 switch (optype) {
246 case op_disp: disp = value; break;
247 case op_reg: reg = value; break;
248 case op_base: base = value; break;
249 case op_index: index = value; break;
250 case op_scale: scale = value; break;
251 case op_imm: imm = value; break;
252 default: abort();
253 }
254 }
255 };
256
257 #define MAX_INSNS 1024
258 #define MAX_INSN_LENGTH 16
259 #define MAX_INSN_OPERANDS 3
260
261 struct insn_t {
262 char name[16];
263 int n_operands;
264 operand_t operands[MAX_INSN_OPERANDS];
265
266 void clear() {
267 memset(name, 0, sizeof(name));
268 n_operands = 0;
269 for (int i = 0; i < MAX_INSN_OPERANDS; i++)
270 operands[i].clear();
271 }
272
273 void pretty_print() {
274 printf("%s, %d operands\n", name, n_operands);
275 for (int i = 0; i < n_operands; i++) {
276 operand_t *op = &operands[i];
277 if (op->reg != -1)
278 printf(" reg r%d\n", op->reg);
279 else {
280 printf(" mem 0x%08x(", op->disp);
281 if (op->base != -1)
282 printf("r%d", op->base);
283 printf(",");
284 if (op->index != -1)
285 printf("r%d", op->index);
286 printf(",");
287 if (op->base != -1 || op->index != -1)
288 printf("%d", op->scale);
289 printf(")\n");
290 }
291 }
292 }
293 };
294
295 static inline char *find_blanks(char *p)
296 {
297 while (*p && !isspace(*p))
298 ++p;
299 return p;
300 }
301
302 static inline char *skip_blanks(char *p)
303 {
304 while (*p && isspace(*p))
305 ++p;
306 return p;
307 }
308
309 static int parse_reg(operand_t *op, int optype, char *buf)
310 {
311 int reg = X86_NOREG;
312 int len = 0;
313 char *p = buf;
314 switch (p[0]) {
315 case 'a': case 'A':
316 len = 2;
317 switch (p[1]) {
318 case 'l': case 'L': reg = X86_AL; break;
319 case 'h': case 'H': reg = X86_AH; break;
320 case 'x': case 'X': reg = X86_AX; break;
321 }
322 break;
323 case 'b': case 'B':
324 len = 2;
325 switch (p[1]) {
326 case 'l': case 'L': reg = X86_BL; break;
327 case 'h': case 'H': reg = X86_BH; break;
328 case 'x': case 'X': reg = X86_BX; break;
329 case 'p': case 'P':
330 switch (p[2]) {
331 #if X86_TARGET_64BIT
332 case 'l': case 'L': reg = X86_BPL, ++len; break;
333 #endif
334 default: reg = X86_BP; break;
335 }
336 break;
337 }
338 break;
339 case 'c': case 'C':
340 len = 2;
341 switch (p[1]) {
342 case 'l': case 'L': reg = X86_CL; break;
343 case 'h': case 'H': reg = X86_CH; break;
344 case 'x': case 'X': reg = X86_CX; break;
345 }
346 break;
347 case 'd': case 'D':
348 len = 2;
349 switch (p[1]) {
350 case 'l': case 'L': reg = X86_DL; break;
351 case 'h': case 'H': reg = X86_DH; break;
352 case 'x': case 'X': reg = X86_DX; break;
353 case 'i': case 'I':
354 switch (p[2]) {
355 #if X86_TARGET_64BIT
356 case 'l': case 'L': reg = X86_DIL; ++len; break;
357 #endif
358 default: reg = X86_DI; break;
359 }
360 break;
361 }
362 break;
363 case 's': case 'S':
364 len = 2;
365 switch (p[2]) {
366 #if X86_TARGET_64BIT
367 case 'l': case 'L':
368 ++len;
369 switch (p[1]) {
370 case 'p': case 'P': reg = X86_SPL; break;
371 case 'i': case 'I': reg = X86_SIL; break;
372 }
373 break;
374 #endif
375 case '(':
376 if ((p[1] == 't' || p[1] == 'T') && isdigit(p[3]) && p[4] == ')')
377 len += 3, reg = X86_ST0 + (p[3] - '0');
378 break;
379 default:
380 switch (p[1]) {
381 case 't': case 'T': reg = X86_ST0; break;
382 case 'p': case 'P': reg = X86_SP; break;
383 case 'i': case 'I': reg = X86_SI; break;
384 }
385 break;
386 }
387 break;
388 case 'e': case 'E':
389 len = 3;
390 switch (p[2]) {
391 case 'x': case 'X':
392 switch (p[1]) {
393 case 'a': case 'A': reg = X86_EAX; break;
394 case 'b': case 'B': reg = X86_EBX; break;
395 case 'c': case 'C': reg = X86_ECX; break;
396 case 'd': case 'D': reg = X86_EDX; break;
397 }
398 break;
399 case 'i': case 'I':
400 switch (p[1]) {
401 case 's': case 'S': reg = X86_ESI; break;
402 case 'd': case 'D': reg = X86_EDI; break;
403 }
404 break;
405 case 'p': case 'P':
406 switch (p[1]) {
407 case 'b': case 'B': reg = X86_EBP; break;
408 case 's': case 'S': reg = X86_ESP; break;
409 }
410 break;
411 }
412 break;
413 #if X86_TARGET_64BIT
414 case 'r': case 'R':
415 len = 3;
416 switch (p[2]) {
417 case 'x': case 'X':
418 switch (p[1]) {
419 case 'a': case 'A': reg = X86_RAX; break;
420 case 'b': case 'B': reg = X86_RBX; break;
421 case 'c': case 'C': reg = X86_RCX; break;
422 case 'd': case 'D': reg = X86_RDX; break;
423 }
424 break;
425 case 'i': case 'I':
426 switch (p[1]) {
427 case 's': case 'S': reg = X86_RSI; break;
428 case 'd': case 'D': reg = X86_RDI; break;
429 }
430 break;
431 case 'p': case 'P':
432 switch (p[1]) {
433 case 'b': case 'B': reg = X86_RBP; break;
434 case 's': case 'S': reg = X86_RSP; break;
435 }
436 break;
437 case 'b': case 'B':
438 switch (p[1]) {
439 case '8': reg = X86_R8B; break;
440 case '9': reg = X86_R9B; break;
441 }
442 break;
443 case 'w': case 'W':
444 switch (p[1]) {
445 case '8': reg = X86_R8W; break;
446 case '9': reg = X86_R9W; break;
447 }
448 break;
449 case 'd': case 'D':
450 switch (p[1]) {
451 case '8': reg = X86_R8D; break;
452 case '9': reg = X86_R9D; break;
453 }
454 break;
455 case '0': case '1': case '2': case '3': case '4': case '5':
456 if (p[1] == '1') {
457 const int r = p[2] - '0';
458 switch (p[3]) {
459 case 'b': case 'B': reg = X86_R10B + r, ++len; break;
460 case 'w': case 'W': reg = X86_R10W + r, ++len; break;
461 case 'd': case 'D': reg = X86_R10D + r, ++len; break;
462 default: reg = X86_R10 + r; break;
463 }
464 }
465 break;
466 default:
467 switch (p[1]) {
468 case '8': reg = X86_R8, len = 2; break;
469 case '9': reg = X86_R9, len = 2; break;
470 }
471 break;
472 }
473 break;
474 #endif
475 case 'm': case 'M':
476 if ((p[1] == 'm' || p[1] == 'M') && isdigit(p[2]))
477 reg = X86_MM0 + (p[2] - '0'), len = 3;
478 break;
479 case 'x': case 'X':
480 if ((p[1] == 'm' || p[1] == 'M') && (p[2] == 'm' || p[2] == 'M')) {
481 #if X86_TARGET_64BIT
482 if (p[3] == '1' && isdigit(p[4]))
483 reg = X86_XMM10 + (p[4] - '0'), len = 5;
484 else
485 #endif
486 if (isdigit(p[3]))
487 reg = X86_XMM0 + (p[3] - '0'), len = 4;
488 }
489 break;
490 }
491
492 if (len > 0 && reg != X86_NOREG) {
493 op->fill(optype, reg);
494 return len;
495 }
496
497 return X86_NOREG;
498 }
499
500 static unsigned long parse_imm(char *nptr, char **endptr, int base = 0)
501 {
502 errno = 0;
503 #if X86_TARGET_64BIT
504 if (sizeof(unsigned long) != 8) {
505 unsigned long long val = strtoull(nptr, endptr, 0);
506 if (errno == 0)
507 return val;
508 abort();
509 }
510 #endif
511 unsigned long val = strtoul(nptr, endptr, 0);
512 if (errno == 0)
513 return val;
514 abort();
515 return 0;
516 }
517
518 static int parse_mem(operand_t *op, char *buf)
519 {
520 char *p = buf;
521
522 if (strncmp(buf, "0x", 2) == 0)
523 op->disp = parse_imm(buf, &p, 16);
524
525 if (*p == '(') {
526 p++;
527
528 if (*p == '%') {
529 p++;
530
531 int n = parse_reg(op, op_base, p);
532 if (n <= 0)
533 return -3;
534 p += n;
535 }
536
537 if (*p == ',') {
538 p++;
539
540 if (*p == '%') {
541 int n = parse_reg(op, op_index, ++p);
542 if (n <= 0)
543 return -4;
544 p += n;
545
546 if (*p != ',')
547 return -5;
548 p++;
549
550 goto do_parse_scale;
551 }
552 else if (isdigit(*p)) {
553 do_parse_scale:
554 long val = strtol(p, &p, 10);
555 if (val == 0 && errno == EINVAL)
556 abort();
557 op->scale = val;
558 }
559 }
560
561 if (*p != ')')
562 return -6;
563 p++;
564 }
565
566 return p - buf;
567 }
568
569 static void parse_insn(insn_t *ii, char *buf)
570 {
571 char *p = buf;
572 ii->clear();
573
574 #if 0
575 printf("BUF: %s\n", buf);
576 #endif
577
578 if (strncmp(p, "rex64", 5) == 0) {
579 char *q = find_blanks(p);
580 if (verbose > 1) {
581 char prefix[16];
582 memset(prefix, 0, sizeof(prefix));
583 memcpy(prefix, p, q - p);
584 fprintf(stderr, "Instruction '%s', skip REX prefix '%s'\n", buf, prefix);
585 }
586 p = skip_blanks(q);
587 }
588
589 if (strncmp(p, "rep", 3) == 0) {
590 char *q = find_blanks(p);
591 if (verbose > 1) {
592 char prefix[16];
593 memset(prefix, 0, sizeof(prefix));
594 memcpy(prefix, p, q - p);
595 fprintf(stderr, "Instruction '%s', skip REP prefix '%s'\n", buf, prefix);
596 }
597 p = skip_blanks(q);
598 }
599
600 for (int i = 0; !isspace(*p); i++)
601 ii->name[i] = *p++;
602
603 while (*p && isspace(*p))
604 p++;
605 if (*p == '\0')
606 return;
607
608 int n_operands = 0;
609 int optype = op_reg;
610 bool done = false;
611 while (!done) {
612 int n;
613 switch (*p) {
614 case '%':
615 n = parse_reg(&ii->operands[n_operands], optype, ++p);
616 if (n <= 0) {
617 fprintf(stderr, "parse_reg(%s) error %d\n", p, n);
618 abort();
619 }
620 p += n;
621 break;
622 case '0': case '(':
623 n = parse_mem(&ii->operands[n_operands], p);
624 if (n <= 0) {
625 fprintf(stderr, "parse_mem(%s) error %d\n", p, n);
626 abort();
627 }
628 p += n;
629 break;
630 case '$': {
631 ii->operands[n_operands].imm = parse_imm(++p, &p, 0);
632 break;
633 }
634 case '*':
635 p++;
636 break;
637 case ',':
638 n_operands++;
639 p++;
640 break;
641 case ' ': case '\t':
642 p++;
643 break;
644 case '\0':
645 done = true;
646 break;
647 default:
648 fprintf(stderr, "parse error> %s\n", p);
649 abort();
650 }
651 }
652 ii->n_operands = n_operands + 1;
653 }
654
655 static unsigned long n_tests, n_failures;
656 static unsigned long n_all_tests, n_all_failures;
657
658 static bool check_unary(insn_t *ii, const char *name)
659 {
660 if (strcasecmp(ii->name, name) != 0) {
661 fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
662 return false;
663 }
664
665 if (ii->n_operands != 0) {
666 fprintf(stderr, "ERROR: instruction expected 0 operand, got %d\n", ii->n_operands);
667 return false;
668 }
669
670 return true;
671 }
672
673 static bool check_reg(insn_t *ii, const char *name, int r)
674 {
675 if (strcasecmp(ii->name, name) != 0) {
676 fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
677 return false;
678 }
679
680 if (ii->n_operands != 1) {
681 fprintf(stderr, "ERROR: instruction expected 1 operand, got %d\n", ii->n_operands);
682 return false;
683 }
684
685 int reg = ii->operands[0].reg;
686
687 if (reg != r) {
688 fprintf(stderr, "ERROR: instruction expected r%d as source, got ", r);
689 if (reg == -1)
690 fprintf(stderr, "nothing\n");
691 else
692 fprintf(stderr, "r%d\n", reg);
693 return false;
694 }
695
696 return true;
697 }
698
699 static bool check_reg_reg(insn_t *ii, const char *name, int s, int d)
700 {
701 if (strcasecmp(ii->name, name) != 0) {
702 fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
703 return false;
704 }
705
706 if (ii->n_operands != 2) {
707 fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands);
708 return false;
709 }
710
711 int srcreg = ii->operands[0].reg;
712 int dstreg = ii->operands[1].reg;
713
714 if (srcreg != s) {
715 fprintf(stderr, "ERROR: instruction expected r%d as source, got ", s);
716 if (srcreg == -1)
717 fprintf(stderr, "nothing\n");
718 else
719 fprintf(stderr, "r%d\n", srcreg);
720 return false;
721 }
722
723 if (dstreg != d) {
724 fprintf(stderr, "ERROR: instruction expected r%d as destination, got ", d);
725 if (dstreg == -1)
726 fprintf(stderr, "nothing\n");
727 else
728 fprintf(stderr, "r%d\n", dstreg);
729 return false;
730 }
731
732 return true;
733 }
734
735 static bool check_imm_reg(insn_t *ii, const char *name, uint32 v, int d, int mode = -1)
736 {
737 if (strcasecmp(ii->name, name) != 0) {
738 fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
739 return false;
740 }
741
742 if (ii->n_operands != 2) {
743 fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands);
744 return false;
745 }
746
747 uint32 imm = ii->operands[0].imm;
748 int dstreg = ii->operands[1].reg;
749
750 if (mode == -1) {
751 char suffix = name[strlen(name) - 1];
752 switch (suffix) {
753 case 'b': mode = 1; break;
754 case 'w': mode = 2; break;
755 case 'l': mode = 4; break;
756 case 'q': mode = 8; break;
757 }
758 }
759 switch (mode) {
760 case 1: v &= 0xff; break;
761 case 2: v &= 0xffff; break;
762 }
763
764 if (imm != v) {
765 fprintf(stderr, "ERROR: instruction expected 0x%08x as immediate, got ", v);
766 if (imm == -1)
767 fprintf(stderr, "nothing\n");
768 else
769 fprintf(stderr, "0x%08x\n", imm);
770 return false;
771 }
772
773 if (dstreg != d) {
774 fprintf(stderr, "ERROR: instruction expected r%d as destination, got ", d);
775 if (dstreg == -1)
776 fprintf(stderr, "nothing\n");
777 else
778 fprintf(stderr, "%d\n", dstreg);
779 return false;
780 }
781
782 return true;
783 }
784
785 static bool do_check_mem(insn_t *ii, uint32 D, int B, int I, int S, int Mpos)
786 {
787 operand_t *mem = &ii->operands[Mpos];
788 uint32 d = mem->disp;
789 int b = mem->base;
790 int i = mem->index;
791 int s = mem->scale;
792
793 if (d != D) {
794 fprintf(stderr, "ERROR: instruction expected 0x%08x as displacement, got 0x%08x\n", D, d);
795 return false;
796 }
797
798 if (b != B) {
799 fprintf(stderr, "ERROR: instruction expected r%d as base, got r%d\n", B, b);
800 return false;
801 }
802
803 if (i != I) {
804 fprintf(stderr, "ERROR: instruction expected r%d as index, got r%d\n", I, i);
805 return false;
806 }
807
808 if (s != S) {
809 fprintf(stderr, "ERROR: instruction expected %d as scale factor, got %d\n", S, s);
810 return false;
811 }
812
813 return true;
814 }
815
816 static bool check_mem(insn_t *ii, const char *name, uint32 D, int B, int I, int S)
817 {
818 if (strcasecmp(ii->name, name) != 0) {
819 fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
820 return false;
821 }
822
823 if (ii->n_operands != 1) {
824 fprintf(stderr, "ERROR: instruction expected 1 operand, got %d\n", ii->n_operands);
825 return false;
826 }
827
828 return do_check_mem(ii, D, B, I, S, 0);
829 }
830
831 static bool check_mem_reg(insn_t *ii, const char *name, uint32 D, int B, int I, int S, int R, int Rpos = 1)
832 {
833 if (strcasecmp(ii->name, name) != 0) {
834 fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
835 return false;
836 }
837
838 if (ii->n_operands != 2) {
839 fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands);
840 return false;
841 }
842
843 if (!do_check_mem(ii, D, B, I, S, Rpos ^ 1))
844 return false;
845
846 int r = ii->operands[Rpos].reg;
847
848 if (r != R) {
849 fprintf(stderr, "ERROR: instruction expected r%d as reg operand, got r%d\n", R, r);
850 return false;
851 }
852
853 return true;
854 }
855
856 static inline bool check_reg_mem(insn_t *ii, const char *name, uint32 D, int B, int I, int S, int R)
857 {
858 return check_mem_reg(ii, name, D, B, I, S, R, 0);
859 }
860
861 static void show_instruction(const char *buffer, const uint8 *bytes)
862 {
863 if (verbose > 1) {
864 if (1) {
865 for (int j = 0; j < MAX_INSN_LENGTH; j++)
866 fprintf(stderr, "%02x ", bytes[j]);
867 fprintf(stderr, "| ");
868 }
869 fprintf(stderr, "%s\n", buffer);
870 }
871 }
872
873 static void show_status(unsigned long n_tests)
874 {
875 #if 1
876 const unsigned long N_STEPS = 100000;
877 static const char cursors[] = { '-', '\\', '|', '/' };
878 if ((n_tests % N_STEPS) == 0) {
879 printf(" %c (%d)\r", cursors[(n_tests/N_STEPS)%sizeof(cursors)], n_tests);
880 fflush(stdout);
881 }
882 #else
883 const unsigned long N_STEPS = 1000000;
884 if ((n_tests % N_STEPS) == 0)
885 printf(" ... %d\n", n_tests);
886 #endif
887 }
888
889 int main(void)
890 {
891 static char buffer[1024];
892 static uint8 block[MAX_INSNS * MAX_INSN_LENGTH];
893 static char *insns[MAX_INSNS];
894 static int modes[MAX_INSNS];
895 n_all_tests = n_all_failures = 0;
896
897 #if TEST_INST_ALU_REG
898 printf("Testing reg forms\n");
899 n_tests = n_failures = 0;
900 for (int r = 0; r < X86_MAX_ALU_REGS; r++) {
901 set_target(block);
902 uint8 *b = get_target();
903 int i = 0;
904 #define GEN(INSN, GENOP) do { \
905 insns[i++] = INSN; \
906 GENOP##r(r); \
907 } while (0)
908 #define GEN64(INSN, GENOP) do { \
909 if (X86_TARGET_64BIT) \
910 GEN(INSN, GENOP); \
911 } while (0)
912 #define GENA(INSN, GENOP) do { \
913 if (VALID_REG8(r)) \
914 GEN(INSN "b", GENOP##B); \
915 GEN(INSN "w", GENOP##W); \
916 GEN(INSN "l", GENOP##L); \
917 GEN64(INSN "q", GENOP##Q); \
918 } while (0)
919 GENA("not", NOT);
920 GENA("neg", NEG);
921 GENA("mul", MUL);
922 GENA("imul", IMUL);
923 GENA("div", DIV);
924 GENA("idiv", IDIV);
925 GENA("dec", DEC);
926 GENA("inc", INC);
927 if (X86_TARGET_64BIT) {
928 GEN("callq", CALLs);
929 GEN("jmpq", JMPs);
930 GEN("pushq", PUSHQ);
931 GEN("popq", POPQ);
932 }
933 else {
934 GEN("calll", CALLs);
935 GEN("jmpl", JMPs);
936 GEN("pushl", PUSHL);
937 GEN("popl", POPL);
938 }
939 GEN("bswap", BSWAPL); // FIXME: disass bug? no suffix
940 GEN64("bswap", BSWAPQ); // FIXME: disass bug? no suffix
941 if (VALID_REG8(r)) {
942 GEN("seto", SETO);
943 GEN("setno", SETNO);
944 GEN("setb", SETB);
945 GEN("setae", SETAE);
946 GEN("sete", SETE);
947 GEN("setne", SETNE);
948 GEN("setbe", SETBE);
949 GEN("seta", SETA);
950 GEN("sets", SETS);
951 GEN("setns", SETNS);
952 GEN("setp", SETP);
953 GEN("setnp", SETNP);
954 GEN("setl", SETL);
955 GEN("setge", SETGE);
956 GEN("setle", SETLE);
957 GEN("setg", SETG);
958 }
959 #undef GENA
960 #undef GEN64
961 #undef GEN
962 int last_insn = i;
963 uint8 *e = get_target();
964
965 uint8 *p = b;
966 i = 0;
967 while (p < e) {
968 int n = disass_x86(buffer, (uintptr)p);
969 insn_t ii;
970 parse_insn(&ii, buffer);
971
972 if (!check_reg(&ii, insns[i], r)) {
973 show_instruction(buffer, p);
974 n_failures++;
975 }
976
977 p += n;
978 i += 1;
979 n_tests++;
980 }
981 if (i != last_insn)
982 abort();
983 }
984 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
985 n_all_tests += n_tests;
986 n_all_failures += n_failures;
987 #endif
988
989 #if TEST_INST_ALU_REG_REG
990 printf("Testing reg,reg forms\n");
991 n_tests = n_failures = 0;
992 for (int s = 0; s < X86_MAX_ALU_REGS; s++) {
993 for (int d = 0; d < X86_MAX_ALU_REGS; d++) {
994 set_target(block);
995 uint8 *b = get_target();
996 int i = 0;
997 #define GEN(INSN, GENOP) do { \
998 insns[i++] = INSN; \
999 GENOP##rr(s, d); \
1000 } while (0)
1001 #define GEN64(INSN, GENOP) do { \
1002 if (X86_TARGET_64BIT) \
1003 GEN(INSN, GENOP); \
1004 } while (0)
1005 #define GEN1(INSN, GENOP, OP) do { \
1006 insns[i++] = INSN; \
1007 GENOP##rr(OP, s, d); \
1008 } while (0)
1009 #define GENA(INSN, GENOP) do { \
1010 if (VALID_REG8(s) && VALID_REG8(d)) \
1011 GEN(INSN "b", GENOP##B); \
1012 GEN(INSN "w", GENOP##W); \
1013 GEN(INSN "l", GENOP##L); \
1014 GEN64(INSN "q", GENOP##Q); \
1015 } while (0)
1016 GENA("adc", ADC);
1017 GENA("add", ADD);
1018 GENA("and", AND);
1019 GENA("cmp", CMP);
1020 GENA("or", OR);
1021 GENA("sbb", SBB);
1022 GENA("sub", SUB);
1023 GENA("xor", XOR);
1024 GENA("mov", MOV);
1025 GEN("btw", BTW);
1026 GEN("btl", BTL);
1027 GEN64("btq", BTQ);
1028 GEN("btcw", BTCW);
1029 GEN("btcl", BTCL);
1030 GEN64("btcq", BTCQ);
1031 GEN("btrw", BTRW);
1032 GEN("btrl", BTRL);
1033 GEN64("btrq", BTRQ);
1034 GEN("btsw", BTSW);
1035 GEN("btsl", BTSL);
1036 GEN64("btsq", BTSQ);
1037 GEN("imulw", IMULW);
1038 GEN("imull", IMULL);
1039 GEN64("imulq", IMULQ);
1040 GEN1("cmove", CMOVW, X86_CC_Z);
1041 GEN1("cmove", CMOVL, X86_CC_Z);
1042 if (X86_TARGET_64BIT)
1043 GEN1("cmove", CMOVQ, X86_CC_Z);
1044 GENA("test", TEST);
1045 GENA("cmpxchg", CMPXCHG);
1046 GENA("xadd", XADD);
1047 GENA("xchg", XCHG);
1048 GEN("bsfw", BSFW);
1049 GEN("bsfl", BSFL);
1050 GEN64("bsfq", BSFQ);
1051 GEN("bsrw", BSRW);
1052 GEN("bsrl", BSRL);
1053 GEN64("bsrq", BSRQ);
1054 if (VALID_REG8(s)) {
1055 GEN("movsbw", MOVSBW);
1056 GEN("movsbl", MOVSBL);
1057 GEN64("movsbq", MOVSBQ);
1058 GEN("movzbw", MOVZBW);
1059 GEN("movzbl", MOVZBL);
1060 GEN64("movzbq", MOVZBQ);
1061 }
1062 GEN("movswl", MOVSWL);
1063 GEN64("movswq", MOVSWQ);
1064 GEN("movzwl", MOVZWL);
1065 GEN64("movzwq", MOVZWQ);
1066 GEN64("movslq", MOVSLQ);
1067 #undef GENA
1068 #undef GEN1
1069 #undef GEN64
1070 #undef GEN
1071 int last_insn = i;
1072 uint8 *e = get_target();
1073
1074 uint8 *p = b;
1075 i = 0;
1076 while (p < e) {
1077 int n = disass_x86(buffer, (uintptr)p);
1078 insn_t ii;
1079 parse_insn(&ii, buffer);
1080
1081 if (!check_reg_reg(&ii, insns[i], s, d)) {
1082 show_instruction(buffer, p);
1083 n_failures++;
1084 }
1085
1086 p += n;
1087 i += 1;
1088 n_tests++;
1089 }
1090 if (i != last_insn)
1091 abort();
1092 }
1093 }
1094 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1095 n_all_tests += n_tests;
1096 n_all_failures += n_failures;
1097 #endif
1098
1099 #if TEST_INST_ALU_CNT_REG
1100 printf("Testing cl,reg forms\n");
1101 n_tests = n_failures = 0;
1102 for (int d = 0; d < X86_MAX_ALU_REGS; d++) {
1103 set_target(block);
1104 uint8 *b = get_target();
1105 int i = 0;
1106 #define GEN(INSN, GENOP) do { \
1107 insns[i++] = INSN; \
1108 GENOP##rr(X86_CL, d); \
1109 } while (0)
1110 #define GEN64(INSN, GENOP) do { \
1111 if (X86_TARGET_64BIT) \
1112 GEN(INSN, GENOP); \
1113 } while (0)
1114 #define GENA(INSN, GENOP) do { \
1115 if (VALID_REG8(d)) \
1116 GEN(INSN "b", GENOP##B); \
1117 GEN(INSN "w", GENOP##W); \
1118 GEN(INSN "l", GENOP##L); \
1119 GEN64(INSN "q", GENOP##Q); \
1120 } while (0)
1121 GENA("rol", ROL);
1122 GENA("ror", ROR);
1123 GENA("rcl", RCL);
1124 GENA("rcr", RCR);
1125 GENA("shl", SHL);
1126 GENA("shr", SHR);
1127 GENA("sar", SAR);
1128 #undef GENA
1129 #undef GEN64
1130 #undef GEN
1131 int last_insn = i;
1132 uint8 *e = get_target();
1133
1134 uint8 *p = b;
1135 i = 0;
1136 while (p < e) {
1137 int n = disass_x86(buffer, (uintptr)p);
1138 insn_t ii;
1139 parse_insn(&ii, buffer);
1140
1141 if (!check_reg_reg(&ii, insns[i], X86_CL, d)) {
1142 show_instruction(buffer, p);
1143 n_failures++;
1144 }
1145
1146 p += n;
1147 i += 1;
1148 n_tests++;
1149 }
1150 if (i != last_insn)
1151 abort();
1152 }
1153 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1154 n_all_tests += n_tests;
1155 n_all_failures += n_failures;
1156 #endif
1157
1158 static const uint32 imm_table[] = {
1159 0x00000000, 0x00000001, 0x00000002, 0x00000004,
1160 0x00000008, 0x00000010, 0x00000020, 0x00000040,
1161 0x00000080, 0x000000fe, 0x000000ff, 0x00000100,
1162 0x00000101, 0x00000102, 0xfffffffe, 0xffffffff,
1163 0x00000000, 0x10000000, 0x20000000, 0x30000000,
1164 0x40000000, 0x50000000, 0x60000000, 0x70000000,
1165 0x80000000, 0x90000000, 0xa0000000, 0xb0000000,
1166 0xc0000000, 0xd0000000, 0xe0000000, 0xf0000000,
1167 0xfffffffd, 0xfffffffe, 0xffffffff, 0x00000001,
1168 0x00000002, 0x00000003, 0x11111111, 0x22222222,
1169 0x33333333, 0x44444444, 0x55555555, 0x66666666,
1170 0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa,
1171 0xbbbbbbbb, 0xcccccccc, 0xdddddddd, 0xeeeeeeee,
1172 };
1173 const int n_imm_tab_count = sizeof(imm_table)/sizeof(imm_table[0]);
1174
1175 #if TEST_INST_ALU_IMM_REG
1176 printf("Testing imm,reg forms\n");
1177 n_tests = n_failures = 0;
1178 for (int j = 0; j < n_imm_tab_count; j++) {
1179 const uint32 value = imm_table[j];
1180 for (int d = 0; d < X86_MAX_ALU_REGS; d++) {
1181 set_target(block);
1182 uint8 *b = get_target();
1183 int i = 0;
1184 #define GEN(INSN, GENOP) do { \
1185 insns[i] = INSN; \
1186 modes[i] = -1; \
1187 i++; GENOP##ir(value, d); \
1188 } while (0)
1189 #define GEN64(INSN, GENOP) do { \
1190 if (X86_TARGET_64BIT) \
1191 GEN(INSN, GENOP); \
1192 } while (0)
1193 #define GENM(INSN, GENOP, MODE) do { \
1194 insns[i] = INSN; \
1195 modes[i] = MODE; \
1196 i++; GENOP##ir(value, d); \
1197 } while (0)
1198 #define GENM64(INSN, GENOP, MODE) do { \
1199 if (X86_TARGET_64BIT) \
1200 GENM(INSN, GENOP, MODE); \
1201 } while (0)
1202 #define GENA(INSN, GENOP) do { \
1203 if (VALID_REG8(d)) \
1204 GEN(INSN "b", GENOP##B); \
1205 GEN(INSN "w", GENOP##W); \
1206 GEN(INSN "l", GENOP##L); \
1207 GEN64(INSN "q", GENOP##Q); \
1208 } while (0)
1209 #define GENAM(INSN, GENOP, MODE) do { \
1210 if (VALID_REG8(d)) \
1211 GENM(INSN "b", GENOP##B, MODE); \
1212 GENM(INSN "w", GENOP##W, MODE); \
1213 GENM(INSN "l", GENOP##L, MODE); \
1214 GENM64(INSN "q", GENOP##Q, MODE); \
1215 } while (0)
1216 GENA("adc", ADC);
1217 GENA("add", ADD);
1218 GENA("and", AND);
1219 GENA("cmp", CMP);
1220 GENA("or", OR);
1221 GENA("sbb", SBB);
1222 GENA("sub", SUB);
1223 GENA("xor", XOR);
1224 GENA("mov", MOV);
1225 GENM("btw", BTW, 1);
1226 GENM("btl", BTL, 1);
1227 GENM64("btq", BTQ, 1);
1228 GENM("btcw", BTCW, 1);
1229 GENM("btcl", BTCL, 1);
1230 GENM64("btcq", BTCQ, 1);
1231 GENM("btrw", BTRW, 1);
1232 GENM("btrl", BTRL, 1);
1233 GENM64("btrq", BTRQ, 1);
1234 GENM("btsw", BTSW, 1);
1235 GENM("btsl", BTSL, 1);
1236 GENM64("btsq", BTSQ, 1);
1237 if (value != 1) {
1238 GENAM("rol", ROL, 1);
1239 GENAM("ror", ROR, 1);
1240 GENAM("rcl", RCL, 1);
1241 GENAM("rcr", RCR, 1);
1242 GENAM("shl", SHL, 1);
1243 GENAM("shr", SHR, 1);
1244 GENAM("sar", SAR, 1);
1245 }
1246 GENA("test", TEST);
1247 #undef GENAM
1248 #undef GENA
1249 #undef GENM64
1250 #undef GENM
1251 #undef GEN64
1252 #undef GEN
1253 int last_insn = i;
1254 uint8 *e = get_target();
1255
1256 uint8 *p = b;
1257 i = 0;
1258 while (p < e) {
1259 int n = disass_x86(buffer, (uintptr)p);
1260 insn_t ii;
1261 parse_insn(&ii, buffer);
1262
1263 if (!check_imm_reg(&ii, insns[i], value, d, modes[i])) {
1264 show_instruction(buffer, p);
1265 n_failures++;
1266 }
1267
1268 p += n;
1269 i += 1;
1270 n_tests++;
1271 }
1272 if (i != last_insn)
1273 abort();
1274 }
1275 }
1276 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1277 n_all_tests += n_tests;
1278 n_all_failures += n_failures;
1279 #endif
1280
1281 static const uint32 off_table[] = {
1282 0x00000000,
1283 0x00000001,
1284 0x00000040,
1285 0x00000080,
1286 0x000000ff,
1287 0x00000100,
1288 0xfffffffe,
1289 0xffffffff,
1290 };
1291 const int off_table_count = sizeof(off_table) / sizeof(off_table[0]);
1292
1293 #if TEST_INST_ALU_MEM_REG
1294 printf("Testing mem,reg forms\n");
1295 n_tests = n_failures = 0;
1296 for (int d = 0; d < off_table_count; d++) {
1297 const uint32 D = off_table[d];
1298 for (int B = -1; B < X86_MAX_ALU_REGS; B++) {
1299 for (int I = -1; I < X86_MAX_ALU_REGS; I++) {
1300 if (I == X86_RSP)
1301 continue;
1302 for (int S = 1; S < 16; S *= 2) {
1303 if (I == -1 && S > 1)
1304 continue;
1305 for (int r = 0; r < X86_MAX_ALU_REGS; r++) {
1306 set_target(block);
1307 uint8 *b = get_target();
1308 int i = 0;
1309 #define GEN(INSN, GENOP) do { \
1310 insns[i++] = INSN; \
1311 GENOP##mr(D, B, I, S, r); \
1312 } while (0)
1313 #define GEN64(INSN, GENOP) do { \
1314 if (X86_TARGET_64BIT) \
1315 GEN(INSN, GENOP); \
1316 } while (0)
1317 #define GENA(INSN, GENOP) do { \
1318 if (VALID_REG8(r)) \
1319 GEN(INSN "b", GENOP##B); \
1320 GEN(INSN "w", GENOP##W); \
1321 GEN(INSN "l", GENOP##L); \
1322 GEN64(INSN "q", GENOP##Q); \
1323 } while (0)
1324 GENA("adc", ADC);
1325 GENA("add", ADD);
1326 GENA("and", AND);
1327 GENA("cmp", CMP);
1328 GENA("or", OR);
1329 GENA("sbb", SBB);
1330 GENA("sub", SUB);
1331 GENA("xor", XOR);
1332 GENA("mov", MOV);
1333 GEN("imulw", IMULW);
1334 GEN("imull", IMULL);
1335 GEN64("imulq", IMULQ);
1336 GEN("bsfw", BSFW);
1337 GEN("bsfl", BSFL);
1338 GEN64("bsfq", BSFQ);
1339 GEN("bsrw", BSRW);
1340 GEN("bsrl", BSRL);
1341 GEN64("bsrq", BSRQ);
1342 GEN("movsbw", MOVSBW);
1343 GEN("movsbl", MOVSBL);
1344 GEN64("movsbq", MOVSBQ);
1345 GEN("movzbw", MOVZBW);
1346 GEN("movzbl", MOVZBL);
1347 GEN64("movzbq", MOVZBQ);
1348 GEN("movswl", MOVSWL);
1349 GEN64("movswq", MOVSWQ);
1350 GEN("movzwl", MOVZWL);
1351 GEN64("movzwq", MOVZWQ);
1352 GEN64("movslq", MOVSLQ);
1353 #undef GENA
1354 #undef GEN64
1355 #undef GEN
1356 int last_insn = i;
1357 uint8 *e = get_target();
1358
1359 uint8 *p = b;
1360 i = 0;
1361 while (p < e) {
1362 int n = disass_x86(buffer, (uintptr)p);
1363 insn_t ii;
1364 parse_insn(&ii, buffer);
1365
1366 if (!check_mem_reg(&ii, insns[i], D, B, I, S, r)) {
1367 show_instruction(buffer, p);
1368 n_failures++;
1369 }
1370
1371 p += n;
1372 i += 1;
1373 n_tests++;
1374 show_status(n_tests);
1375 }
1376 if (i != last_insn)
1377 abort();
1378 }
1379 }
1380 }
1381 }
1382 }
1383 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1384 n_all_tests += n_tests;
1385 n_all_failures += n_failures;
1386 #endif
1387
1388 #if TEST_INST_FPU_UNARY
1389 printf("Testing FPU unary forms\n");
1390 n_tests = n_failures = 0;
1391 {
1392 set_target(block);
1393 uint8 *b = get_target();
1394 int i = 0;
1395 #define GEN(INSN, GENOP) do { \
1396 insns[i++] = INSN; \
1397 GENOP(); \
1398 } while (0)
1399 GEN("f2xm1", F2XM1);
1400 GEN("fabs", FABS);
1401 GEN("fchs", FCHS);
1402 GEN("fcompp", FCOMPP);
1403 GEN("fcos", FCOS);
1404 GEN("fdecstp", FDECSTP);
1405 GEN("fincstp", FINCSTP);
1406 GEN("fld1", FLD1);
1407 GEN("fldl2t", FLDL2T);
1408 GEN("fldl2e", FLDL2E);
1409 GEN("fldpi", FLDPI);
1410 GEN("fldlg2", FLDLG2);
1411 GEN("fldln2", FLDLN2);
1412 GEN("fldz", FLDZ);
1413 GEN("fnop", FNOP);
1414 GEN("fpatan", FPATAN);
1415 GEN("fprem", FPREM);
1416 GEN("fprem1", FPREM1);
1417 GEN("fptan", FPTAN);
1418 GEN("frndint", FRNDINT);
1419 GEN("fscale", FSCALE);
1420 GEN("fsin", FSIN);
1421 GEN("fsincos", FSINCOS);
1422 GEN("fsqrt", FSQRT);
1423 GEN("ftst", FTST);
1424 GEN("fucompp", FUCOMPP);
1425 GEN("fxam", FXAM);
1426 GEN("fxtract", FXTRACT);
1427 GEN("fyl2x", FYL2X);
1428 GEN("fyl2xp1", FYL2XP1);
1429 #undef GEN
1430 int last_insn = i;
1431 uint8 *e = get_target();
1432
1433 uint8 *p = b;
1434 i = 0;
1435 while (p < e) {
1436 int n = disass_x86(buffer, (uintptr)p);
1437 insn_t ii;
1438 parse_insn(&ii, buffer);
1439
1440 if (!check_unary(&ii, insns[i])) {
1441 show_instruction(buffer, p);
1442 n_failures++;
1443 }
1444
1445 p += n;
1446 i += 1;
1447 n_tests++;
1448 }
1449 if (i != last_insn)
1450 abort();
1451 }
1452 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1453 n_all_tests += n_tests;
1454 n_all_failures += n_failures;
1455 #endif
1456
1457 #if TEST_INST_FPU_REG
1458 printf("Testing FPU reg forms\n");
1459 n_tests = n_failures = 0;
1460 for (int r = 0; r < X86_MAX_FPU_REGS; r++) {
1461 set_target(block);
1462 uint8 *b = get_target();
1463 int i = 0;
1464 #define GENr(INSN, GENOP) do { \
1465 insns[i] = INSN; \
1466 modes[i] = 0; \
1467 i++, GENOP##r(r); \
1468 } while (0)
1469 #define GENr0(INSN, GENOP) do { \
1470 insns[i] = INSN; \
1471 modes[i] = 1; \
1472 i++, GENOP##r0(r); \
1473 } while (0)
1474 #define GEN0r(INSN, GENOP) do { \
1475 insns[i] = INSN; \
1476 modes[i] = 2; \
1477 i++, GENOP##0r(r); \
1478 } while (0)
1479 GENr("fcom", FCOM);
1480 GENr("fcomp", FCOMP);
1481 GENr("ffree", FFREE);
1482 GENr("fxch", FXCH);
1483 GENr("fst", FST);
1484 GENr("fstp", FSTP);
1485 GENr("fucom", FUCOM);
1486 GENr("fucomp", FUCOMP);
1487 GENr0("fadd", FADD);
1488 GENr0("fcmovb", FCMOVB);
1489 GENr0("fcmove", FCMOVE);
1490 GENr0("fcmovbe", FCMOVBE);
1491 GENr0("fcmovu", FCMOVU);
1492 GENr0("fcmovnb", FCMOVNB);
1493 GENr0("fcmovne", FCMOVNE);
1494 GENr0("fcmovnbe", FCMOVNBE);
1495 GENr0("fcmovnu", FCMOVNU);
1496 GENr0("fcomi", FCOMI);
1497 GENr0("fcomip", FCOMIP);
1498 GENr0("fucomi", FUCOMI);
1499 GENr0("fucomip", FUCOMIP);
1500 GENr0("fdiv", FDIV);
1501 GENr0("fdivr", FDIVR);
1502 GENr0("fmul", FMUL);
1503 GENr0("fsub", FSUB);
1504 GENr0("fsubr", FSUBR);
1505 #undef GEN0r
1506 #undef GENr0
1507 #undef GENr
1508 int last_insn = i;
1509 uint8 *e = get_target();
1510
1511 uint8 *p = b;
1512 i = 0;
1513 while (p < e) {
1514 int n = disass_x86(buffer, (uintptr)p);
1515 insn_t ii;
1516 parse_insn(&ii, buffer);
1517
1518 switch (modes[i]) {
1519 case 0:
1520 if (!check_reg(&ii, insns[i], r)) {
1521 show_instruction(buffer, p);
1522 n_failures++;
1523 }
1524 break;
1525 case 1:
1526 if (!check_reg_reg(&ii, insns[i], r, 0)) {
1527 show_instruction(buffer, p);
1528 n_failures++;
1529 }
1530 break;
1531 case 2:
1532 if (!check_reg_reg(&ii, insns[i], 0, r)) {
1533 show_instruction(buffer, p);
1534 n_failures++;
1535 }
1536 break;
1537 }
1538
1539 p += n;
1540 i += 1;
1541 n_tests++;
1542 }
1543 if (i != last_insn)
1544 abort();
1545 }
1546 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1547 n_all_tests += n_tests;
1548 n_all_failures += n_failures;
1549 #endif
1550
1551 #if TEST_INST_FPU_MEM
1552 printf("Testing FPU mem forms\n");
1553 n_tests = n_failures = 0;
1554 for (int d = 0; d < off_table_count; d++) {
1555 const uint32 D = off_table[d];
1556 for (int B = -1; B < X86_MAX_ALU_REGS; B++) {
1557 for (int I = -1; I < X86_MAX_ALU_REGS; I++) {
1558 if (I == X86_RSP)
1559 continue;
1560 for (int S = 1; S < 16; S *= 2) {
1561 if (I == -1 && S > 1)
1562 continue;
1563 set_target(block);
1564 uint8 *b = get_target();
1565 int i = 0;
1566 #define GEN(INSN, GENOP) do { \
1567 insns[i++] = INSN; \
1568 GENOP##m(D, B, I, S); \
1569 } while (0)
1570 GEN("fadds", FADDS);
1571 GEN("faddl", FADDD);
1572 GEN("fiadd", FIADDW);
1573 GEN("fiaddl", FIADDL);
1574 GEN("fbld", FBLD);
1575 GEN("fbstp", FBSTP);
1576 GEN("fcoms", FCOMS);
1577 GEN("fcoml", FCOMD);
1578 GEN("fcomps", FCOMPS);
1579 GEN("fcompl", FCOMPD);
1580 GEN("fdivs", FDIVS);
1581 GEN("fdivl", FDIVD);
1582 GEN("fidiv", FIDIVW);
1583 GEN("fidivl", FIDIVL);
1584 GEN("fdivrs", FDIVRS);
1585 GEN("fdivrl", FDIVRD);
1586 GEN("fidivr", FIDIVRW);
1587 GEN("fidivrl", FIDIVRL);
1588 GEN("ficom", FICOMW);
1589 GEN("ficoml", FICOML);
1590 GEN("ficomp", FICOMPW);
1591 GEN("ficompl", FICOMPL);
1592 GEN("fild", FILDW);
1593 GEN("fildl", FILDL);
1594 GEN("fildll", FILDQ);
1595 GEN("fist", FISTW);
1596 GEN("fistl", FISTL);
1597 GEN("fistp", FISTPW);
1598 GEN("fistpl", FISTPL);
1599 GEN("fistpll", FISTPQ);
1600 GEN("fisttp", FISTTPW);
1601 GEN("fisttpl", FISTTPL);
1602 GEN("fisttpll", FISTTPQ);
1603 GEN("flds", FLDS);
1604 GEN("fldl", FLDD);
1605 GEN("fldt", FLDT);
1606 GEN("fmuls", FMULS);
1607 GEN("fmull", FMULD);
1608 GEN("fimul", FIMULW);
1609 GEN("fimull", FIMULL);
1610 GEN("fsts", FSTS);
1611 GEN("fstl", FSTD);
1612 GEN("fstps", FSTPS);
1613 GEN("fstpl", FSTPD);
1614 GEN("fstpt", FSTPT);
1615 GEN("fsubs", FSUBS);
1616 GEN("fsubl", FSUBD);
1617 GEN("fisub", FISUBW);
1618 GEN("fisubl", FISUBL);
1619 GEN("fsubrs", FSUBRS);
1620 GEN("fsubrl", FSUBRD);
1621 GEN("fisubr", FISUBRW);
1622 GEN("fisubrl", FISUBRL);
1623 #undef GEN
1624 int last_insn = i;
1625 uint8 *e = get_target();
1626
1627 uint8 *p = b;
1628 i = 0;
1629 while (p < e) {
1630 int n = disass_x86(buffer, (uintptr)p);
1631 insn_t ii;
1632 parse_insn(&ii, buffer);
1633
1634 if (!check_mem(&ii, insns[i], D, B, I, S)) {
1635 show_instruction(buffer, p);
1636 n_failures++;
1637 }
1638
1639 p += n;
1640 i += 1;
1641 n_tests++;
1642 show_status(n_tests);
1643 }
1644 if (i != last_insn)
1645 abort();
1646 }
1647 }
1648 }
1649 }
1650 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1651 n_all_tests += n_tests;
1652 n_all_failures += n_failures;
1653 #endif
1654
1655 #if TEST_INST_MMX_REG_REG
1656 printf("Testing MMX reg,reg forms\n");
1657 n_tests = n_failures = 0;
1658 for (int s = 0; s < X86_MAX_MMX_REGS; s++) {
1659 for (int d = 0; d < X86_MAX_MMX_REGS; d++) {
1660 set_target(block);
1661 uint8 *b = get_target();
1662 int i = 0;
1663 #define GEN(INSN, GENOP) do { \
1664 insns[i++] = INSN; \
1665 MMX_##GENOP##rr(s, d); \
1666 } while (0)
1667 #define GEN64(INSN, GENOP) do { \
1668 if (X86_TARGET_64BIT) \
1669 GEN(INSN, GENOP); \
1670 } while (0)
1671 GEN("movq", MOVQ);
1672 GEN("packsswb", PACKSSWB);
1673 GEN("packssdw", PACKSSDW);
1674 GEN("packuswb", PACKUSWB);
1675 GEN("paddb", PADDB);
1676 GEN("paddw", PADDW);
1677 GEN("paddd", PADDD);
1678 GEN("paddq", PADDQ);
1679 GEN("paddsb", PADDSB);
1680 GEN("paddsw", PADDSW);
1681 GEN("paddusb", PADDUSB);
1682 GEN("paddusw", PADDUSW);
1683 GEN("pand", PAND);
1684 GEN("pandn", PANDN);
1685 GEN("pavgb", PAVGB);
1686 GEN("pavgw", PAVGW);
1687 GEN("pcmpeqb", PCMPEQB);
1688 GEN("pcmpeqw", PCMPEQW);
1689 GEN("pcmpeqd", PCMPEQD);
1690 GEN("pcmpgtb", PCMPGTB);
1691 GEN("pcmpgtw", PCMPGTW);
1692 GEN("pcmpgtd", PCMPGTD);
1693 GEN("pmaddwd", PMADDWD);
1694 GEN("pmaxsw", PMAXSW);
1695 GEN("pmaxub", PMAXUB);
1696 GEN("pminsw", PMINSW);
1697 GEN("pminub", PMINUB);
1698 GEN("pmulhuw", PMULHUW);
1699 GEN("pmulhw", PMULHW);
1700 GEN("pmullw", PMULLW);
1701 GEN("pmuludq", PMULUDQ);
1702 GEN("por", POR);
1703 GEN("psadbw", PSADBW);
1704 GEN("psllw", PSLLW);
1705 GEN("pslld", PSLLD);
1706 GEN("psllq", PSLLQ);
1707 GEN("psraw", PSRAW);
1708 GEN("psrad", PSRAD);
1709 GEN("psrlw", PSRLW);
1710 GEN("psrld", PSRLD);
1711 GEN("psrlq", PSRLQ);
1712 GEN("psubb", PSUBB);
1713 GEN("psubw", PSUBW);
1714 GEN("psubd", PSUBD);
1715 GEN("psubq", PSUBQ);
1716 GEN("psubsb", PSUBSB);
1717 GEN("psubsw", PSUBSW);
1718 GEN("psubusb", PSUBUSB);
1719 GEN("psubusw", PSUBUSW);
1720 GEN("punpckhbw", PUNPCKHBW);
1721 GEN("punpckhwd", PUNPCKHWD);
1722 GEN("punpckhdq", PUNPCKHDQ);
1723 GEN("punpcklbw", PUNPCKLBW);
1724 GEN("punpcklwd", PUNPCKLWD);
1725 GEN("punpckldq", PUNPCKLDQ);
1726 GEN("pxor", PXOR);
1727 GEN("pabsb", PABSB);
1728 GEN("pabsw", PABSW);
1729 GEN("pabsd", PABSD);
1730 GEN("phaddw", PHADDW);
1731 GEN("phaddd", PHADDD);
1732 GEN("phaddsw", PHADDSW);
1733 GEN("phsubw", PHSUBW);
1734 GEN("phsubd", PHSUBD);
1735 GEN("phsubsw", PHSUBSW);
1736 GEN("pmaddubsw", PMADDUBSW);
1737 GEN("pmulhrsw", PMULHRSW);
1738 GEN("pshufb", PSHUFB);
1739 GEN("psignb", PSIGNB);
1740 GEN("psignw", PSIGNW);
1741 GEN("psignd", PSIGND);
1742 #undef GEN64
1743 #undef GEN
1744 int last_insn = i;
1745 uint8 *e = get_target();
1746
1747 uint8 *p = b;
1748 i = 0;
1749 while (p < e) {
1750 int n = disass_x86(buffer, (uintptr)p);
1751 insn_t ii;
1752 parse_insn(&ii, buffer);
1753
1754 if (!check_reg_reg(&ii, insns[i], s, d)) {
1755 show_instruction(buffer, p);
1756 n_failures++;
1757 }
1758
1759 p += n;
1760 i += 1;
1761 n_tests++;
1762 }
1763 if (i != last_insn)
1764 abort();
1765 }
1766 }
1767 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1768 n_all_tests += n_tests;
1769 n_all_failures += n_failures;
1770 #endif
1771
1772 static const uint8 imm8_table[] = {
1773 0x00, 0x01, 0x02, 0x03,
1774 0x06, 0x07, 0x08, 0x09,
1775 0x0e, 0x0f, 0x10, 0x11,
1776 0x1e, 0x1f, 0x20, 0x21,
1777 0xfc, 0xfd, 0xfe, 0xff,
1778 };
1779 const int n_imm8_tab_count = sizeof(imm8_table)/sizeof(imm8_table[0]);
1780
1781 #if TEST_INST_MMX_IMM_REG
1782 printf("Testing imm,reg forms\n");
1783 n_tests = n_failures = 0;
1784 for (int j = 0; j < n_imm8_tab_count; j++) {
1785 const uint8 value = imm8_table[j];
1786 for (int d = 0; d < X86_MAX_MMX_REGS; d++) {
1787 set_target(block);
1788 uint8 *b = get_target();
1789 int i = 0;
1790 #define GEN(INSN, GENOP) do { \
1791 insns[i] = INSN; \
1792 modes[i] = 1; \
1793 i++; MMX_##GENOP##ir(value, d); \
1794 } while (0)
1795 GEN("psllw", PSLLW);
1796 GEN("pslld", PSLLD);
1797 GEN("psllq", PSLLQ);
1798 GEN("psraw", PSRAW);
1799 GEN("psrad", PSRAD);
1800 GEN("psrlw", PSRLW);
1801 GEN("psrld", PSRLD);
1802 GEN("psrlq", PSRLQ);
1803 #undef GEN
1804 int last_insn = i;
1805 uint8 *e = get_target();
1806
1807 uint8 *p = b;
1808 i = 0;
1809 while (p < e) {
1810 int n = disass_x86(buffer, (uintptr)p);
1811 insn_t ii;
1812 parse_insn(&ii, buffer);
1813
1814 if (!check_imm_reg(&ii, insns[i], value, d, modes[i])) {
1815 show_instruction(buffer, p);
1816 n_failures++;
1817 }
1818
1819 p += n;
1820 i += 1;
1821 n_tests++;
1822 }
1823 if (i != last_insn)
1824 abort();
1825 }
1826 }
1827 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1828 n_all_tests += n_tests;
1829 n_all_failures += n_failures;
1830 #endif
1831
1832 #if TEST_INST_MMX_MEM_REG
1833 printf("Testing MMX mem,reg forms\n");
1834 n_tests = n_failures = 0;
1835 for (int d = 0; d < off_table_count; d++) {
1836 const uint32 D = off_table[d];
1837 for (int B = -1; B < X86_MAX_ALU_REGS; B++) {
1838 for (int I = -1; I < X86_MAX_ALU_REGS; I++) {
1839 if (I == X86_RSP)
1840 continue;
1841 for (int S = 1; S < 16; S *= 2) {
1842 if (I == -1 && S > 1)
1843 continue;
1844 for (int r = 0; r < X86_MAX_MMX_REGS; r++) {
1845 set_target(block);
1846 uint8 *b = get_target();
1847 int i = 0;
1848 #define _GENrm(INSN, GENOP) do { \
1849 insns[i] = INSN; \
1850 modes[i] = 0; \
1851 i++; MMX_##GENOP##rm(r, D, B, I, S); \
1852 } while (0)
1853 #define _GENmr(INSN, GENOP) do { \
1854 insns[i] = INSN; \
1855 modes[i] = 1; \
1856 i++; MMX_##GENOP##mr(D, B, I, S, r); \
1857 } while (0)
1858 #define GEN(INSN, GENOP) do { \
1859 _GENmr(INSN, GENOP); \
1860 } while (0)
1861 _GENmr("movd", MOVD);
1862 _GENrm("movd", MOVD);
1863 _GENmr("movq", MOVQ);
1864 _GENrm("movq", MOVQ);
1865 GEN("packsswb", PACKSSWB);
1866 GEN("packssdw", PACKSSDW);
1867 GEN("packuswb", PACKUSWB);
1868 GEN("paddb", PADDB);
1869 GEN("paddw", PADDW);
1870 GEN("paddd", PADDD);
1871 GEN("paddq", PADDQ);
1872 GEN("paddsb", PADDSB);
1873 GEN("paddsw", PADDSW);
1874 GEN("paddusb", PADDUSB);
1875 GEN("paddusw", PADDUSW);
1876 GEN("pand", PAND);
1877 GEN("pandn", PANDN);
1878 GEN("pavgb", PAVGB);
1879 GEN("pavgw", PAVGW);
1880 GEN("pcmpeqb", PCMPEQB);
1881 GEN("pcmpeqw", PCMPEQW);
1882 GEN("pcmpeqd", PCMPEQD);
1883 GEN("pcmpgtb", PCMPGTB);
1884 GEN("pcmpgtw", PCMPGTW);
1885 GEN("pcmpgtd", PCMPGTD);
1886 GEN("pmaddwd", PMADDWD);
1887 GEN("pmaxsw", PMAXSW);
1888 GEN("pmaxub", PMAXUB);
1889 GEN("pminsw", PMINSW);
1890 GEN("pminub", PMINUB);
1891 GEN("pmulhuw", PMULHUW);
1892 GEN("pmulhw", PMULHW);
1893 GEN("pmullw", PMULLW);
1894 GEN("pmuludq", PMULUDQ);
1895 GEN("por", POR);
1896 GEN("psadbw", PSADBW);
1897 GEN("psllw", PSLLW);
1898 GEN("pslld", PSLLD);
1899 GEN("psllq", PSLLQ);
1900 GEN("psraw", PSRAW);
1901 GEN("psrad", PSRAD);
1902 GEN("psrlw", PSRLW);
1903 GEN("psrld", PSRLD);
1904 GEN("psrlq", PSRLQ);
1905 GEN("psubb", PSUBB);
1906 GEN("psubw", PSUBW);
1907 GEN("psubd", PSUBD);
1908 GEN("psubq", PSUBQ);
1909 GEN("psubsb", PSUBSB);
1910 GEN("psubsw", PSUBSW);
1911 GEN("psubusb", PSUBUSB);
1912 GEN("psubusw", PSUBUSW);
1913 GEN("punpckhbw", PUNPCKHBW);
1914 GEN("punpckhwd", PUNPCKHWD);
1915 GEN("punpckhdq", PUNPCKHDQ);
1916 GEN("punpcklbw", PUNPCKLBW);
1917 GEN("punpcklwd", PUNPCKLWD);
1918 GEN("punpckldq", PUNPCKLDQ);
1919 GEN("pxor", PXOR);
1920 GEN("pabsb", PABSB);
1921 GEN("pabsw", PABSW);
1922 GEN("pabsd", PABSD);
1923 GEN("phaddw", PHADDW);
1924 GEN("phaddd", PHADDD);
1925 GEN("phaddsw", PHADDSW);
1926 GEN("phsubw", PHSUBW);
1927 GEN("phsubd", PHSUBD);
1928 GEN("phsubsw", PHSUBSW);
1929 GEN("pmaddubsw", PMADDUBSW);
1930 GEN("pmulhrsw", PMULHRSW);
1931 GEN("pshufb", PSHUFB);
1932 GEN("psignb", PSIGNB);
1933 GEN("psignw", PSIGNW);
1934 GEN("psignd", PSIGND);
1935 #undef GEN
1936 #undef _GENmr
1937 #undef _GENrm
1938 int last_insn = i;
1939 uint8 *e = get_target();
1940
1941 uint8 *p = b;
1942 i = 0;
1943 while (p < e) {
1944 int n = disass_x86(buffer, (uintptr)p);
1945 insn_t ii;
1946 parse_insn(&ii, buffer);
1947
1948 if (!check_mem_reg(&ii, insns[i], D, B, I, S, r, modes[i])) {
1949 show_instruction(buffer, p);
1950 n_failures++;
1951 }
1952
1953 p += n;
1954 i += 1;
1955 n_tests++;
1956 show_status(n_tests);
1957 }
1958 if (i != last_insn)
1959 abort();
1960 }
1961 }
1962 }
1963 }
1964 }
1965 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1966 n_all_tests += n_tests;
1967 n_all_failures += n_failures;
1968 #endif
1969
1970 #if TEST_INST_SSE_REG_REG
1971 printf("Testing SSE reg,reg forms\n");
1972 n_tests = n_failures = 0;
1973 for (int s = 0; s < X86_MAX_SSE_REGS; s++) {
1974 for (int d = 0; d < X86_MAX_SSE_REGS; d++) {
1975 set_target(block);
1976 uint8 *b = get_target();
1977 int i = 0;
1978 #define GEN(INSN, GENOP) do { \
1979 insns[i++] = INSN; \
1980 GENOP##rr(s, d); \
1981 } while (0)
1982 #define GEN64(INSN, GENOP) do { \
1983 if (X86_TARGET_64BIT) \
1984 GEN(INSN, GENOP); \
1985 } while (0)
1986 #define GEN1(INSN, GENOP) do { \
1987 GEN(INSN "s", GENOP##S); \
1988 GEN(INSN "d", GENOP##D); \
1989 } while (0)
1990 #define GENA(INSN, GENOP) do { \
1991 GEN1(INSN "s", GENOP##S); \
1992 GEN1(INSN "p", GENOP##P); \
1993 } while (0)
1994 #define GENI(INSN, GENOP, IMM) do { \
1995 insns[i++] = INSN; \
1996 GENOP##rr(IMM, s, d); \
1997 } while (0)
1998 #define GENI1(INSN, GENOP, IMM) do { \
1999 GENI(INSN "s", GENOP##S, IMM); \
2000 GENI(INSN "d", GENOP##D, IMM); \
2001 } while (0)
2002 #define GENIA(INSN, GENOP, IMM) do { \
2003 GENI1(INSN "s", GENOP##S, IMM); \
2004 GENI1(INSN "p", GENOP##P, IMM); \
2005 } while (0)
2006 GEN1("andp", ANDP);
2007 GEN1("andnp", ANDNP);
2008 GEN1("orp", ORP);
2009 GEN1("xorp", XORP);
2010 GENA("add", ADD);
2011 GENA("sub", SUB);
2012 GENA("mul", MUL);
2013 GENA("div", DIV);
2014 GEN1("comis", COMIS);
2015 GEN1("ucomis", UCOMIS);
2016 GENA("min", MIN);
2017 GENA("max", MAX);
2018 GEN("rcpss", RCPSS);
2019 GEN("rcpps", RCPPS);
2020 GEN("rsqrtss", RSQRTSS);
2021 GEN("rsqrtps", RSQRTPS);
2022 GENA("sqrt", SQRT);
2023 GENIA("cmpeq", CMP, X86_SSE_CC_EQ);
2024 GENIA("cmplt", CMP, X86_SSE_CC_LT);
2025 GENIA("cmple", CMP, X86_SSE_CC_LE);
2026 GENIA("cmpunord", CMP, X86_SSE_CC_U);
2027 GENIA("cmpneq", CMP, X86_SSE_CC_NEQ);
2028 GENIA("cmpnlt", CMP, X86_SSE_CC_NLT);
2029 GENIA("cmpnle", CMP, X86_SSE_CC_NLE);
2030 GENIA("cmpord", CMP, X86_SSE_CC_O);
2031 GEN1("movap", MOVAP);
2032 GEN("movdqa", MOVDQA);
2033 GEN("movdqu", MOVDQU);
2034 GEN("movd", MOVDXD);
2035 GEN64("movd", MOVQXD); // FIXME: disass bug? "movq" expected
2036 GEN("movd", MOVDXS);
2037 GEN64("movd", MOVQXS); // FIXME: disass bug? "movq" expected
2038 GEN("cvtdq2pd", CVTDQ2PD);
2039 GEN("cvtdq2ps", CVTDQ2PS);
2040 GEN("cvtpd2dq", CVTPD2DQ);
2041 GEN("cvtpd2ps", CVTPD2PS);
2042 GEN("cvtps2dq", CVTPS2DQ);
2043 GEN("cvtps2pd", CVTPS2PD);
2044 GEN("cvtsd2si", CVTSD2SIL);
2045 GEN64("cvtsd2siq", CVTSD2SIQ);
2046 GEN("cvtsd2ss", CVTSD2SS);
2047 GEN("cvtsi2sd", CVTSI2SDL);
2048 GEN64("cvtsi2sdq", CVTSI2SDQ);
2049 GEN("cvtsi2ss", CVTSI2SSL);
2050 GEN64("cvtsi2ssq", CVTSI2SSQ);
2051 GEN("cvtss2sd", CVTSS2SD);
2052 GEN("cvtss2si", CVTSS2SIL);
2053 GEN64("cvtss2siq", CVTSS2SIQ);
2054 GEN("cvttpd2dq", CVTTPD2DQ);
2055 GEN("cvttps2dq", CVTTPS2DQ);
2056 GEN("cvttsd2si", CVTTSD2SIL);
2057 GEN64("cvttsd2siq", CVTTSD2SIQ);
2058 GEN("cvttss2si", CVTTSS2SIL);
2059 GEN64("cvttss2siq", CVTTSS2SIQ);
2060 if (s < 8) {
2061 // MMX source register
2062 GEN("cvtpi2pd", CVTPI2PD);
2063 GEN("cvtpi2ps", CVTPI2PS);
2064 }
2065 if (d < 8) {
2066 // MMX dest register
2067 GEN("cvtpd2pi", CVTPD2PI);
2068 GEN("cvtps2pi", CVTPS2PI);
2069 GEN("cvttpd2pi", CVTTPD2PI);
2070 GEN("cvttps2pi", CVTTPS2PI);
2071 }
2072 #undef GENIA
2073 #undef GENI1
2074 #undef GENI
2075 #undef GENA
2076 #undef GEN1
2077 #undef GEN64
2078 #undef GEN
2079 int last_insn = i;
2080 uint8 *e = get_target();
2081
2082 uint8 *p = b;
2083 i = 0;
2084 while (p < e) {
2085 int n = disass_x86(buffer, (uintptr)p);
2086 insn_t ii;
2087 parse_insn(&ii, buffer);
2088
2089 if (!check_reg_reg(&ii, insns[i], s, d)) {
2090 show_instruction(buffer, p);
2091 n_failures++;
2092 }
2093
2094 p += n;
2095 i += 1;
2096 n_tests++;
2097 }
2098 if (i != last_insn)
2099 abort();
2100 }
2101 }
2102 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
2103 n_all_tests += n_tests;
2104 n_all_failures += n_failures;
2105 #endif
2106
2107 #if TEST_INST_SSE_MEM_REG
2108 printf("Testing SSE mem,reg forms\n");
2109 n_tests = n_failures = 0;
2110 for (int d = 0; d < off_table_count; d++) {
2111 const uint32 D = off_table[d];
2112 for (int B = -1; B < X86_MAX_ALU_REGS; B++) {
2113 for (int I = -1; I < X86_MAX_ALU_REGS; I++) {
2114 if (I == X86_RSP)
2115 continue;
2116 for (int S = 1; S < 16; S *= 2) {
2117 if (I == -1 && S > 1)
2118 continue;
2119 for (int r = 0; r < X86_MAX_SSE_REGS; r++) {
2120 set_target(block);
2121 uint8 *b = get_target();
2122 int i = 0;
2123 #define GEN(INSN, GENOP) do { \
2124 insns[i++] = INSN; \
2125 GENOP##mr(D, B, I, S, r); \
2126 } while (0)
2127 #define GEN64(INSN, GENOP) do { \
2128 if (X86_TARGET_64BIT) \
2129 GEN(INSN, GENOP); \
2130 } while (0)
2131 #define GEN1(INSN, GENOP) do { \
2132 GEN(INSN "s", GENOP##S); \
2133 GEN(INSN "d", GENOP##D); \
2134 } while (0)
2135 #define GENA(INSN, GENOP) do { \
2136 GEN1(INSN "s", GENOP##S); \
2137 GEN1(INSN "p", GENOP##P); \
2138 } while (0)
2139 #define GENI(INSN, GENOP, IMM) do { \
2140 insns[i++] = INSN; \
2141 GENOP##mr(IMM, D, B, I, S, r); \
2142 } while (0)
2143 #define GENI1(INSN, GENOP, IMM) do { \
2144 GENI(INSN "s", GENOP##S, IMM); \
2145 GENI(INSN "d", GENOP##D, IMM); \
2146 } while (0)
2147 #define GENIA(INSN, GENOP, IMM) do { \
2148 GENI1(INSN "s", GENOP##S, IMM); \
2149 GENI1(INSN "p", GENOP##P, IMM); \
2150 } while (0)
2151 GEN1("andp", ANDP);
2152 GEN1("andnp", ANDNP);
2153 GEN1("orp", ORP);
2154 GEN1("xorp", XORP);
2155 GENA("add", ADD);
2156 GENA("sub", SUB);
2157 GENA("mul", MUL);
2158 GENA("div", DIV);
2159 GEN1("comis", COMIS);
2160 GEN1("ucomis", UCOMIS);
2161 GENA("min", MIN);
2162 GENA("max", MAX);
2163 GEN("rcpss", RCPSS);
2164 GEN("rcpps", RCPPS);
2165 GEN("rsqrtss", RSQRTSS);
2166 GEN("rsqrtps", RSQRTPS);
2167 GENA("sqrt", SQRT);
2168 GENIA("cmpeq", CMP, X86_SSE_CC_EQ);
2169 GENIA("cmplt", CMP, X86_SSE_CC_LT);
2170 GENIA("cmple", CMP, X86_SSE_CC_LE);
2171 GENIA("cmpunord", CMP, X86_SSE_CC_U);
2172 GENIA("cmpneq", CMP, X86_SSE_CC_NEQ);
2173 GENIA("cmpnlt", CMP, X86_SSE_CC_NLT);
2174 GENIA("cmpnle", CMP, X86_SSE_CC_NLE);
2175 GENIA("cmpord", CMP, X86_SSE_CC_O);
2176 GEN1("movap", MOVAP);
2177 GEN("movdqa", MOVDQA);
2178 GEN("movdqu", MOVDQU);
2179 #if 0
2180 // FIXME: extraneous REX bits generated
2181 GEN("movd", MOVDXD);
2182 GEN64("movd", MOVQXD); // FIXME: disass bug? "movq" expected
2183 #endif
2184 GEN("cvtdq2pd", CVTDQ2PD);
2185 GEN("cvtdq2ps", CVTDQ2PS);
2186 GEN("cvtpd2dq", CVTPD2DQ);
2187 GEN("cvtpd2ps", CVTPD2PS);
2188 GEN("cvtps2dq", CVTPS2DQ);
2189 GEN("cvtps2pd", CVTPS2PD);
2190 GEN("cvtsd2si", CVTSD2SIL);
2191 GEN64("cvtsd2siq", CVTSD2SIQ);
2192 GEN("cvtsd2ss", CVTSD2SS);
2193 GEN("cvtsi2sd", CVTSI2SDL);
2194 GEN64("cvtsi2sdq", CVTSI2SDQ);
2195 GEN("cvtsi2ss", CVTSI2SSL);
2196 GEN64("cvtsi2ssq", CVTSI2SSQ);
2197 GEN("cvtss2sd", CVTSS2SD);
2198 GEN("cvtss2si", CVTSS2SIL);
2199 GEN64("cvtss2siq", CVTSS2SIQ);
2200 GEN("cvttpd2dq", CVTTPD2DQ);
2201 GEN("cvttps2dq", CVTTPS2DQ);
2202 GEN("cvttsd2si", CVTTSD2SIL);
2203 GEN64("cvttsd2siq", CVTTSD2SIQ);
2204 GEN("cvttss2si", CVTTSS2SIL);
2205 GEN64("cvttss2siq", CVTTSS2SIQ);
2206 if (r < 8) {
2207 // MMX dest register
2208 GEN("cvtpd2pi", CVTPD2PI);
2209 GEN("cvtps2pi", CVTPS2PI);
2210 GEN("cvttpd2pi", CVTTPD2PI);
2211 GEN("cvttps2pi", CVTTPS2PI);
2212 }
2213 #undef GENIA
2214 #undef GENI1
2215 #undef GENI
2216 #undef GENA
2217 #undef GEN1
2218 #undef GEN64
2219 #undef GEN
2220 int last_insn = i;
2221 uint8 *e = get_target();
2222
2223 uint8 *p = b;
2224 i = 0;
2225 while (p < e) {
2226 int n = disass_x86(buffer, (uintptr)p);
2227 insn_t ii;
2228 parse_insn(&ii, buffer);
2229
2230 if (!check_mem_reg(&ii, insns[i], D, B, I, S, r)) {
2231 show_instruction(buffer, p);
2232 n_failures++;
2233 }
2234
2235 p += n;
2236 i += 1;
2237 n_tests++;
2238 show_status(n_tests);
2239 }
2240 if (i != last_insn)
2241 abort();
2242 }
2243 }
2244 }
2245 }
2246 }
2247 printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
2248 n_all_tests += n_tests;
2249 n_all_failures += n_failures;
2250 #endif
2251
2252 printf("\n");
2253 printf("All %ld tests run, %ld failures\n", n_all_tests, n_all_failures);
2254 }