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.9
Committed: 2008-02-12T14:42:09Z (16 years, 9 months ago) by gbeauche
Branch: MAIN
Changes since 1.8: +351 -22 lines
Log Message:
Add MMX instructions

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