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.7
Committed: 2008-02-12T00:45:24Z (16 years, 9 months ago) by gbeauche
Branch: MAIN
Changes since 1.6: +185 -64 lines
Log Message:
Fix decoding of 64-bit values on 32-bit hosts. Improve register decoding speed
by more than 2x, aka use a big switch/tree to lookup the register ID from string.

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.6 * STATUS: 21M 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     #define TEST_INST_VPU 1
51     #if TEST_INST_ALU
52 gbeauche 1.3 #define TEST_INST_ALU_REG 1
53     #define TEST_INST_ALU_REG_REG 1
54     #define TEST_INST_ALU_CNT_REG 1
55     #define TEST_INST_ALU_IMM_REG 1
56     #define TEST_INST_ALU_MEM_REG 1
57 gbeauche 1.4 #endif
58     #if TEST_INST_VPU
59     #define TEST_INST_VPU_REG 1
60     #define TEST_INST_VPU_REG_REG 1
61     #define TEST_INST_VPU_MEM_REG 1
62     #endif
63 gbeauche 1.3
64 gbeauche 1.1 #undef abort
65     #define abort() do { \
66     fprintf(stderr, "ABORT: %s, line %d\n", __FILE__, __LINE__); \
67     (abort)(); \
68     } while (0)
69    
70     #define X86_TARGET_64BIT 1
71     #define X86_FLAT_REGISTERS 0
72     #define X86_OPTIMIZE_ALU 1
73     #define X86_OPTIMIZE_ROTSHI 1
74 gbeauche 1.5 #define X86_RIP_RELATIVE_ADDR 0
75 gbeauche 1.1 #include "compiler/codegen_x86.h"
76    
77     #define x86_emit_byte(B) emit_byte(B)
78     #define x86_emit_word(W) emit_word(W)
79     #define x86_emit_long(L) emit_long(L)
80     #define x86_emit_quad(Q) emit_quad(Q)
81     #define x86_get_target() get_target()
82     #define x86_emit_failure(MSG) jit_fail(MSG, __FILE__, __LINE__, __FUNCTION__)
83    
84     static void jit_fail(const char *msg, const char *file, int line, const char *function)
85     {
86     fprintf(stderr, "JIT failure in function %s from file %s at line %d: %s\n",
87     function, file, line, msg);
88     abort();
89     }
90    
91     static uint8 *target;
92    
93     static inline void emit_byte(uint8 x)
94     {
95     *target++ = x;
96     }
97    
98     static inline void emit_word(uint16 x)
99     {
100     *((uint16 *)target) = x;
101     target += 2;
102     }
103    
104     static inline void emit_long(uint32 x)
105     {
106     *((uint32 *)target) = x;
107     target += 4;
108     }
109    
110     static inline void emit_quad(uint64 x)
111     {
112     *((uint64 *)target) = x;
113     target += 8;
114     }
115    
116     static inline void set_target(uint8 *t)
117     {
118     target = t;
119     }
120    
121     static inline uint8 *get_target(void)
122     {
123     return target;
124     }
125    
126     static uint32 mon_read_byte(uintptr addr)
127     {
128     uint8 *m = (uint8 *)addr;
129     return (uint32)(*m);
130     }
131    
132     extern "C" {
133     #include "disass/dis-asm.h"
134    
135     int buffer_read_memory(bfd_vma from, bfd_byte *to, unsigned int length, struct disassemble_info *info)
136     {
137     while (length--)
138     *to++ = mon_read_byte(from++);
139     return 0;
140     }
141    
142     void perror_memory(int status, bfd_vma memaddr, struct disassemble_info *info)
143     {
144     info->fprintf_func(info->stream, "Unknown error %d\n", status);
145     }
146    
147     void generic_print_address(bfd_vma addr, struct disassemble_info *info)
148     {
149     if (addr >= UVAL64(0x100000000))
150     info->fprintf_func(info->stream, "$%08x%08x", (uint32)(addr >> 32), (uint32)addr);
151     else
152     info->fprintf_func(info->stream, "$%08x", (uint32)addr);
153     }
154    
155     int generic_symbol_at_address(bfd_vma addr, struct disassemble_info *info)
156     {
157     return 0;
158     }
159     }
160    
161     struct SFILE {
162     char *buffer;
163     char *current;
164     };
165    
166     static int mon_sprintf(SFILE *f, const char *format, ...)
167     {
168     int n;
169     va_list args;
170     va_start(args, format);
171     vsprintf(f->current, format, args);
172     f->current += n = strlen(f->current);
173     va_end(args);
174     return n;
175     }
176    
177     static int disass_x86(char *buf, uintptr adr)
178     {
179     disassemble_info info;
180     SFILE sfile;
181     sfile.buffer = buf;
182     sfile.current = buf;
183     INIT_DISASSEMBLE_INFO(info, (FILE *)&sfile, (fprintf_ftype)mon_sprintf);
184     info.mach = bfd_mach_x86_64;
185     info.disassembler_options = "suffix";
186     return print_insn_i386(adr, &info);
187     }
188    
189     enum {
190     op_disp,
191     op_reg,
192     op_base,
193     op_index,
194     op_scale,
195     op_imm,
196     };
197     struct operand_t {
198     int32 disp;
199     int8 reg;
200     int8 base;
201     int8 index;
202     int8 scale;
203     int64 imm;
204    
205     void clear() {
206     disp = imm = 0;
207     reg = base = index = -1;
208     scale = 1;
209     }
210    
211     void fill(int optype, int value) {
212     switch (optype) {
213     case op_disp: disp = value; break;
214     case op_reg: reg = value; break;
215     case op_base: base = value; break;
216     case op_index: index = value; break;
217     case op_scale: scale = value; break;
218     case op_imm: imm = value; break;
219     default: abort();
220     }
221     }
222     };
223    
224     struct insn_t {
225     char name[16];
226     int n_operands;
227     #define MAX_OPERANDS 3
228     operand_t operands[MAX_OPERANDS];
229    
230     void clear() {
231     memset(name, 0, sizeof(name));
232     n_operands = 0;
233     for (int i = 0; i < MAX_OPERANDS; i++)
234     operands[i].clear();
235     }
236    
237     void pretty_print() {
238     printf("%s, %d operands\n", name, n_operands);
239     for (int i = 0; i < n_operands; i++) {
240     operand_t *op = &operands[i];
241     if (op->reg != -1)
242     printf(" reg r%d\n", op->reg);
243     else {
244     printf(" mem 0x%08x(", op->disp);
245     if (op->base != -1)
246     printf("r%d", op->base);
247     printf(",");
248     if (op->index != -1)
249     printf("r%d", op->index);
250     printf(",");
251     if (op->base != -1 || op->index != -1)
252     printf("%d", op->scale);
253     printf(")\n");
254     }
255     }
256     }
257     };
258    
259 gbeauche 1.2 static inline char *find_blanks(char *p)
260     {
261     while (*p && !isspace(*p))
262     ++p;
263     return p;
264     }
265    
266     static inline char *skip_blanks(char *p)
267     {
268     while (*p && isspace(*p))
269     ++p;
270     return p;
271     }
272    
273 gbeauche 1.1 static int parse_reg(operand_t *op, int optype, char *buf)
274     {
275 gbeauche 1.7 int reg = X86_NOREG;
276 gbeauche 1.4 int len = 0;
277     char *p = buf;
278 gbeauche 1.7 switch (p[0]) {
279     case 'a': case 'A':
280     len = 2;
281     switch (p[1]) {
282     case 'l': case 'L': reg = X86_AL; break;
283     case 'h': case 'H': reg = X86_AH; break;
284     case 'x': case 'X': reg = X86_AX; break;
285     }
286     break;
287     case 'b': case 'B':
288     len = 2;
289     switch (p[1]) {
290     case 'l': case 'L': reg = X86_BL; break;
291     case 'h': case 'H': reg = X86_BH; break;
292     case 'x': case 'X': reg = X86_BX; break;
293     case 'p': case 'P':
294     switch (p[2]) {
295     case 'l': case 'L': reg = X86_BPL, ++len; break;
296     default: reg = X86_BP; break;
297     }
298     break;
299     }
300     break;
301     case 'c': case 'C':
302     len = 2;
303     switch (p[1]) {
304     case 'l': case 'L': reg = X86_CL; break;
305     case 'h': case 'H': reg = X86_CH; break;
306     case 'x': case 'X': reg = X86_CX; break;
307     }
308     break;
309     case 'd': case 'D':
310     len = 2;
311     switch (p[1]) {
312     case 'l': case 'L': reg = X86_DL; break;
313     case 'h': case 'H': reg = X86_DH; break;
314     case 'x': case 'X': reg = X86_DX; break;
315     case 'i': case 'I':
316     switch (p[2]) {
317     case 'l': case 'L': reg = X86_DIL; ++len; break;
318     default: reg = X86_DI; break;
319     }
320     break;
321     }
322     break;
323     case 's': case 'S':
324     len = 2;
325     switch (p[2]) {
326     case 'l': case 'L':
327     ++len;
328     switch (p[1]) {
329     case 'p': case 'P': reg = X86_SPL; break;
330     case 'i': case 'I': reg = X86_SIL; break;
331     }
332     break;
333     default:
334     switch (p[1]) {
335     case 'p': case 'P': reg = X86_SP; break;
336     case 'i': case 'I': reg = X86_SI; break;
337     }
338     break;
339     }
340     break;
341     case 'e': case 'E':
342     len = 3;
343     switch (p[2]) {
344     case 'x': case 'X':
345     switch (p[1]) {
346     case 'a': case 'A': reg = X86_EAX; break;
347     case 'b': case 'B': reg = X86_EBX; break;
348     case 'c': case 'C': reg = X86_ECX; break;
349     case 'd': case 'D': reg = X86_EDX; break;
350     }
351     break;
352     case 'i': case 'I':
353     switch (p[1]) {
354     case 's': case 'S': reg = X86_ESI; break;
355     case 'd': case 'D': reg = X86_EDI; break;
356     }
357     break;
358     case 'p': case 'P':
359     switch (p[1]) {
360     case 'b': case 'B': reg = X86_EBP; break;
361     case 's': case 'S': reg = X86_ESP; break;
362     }
363     break;
364     }
365     break;
366     case 'r': case 'R':
367     len = 3;
368     switch (p[2]) {
369     case 'x': case 'X':
370     switch (p[1]) {
371     case 'a': case 'A': reg = X86_RAX; break;
372     case 'b': case 'B': reg = X86_RBX; break;
373     case 'c': case 'C': reg = X86_RCX; break;
374     case 'd': case 'D': reg = X86_RDX; break;
375     }
376     break;
377     case 'i': case 'I':
378     switch (p[1]) {
379     case 's': case 'S': reg = X86_RSI; break;
380     case 'd': case 'D': reg = X86_RDI; break;
381     }
382     break;
383     case 'p': case 'P':
384     switch (p[1]) {
385     case 'b': case 'B': reg = X86_RBP; break;
386     case 's': case 'S': reg = X86_RSP; break;
387     }
388     break;
389     case 'b': case 'B':
390     switch (p[1]) {
391     case '8': reg = X86_R8B; break;
392     case '9': reg = X86_R9B; break;
393     }
394     break;
395     case 'w': case 'W':
396     switch (p[1]) {
397     case '8': reg = X86_R8W; break;
398     case '9': reg = X86_R9W; break;
399     }
400     break;
401     case 'd': case 'D':
402     switch (p[1]) {
403     case '8': reg = X86_R8D; break;
404     case '9': reg = X86_R9D; break;
405     }
406     break;
407     case '0': case '1': case '2': case '3': case '4': case '5':
408     if (p[1] == '1') {
409     const int r = 10 + (p[2] - '0');
410     switch (p[3]) {
411     case 'b': case 'B': reg = X86_Reg8L_Base + r, ++len; break;
412     case 'w': case 'W': reg = X86_Reg16_Base + r, ++len; break;
413     case 'd': case 'D': reg = X86_Reg32_Base + r, ++len; break;
414     default: reg = X86_Reg64_Base + r; break;
415     }
416     }
417     break;
418     default:
419     if (isdigit(p[1]))
420     reg = X86_Reg64_Base + (p[1] - '0'), len = 2;
421     break;
422     }
423     break;
424     case 'm': case 'M':
425     if ((p[1] == 'm' || p[1] == 'M') && isdigit(p[2]))
426     reg = X86_RegMMX_Base + (p[2] - '0'), len = 3;
427     break;
428 gbeauche 1.4 case 'x': case 'X':
429 gbeauche 1.7 if ((p[1] == 'm' || p[1] == 'M') && (p[2] == 'm' || p[2] == 'M')) {
430     if (p[3] == '1' && isdigit(p[4]))
431     reg = 10 + (p[4] - '0'), len = 5;
432     else if (isdigit(p[3]))
433     reg = p[3] - '0', len = 4;
434 gbeauche 1.4 }
435     break;
436     }
437    
438 gbeauche 1.7 if (len > 0 && reg != X86_NOREG) {
439     op->fill(optype, reg);
440     return len;
441 gbeauche 1.1 }
442 gbeauche 1.4
443 gbeauche 1.7 return X86_NOREG;
444     }
445    
446     static unsigned long parse_imm(char *nptr, char **endptr, int base = 0)
447     {
448     unsigned long val = 0;
449     errno = 0;
450     if (X86_TARGET_64BIT && sizeof(unsigned long) != 8) {
451     unsigned long long v = strtoull(nptr, endptr, 0);
452     if (errno == 0)
453     val = v;
454     else
455     abort();
456     }
457     else {
458     unsigned long v = strtoul(nptr, endptr, 0);
459     if (errno == 0)
460     val = v;
461     else
462     abort();
463     }
464     return val;
465 gbeauche 1.1 }
466    
467     static int parse_mem(operand_t *op, char *buf)
468     {
469     char *p = buf;
470    
471 gbeauche 1.7 if (strncmp(buf, "0x", 2) == 0)
472     op->disp = parse_imm(buf, &p, 16);
473 gbeauche 1.1
474     if (*p == '(') {
475     p++;
476    
477     if (*p == '%') {
478     p++;
479    
480     int n = parse_reg(op, op_base, p);
481     if (n <= 0)
482     return -3;
483     p += n;
484     }
485    
486     if (*p == ',') {
487     p++;
488    
489     if (*p == '%') {
490     int n = parse_reg(op, op_index, ++p);
491     if (n <= 0)
492     return -4;
493     p += n;
494    
495     if (*p != ',')
496     return -5;
497     p++;
498    
499     goto do_parse_scale;
500     }
501     else if (isdigit(*p)) {
502     do_parse_scale:
503     long val = strtol(p, &p, 10);
504     if (val == 0 && errno == EINVAL)
505     abort();
506     op->scale = val;
507     }
508     }
509    
510     if (*p != ')')
511     return -6;
512     p++;
513     }
514    
515     return p - buf;
516     }
517    
518     static void parse_insn(insn_t *ii, char *buf)
519     {
520     char *p = buf;
521     ii->clear();
522    
523 gbeauche 1.4 #if 0
524     printf("BUF: %s\n", buf);
525     #endif
526    
527 gbeauche 1.2 if (strncmp(p, "rex64", 5) == 0) {
528     char *q = find_blanks(p);
529     if (verbose > 1) {
530     char prefix[16];
531     memset(prefix, 0, sizeof(prefix));
532     memcpy(prefix, p, q - p);
533     fprintf(stderr, "Instruction '%s', skip REX prefix '%s'\n", buf, prefix);
534     }
535     p = skip_blanks(q);
536     }
537    
538 gbeauche 1.4 if (strncmp(p, "rep", 3) == 0) {
539     char *q = find_blanks(p);
540     if (verbose > 1) {
541     char prefix[16];
542     memset(prefix, 0, sizeof(prefix));
543     memcpy(prefix, p, q - p);
544     fprintf(stderr, "Instruction '%s', skip REP prefix '%s'\n", buf, prefix);
545     }
546     p = skip_blanks(q);
547     }
548    
549 gbeauche 1.1 for (int i = 0; !isspace(*p); i++)
550     ii->name[i] = *p++;
551    
552     while (*p && isspace(*p))
553     p++;
554     if (*p == '\0')
555     return;
556    
557     int n_operands = 0;
558     int optype = op_reg;
559     bool done = false;
560     while (!done) {
561     int n;
562     switch (*p) {
563     case '%':
564     n = parse_reg(&ii->operands[n_operands], optype, ++p);
565     if (n <= 0) {
566     fprintf(stderr, "parse_reg(%s) error %d\n", p, n);
567     abort();
568     }
569     p += n;
570     break;
571     case '0': case '(':
572     n = parse_mem(&ii->operands[n_operands], p);
573     if (n <= 0) {
574     fprintf(stderr, "parse_mem(%s) error %d\n", p, n);
575     abort();
576     }
577     p += n;
578     break;
579     case '$': {
580 gbeauche 1.7 ii->operands[n_operands].imm = parse_imm(++p, &p, 0);
581 gbeauche 1.1 break;
582     }
583     case '*':
584     p++;
585     break;
586     case ',':
587     n_operands++;
588     p++;
589     break;
590     case ' ': case '\t':
591     p++;
592     break;
593     case '\0':
594     done = true;
595     break;
596     default:
597     fprintf(stderr, "parse error> %s\n", p);
598     abort();
599     }
600     }
601     ii->n_operands = n_operands + 1;
602     }
603    
604 gbeauche 1.3 static unsigned long n_tests, n_failures;
605     static unsigned long n_all_tests, n_all_failures;
606 gbeauche 1.1
607     static bool check_reg(insn_t *ii, const char *name, int r)
608     {
609     if (strcasecmp(ii->name, name) != 0) {
610     fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
611     return false;
612     }
613    
614     if (ii->n_operands != 1) {
615     fprintf(stderr, "ERROR: instruction expected 1 operand, got %d\n", ii->n_operands);
616     return false;
617     }
618    
619     int reg = ii->operands[0].reg;
620    
621     if (reg != r) {
622     fprintf(stderr, "ERROR: instruction expected r%d as source, got ", r);
623     if (reg == -1)
624     fprintf(stderr, "nothing\n");
625     else
626 gbeauche 1.7 fprintf(stderr, "r%d\n", reg);
627 gbeauche 1.1 return false;
628     }
629    
630     return true;
631     }
632    
633     static bool check_reg_reg(insn_t *ii, const char *name, int s, int d)
634     {
635     if (strcasecmp(ii->name, name) != 0) {
636     fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
637     return false;
638     }
639    
640     if (ii->n_operands != 2) {
641     fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands);
642     return false;
643     }
644    
645     int srcreg = ii->operands[0].reg;
646     int dstreg = ii->operands[1].reg;
647    
648     if (srcreg != s) {
649     fprintf(stderr, "ERROR: instruction expected r%d as source, got ", s);
650     if (srcreg == -1)
651     fprintf(stderr, "nothing\n");
652     else
653 gbeauche 1.4 fprintf(stderr, "r%d\n", srcreg);
654 gbeauche 1.1 return false;
655     }
656    
657     if (dstreg != d) {
658     fprintf(stderr, "ERROR: instruction expected r%d as destination, got ", d);
659     if (dstreg == -1)
660     fprintf(stderr, "nothing\n");
661     else
662 gbeauche 1.4 fprintf(stderr, "r%d\n", dstreg);
663 gbeauche 1.1 return false;
664     }
665    
666     return true;
667     }
668    
669     static bool check_imm_reg(insn_t *ii, const char *name, uint32 v, int d, int mode = -1)
670     {
671     if (strcasecmp(ii->name, name) != 0) {
672     fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
673     return false;
674     }
675    
676     if (ii->n_operands != 2) {
677     fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands);
678     return false;
679     }
680    
681     uint32 imm = ii->operands[0].imm;
682     int dstreg = ii->operands[1].reg;
683    
684     if (mode == -1) {
685     char suffix = name[strlen(name) - 1];
686     switch (suffix) {
687     case 'b': mode = 1; break;
688     case 'w': mode = 2; break;
689     case 'l': mode = 4; break;
690     case 'q': mode = 8; break;
691     }
692     }
693     switch (mode) {
694     case 1: v &= 0xff; break;
695     case 2: v &= 0xffff; break;
696     }
697    
698     if (imm != v) {
699     fprintf(stderr, "ERROR: instruction expected 0x%08x as immediate, got ", v);
700     if (imm == -1)
701     fprintf(stderr, "nothing\n");
702     else
703     fprintf(stderr, "0x%08x\n", imm);
704     return false;
705     }
706    
707     if (dstreg != d) {
708     fprintf(stderr, "ERROR: instruction expected r%d as destination, got ", d);
709     if (dstreg == -1)
710     fprintf(stderr, "nothing\n");
711     else
712     fprintf(stderr, "%d\n", dstreg);
713     return false;
714     }
715    
716     return true;
717     }
718    
719     static bool check_mem_reg(insn_t *ii, const char *name, uint32 D, int B, int I, int S, int R)
720     {
721     if (strcasecmp(ii->name, name) != 0) {
722     fprintf(stderr, "ERROR: instruction mismatch, expected %s, got %s\n", name, ii->name);
723     return false;
724     }
725    
726     if (ii->n_operands != 2) {
727     fprintf(stderr, "ERROR: instruction expected 2 operands, got %d\n", ii->n_operands);
728     return false;
729     }
730    
731     operand_t *mem = &ii->operands[0];
732     operand_t *reg = &ii->operands[1];
733    
734     uint32 d = mem->disp;
735     int b = mem->base;
736     int i = mem->index;
737     int s = mem->scale;
738     int r = reg->reg;
739    
740     if (d != D) {
741     fprintf(stderr, "ERROR: instruction expected 0x%08x as displacement, got 0x%08x\n", D, d);
742     return false;
743     }
744    
745     if (b != B) {
746     fprintf(stderr, "ERROR: instruction expected r%d as base, got r%d\n", B, b);
747     return false;
748     }
749    
750     if (i != I) {
751     fprintf(stderr, "ERROR: instruction expected r%d as index, got r%d\n", I, i);
752     return false;
753     }
754    
755     if (s != S) {
756     fprintf(stderr, "ERROR: instruction expected %d as scale factor, got %d\n", S, s);
757     return false;
758     }
759    
760     if (r != R) {
761     fprintf(stderr, "ERROR: instruction expected r%d as reg operand, got r%d\n", R, r);
762     return false;
763     }
764    
765     return true;
766     }
767    
768 gbeauche 1.3 static void show_status(unsigned long n_tests)
769     {
770     #if 1
771     const unsigned long N_STEPS = 100000;
772     static const char cursors[] = { '-', '\\', '|', '/' };
773     if ((n_tests % N_STEPS) == 0) {
774     printf(" %c (%d)\r", cursors[(n_tests/N_STEPS)%sizeof(cursors)], n_tests);
775     fflush(stdout);
776     }
777     #else
778     const unsigned long N_STEPS = 1000000;
779     if ((n_tests % N_STEPS) == 0)
780     printf(" ... %d\n", n_tests);
781     #endif
782     }
783    
784 gbeauche 1.1 int main(void)
785     {
786     static char buffer[1024];
787     #define MAX_INSN_LENGTH 16
788     #define MAX_INSNS 1024
789     static uint8 block[MAX_INSNS * MAX_INSN_LENGTH];
790     static char *insns[MAX_INSNS];
791     static int modes[MAX_INSNS];
792     n_all_tests = n_all_failures = 0;
793    
794 gbeauche 1.3 #if TEST_INST_ALU_REG
795 gbeauche 1.1 printf("Testing reg forms\n");
796     n_tests = n_failures = 0;
797     for (int r = 0; r < 16; r++) {
798     set_target(block);
799     uint8 *b = get_target();
800     int i = 0;
801     #define GEN(INSN, GENOP) do { \
802     insns[i++] = INSN; \
803     GENOP##r(r); \
804     } while (0)
805     #define GENA(INSN, GENOP) do { \
806     GEN(INSN "b", GENOP##B); \
807     GEN(INSN "w", GENOP##W); \
808     GEN(INSN "l", GENOP##L); \
809     GEN(INSN "q", GENOP##Q); \
810     } while (0)
811     GENA("not", NOT);
812     GENA("neg", NEG);
813     GENA("mul", MUL);
814     GENA("imul", IMUL);
815     GENA("div", DIV);
816     GENA("idiv", IDIV);
817     GENA("dec", DEC);
818     GENA("inc", INC);
819     GEN("callq", CALLs);
820     GEN("jmpq", JMPs);
821 gbeauche 1.2 GEN(X86_TARGET_64BIT ? "pushq" : "pushl", PUSHQ);
822     GEN(X86_TARGET_64BIT ? "popq" : "popl", POPQ);
823 gbeauche 1.1 GEN("bswap", BSWAPL); // FIXME: disass bug? no suffix
824     GEN("bswap", BSWAPQ); // FIXME: disass bug? no suffix
825     GEN("seto", SETO);
826     GEN("setno", SETNO);
827     GEN("setb", SETB);
828     GEN("setae", SETAE);
829     GEN("sete", SETE);
830     GEN("setne", SETNE);
831     GEN("setbe", SETBE);
832     GEN("seta", SETA);
833     GEN("sets", SETS);
834     GEN("setns", SETNS);
835     GEN("setp", SETP);
836     GEN("setnp", SETNP);
837     GEN("setl", SETL);
838     GEN("setge", SETGE);
839     GEN("setle", SETLE);
840     GEN("setg", SETG);
841     #undef GENA
842     #undef GEN
843     int last_insn = i;
844     uint8 *e = get_target();
845    
846     uint8 *p = b;
847     i = 0;
848     while (p < e) {
849     int n = disass_x86(buffer, (uintptr)p);
850     insn_t ii;
851     parse_insn(&ii, buffer);
852    
853     if (!check_reg(&ii, insns[i], r)) {
854     if (verbose > 1)
855     fprintf(stderr, "%s\n", buffer);
856     n_failures++;
857     }
858    
859     p += n;
860     i += 1;
861     n_tests++;
862     }
863     if (i != last_insn)
864     abort();
865     }
866     printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
867     n_all_tests += n_tests;
868     n_all_failures += n_failures;
869 gbeauche 1.3 #endif
870 gbeauche 1.1
871 gbeauche 1.3 #if TEST_INST_ALU_REG_REG
872 gbeauche 1.1 printf("Testing reg,reg forms\n");
873     n_tests = n_failures = 0;
874     for (int s = 0; s < 16; s++) {
875     for (int d = 0; d < 16; d++) {
876     set_target(block);
877     uint8 *b = get_target();
878     int i = 0;
879     #define GEN(INSN, GENOP) do { \
880     insns[i++] = INSN; \
881     GENOP##rr(s, d); \
882     } while (0)
883     #define GEN1(INSN, GENOP, OP) do { \
884     insns[i++] = INSN; \
885     GENOP##rr(OP, s, d); \
886     } while (0)
887     #define GENA(INSN, GENOP) do { \
888     GEN(INSN "b", GENOP##B); \
889     GEN(INSN "w", GENOP##W); \
890     GEN(INSN "l", GENOP##L); \
891     GEN(INSN "q", GENOP##Q); \
892     } while (0)
893     GENA("adc", ADC);
894     GENA("add", ADD);
895     GENA("and", AND);
896     GENA("cmp", CMP);
897     GENA("or", OR);
898     GENA("sbb", SBB);
899     GENA("sub", SUB);
900     GENA("xor", XOR);
901     GENA("mov", MOV);
902     GEN("btw", BTW);
903     GEN("btl", BTL);
904     GEN("btq", BTQ);
905     GEN("btcw", BTCW);
906     GEN("btcl", BTCL);
907     GEN("btcq", BTCQ);
908     GEN("btrw", BTRW);
909     GEN("btrl", BTRL);
910     GEN("btrq", BTRQ);
911     GEN("btsw", BTSW);
912     GEN("btsl", BTSL);
913     GEN("btsq", BTSQ);
914     GEN("imulw", IMULW);
915     GEN("imull", IMULL);
916     GEN("imulq", IMULQ);
917     GEN1("cmove", CMOVW, X86_CC_Z);
918     GEN1("cmove", CMOVL, X86_CC_Z);
919     GEN1("cmove", CMOVQ, X86_CC_Z);
920     GENA("test", TEST);
921     GENA("cmpxchg", CMPXCHG);
922     GENA("xadd", XADD);
923     GENA("xchg", XCHG);
924     GEN("bsfw", BSFW);
925     GEN("bsfl", BSFL);
926     GEN("bsfq", BSFQ);
927     GEN("bsrw", BSRW);
928     GEN("bsrl", BSRL);
929     GEN("bsrq", BSRQ);
930     GEN("movsbw", MOVSBW);
931     GEN("movsbl", MOVSBL);
932     GEN("movsbq", MOVSBQ);
933     GEN("movzbw", MOVZBW);
934     GEN("movzbl", MOVZBL);
935     GEN("movzbq", MOVZBQ);
936     GEN("movswl", MOVSWL);
937     GEN("movswq", MOVSWQ);
938     GEN("movzwl", MOVZWL);
939     GEN("movzwq", MOVZWQ);
940     GEN("movslq", MOVSLQ);
941     #undef GENA
942     #undef GEN1
943     #undef GEN
944     int last_insn = i;
945     uint8 *e = get_target();
946    
947     uint8 *p = b;
948     i = 0;
949     while (p < e) {
950     int n = disass_x86(buffer, (uintptr)p);
951     insn_t ii;
952     parse_insn(&ii, buffer);
953    
954     if (!check_reg_reg(&ii, insns[i], s, d)) {
955     if (verbose > 1)
956     fprintf(stderr, "%s\n", buffer);
957     n_failures++;
958     }
959    
960     p += n;
961     i += 1;
962     n_tests++;
963     }
964     if (i != last_insn)
965     abort();
966     }
967     }
968     printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
969     n_all_tests += n_tests;
970     n_all_failures += n_failures;
971 gbeauche 1.3 #endif
972 gbeauche 1.1
973 gbeauche 1.3 #if TEST_INST_ALU_CNT_REG
974 gbeauche 1.1 printf("Testing cl,reg forms\n");
975     n_tests = n_failures = 0;
976     for (int d = 0; d < 16; d++) {
977     set_target(block);
978     uint8 *b = get_target();
979     int i = 0;
980     #define GEN(INSN, GENOP) do { \
981     insns[i++] = INSN; \
982     GENOP##rr(X86_CL, d); \
983     } while (0)
984     #define GENA(INSN, GENOP) do { \
985     GEN(INSN "b", GENOP##B); \
986     GEN(INSN "w", GENOP##W); \
987     GEN(INSN "l", GENOP##L); \
988     GEN(INSN "q", GENOP##Q); \
989     } while (0)
990     GENA("rol", ROL);
991     GENA("ror", ROR);
992     GENA("rcl", RCL);
993     GENA("rcr", RCR);
994     GENA("shl", SHL);
995     GENA("shr", SHR);
996     GENA("sar", SAR);
997     #undef GENA
998     #undef GEN
999     int last_insn = i;
1000     uint8 *e = get_target();
1001    
1002     uint8 *p = b;
1003     i = 0;
1004     while (p < e) {
1005     int n = disass_x86(buffer, (uintptr)p);
1006     insn_t ii;
1007     parse_insn(&ii, buffer);
1008    
1009     if (!check_reg_reg(&ii, insns[i], X86_CL, d)) {
1010     if (verbose > 1)
1011     fprintf(stderr, "%s\n", buffer);
1012     n_failures++;
1013     }
1014    
1015     p += n;
1016     i += 1;
1017     n_tests++;
1018     }
1019     if (i != last_insn)
1020     abort();
1021     }
1022     printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1023     n_all_tests += n_tests;
1024     n_all_failures += n_failures;
1025 gbeauche 1.3 #endif
1026 gbeauche 1.1
1027     static const uint32 imm_table[] = {
1028     0x00000000, 0x00000001, 0x00000002, 0x00000004,
1029     0x00000008, 0x00000010, 0x00000020, 0x00000040,
1030     0x00000080, 0x000000fe, 0x000000ff, 0x00000100,
1031     0x00000101, 0x00000102, 0xfffffffe, 0xffffffff,
1032     0x00000000, 0x10000000, 0x20000000, 0x30000000,
1033     0x40000000, 0x50000000, 0x60000000, 0x70000000,
1034     0x80000000, 0x90000000, 0xa0000000, 0xb0000000,
1035     0xc0000000, 0xd0000000, 0xe0000000, 0xf0000000,
1036     0xfffffffd, 0xfffffffe, 0xffffffff, 0x00000001,
1037     0x00000002, 0x00000003, 0x11111111, 0x22222222,
1038     0x33333333, 0x44444444, 0x55555555, 0x66666666,
1039     0x77777777, 0x88888888, 0x99999999, 0xaaaaaaaa,
1040     0xbbbbbbbb, 0xcccccccc, 0xdddddddd, 0xeeeeeeee,
1041     };
1042     const int n_imm_tab_count = sizeof(imm_table)/sizeof(imm_table[0]);
1043 gbeauche 1.4
1044     #if TEST_INST_ALU_IMM_REG
1045     printf("Testing imm,reg forms\n");
1046 gbeauche 1.1 n_tests = n_failures = 0;
1047     for (int j = 0; j < n_imm_tab_count; j++) {
1048     const uint32 value = imm_table[j];
1049     for (int d = 0; d < 16; d++) {
1050     set_target(block);
1051     uint8 *b = get_target();
1052     int i = 0;
1053     #define GEN(INSN, GENOP) do { \
1054     insns[i] = INSN; \
1055     modes[i] = -1; \
1056     i++; GENOP##ir(value, d); \
1057     } while (0)
1058     #define GENM(INSN, GENOP, MODE) do { \
1059     insns[i] = INSN; \
1060     modes[i] = MODE; \
1061     i++; GENOP##ir(value, d); \
1062     } while (0)
1063     #define GENA(INSN, GENOP) do { \
1064     GEN(INSN "b", GENOP##B); \
1065     GEN(INSN "w", GENOP##W); \
1066     GEN(INSN "l", GENOP##L); \
1067     GEN(INSN "q", GENOP##Q); \
1068     } while (0)
1069     #define GENAM(INSN, GENOP, MODE) do { \
1070     GENM(INSN "b", GENOP##B, MODE); \
1071     GENM(INSN "w", GENOP##W, MODE); \
1072     GENM(INSN "l", GENOP##L, MODE); \
1073     GENM(INSN "q", GENOP##Q, MODE); \
1074     } while (0)
1075     GENA("adc", ADC);
1076     GENA("add", ADD);
1077     GENA("and", AND);
1078     GENA("cmp", CMP);
1079     GENA("or", OR);
1080     GENA("sbb", SBB);
1081     GENA("sub", SUB);
1082     GENA("xor", XOR);
1083     GENA("mov", MOV);
1084     GENM("btw", BTW, 1);
1085     GENM("btl", BTL, 1);
1086     GENM("btq", BTQ, 1);
1087     GENM("btcw", BTCW, 1);
1088     GENM("btcl", BTCL, 1);
1089     GENM("btcq", BTCQ, 1);
1090     GENM("btrw", BTRW, 1);
1091     GENM("btrl", BTRL, 1);
1092     GENM("btrq", BTRQ, 1);
1093     GENM("btsw", BTSW, 1);
1094     GENM("btsl", BTSL, 1);
1095     GENM("btsq", BTSQ, 1);
1096     if (value != 1) {
1097     GENAM("rol", ROL, 1);
1098     GENAM("ror", ROR, 1);
1099     GENAM("rcl", RCL, 1);
1100     GENAM("rcr", RCR, 1);
1101     GENAM("shl", SHL, 1);
1102     GENAM("shr", SHR, 1);
1103     GENAM("sar", SAR, 1);
1104     }
1105     GENA("test", TEST);
1106     #undef GENAM
1107     #undef GENA
1108     #undef GENM
1109     #undef GEN
1110     int last_insn = i;
1111     uint8 *e = get_target();
1112    
1113     uint8 *p = b;
1114     i = 0;
1115     while (p < e) {
1116     int n = disass_x86(buffer, (uintptr)p);
1117     insn_t ii;
1118     parse_insn(&ii, buffer);
1119    
1120     if (!check_imm_reg(&ii, insns[i], value, d, modes[i])) {
1121     if (verbose > 1)
1122     fprintf(stderr, "%s\n", buffer);
1123     n_failures++;
1124     }
1125    
1126     p += n;
1127     i += 1;
1128     n_tests++;
1129     }
1130     if (i != last_insn)
1131     abort();
1132     }
1133     }
1134     printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1135     n_all_tests += n_tests;
1136     n_all_failures += n_failures;
1137 gbeauche 1.3 #endif
1138 gbeauche 1.1
1139     static const uint32 off_table[] = {
1140     0x00000000,
1141     0x00000001,
1142     0x00000040,
1143     0x00000080,
1144     0x000000ff,
1145     0x00000100,
1146     0xfffffffe,
1147     0xffffffff,
1148     };
1149     const int off_table_count = sizeof(off_table) / sizeof(off_table[0]);
1150 gbeauche 1.4
1151     #if TEST_INST_ALU_MEM_REG
1152     printf("Testing mem,reg forms\n");
1153     n_tests = n_failures = 0;
1154 gbeauche 1.1 for (int d = 0; d < off_table_count; d++) {
1155     const uint32 D = off_table[d];
1156     for (int B = -1; B < 16; B++) {
1157     for (int I = -1; I < 16; I++) {
1158     if (I == X86_RSP)
1159     continue;
1160 gbeauche 1.5 for (int S = 1; S < 16; S *= 2) {
1161     if (I == -1 && S > 1)
1162 gbeauche 1.1 continue;
1163     for (int r = 0; r < 16; r++) {
1164     set_target(block);
1165     uint8 *b = get_target();
1166     int i = 0;
1167     #define GEN(INSN, GENOP) do { \
1168     insns[i++] = INSN; \
1169     GENOP##mr(D, B, I, S, r); \
1170     } while (0)
1171     #define GENA(INSN, GENOP) do { \
1172     GEN(INSN "b", GENOP##B); \
1173     GEN(INSN "w", GENOP##W); \
1174     GEN(INSN "l", GENOP##L); \
1175     GEN(INSN "q", GENOP##Q); \
1176     } while (0)
1177     GENA("adc", ADC);
1178     GENA("add", ADD);
1179     GENA("and", AND);
1180     GENA("cmp", CMP);
1181     GENA("or", OR);
1182     GENA("sbb", SBB);
1183     GENA("sub", SUB);
1184     GENA("xor", XOR);
1185     GENA("mov", MOV);
1186     GEN("imulw", IMULW);
1187     GEN("imull", IMULL);
1188     GEN("imulq", IMULQ);
1189     GEN("bsfw", BSFW);
1190     GEN("bsfl", BSFL);
1191     GEN("bsfq", BSFQ);
1192     GEN("bsrw", BSRW);
1193     GEN("bsrl", BSRL);
1194     GEN("bsrq", BSRQ);
1195     GEN("movsbw", MOVSBW);
1196     GEN("movsbl", MOVSBL);
1197     GEN("movsbq", MOVSBQ);
1198     GEN("movzbw", MOVZBW);
1199     GEN("movzbl", MOVZBL);
1200     GEN("movzbq", MOVZBQ);
1201     GEN("movswl", MOVSWL);
1202     GEN("movswq", MOVSWQ);
1203     GEN("movzwl", MOVZWL);
1204     GEN("movzwq", MOVZWQ);
1205     GEN("movslq", MOVSLQ);
1206     #undef GENA
1207     #undef GEN
1208     int last_insn = i;
1209     uint8 *e = get_target();
1210    
1211     uint8 *p = b;
1212     i = 0;
1213     while (p < e) {
1214     int n = disass_x86(buffer, (uintptr)p);
1215     insn_t ii;
1216     parse_insn(&ii, buffer);
1217    
1218     if (!check_mem_reg(&ii, insns[i], D, B, I, S, r)) {
1219     if (verbose > 1)
1220     fprintf(stderr, "%s\n", buffer);
1221     n_failures++;
1222     }
1223    
1224     p += n;
1225     i += 1;
1226     n_tests++;
1227 gbeauche 1.3 show_status(n_tests);
1228 gbeauche 1.1 }
1229     if (i != last_insn)
1230     abort();
1231     }
1232     }
1233     }
1234     }
1235     }
1236     printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1237     n_all_tests += n_tests;
1238     n_all_failures += n_failures;
1239 gbeauche 1.3 #endif
1240 gbeauche 1.1
1241 gbeauche 1.4 #if TEST_INST_VPU_REG_REG
1242     printf("Testing SIMD reg,reg forms\n");
1243     n_tests = n_failures = 0;
1244     for (int s = 0; s < 16; s++) {
1245     for (int d = 0; d < 16; d++) {
1246     set_target(block);
1247     uint8 *b = get_target();
1248     int i = 0;
1249     #define GEN(INSN, GENOP) do { \
1250     insns[i++] = INSN; \
1251     GENOP##rr(s, d); \
1252     } while (0)
1253     #define GEN1(INSN, GENOP) do { \
1254     GEN(INSN "s", GENOP##S); \
1255     GEN(INSN "d", GENOP##D); \
1256     } while (0)
1257     #define GENA(INSN, GENOP) do { \
1258     GEN1(INSN "s", GENOP##S); \
1259     GEN1(INSN "p", GENOP##P); \
1260     } while (0)
1261     #define GENI(INSN, GENOP, IMM) do { \
1262     insns[i++] = INSN; \
1263     GENOP##rr(IMM, s, d); \
1264     } while (0)
1265     #define GENI1(INSN, GENOP, IMM) do { \
1266     GENI(INSN "s", GENOP##S, IMM); \
1267     GENI(INSN "d", GENOP##D, IMM); \
1268     } while (0)
1269     #define GENIA(INSN, GENOP, IMM) do { \
1270     GENI1(INSN "s", GENOP##S, IMM); \
1271     GENI1(INSN "p", GENOP##P, IMM); \
1272     } while (0)
1273     GEN1("andp", ANDP);
1274     GEN1("andnp", ANDNP);
1275     GEN1("orp", ORP);
1276     GEN1("xorp", XORP);
1277     GENA("add", ADD);
1278     GENA("sub", SUB);
1279     GENA("mul", MUL);
1280     GENA("div", DIV);
1281     GEN1("comis", COMIS);
1282     GEN1("ucomis", UCOMIS);
1283     GENA("min", MIN);
1284     GENA("max", MAX);
1285     GEN("rcpss", RCPSS);
1286     GEN("rcpps", RCPPS);
1287     GEN("rsqrtss", RSQRTSS);
1288     GEN("rsqrtps", RSQRTPS);
1289     GENA("sqrt", SQRT);
1290     GENIA("cmpeq", CMP, X86_SSE_CC_EQ);
1291     GENIA("cmplt", CMP, X86_SSE_CC_LT);
1292     GENIA("cmple", CMP, X86_SSE_CC_LE);
1293     GENIA("cmpunord", CMP, X86_SSE_CC_U);
1294     GENIA("cmpneq", CMP, X86_SSE_CC_NEQ);
1295     GENIA("cmpnlt", CMP, X86_SSE_CC_NLT);
1296     GENIA("cmpnle", CMP, X86_SSE_CC_NLE);
1297     GENIA("cmpord", CMP, X86_SSE_CC_O);
1298     GEN1("movap", MOVAP);
1299     GEN("movdqa", MOVDQA);
1300     GEN("movdqu", MOVDQU);
1301     GEN("movd", MOVDXD);
1302 gbeauche 1.5 GEN("movd", MOVQXD); // FIXME: disass bug? "movq" expected
1303 gbeauche 1.4 GEN("movd", MOVDXS);
1304 gbeauche 1.5 GEN("movd", MOVQXS); // FIXME: disass bug? "movq" expected
1305 gbeauche 1.6 GEN("cvtdq2pd", CVTDQ2PD);
1306     GEN("cvtdq2ps", CVTDQ2PS);
1307     GEN("cvtpd2dq", CVTPD2DQ);
1308     GEN("cvtpd2ps", CVTPD2PS);
1309     GEN("cvtps2dq", CVTPS2DQ);
1310     GEN("cvtps2pd", CVTPS2PD);
1311     GEN("cvtsd2si", CVTSD2SIL);
1312     GEN("cvtsd2siq", CVTSD2SIQ);
1313     GEN("cvtsd2ss", CVTSD2SS);
1314     GEN("cvtsi2sd", CVTSI2SDL);
1315     GEN("cvtsi2sdq", CVTSI2SDQ);
1316     GEN("cvtsi2ss", CVTSI2SSL);
1317     GEN("cvtsi2ssq", CVTSI2SSQ);
1318     GEN("cvtss2sd", CVTSS2SD);
1319     GEN("cvtss2si", CVTSS2SIL);
1320     GEN("cvtss2siq", CVTSS2SIQ);
1321     GEN("cvttpd2dq", CVTTPD2DQ);
1322     GEN("cvttps2dq", CVTTPS2DQ);
1323     GEN("cvttsd2si", CVTTSD2SIL);
1324     GEN("cvttsd2siq", CVTTSD2SIQ);
1325     GEN("cvttss2si", CVTTSS2SIL);
1326     GEN("cvttss2siq", CVTTSS2SIQ);
1327     if (s < 8) {
1328     // MMX source register
1329     GEN("cvtpi2pd", CVTPI2PD);
1330     GEN("cvtpi2ps", CVTPI2PS);
1331     }
1332     if (d < 8) {
1333     // MMX dest register
1334     GEN("cvtpd2pi", CVTPD2PI);
1335     GEN("cvtps2pi", CVTPS2PI);
1336     GEN("cvttpd2pi", CVTTPD2PI);
1337     GEN("cvttps2pi", CVTTPS2PI);
1338     }
1339 gbeauche 1.4 #undef GENIA
1340     #undef GENI1
1341     #undef GENI
1342     #undef GENA
1343     #undef GEN1
1344     #undef GEN
1345     int last_insn = i;
1346     uint8 *e = get_target();
1347    
1348     uint8 *p = b;
1349     i = 0;
1350     while (p < e) {
1351     int n = disass_x86(buffer, (uintptr)p);
1352     insn_t ii;
1353     parse_insn(&ii, buffer);
1354    
1355     if (!check_reg_reg(&ii, insns[i], s, d)) {
1356     if (verbose > 1) {
1357     if (1) {
1358     for (int j = 0; j < MAX_INSN_LENGTH; j++)
1359     fprintf(stderr, "%02x ", p[j]);
1360     fprintf(stderr, "| ");
1361     }
1362     fprintf(stderr, "%s\n", buffer);
1363     }
1364     n_failures++;
1365     }
1366    
1367     p += n;
1368     i += 1;
1369     n_tests++;
1370     }
1371     if (i != last_insn)
1372     abort();
1373     }
1374     }
1375     printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1376     n_all_tests += n_tests;
1377     n_all_failures += n_failures;
1378     #endif
1379    
1380     #if TEST_INST_VPU_MEM_REG
1381     printf("Testing SIMD mem,reg forms\n");
1382     n_tests = n_failures = 0;
1383     for (int d = 0; d < off_table_count; d++) {
1384     const uint32 D = off_table[d];
1385     for (int B = -1; B < 16; B++) {
1386     for (int I = -1; I < 16; I++) {
1387     if (I == X86_RSP)
1388     continue;
1389 gbeauche 1.5 for (int S = 1; S < 16; S *= 2) {
1390     if (I == -1 && S > 1)
1391 gbeauche 1.4 continue;
1392     for (int r = 0; r < 16; r++) {
1393     set_target(block);
1394     uint8 *b = get_target();
1395     int i = 0;
1396     #define GEN(INSN, GENOP) do { \
1397     insns[i++] = INSN; \
1398     GENOP##mr(D, B, I, S, r); \
1399     } while (0)
1400     #define GEN1(INSN, GENOP) do { \
1401     GEN(INSN "s", GENOP##S); \
1402     GEN(INSN "d", GENOP##D); \
1403     } while (0)
1404     #define GENA(INSN, GENOP) do { \
1405     GEN1(INSN "s", GENOP##S); \
1406     GEN1(INSN "p", GENOP##P); \
1407     } while (0)
1408     #define GENI(INSN, GENOP, IMM) do { \
1409     insns[i++] = INSN; \
1410     GENOP##mr(IMM, D, B, I, S, r); \
1411     } while (0)
1412     #define GENI1(INSN, GENOP, IMM) do { \
1413     GENI(INSN "s", GENOP##S, IMM); \
1414     GENI(INSN "d", GENOP##D, IMM); \
1415     } while (0)
1416     #define GENIA(INSN, GENOP, IMM) do { \
1417     GENI1(INSN "s", GENOP##S, IMM); \
1418     GENI1(INSN "p", GENOP##P, IMM); \
1419     } while (0)
1420     GEN1("andp", ANDP);
1421     GEN1("andnp", ANDNP);
1422     GEN1("orp", ORP);
1423     GEN1("xorp", XORP);
1424     GENA("add", ADD);
1425     GENA("sub", SUB);
1426     GENA("mul", MUL);
1427     GENA("div", DIV);
1428     GEN1("comis", COMIS);
1429     GEN1("ucomis", UCOMIS);
1430     GENA("min", MIN);
1431     GENA("max", MAX);
1432     GEN("rcpss", RCPSS);
1433     GEN("rcpps", RCPPS);
1434     GEN("rsqrtss", RSQRTSS);
1435     GEN("rsqrtps", RSQRTPS);
1436     GENA("sqrt", SQRT);
1437     GENIA("cmpeq", CMP, X86_SSE_CC_EQ);
1438     GENIA("cmplt", CMP, X86_SSE_CC_LT);
1439     GENIA("cmple", CMP, X86_SSE_CC_LE);
1440     GENIA("cmpunord", CMP, X86_SSE_CC_U);
1441     GENIA("cmpneq", CMP, X86_SSE_CC_NEQ);
1442     GENIA("cmpnlt", CMP, X86_SSE_CC_NLT);
1443     GENIA("cmpnle", CMP, X86_SSE_CC_NLE);
1444     GENIA("cmpord", CMP, X86_SSE_CC_O);
1445     GEN1("movap", MOVAP);
1446     GEN("movdqa", MOVDQA);
1447     GEN("movdqu", MOVDQU);
1448     #if 0
1449     // FIXME: extraneous REX bits generated
1450     GEN("movd", MOVDXD);
1451 gbeauche 1.5 GEN("movd", MOVQXD); // FIXME: disass bug? "movq" expected
1452 gbeauche 1.4 #endif
1453 gbeauche 1.6 GEN("cvtdq2pd", CVTDQ2PD);
1454     GEN("cvtdq2ps", CVTDQ2PS);
1455     GEN("cvtpd2dq", CVTPD2DQ);
1456     GEN("cvtpd2ps", CVTPD2PS);
1457     GEN("cvtps2dq", CVTPS2DQ);
1458     GEN("cvtps2pd", CVTPS2PD);
1459     GEN("cvtsd2si", CVTSD2SIL);
1460     GEN("cvtsd2siq", CVTSD2SIQ);
1461     GEN("cvtsd2ss", CVTSD2SS);
1462     GEN("cvtsi2sd", CVTSI2SDL);
1463     GEN("cvtsi2sdq", CVTSI2SDQ);
1464     GEN("cvtsi2ss", CVTSI2SSL);
1465     GEN("cvtsi2ssq", CVTSI2SSQ);
1466     GEN("cvtss2sd", CVTSS2SD);
1467     GEN("cvtss2si", CVTSS2SIL);
1468     GEN("cvtss2siq", CVTSS2SIQ);
1469     GEN("cvttpd2dq", CVTTPD2DQ);
1470     GEN("cvttps2dq", CVTTPS2DQ);
1471     GEN("cvttsd2si", CVTTSD2SIL);
1472     GEN("cvttsd2siq", CVTTSD2SIQ);
1473     GEN("cvttss2si", CVTTSS2SIL);
1474     GEN("cvttss2siq", CVTTSS2SIQ);
1475     if (r < 8) {
1476     // MMX dest register
1477     GEN("cvtpd2pi", CVTPD2PI);
1478     GEN("cvtps2pi", CVTPS2PI);
1479     GEN("cvttpd2pi", CVTTPD2PI);
1480     GEN("cvttps2pi", CVTTPS2PI);
1481     }
1482 gbeauche 1.4 #undef GENIA
1483     #undef GENI1
1484     #undef GENI
1485     #undef GENA
1486     #undef GEN1
1487     #undef GEN
1488     int last_insn = i;
1489     uint8 *e = get_target();
1490    
1491     uint8 *p = b;
1492     i = 0;
1493     while (p < e) {
1494     int n = disass_x86(buffer, (uintptr)p);
1495     insn_t ii;
1496     parse_insn(&ii, buffer);
1497    
1498     if (!check_mem_reg(&ii, insns[i], D, B, I, S, r)) {
1499     if (verbose > 1) {
1500     if (1) {
1501     for (int j = 0; j < MAX_INSN_LENGTH; j++)
1502     fprintf(stderr, "%02x ", p[j]);
1503     fprintf(stderr, "| ");
1504     }
1505     fprintf(stderr, "%s\n", buffer);
1506     }
1507     n_failures++;
1508     }
1509    
1510     p += n;
1511     i += 1;
1512     n_tests++;
1513     show_status(n_tests);
1514     }
1515     if (i != last_insn)
1516     abort();
1517     }
1518     }
1519     }
1520     }
1521     }
1522     printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
1523     n_all_tests += n_tests;
1524     n_all_failures += n_failures;
1525     #endif
1526    
1527 gbeauche 1.1 printf("\n");
1528     printf("All %ld tests run, %ld failures\n", n_all_tests, n_all_failures);
1529     }