From 4f27e217a864d8ddb74265d24a5aadea0a3ec92d Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Sat, 14 May 2016 04:33:41 +0200 Subject: [PATCH] x86-asm: Fix signed constants and opcode order Two things: negative constants were rejected (e.g. "add $-15,%eax"). Second the insn order was such that the arithmetic IM8S forms weren't used (always the IM32 ones). Switching them prefers those but requires a fix for size calculation in case the opcodes were OPC_ARITH and OPC_WLX (whose size starts with 1, not zero). --- i386-asm.c | 4 +++- i386-asm.h | 2 +- tests/asmtest.S | 7 +++++++ x86_64-asm.h | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/i386-asm.c b/i386-asm.c index 7b92ccb..8baad47 100644 --- a/i386-asm.c +++ b/i386-asm.c @@ -355,7 +355,7 @@ static void parse_operand(TCCState *s1, Operand *op) if (op->e.v == (uint16_t)op->e.v) op->type |= OP_IM16; #ifdef TCC_TARGET_X86_64 - if (op->e.v != (uint32_t)op->e.v) + if (op->e.v != (int32_t)op->e.v) op->type = OP_IM64; #endif } @@ -551,6 +551,8 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) if (!(opcode >= pa->sym && opcode < pa->sym + 8*NBWLX)) continue; s = (opcode - pa->sym) % NBWLX; + if ((pa->instr_type & OPC_BWLX) == OPC_WLX) + s++; } else if (pa->instr_type & OPC_SHIFT) { if (!(opcode >= pa->sym && opcode < pa->sym + 7*NBWLX)) continue; diff --git a/i386-asm.h b/i386-asm.h index 2074ecd..ae7d899 100644 --- a/i386-asm.h +++ b/i386-asm.h @@ -157,8 +157,8 @@ ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32)) ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */ ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLX, OPT_IM, OPT_EAX)) -ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG)) ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REG)) +ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG)) ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) diff --git a/tests/asmtest.S b/tests/asmtest.S index e50a5d0..e8865f1 100644 --- a/tests/asmtest.S +++ b/tests/asmtest.S @@ -156,6 +156,8 @@ movl %ebx, %fs addl $0x123, %eax add $0x123, %ebx +add $-16, %ecx +add $-0x123, %esi addl $0x123, 0x100 addl $0x123, 0x100(%ebx) addl $0x123, 0x100(%ebx,%edx,2) @@ -216,6 +218,8 @@ add (%ebx), %dl div %bl div %ecx, %eax +and $15,%bx +and $-20,%edx shl %edx shl $10, %edx @@ -690,3 +694,6 @@ ft1: ft2: ft3: ft4: ft5: ft6: ft7: ft8: ft9: .type ft8,"function" pause +.rept 6 + nop +.endr diff --git a/x86_64-asm.h b/x86_64-asm.h index 74bc446..c6c74e7 100644 --- a/x86_64-asm.h +++ b/x86_64-asm.h @@ -166,8 +166,8 @@ ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32)) ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */ ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLX, OPT_IM, OPT_EAX)) -ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG)) ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REG)) +ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG)) ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))