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
0.5.0rc2
Peter Johnson 19 years ago
parent 29b0319135
commit 035139d614
  1. 3
      modules/arch/x86/tests/Makefile.inc
  2. 29
      modules/arch/x86/tests/pushnosize.asm
  3. 3
      modules/arch/x86/tests/pushnosize.errwarn
  4. 85
      modules/arch/x86/tests/pushnosize.hex
  5. 15
      modules/arch/x86/x86id.re

@ -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

@ -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

@ -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

@ -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

@ -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;

Loading…
Cancel
Save