- Fix CMPSD, COMISS, COMISD, UCOMISS, UCOMISD, MOVD/MOVQ %xmm,%reg

- Rename X86_SSE_CC_NE to X86_SSE_CC_NEQ (match Intel reference manual)
- Rename MOVDLX to MOVDXD (%Xmm register as Destination)
- Rename MOVDQX to MOVQXD (%Xmm register as Destination)
- Rename MOVDXL to MOVDXS (%Xmm register as Source)
- Rename MOVDXQ to MOVQXS (%Xmm register as Source)
This commit is contained in:
gbeauche 2008-02-11 16:13:47 +00:00
parent f8e11d9aba
commit 3ea69bfc5c
2 changed files with 298 additions and 27 deletions

View File

@ -1650,7 +1650,7 @@ enum {
X86_SSE_CC_LE = 2,
X86_SSE_CC_GE = 2,
X86_SSE_CC_U = 3,
X86_SSE_CC_NE = 4,
X86_SSE_CC_NEQ = 4,
X86_SSE_CC_NLT = 5,
X86_SSE_CC_NGT = 5,
X86_SSE_CC_NLE = 6,
@ -1793,8 +1793,8 @@ enum {
#define _SSESDrr(OP,RS,RD) _SSELrr(0xf2, OP, RS,_rX, RD,_rX)
#define _SSESDmr(OP,MD,MB,MI,MS,RD) _SSELmr(0xf2, OP, MD, MB, MI, MS, RD,_rX)
#define _SSESDrm(OP,RS,MD,MB,MI,MS) _SSELrm(0xf2, OP, RS,_rX, MD, MB, MI, MS)
#define _SSESDirr(OP,IM,RS,RD) _SSELirr(0xf2, IM, OP, RS, RD)
#define _SSESDimr(OP,IM,MD,MB,MI,MS,RD) _SSELimr(0xf2, IM, OP, MD, MB, MI, MS, RD)
#define _SSESDirr(OP,IM,RS,RD) _SSELirr(0xf2, OP, IM, RS, RD)
#define _SSESDimr(OP,IM,MD,MB,MI,MS,RD) _SSELimr(0xf2, OP, IM, MD, MB, MI, MS, RD)
#define ADDPSrr(RS, RD) _SSEPSrr(X86_SSE_ADD, RS, RD)
#define ADDPSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_ADD, MD, MB, MI, MS, RD)
@ -1906,15 +1906,15 @@ enum {
#define XORPDrr(RS, RD) _SSEPDrr(X86_SSE_XOR, RS, RD)
#define XORPDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_XOR, MD, MB, MI, MS, RD)
#define COMISSrr(RS, RD) _SSESSrr(X86_SSE_COMI, RS, RD)
#define COMISSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_COMI, MD, MB, MI, MS, RD)
#define COMISDrr(RS, RD) _SSESDrr(X86_SSE_COMI, RS, RD)
#define COMISDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_COMI, MD, MB, MI, MS, RD)
#define COMISSrr(RS, RD) _SSEPSrr(X86_SSE_COMI, RS, RD)
#define COMISSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_COMI, MD, MB, MI, MS, RD)
#define COMISDrr(RS, RD) _SSEPDrr(X86_SSE_COMI, RS, RD)
#define COMISDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_COMI, MD, MB, MI, MS, RD)
#define UCOMISSrr(RS, RD) _SSESSrr(X86_SSE_UCOMI, RS, RD)
#define UCOMISSmr(MD, MB, MI, MS, RD) _SSESSmr(X86_SSE_UCOMI, MD, MB, MI, MS, RD)
#define UCOMISDrr(RS, RD) _SSESDrr(X86_SSE_UCOMI, RS, RD)
#define UCOMISDmr(MD, MB, MI, MS, RD) _SSESDmr(X86_SSE_UCOMI, MD, MB, MI, MS, RD)
#define UCOMISSrr(RS, RD) _SSEPSrr(X86_SSE_UCOMI, RS, RD)
#define UCOMISSmr(MD, MB, MI, MS, RD) _SSEPSmr(X86_SSE_UCOMI, MD, MB, MI, MS, RD)
#define UCOMISDrr(RS, RD) _SSEPDrr(X86_SSE_UCOMI, RS, RD)
#define UCOMISDmr(MD, MB, MI, MS, RD) _SSEPDmr(X86_SSE_UCOMI, MD, MB, MI, MS, RD)
#define MOVAPSrr(RS, RD) _SSEPSrr(0x28, RS, RD)
#define MOVAPSmr(MD, MB, MI, MS, RD) _SSEPSmr(0x28, MD, MB, MI, MS, RD)
@ -1964,15 +1964,15 @@ enum {
#define CVTSI2SDQrr(RS, RD) _SSEQrr(0xf2, X86_SSE_CVTIS, RS,_r8, RD,_rX)
#define CVTSI2SDQmr(MD, MB, MI, MS, RD) _SSEQmr(0xf2, X86_SSE_CVTIS, MD, MB, MI, MS, RD,_rX)
#define MOVDLXrr(RS, RD) _SSELrr(0x66, 0x6e, RS,_r4, RD,_rX)
#define MOVDLXmr(MD, MB, MI, MS, RD) _SSELmr(0x66, 0x6e, MD, MB, MI, MS, RD,_rX)
#define MOVDQXrr(RS, RD) _SSEQrr(0x66, 0x6e, RS,_r8, RD,_rX)
#define MOVDQXmr(MD, MB, MI, MS, RD) _SSEQmr(0x66, 0x6e, MD, MB, MI, MS, RD,_rX)
#define MOVDXDrr(RS, RD) _SSELrr(0x66, 0x6e, RS,_r4, RD,_rX)
#define MOVDXDmr(MD, MB, MI, MS, RD) _SSELmr(0x66, 0x6e, MD, MB, MI, MS, RD,_rX)
#define MOVQXDrr(RS, RD) _SSEQrr(0x66, 0x6e, RS,_r8, RD,_rX)
#define MOVQXDmr(MD, MB, MI, MS, RD) _SSEQmr(0x66, 0x6e, MD, MB, MI, MS, RD,_rX)
#define MOVDXLrr(RS, RD) _SSELrr(0x66, 0x7e, RS,_rX, RD,_r4)
#define MOVDXLrm(RS, MD, MB, MI, MS) _SSELrm(0x66, 0x7e, RS,_rX, MD, MB, MI, MS)
#define MOVDXQrr(RS, RD) _SSEQrr(0x66, 0x7e, RS,_rX, RD,_r8)
#define MOVDXQrm(RS, MD, MB, MI, MS) _SSEQrm(0x66, 0x7e, RS,_rX, MD, MB, MI, MS)
#define MOVDXSrr(RS, RD) _SSELrr(0x66, 0x7e, RD,_r4, RS,_rX)
#define MOVDXSrm(RS, MD, MB, MI, MS) _SSELrm(0x66, 0x7e, RS,_rX, MD, MB, MI, MS)
#define MOVQXSrr(RS, RD) _SSEQrr(0x66, 0x7e, RD,_r8, RS,_rX)
#define MOVQXSrm(RS, MD, MB, MI, MS) _SSEQrm(0x66, 0x7e, RS,_rX, MD, MB, MI, MS)
#define MOVDLMrr(RS, RD) __SSELrr( 0x6e, RS,_r4, RD,_rM)
#define MOVDLMmr(MD, MB, MI, MS, RD) __SSELmr( 0x6e, MD, MB, MI, MS, RD,_rM)

View File

@ -26,7 +26,7 @@
***********************************************************************/
/*
* STATUS: 5.5M variations covering unary register based operations,
* STATUS: 13M variations covering unary register based operations,
* reg/reg operations, imm/reg operations.
*
* TODO:
@ -46,11 +46,20 @@
static int verbose = 2;
#define TEST_INST_ALU 1
#define TEST_INST_VPU 1
#if TEST_INST_ALU
#define TEST_INST_ALU_REG 1
#define TEST_INST_ALU_REG_REG 1
#define TEST_INST_ALU_CNT_REG 1
#define TEST_INST_ALU_IMM_REG 1
#define TEST_INST_ALU_MEM_REG 1
#endif
#if TEST_INST_VPU
#define TEST_INST_VPU_REG 1
#define TEST_INST_VPU_REG_REG 1
#define TEST_INST_VPU_MEM_REG 1
#endif
#undef abort
#define abort() do { \
@ -294,6 +303,26 @@ static inline char *skip_blanks(char *p)
static int parse_reg(operand_t *op, int optype, char *buf)
{
// fast lookup (SSE registers)
int reg = 0;
int len = 0;
char *p = buf;
switch (*p) {
case 'x': case 'X':
if (strncasecmp(p, "xmm", 3) == 0) {
len = 3;
if (isdigit(p[len+1]) && p[len] == '1')
reg = 10, len++;
if (isdigit(p[len])) {
reg += p[len++] - '0';
op->fill(optype, X86_RegXMM_Base + reg);
return len;
}
}
break;
}
// slow table lookup
for (int i = 0; regnames[i].name; i++) {
int len = strlen(regnames[i].name);
if (strncasecmp(regnames[i].name, buf, len) == 0) {
@ -301,6 +330,8 @@ static int parse_reg(operand_t *op, int optype, char *buf)
return len;
}
}
// nothing found
return 0;
}
@ -364,6 +395,10 @@ static void parse_insn(insn_t *ii, char *buf)
char *p = buf;
ii->clear();
#if 0
printf("BUF: %s\n", buf);
#endif
if (strncmp(p, "rex64", 5) == 0) {
char *q = find_blanks(p);
if (verbose > 1) {
@ -375,6 +410,17 @@ static void parse_insn(insn_t *ii, char *buf)
p = skip_blanks(q);
}
if (strncmp(p, "rep", 3) == 0) {
char *q = find_blanks(p);
if (verbose > 1) {
char prefix[16];
memset(prefix, 0, sizeof(prefix));
memcpy(prefix, p, q - p);
fprintf(stderr, "Instruction '%s', skip REP prefix '%s'\n", buf, prefix);
}
p = skip_blanks(q);
}
for (int i = 0; !isspace(*p); i++)
ii->name[i] = *p++;
@ -482,7 +528,7 @@ static bool check_reg_reg(insn_t *ii, const char *name, int s, int d)
if (srcreg == -1)
fprintf(stderr, "nothing\n");
else
fprintf(stderr, "%d\n", srcreg);
fprintf(stderr, "r%d\n", srcreg);
return false;
}
@ -491,7 +537,7 @@ static bool check_reg_reg(insn_t *ii, const char *name, int s, int d)
if (dstreg == -1)
fprintf(stderr, "nothing\n");
else
fprintf(stderr, "%d\n", dstreg);
fprintf(stderr, "r%d\n", dstreg);
return false;
}
@ -856,8 +902,6 @@ int main(void)
n_all_failures += n_failures;
#endif
#if TEST_INST_ALU_IMM_REG
printf("Testing imm,reg forms\n");
static const uint32 imm_table[] = {
0x00000000, 0x00000001, 0x00000002, 0x00000004,
0x00000008, 0x00000010, 0x00000020, 0x00000040,
@ -874,6 +918,9 @@ int main(void)
0xbbbbbbbb, 0xcccccccc, 0xdddddddd, 0xeeeeeeee,
};
const int n_imm_tab_count = sizeof(imm_table)/sizeof(imm_table[0]);
#if TEST_INST_ALU_IMM_REG
printf("Testing imm,reg forms\n");
n_tests = n_failures = 0;
for (int j = 0; j < n_imm_tab_count; j++) {
const uint32 value = imm_table[j];
@ -967,9 +1014,6 @@ int main(void)
n_all_failures += n_failures;
#endif
#if TEST_INST_ALU_MEM_REG
printf("Testing mem,reg forms\n");
n_tests = n_failures = 0;
static const uint32 off_table[] = {
0x00000000,
0x00000001,
@ -981,6 +1025,10 @@ int main(void)
0xffffffff,
};
const int off_table_count = sizeof(off_table) / sizeof(off_table[0]);
#if TEST_INST_ALU_MEM_REG
printf("Testing mem,reg forms\n");
n_tests = n_failures = 0;
for (int d = 0; d < off_table_count; d++) {
const uint32 D = off_table[d];
for (int B = -1; B < 16; B++) {
@ -1068,6 +1116,229 @@ int main(void)
n_all_failures += n_failures;
#endif
#if TEST_INST_VPU_REG_REG
printf("Testing SIMD reg,reg forms\n");
n_tests = n_failures = 0;
for (int s = 0; s < 16; s++) {
for (int d = 0; d < 16; d++) {
set_target(block);
uint8 *b = get_target();
int i = 0;
#define GEN(INSN, GENOP) do { \
insns[i++] = INSN; \
GENOP##rr(s, d); \
} while (0)
#define GEN1(INSN, GENOP) do { \
GEN(INSN "s", GENOP##S); \
GEN(INSN "d", GENOP##D); \
} while (0)
#define GENA(INSN, GENOP) do { \
GEN1(INSN "s", GENOP##S); \
GEN1(INSN "p", GENOP##P); \
} while (0)
#define GENI(INSN, GENOP, IMM) do { \
insns[i++] = INSN; \
GENOP##rr(IMM, s, d); \
} while (0)
#define GENI1(INSN, GENOP, IMM) do { \
GENI(INSN "s", GENOP##S, IMM); \
GENI(INSN "d", GENOP##D, IMM); \
} while (0)
#define GENIA(INSN, GENOP, IMM) do { \
GENI1(INSN "s", GENOP##S, IMM); \
GENI1(INSN "p", GENOP##P, IMM); \
} while (0)
GEN1("andp", ANDP);
GEN1("andnp", ANDNP);
GEN1("orp", ORP);
GEN1("xorp", XORP);
GENA("add", ADD);
GENA("sub", SUB);
GENA("mul", MUL);
GENA("div", DIV);
GEN1("comis", COMIS);
GEN1("ucomis", UCOMIS);
GENA("min", MIN);
GENA("max", MAX);
GEN("rcpss", RCPSS);
GEN("rcpps", RCPPS);
GEN("rsqrtss", RSQRTSS);
GEN("rsqrtps", RSQRTPS);
GENA("sqrt", SQRT);
GENIA("cmpeq", CMP, X86_SSE_CC_EQ);
GENIA("cmplt", CMP, X86_SSE_CC_LT);
GENIA("cmple", CMP, X86_SSE_CC_LE);
GENIA("cmpunord", CMP, X86_SSE_CC_U);
GENIA("cmpneq", CMP, X86_SSE_CC_NEQ);
GENIA("cmpnlt", CMP, X86_SSE_CC_NLT);
GENIA("cmpnle", CMP, X86_SSE_CC_NLE);
GENIA("cmpord", CMP, X86_SSE_CC_O);
GEN1("movap", MOVAP);
GEN("movdqa", MOVDQA);
GEN("movdqu", MOVDQU);
GEN("movd", MOVDXD);
GEN("movd", MOVQXD); // FIXME: disass bug? movq
GEN("movd", MOVDXS);
GEN("movd", MOVQXS); // FIXME: disass bug? movq
#undef GENIA
#undef GENI1
#undef GENI
#undef GENA
#undef GEN1
#undef GEN
int last_insn = i;
uint8 *e = get_target();
uint8 *p = b;
i = 0;
while (p < e) {
int n = disass_x86(buffer, (uintptr)p);
insn_t ii;
parse_insn(&ii, buffer);
if (!check_reg_reg(&ii, insns[i], s, d)) {
if (verbose > 1) {
if (1) {
for (int j = 0; j < MAX_INSN_LENGTH; j++)
fprintf(stderr, "%02x ", p[j]);
fprintf(stderr, "| ");
}
fprintf(stderr, "%s\n", buffer);
}
n_failures++;
}
p += n;
i += 1;
n_tests++;
}
if (i != last_insn)
abort();
}
}
printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
n_all_tests += n_tests;
n_all_failures += n_failures;
#endif
#if TEST_INST_VPU_MEM_REG
printf("Testing SIMD mem,reg forms\n");
n_tests = n_failures = 0;
for (int d = 0; d < off_table_count; d++) {
const uint32 D = off_table[d];
for (int B = -1; B < 16; B++) {
for (int I = -1; I < 16; I++) {
if (I == X86_RSP)
continue;
for (int S = 1; S < 8; S *= 2) {
if (I == -1)
continue;
for (int r = 0; r < 16; r++) {
set_target(block);
uint8 *b = get_target();
int i = 0;
#define GEN(INSN, GENOP) do { \
insns[i++] = INSN; \
GENOP##mr(D, B, I, S, r); \
} while (0)
#define GEN1(INSN, GENOP) do { \
GEN(INSN "s", GENOP##S); \
GEN(INSN "d", GENOP##D); \
} while (0)
#define GENA(INSN, GENOP) do { \
GEN1(INSN "s", GENOP##S); \
GEN1(INSN "p", GENOP##P); \
} while (0)
#define GENI(INSN, GENOP, IMM) do { \
insns[i++] = INSN; \
GENOP##mr(IMM, D, B, I, S, r); \
} while (0)
#define GENI1(INSN, GENOP, IMM) do { \
GENI(INSN "s", GENOP##S, IMM); \
GENI(INSN "d", GENOP##D, IMM); \
} while (0)
#define GENIA(INSN, GENOP, IMM) do { \
GENI1(INSN "s", GENOP##S, IMM); \
GENI1(INSN "p", GENOP##P, IMM); \
} while (0)
GEN1("andp", ANDP);
GEN1("andnp", ANDNP);
GEN1("orp", ORP);
GEN1("xorp", XORP);
GENA("add", ADD);
GENA("sub", SUB);
GENA("mul", MUL);
GENA("div", DIV);
GEN1("comis", COMIS);
GEN1("ucomis", UCOMIS);
GENA("min", MIN);
GENA("max", MAX);
GEN("rcpss", RCPSS);
GEN("rcpps", RCPPS);
GEN("rsqrtss", RSQRTSS);
GEN("rsqrtps", RSQRTPS);
GENA("sqrt", SQRT);
GENIA("cmpeq", CMP, X86_SSE_CC_EQ);
GENIA("cmplt", CMP, X86_SSE_CC_LT);
GENIA("cmple", CMP, X86_SSE_CC_LE);
GENIA("cmpunord", CMP, X86_SSE_CC_U);
GENIA("cmpneq", CMP, X86_SSE_CC_NEQ);
GENIA("cmpnlt", CMP, X86_SSE_CC_NLT);
GENIA("cmpnle", CMP, X86_SSE_CC_NLE);
GENIA("cmpord", CMP, X86_SSE_CC_O);
GEN1("movap", MOVAP);
GEN("movdqa", MOVDQA);
GEN("movdqu", MOVDQU);
#if 0
// FIXME: extraneous REX bits generated
GEN("movd", MOVDXD);
GEN("movd", MOVQXD); // FIXME: disass bug? movq
#endif
#undef GENIA
#undef GENI1
#undef GENI
#undef GENA
#undef GEN1
#undef GEN
int last_insn = i;
uint8 *e = get_target();
uint8 *p = b;
i = 0;
while (p < e) {
int n = disass_x86(buffer, (uintptr)p);
insn_t ii;
parse_insn(&ii, buffer);
if (!check_mem_reg(&ii, insns[i], D, B, I, S, r)) {
if (verbose > 1) {
if (1) {
for (int j = 0; j < MAX_INSN_LENGTH; j++)
fprintf(stderr, "%02x ", p[j]);
fprintf(stderr, "| ");
}
fprintf(stderr, "%s\n", buffer);
}
n_failures++;
}
p += n;
i += 1;
n_tests++;
show_status(n_tests);
}
if (i != last_insn)
abort();
}
}
}
}
}
printf(" done %ld/%ld\n", n_tests - n_failures, n_tests);
n_all_tests += n_tests;
n_all_failures += n_failures;
#endif
printf("\n");
printf("All %ld tests run, %ld failures\n", n_all_tests, n_all_failures);
}