]> granicus.if.org Git - yasm/commitdiff
Fix #67 by autosizing push immediate with no specified size to either 8 bit
authorPeter Johnson <peter@tortall.net>
Fri, 10 Feb 2006 04:24:12 +0000 (04:24 -0000)
committerPeter Johnson <peter@tortall.net>
Fri, 10 Feb 2006 04:24:12 +0000 (04:24 -0000)
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
modules/arch/x86/tests/pushnosize.asm [new file with mode: 0644]
modules/arch/x86/tests/pushnosize.errwarn [new file with mode: 0644]
modules/arch/x86/tests/pushnosize.hex [new file with mode: 0644]
modules/arch/x86/x86id.re

index 616da6a7c86c22fe532adcdbccf4c8f73a6387d5..ac154bd389ba0202fe705a1e088ba08c0c4df19d 100644 (file)
@@ -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 (file)
index 0000000..30451a1
--- /dev/null
@@ -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 (file)
index 0000000..a042edf
--- /dev/null
@@ -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 (file)
index 0000000..e963668
--- /dev/null
@@ -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 
index 13497c821796613e731833635808a87e7c05ead1..2712436f555b087fefaa86ba326d2f73ed3fe13f 100644 (file)
@@ -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;