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 )