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.8
Committed: 2008-02-12T09:55:36Z (16 years, 9 months ago) by gbeauche
Branch: MAIN
Changes since 1.7: +235 -154 lines
Log Message:
- Fix tests for 32-bit code generation
- Simplify parse_imm() and factor out failure messages to show_instruction()

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