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, 7 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

# User Rev Content
1 gbeauche 1.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 gbeauche 1.10 * Copyright 2004-2008 Gwenole Beauchesne
11 gbeauche 1.1 *
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 gbeauche 1.9 * STATUS: 26M variations covering unary register based operations,
30 gbeauche 1.1 * 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 gbeauche 1.2 static int verbose = 2;
48    
49 gbeauche 1.4 #define TEST_INST_ALU 1
50 gbeauche 1.10 #define TEST_INST_FPU 1
51 gbeauche 1.9 #define TEST_INST_MMX 1
52 gbeauche 1.8 #define TEST_INST_SSE 1
53 gbeauche 1.4 #if TEST_INST_ALU
54 gbeauche 1.3 #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 gbeauche 1.4 #endif
60 gbeauche 1.10 #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 gbeauche 1.9 #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 gbeauche 1.8 #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 gbeauche 1.4 #endif
75 gbeauche 1.3
76 gbeauche 1.1 #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 gbeauche 1.5 #define X86_RIP_RELATIVE_ADDR 0
87 gbeauche 1.1 #include "compiler/codegen_x86.h"
88    
89 gbeauche 1.8 #if X86_TARGET_64BIT
90 gbeauche 1.9 #define X86_MAX_ALU_REGS 16
91     #define X86_MAX_SSE_REGS 16
92 gbeauche 1.8 #else
93 gbeauche 1.9 #define X86_MAX_ALU_REGS 8
94     #define X86_MAX_SSE_REGS 8
95 gbeauche 1.8 #endif
96 gbeauche 1.10 #define X86_MAX_FPU_REGS 8
97 gbeauche 1.9 #define X86_MAX_MMX_REGS 8
98 gbeauche 1.8
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 gbeauche 1.9 #define VALID_REG64(r) VALID_REG(r, RAX, X86_MAX_ALU_REGS)
103 gbeauche 1.8 #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 gbeauche 1.9 #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 gbeauche 1.8
110 gbeauche 1.1 #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 gbeauche 1.8 info.mach = X86_TARGET_64BIT ? bfd_mach_x86_64 : bfd_mach_i386_i386;
218 gbeauche 1.1 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 gbeauche 1.8 #define MAX_INSNS 1024
258     #define MAX_INSN_LENGTH 16
259     #define MAX_INSN_OPERANDS 3
260    
261 gbeauche 1.1 struct insn_t {
262     char name[16];
263     int n_operands;
264 gbeauche 1.8 operand_t operands[MAX_INSN_OPERANDS];
265 gbeauche 1.1
266     void clear() {
267     memset(name, 0, sizeof(name));
268     n_operands = 0;
269 gbeauche 1.8 for (int i = 0; i < MAX_INSN_OPERANDS; i++)
270 gbeauche 1.1 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 gbeauche 1.2 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 gbeauche 1.1 static int parse_reg(operand_t *op, int optype, char *buf)
310     {
311 gbeauche 1.7 int reg = X86_NOREG;
312 gbeauche 1.4 int len = 0;
313     char *p = buf;
314 gbeauche 1.7 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 gbeauche 1.8 #if X86_TARGET_64BIT
332 gbeauche 1.7 case 'l': case 'L': reg = X86_BPL, ++len; break;
333 gbeauche 1.8 #endif
334 gbeauche 1.7 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 gbeauche 1.8 #if X86_TARGET_64BIT
356 gbeauche 1.7 case 'l': case 'L': reg = X86_DIL; ++len; break;
357 gbeauche 1.8 #endif
358 gbeauche 1.7 default: reg = X86_DI; break;
359     }
360     break;
361     }
362     break;
363     case 's': case 'S':
364     len = 2;
365     switch (p[2]) {
366 gbeauche 1.8 #if X86_TARGET_64BIT
367 gbeauche 1.7 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 gbeauche 1.8 #endif
375 gbeauche 1.10 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 gbeauche 1.7 default:
380     switch (p[1]) {
381 gbeauche 1.10 case 't': case 'T': reg = X86_ST0; break;
382 gbeauche 1.7 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 gbeauche 1.8 #if X86_TARGET_64BIT
414 gbeauche 1.7 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 gbeauche 1.8 const int r = p[2] - '0';
458 gbeauche 1.7 switch (p[3]) {
459 gbeauche 1.8 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 gbeauche 1.7 }
464     }
465     break;
466     default:
467 gbeauche 1.8 switch (p[1]) {
468     case '8': reg = X86_R8, len = 2; break;
469     case '9': reg = X86_R9, len = 2; break;
470     }
471 gbeauche 1.7 break;
472     }
473     break;
474 gbeauche 1.8 #endif
475 gbeauche 1.7 case 'm': case 'M':
476     if ((p[1] == 'm' || p[1] == 'M') && isdigit(p[2]))
477 gbeauche 1.8 reg = X86_MM0 + (p[2] - '0'), len = 3;
478 gbeauche 1.7 break;
479 gbeauche 1.4 case 'x': case 'X':
480 gbeauche 1.7 if ((p[1] == 'm' || p[1] == 'M') && (p[2] == 'm' || p[2] == 'M')) {
481 gbeauche 1.8 #if X86_TARGET_64BIT
482 gbeauche 1.7 if (p[3] == '1' && isdigit(p[4]))
483 gbeauche 1.8 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 gbeauche 1.4 }
489     break;
490     }
491    
492 gbeauche 1.7 if (len > 0 && reg != X86_NOREG) {
493     op->fill(optype, reg);
494     return len;
495 gbeauche 1.1 }
496 gbeauche 1.4
497 gbeauche 1.7 return X86_NOREG;
498     }
499    
500     static unsigned long parse_imm(char *nptr, char **endptr, int base = 0)
501     {
502     errno = 0;
503 gbeauche 1.8 #if X86_TARGET_64BIT
504     if (sizeof(unsigned long) != 8) {
505     unsigned long long val = strtoull(nptr, endptr, 0);
506 gbeauche 1.7 if (errno == 0)
507 gbeauche 1.8 return val;
508     abort();
509 gbeauche 1.7 }
510 gbeauche 1.8 #endif
511     unsigned long val = strtoul(nptr, endptr, 0);
512     if (errno == 0)
513     return val;
514     abort();
515     return 0;
516 gbeauche 1.1 }
517    
518     static int parse_mem(operand_t *op, char *buf)
519     {
520     char *p = buf;
521    
522 gbeauche 1.7 if (strncmp(buf, "0x", 2) == 0)
523     op->disp = parse_imm(buf, &p, 16);
524 gbeauche 1.1
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 gbeauche 1.4 #if 0
575     printf("BUF: %s\n", buf);
576     #endif
577    
578 gbeauche 1.2 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 gbeauche 1.4 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 gbeauche 1.1 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 gbeauche 1.7 ii->operands[n_operands].imm = parse_imm(++p, &p, 0);
632 gbeauche 1.1 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 gbeauche 1.3 static unsigned long n_tests, n_failures;
656     static unsigned long n_all_tests, n_all_failures;
657 gbeauche 1.1
658 gbeauche 1.10 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 gbeauche 1.1 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 gbeauche 1.7 fprintf(stderr, "r%d\n", reg);
693 gbeauche 1.1 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 gbeauche 1.4 fprintf(stderr, "r%d\n", srcreg);
720 gbeauche 1.1 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 gbeauche 1.4 fprintf(stderr, "r%d\n", dstreg);
729 gbeauche 1.1 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 gbeauche 1.10 static bool do_check_mem(insn_t *ii, uint32 D, int B, int I, int S, int Mpos)
786 gbeauche 1.1 {
787 gbeauche 1.10 operand_t *mem = &ii->operands[Mpos];
788 gbeauche 1.1 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 gbeauche 1.10 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 gbeauche 1.1 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 gbeauche 1.9 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 gbeauche 1.8 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 gbeauche 1.3 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 gbeauche 1.1 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 gbeauche 1.3 #if TEST_INST_ALU_REG
898 gbeauche 1.1 printf("Testing reg forms\n");
899     n_tests = n_failures = 0;
900 gbeauche 1.9 for (int r = 0; r < X86_MAX_ALU_REGS; r++) {
901 gbeauche 1.1 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 gbeauche 1.8 #define GEN64(INSN, GENOP) do { \
909     if (X86_TARGET_64BIT) \
910     GEN(INSN, GENOP); \
911     } while (0)
912 gbeauche 1.1 #define GENA(INSN, GENOP) do { \
913 gbeauche 1.8 if (VALID_REG8(r)) \
914     GEN(INSN "b", GENOP##B); \
915 gbeauche 1.1 GEN(INSN "w", GENOP##W); \
916     GEN(INSN "l", GENOP##L); \
917 gbeauche 1.8 GEN64(INSN "q", GENOP##Q); \
918 gbeauche 1.1 } 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 gbeauche 1.8 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 gbeauche 1.1 GEN("bswap", BSWAPL); // FIXME: disass bug? no suffix
940 gbeauche 1.8 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 gbeauche 1.1 #undef GENA
960 gbeauche 1.8 #undef GEN64
961 gbeauche 1.1 #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 gbeauche 1.8 show_instruction(buffer, p);
974 gbeauche 1.1 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 gbeauche 1.3 #endif
988 gbeauche 1.1
989 gbeauche 1.3 #if TEST_INST_ALU_REG_REG
990 gbeauche 1.1 printf("Testing reg,reg forms\n");
991     n_tests = n_failures = 0;
992 gbeauche 1.9 for (int s = 0; s < X86_MAX_ALU_REGS; s++) {
993     for (int d = 0; d < X86_MAX_ALU_REGS; d++) {
994 gbeauche 1.1 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 gbeauche 1.8 #define GEN64(INSN, GENOP) do { \
1002     if (X86_TARGET_64BIT) \
1003     GEN(INSN, GENOP); \
1004     } while (0)
1005 gbeauche 1.1 #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 gbeauche 1.8 if (VALID_REG8(s) && VALID_REG8(d)) \
1011     GEN(INSN "b", GENOP##B); \
1012 gbeauche 1.1 GEN(INSN "w", GENOP##W); \
1013     GEN(INSN "l", GENOP##L); \
1014 gbeauche 1.8 GEN64(INSN "q", GENOP##Q); \
1015 gbeauche 1.1 } 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 gbeauche 1.8 GEN64("btq", BTQ);
1028 gbeauche 1.1 GEN("btcw", BTCW);
1029     GEN("btcl", BTCL);
1030 gbeauche 1.8 GEN64("btcq", BTCQ);
1031 gbeauche 1.1 GEN("btrw", BTRW);
1032     GEN("btrl", BTRL);
1033 gbeauche 1.8 GEN64("btrq", BTRQ);
1034 gbeauche 1.1 GEN("btsw", BTSW);
1035     GEN("btsl", BTSL);
1036 gbeauche 1.8 GEN64("btsq", BTSQ);
1037 gbeauche 1.1 GEN("imulw", IMULW);
1038     GEN("imull", IMULL);
1039 gbeauche 1.8 GEN64("imulq", IMULQ);
1040 gbeauche 1.1 GEN1("cmove", CMOVW, X86_CC_Z);
1041     GEN1("cmove", CMOVL, X86_CC_Z);
1042 gbeauche 1.8 if (X86_TARGET_64BIT)
1043     GEN1("cmove", CMOVQ, X86_CC_Z);
1044 gbeauche 1.1 GENA("test", TEST);
1045     GENA("cmpxchg", CMPXCHG);
1046     GENA("xadd", XADD);
1047     GENA("xchg", XCHG);
1048     GEN("bsfw", BSFW);
1049     GEN("bsfl", BSFL);
1050 gbeauche 1.8 GEN64("bsfq", BSFQ);
1051 gbeauche 1.1 GEN("bsrw", BSRW);
1052     GEN("bsrl", BSRL);
1053 gbeauche 1.8 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 gbeauche 1.1 GEN("movswl", MOVSWL);
1063 gbeauche 1.8 GEN64("movswq", MOVSWQ);
1064 gbeauche 1.1 GEN("movzwl", MOVZWL);
1065 gbeauche 1.8 GEN64("movzwq", MOVZWQ);
1066     GEN64("movslq", MOVSLQ);
1067 gbeauche 1.1 #undef GENA
1068     #undef GEN1
1069 gbeauche 1.8 #undef GEN64
1070 gbeauche 1.1 #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 gbeauche 1.8 show_instruction(buffer, p);
1083 gbeauche 1.1 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 gbeauche 1.3 #endif
1098 gbeauche 1.1
1099 gbeauche 1.3 #if TEST_INST_ALU_CNT_REG
1100 gbeauche 1.1 printf("Testing cl,reg forms\n");
1101     n_tests = n_failures = 0;
1102 gbeauche 1.9 for (int d = 0; d < X86_MAX_ALU_REGS; d++) {
1103 gbeauche 1.1 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 gbeauche 1.8 #define GEN64(INSN, GENOP) do { \
1111     if (X86_TARGET_64BIT) \
1112     GEN(INSN, GENOP); \
1113     } while (0)
1114 gbeauche 1.1 #define GENA(INSN, GENOP) do { \
1115 gbeauche 1.8 if (VALID_REG8(d)) \
1116     GEN(INSN "b", GENOP##B); \
1117 gbeauche 1.1 GEN(INSN "w", GENOP##W); \
1118     GEN(INSN "l", GENOP##L); \
1119 gbeauche 1.8 GEN64(INSN "q", GENOP##Q); \
1120 gbeauche 1.1 } 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 gbeauche 1.8 #undef GEN64
1130 gbeauche 1.1 #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 gbeauche 1.8 show_instruction(buffer, p);
1143 gbeauche 1.1 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 gbeauche 1.3 #endif
1157 gbeauche 1.1
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 gbeauche 1.4
1175     #if TEST_INST_ALU_IMM_REG
1176     printf("Testing imm,reg forms\n");
1177 gbeauche 1.1 n_tests = n_failures = 0;
1178     for (int j = 0; j < n_imm_tab_count; j++) {
1179     const uint32 value = imm_table[j];
1180 gbeauche 1.9 for (int d = 0; d < X86_MAX_ALU_REGS; d++) {
1181 gbeauche 1.1 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 gbeauche 1.8 #define GEN64(INSN, GENOP) do { \
1190     if (X86_TARGET_64BIT) \
1191     GEN(INSN, GENOP); \
1192     } while (0)
1193 gbeauche 1.1 #define GENM(INSN, GENOP, MODE) do { \
1194     insns[i] = INSN; \
1195     modes[i] = MODE; \
1196     i++; GENOP##ir(value, d); \
1197     } while (0)
1198 gbeauche 1.8 #define GENM64(INSN, GENOP, MODE) do { \
1199     if (X86_TARGET_64BIT) \
1200     GENM(INSN, GENOP, MODE); \
1201     } while (0)
1202 gbeauche 1.1 #define GENA(INSN, GENOP) do { \
1203 gbeauche 1.8 if (VALID_REG8(d)) \
1204 gbeauche 1.1 GEN(INSN "b", GENOP##B); \
1205     GEN(INSN "w", GENOP##W); \
1206     GEN(INSN "l", GENOP##L); \
1207 gbeauche 1.8 GEN64(INSN "q", GENOP##Q); \
1208 gbeauche 1.1 } while (0)
1209     #define GENAM(INSN, GENOP, MODE) do { \
1210 gbeauche 1.8 if (VALID_REG8(d)) \
1211 gbeauche 1.1 GENM(INSN "b", GENOP##B, MODE); \
1212     GENM(INSN "w", GENOP##W, MODE); \
1213     GENM(INSN "l", GENOP##L, MODE); \
1214 gbeauche 1.8 GENM64(INSN "q", GENOP##Q, MODE); \
1215 gbeauche 1.1 } 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 gbeauche 1.8 GENM64("btq", BTQ, 1);
1228 gbeauche 1.1 GENM("btcw", BTCW, 1);
1229     GENM("btcl", BTCL, 1);
1230 gbeauche 1.8 GENM64("btcq", BTCQ, 1);
1231 gbeauche 1.1 GENM("btrw", BTRW, 1);
1232     GENM("btrl", BTRL, 1);
1233 gbeauche 1.8 GENM64("btrq", BTRQ, 1);
1234 gbeauche 1.1 GENM("btsw", BTSW, 1);
1235     GENM("btsl", BTSL, 1);
1236 gbeauche 1.8 GENM64("btsq", BTSQ, 1);
1237 gbeauche 1.1 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 gbeauche 1.8 #undef GENM64
1250 gbeauche 1.1 #undef GENM
1251 gbeauche 1.8 #undef GEN64
1252 gbeauche 1.1 #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 gbeauche 1.8 show_instruction(buffer, p);
1265 gbeauche 1.1 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 gbeauche 1.3 #endif
1280 gbeauche 1.1
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 gbeauche 1.4
1293     #if TEST_INST_ALU_MEM_REG
1294     printf("Testing mem,reg forms\n");
1295     n_tests = n_failures = 0;
1296 gbeauche 1.1 for (int d = 0; d < off_table_count; d++) {
1297     const uint32 D = off_table[d];
1298 gbeauche 1.9 for (int B = -1; B < X86_MAX_ALU_REGS; B++) {
1299     for (int I = -1; I < X86_MAX_ALU_REGS; I++) {
1300 gbeauche 1.1 if (I == X86_RSP)
1301     continue;
1302 gbeauche 1.5 for (int S = 1; S < 16; S *= 2) {
1303     if (I == -1 && S > 1)
1304 gbeauche 1.1 continue;
1305 gbeauche 1.9 for (int r = 0; r < X86_MAX_ALU_REGS; r++) {
1306 gbeauche 1.1 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 gbeauche 1.8 #define GEN64(INSN, GENOP) do { \
1314     if (X86_TARGET_64BIT) \
1315     GEN(INSN, GENOP); \
1316     } while (0)
1317 gbeauche 1.1 #define GENA(INSN, GENOP) do { \
1318 gbeauche 1.8 if (VALID_REG8(r)) \
1319     GEN(INSN "b", GENOP##B); \
1320 gbeauche 1.1 GEN(INSN "w", GENOP##W); \
1321     GEN(INSN "l", GENOP##L); \
1322 gbeauche 1.8 GEN64(INSN "q", GENOP##Q); \
1323 gbeauche 1.1 } 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 gbeauche 1.8 GEN64("imulq", IMULQ);
1336 gbeauche 1.1 GEN("bsfw", BSFW);
1337     GEN("bsfl", BSFL);
1338 gbeauche 1.8 GEN64("bsfq", BSFQ);
1339 gbeauche 1.1 GEN("bsrw", BSRW);
1340     GEN("bsrl", BSRL);
1341 gbeauche 1.8 GEN64("bsrq", BSRQ);
1342 gbeauche 1.1 GEN("movsbw", MOVSBW);
1343     GEN("movsbl", MOVSBL);
1344 gbeauche 1.8 GEN64("movsbq", MOVSBQ);
1345 gbeauche 1.1 GEN("movzbw", MOVZBW);
1346     GEN("movzbl", MOVZBL);
1347 gbeauche 1.8 GEN64("movzbq", MOVZBQ);
1348 gbeauche 1.1 GEN("movswl", MOVSWL);
1349 gbeauche 1.8 GEN64("movswq", MOVSWQ);
1350 gbeauche 1.1 GEN("movzwl", MOVZWL);
1351 gbeauche 1.8 GEN64("movzwq", MOVZWQ);
1352     GEN64("movslq", MOVSLQ);
1353 gbeauche 1.1 #undef GENA
1354 gbeauche 1.8 #undef GEN64
1355 gbeauche 1.1 #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 gbeauche 1.8 show_instruction(buffer, p);
1368 gbeauche 1.1 n_failures++;
1369     }
1370    
1371     p += n;
1372     i += 1;
1373     n_tests++;
1374 gbeauche 1.3 show_status(n_tests);
1375 gbeauche 1.1 }
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 gbeauche 1.3 #endif
1387 gbeauche 1.1
1388 gbeauche 1.10 #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 gbeauche 1.11 GEN("fstl", FSTD);
1612 gbeauche 1.10 GEN("fstps", FSTPS);
1613 gbeauche 1.11 GEN("fstpl", FSTPD);
1614 gbeauche 1.10 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 gbeauche 1.9 #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 gbeauche 1.8 #if TEST_INST_SSE_REG_REG
1971     printf("Testing SSE reg,reg forms\n");
1972 gbeauche 1.4 n_tests = n_failures = 0;
1973 gbeauche 1.9 for (int s = 0; s < X86_MAX_SSE_REGS; s++) {
1974     for (int d = 0; d < X86_MAX_SSE_REGS; d++) {
1975 gbeauche 1.4 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 gbeauche 1.8 #define GEN64(INSN, GENOP) do { \
1983     if (X86_TARGET_64BIT) \
1984     GEN(INSN, GENOP); \
1985     } while (0)
1986 gbeauche 1.4 #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 gbeauche 1.8 GEN64("movd", MOVQXD); // FIXME: disass bug? "movq" expected
2036 gbeauche 1.4 GEN("movd", MOVDXS);
2037 gbeauche 1.8 GEN64("movd", MOVQXS); // FIXME: disass bug? "movq" expected
2038 gbeauche 1.6 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 gbeauche 1.8 GEN64("cvtsd2siq", CVTSD2SIQ);
2046 gbeauche 1.6 GEN("cvtsd2ss", CVTSD2SS);
2047     GEN("cvtsi2sd", CVTSI2SDL);
2048 gbeauche 1.8 GEN64("cvtsi2sdq", CVTSI2SDQ);
2049 gbeauche 1.6 GEN("cvtsi2ss", CVTSI2SSL);
2050 gbeauche 1.8 GEN64("cvtsi2ssq", CVTSI2SSQ);
2051 gbeauche 1.6 GEN("cvtss2sd", CVTSS2SD);
2052     GEN("cvtss2si", CVTSS2SIL);
2053 gbeauche 1.8 GEN64("cvtss2siq", CVTSS2SIQ);
2054 gbeauche 1.6 GEN("cvttpd2dq", CVTTPD2DQ);
2055     GEN("cvttps2dq", CVTTPS2DQ);
2056     GEN("cvttsd2si", CVTTSD2SIL);
2057 gbeauche 1.8 GEN64("cvttsd2siq", CVTTSD2SIQ);
2058 gbeauche 1.6 GEN("cvttss2si", CVTTSS2SIL);
2059 gbeauche 1.8 GEN64("cvttss2siq", CVTTSS2SIQ);
2060 gbeauche 1.6 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 gbeauche 1.4 #undef GENIA
2073     #undef GENI1
2074     #undef GENI
2075     #undef GENA
2076     #undef GEN1
2077 gbeauche 1.8 #undef GEN64
2078 gbeauche 1.4 #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 gbeauche 1.8 show_instruction(buffer, p);
2091 gbeauche 1.4 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 gbeauche 1.8 #if TEST_INST_SSE_MEM_REG
2108     printf("Testing SSE mem,reg forms\n");
2109 gbeauche 1.4 n_tests = n_failures = 0;
2110     for (int d = 0; d < off_table_count; d++) {
2111     const uint32 D = off_table[d];
2112 gbeauche 1.9 for (int B = -1; B < X86_MAX_ALU_REGS; B++) {
2113     for (int I = -1; I < X86_MAX_ALU_REGS; I++) {
2114 gbeauche 1.4 if (I == X86_RSP)
2115     continue;
2116 gbeauche 1.5 for (int S = 1; S < 16; S *= 2) {
2117     if (I == -1 && S > 1)
2118 gbeauche 1.4 continue;
2119 gbeauche 1.9 for (int r = 0; r < X86_MAX_SSE_REGS; r++) {
2120 gbeauche 1.4 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 gbeauche 1.8 #define GEN64(INSN, GENOP) do { \
2128     if (X86_TARGET_64BIT) \
2129     GEN(INSN, GENOP); \
2130     } while (0)
2131 gbeauche 1.4 #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 gbeauche 1.8 GEN64("movd", MOVQXD); // FIXME: disass bug? "movq" expected
2183 gbeauche 1.4 #endif
2184 gbeauche 1.6 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 gbeauche 1.8 GEN64("cvtsd2siq", CVTSD2SIQ);
2192 gbeauche 1.6 GEN("cvtsd2ss", CVTSD2SS);
2193     GEN("cvtsi2sd", CVTSI2SDL);
2194 gbeauche 1.8 GEN64("cvtsi2sdq", CVTSI2SDQ);
2195 gbeauche 1.6 GEN("cvtsi2ss", CVTSI2SSL);
2196 gbeauche 1.8 GEN64("cvtsi2ssq", CVTSI2SSQ);
2197 gbeauche 1.6 GEN("cvtss2sd", CVTSS2SD);
2198     GEN("cvtss2si", CVTSS2SIL);
2199 gbeauche 1.8 GEN64("cvtss2siq", CVTSS2SIQ);
2200 gbeauche 1.6 GEN("cvttpd2dq", CVTTPD2DQ);
2201     GEN("cvttps2dq", CVTTPS2DQ);
2202     GEN("cvttsd2si", CVTTSD2SIL);
2203 gbeauche 1.8 GEN64("cvttsd2siq", CVTTSD2SIQ);
2204 gbeauche 1.6 GEN("cvttss2si", CVTTSS2SIL);
2205 gbeauche 1.8 GEN64("cvttss2siq", CVTTSS2SIQ);
2206 gbeauche 1.6 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 gbeauche 1.4 #undef GENIA
2214     #undef GENI1
2215     #undef GENI
2216     #undef GENA
2217     #undef GEN1
2218 gbeauche 1.8 #undef GEN64
2219 gbeauche 1.4 #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 gbeauche 1.8 show_instruction(buffer, p);
2232 gbeauche 1.4 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 gbeauche 1.1 printf("\n");
2253     printf("All %ld tests run, %ld failures\n", n_all_tests, n_all_failures);
2254     }