aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-05-11 18:54:24 +0200
committerMichael Matz <matz@suse.de>2016-05-11 18:54:24 +0200
commitbd93dc6923a9fe202401666a1f2749fbdced9971 (patch)
tree0dbfb39ff75b6082d4e8bfa287b72ff1e170c678
parent9645b62a65986738e6b70d748890d73daf40508b (diff)
downloadtinycc-bd93dc6923a9fe202401666a1f2749fbdced9971.tar.gz
tinycc-bd93dc6923a9fe202401666a1f2749fbdced9971.tar.bz2
x86: Improve cmov handling
cmov can accept multi sizes, but is also a OPC_TEST opcode, deal with this.
-rw-r--r--i386-asm.c5
-rw-r--r--i386-asm.h2
-rw-r--r--tests/asmtest.S4
-rw-r--r--x86_64-asm.h9
4 files changed, 11 insertions, 9 deletions
diff --git a/i386-asm.c b/i386-asm.c
index 435dd15..69514c0 100644
--- a/i386-asm.c
+++ b/i386-asm.c
@@ -659,6 +659,11 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode)
} else if (pa->instr_type & OPC_TEST) {
if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
continue;
+ /* cmovxx is a test opcode but accepts multiple sizes.
+ TCC doesn't accept the suffixed mnemonic, instead we
+ simply force size autodetection always. */
+ if (pa->instr_type & OPC_WLX)
+ s = NBWLX - 1;
} else if (pa->instr_type & OPC_B) {
#ifdef TCC_TARGET_X86_64
/* Some instructions don't have the full size but only
diff --git a/i386-asm.h b/i386-asm.h
index 6b03f4a..8c8273c 100644
--- a/i386-asm.h
+++ b/i386-asm.h
@@ -382,7 +382,7 @@ ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT
DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
/* pentium pro */
- ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
+ ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST | OPC_WL, OPT_REGW | OPT_EA, OPT_REGW))
#ifdef I386_ASM_16
ALT(DEF_ASM_OP2(cmovno, 0x0f41, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
ALT(DEF_ASM_OP2(cmovc, 0x0f42, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
diff --git a/tests/asmtest.S b/tests/asmtest.S
index 0876aa8..2a9f403 100644
--- a/tests/asmtest.S
+++ b/tests/asmtest.S
@@ -474,6 +474,10 @@ fucomip %st(5), %st
cmovo 0x1000, %eax
cmovs 0x1000, %eax
cmovns %edx, %edi
+ cmovne %ax, %si
+#ifdef __x86_64__
+ cmovz %rdi,%rbx
+#endif
int $3
int $0x10
diff --git a/x86_64-asm.h b/x86_64-asm.h
index d7c0d77..14e5969 100644
--- a/x86_64-asm.h
+++ b/x86_64-asm.h
@@ -367,14 +367,7 @@ ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWLQ, OPT_REG, OPT_REG | OP
DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
/* pentium pro */
-ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(cmovno, 0x0f41, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(cmovc, 0x0f42, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(cmovnc, 0x0f43, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(cmovz, 0x0f44, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(cmovnz, 0x0f45, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(cmovna, 0x0f46, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(cmova, 0x0f47, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
+ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST | OPC_WLQ, OPT_REGW | OPT_EA, OPT_REGW))
DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )