From 035139d614fdb896edef39086d7382dc47e3f525 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Fri, 10 Feb 2006 04:24:12 +0000 Subject: [PATCH] Fix #67 by autosizing push immediate with no specified size to either 8 bit or the current BITS-derived operation size. * x86id.re (OPS_BITS): New match rule for size == BITS setting. (push_insn): Use OPS_BITS for 16-bit/32-bit mode, and reuse GAS rule for 64-bit mode. (yasm_x86__finalize_insn): Set size_lookup[7] to BITS setting. Set opersize based on this value if OPS_BITS is used. * pushnosize.asm: New test for push imm, both sized and unsized, in all BITS modes. svn path=/trunk/yasm/; revision=1371 --- modules/arch/x86/tests/Makefile.inc | 3 + modules/arch/x86/tests/pushnosize.asm | 29 ++++++++ modules/arch/x86/tests/pushnosize.errwarn | 3 + modules/arch/x86/tests/pushnosize.hex | 85 +++++++++++++++++++++++ modules/arch/x86/x86id.re | 15 +++- 5 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 modules/arch/x86/tests/pushnosize.asm create mode 100644 modules/arch/x86/tests/pushnosize.errwarn create mode 100644 modules/arch/x86/tests/pushnosize.hex diff --git a/modules/arch/x86/tests/Makefile.inc b/modules/arch/x86/tests/Makefile.inc index 616da6a7..ac154bd3 100644 --- a/modules/arch/x86/tests/Makefile.inc +++ b/modules/arch/x86/tests/Makefile.inc @@ -127,6 +127,9 @@ EXTRA_DIST += modules/arch/x86/tests/pshift.hex EXTRA_DIST += modules/arch/x86/tests/push64.asm EXTRA_DIST += modules/arch/x86/tests/push64.errwarn EXTRA_DIST += modules/arch/x86/tests/push64.hex +EXTRA_DIST += modules/arch/x86/tests/pushnosize.asm +EXTRA_DIST += modules/arch/x86/tests/pushnosize.errwarn +EXTRA_DIST += modules/arch/x86/tests/pushnosize.hex EXTRA_DIST += modules/arch/x86/tests/rep.asm EXTRA_DIST += modules/arch/x86/tests/rep.errwarn EXTRA_DIST += modules/arch/x86/tests/rep.hex diff --git a/modules/arch/x86/tests/pushnosize.asm b/modules/arch/x86/tests/pushnosize.asm new file mode 100644 index 00000000..30451a16 --- /dev/null +++ b/modules/arch/x86/tests/pushnosize.asm @@ -0,0 +1,29 @@ +[bits 16] +push 0 ; 6A 00 - equivalent to push byte 0 +push byte 0 ; 6A 00 +push word 0 ; 68 0000 +push dword 0 ; 66 68 00000000 +push 128 ; 68 8000 - doesn't fit in byte, equivalent to push word 128 +push byte 128 ; 6A 80 - warning (signed overflow) +push word 128 ; 68 8000 +push dword 128 ; 66 68 80000000 + +[bits 32] +push 0 ; 6A 00 - equivalent to push byte 0 +push byte 0 ; 6A 00 +push word 0 ; 66 68 0000 +push dword 0 ; 68 00000000 +push 128 ; 68 80000000 - doesn't fit in byte -> push dword 128 +push byte 128 ; 6A 80 - warning (signed overflow) +push word 128 ; 66 6A 8000 +push dword 128 ; 6A 80000000 + +[bits 64] +push 0 ; same as bits 32 output +push byte 0 +push word 0 +push dword 0 +push 128 +push byte 128 ; warning +push word 128 +push dword 128 diff --git a/modules/arch/x86/tests/pushnosize.errwarn b/modules/arch/x86/tests/pushnosize.errwarn new file mode 100644 index 00000000..a042edf8 --- /dev/null +++ b/modules/arch/x86/tests/pushnosize.errwarn @@ -0,0 +1,3 @@ +-:7: warning: value does not fit in signed 8 bit field +-:17: warning: value does not fit in signed 8 bit field +-:27: warning: value does not fit in signed 8 bit field diff --git a/modules/arch/x86/tests/pushnosize.hex b/modules/arch/x86/tests/pushnosize.hex new file mode 100644 index 00000000..e9636688 --- /dev/null +++ b/modules/arch/x86/tests/pushnosize.hex @@ -0,0 +1,85 @@ +6a +00 +6a +00 +68 +00 +00 +66 +68 +00 +00 +00 +00 +68 +80 +00 +6a +80 +68 +80 +00 +66 +68 +80 +00 +00 +00 +6a +00 +6a +00 +66 +68 +00 +00 +68 +00 +00 +00 +00 +68 +80 +00 +00 +00 +6a +80 +66 +68 +80 +00 +68 +80 +00 +00 +00 +6a +00 +6a +00 +66 +68 +00 +00 +68 +00 +00 +00 +00 +68 +80 +00 +00 +00 +6a +80 +66 +68 +80 +00 +68 +80 +00 +00 +00 diff --git a/modules/arch/x86/x86id.re b/modules/arch/x86/x86id.re index 13497c82..2712436f 100644 --- a/modules/arch/x86/x86id.re +++ b/modules/arch/x86/x86id.re @@ -110,6 +110,8 @@ RCSID("$Id$"); * 0 = any size acceptable/no size spec acceptable (dep. on strict) * 1/2/3/4 = 8/16/32/64 bits (from user or reg size) * 5/6 = 80/128 bits (from user) + * 7 = current BITS setting; when this is used the size matched + * gets stored into the opersize as well. * - 1 bit = size implicit or explicit ("strictness" of size matching on * non-registers -- registers are always strictly matched): * 0 = user size must exactly match size above. @@ -186,6 +188,7 @@ RCSID("$Id$"); #define OPS_64 (4UL<<5) #define OPS_80 (5UL<<5) #define OPS_128 (6UL<<5) +#define OPS_BITS (7UL<<5) #define OPS_MASK (7UL<<5) #define OPS_SHIFT 5 @@ -633,9 +636,12 @@ static const x86_insn_info push_insn[] = { { CPU_386|CPU_Not64, MOD_GasOnly|MOD_GasSufL, 32, 0, 0, 1, {0x68, 0x6A, 0}, 0, 1, {OPT_Imm|OPS_32|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0, 0} }, - { CPU_Hammer|CPU_64, MOD_GasOnly|MOD_GasSufQ, 64, 64, 0, 1, + { CPU_Hammer|CPU_64, MOD_GasSufQ, 64, 64, 0, 1, {0x68, 0x6A, 0}, 0, 1, {OPT_Imm|OPS_32|OPS_Relaxed|OPA_SImm|OPAP_SImm8Avail, 0, 0} }, + { CPU_Any|CPU_Not64, MOD_GasIllegal, 0, 0, 0, 1, + {0x68, 0x6A, 0}, 0, 1, + {OPT_Imm|OPS_BITS|OPS_Relaxed|OPA_Imm|OPAP_SImm8Avail, 0, 0} }, { CPU_Not64, 0, 0, 0, 0, 1, {0x0E, 0, 0}, 0, 1, {OPT_CS|OPS_Any|OPA_None, 0, 0} }, { CPU_Not64, MOD_GasSufW, 16, 0, 0, 1, {0x0E, 0, 0}, 0, 1, @@ -2212,7 +2218,9 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc, unsigned char im_sign; unsigned char spare; int i; - static const unsigned int size_lookup[] = {0, 1, 2, 4, 8, 10, 16, 0}; + unsigned int size_lookup[] = {0, 1, 2, 4, 8, 10, 16, 0}; + + size_lookup[7] = mode_bits>>3; if (!info) { num_info = 1; @@ -2810,6 +2818,9 @@ yasm_x86__finalize_insn(yasm_arch *arch, yasm_bytecode *bc, yasm_internal_error(N_("unknown operand action")); } + if ((info->operands[i] & OPS_MASK) == OPS_BITS) + insn->common.opersize = (unsigned char)mode_bits; + switch ((int)(info->operands[i] & OPAP_MASK)) { case OPAP_None: break; -- 2.40.0