This is the mail archive of the
binutils@sourceware.cygnus.com
mailing list for the binutils project.
Re: binutils-as: can addr32 prefix be automatically inferred?
- To: Klaus Espenlaub <espenlaub@informatik.uni-ulm.de>
- Subject: Re: binutils-as: can addr32 prefix be automatically inferred?
- From: Alan Modra <alan@SPRI.Levels.UniSA.Edu.Au>
- Date: Tue, 3 Aug 1999 08:48:45 +0930 (CST)
- cc: binutils@sourceware.cygnus.com
On Mon, 2 Aug 1999, Klaus Espenlaub wrote:
> I just stumbled across some old code that already uses the .code16 feature
> of the i386 gas. It contains instructions like
>
> .code16
> movl 8(%ebp),%edx
> leal (%esi,%edx),%eax
>
> The old gas (2.9.1) automatically inferred the required addr32 prefixes for
> these instructions, while the 990628 snapshot just gives error messages:
>
> /tmp/cca19394.s:257: Error: `8(%ebp)' is not a valid 16 bit base/index expression
> /tmp/cca20380.s:289: Error: `(%esi,%edx)' is not a valid 16 bit base/index expression
>
> While this is a valid behaviour, it would be more convenient to put at
> least a limited heuristics into gas, making old code acceptable to the
> newer (and stricter) gas. But if you decide against it, please state that
> somewhere public (like the gas docs) so that there is no further confusion
> about this matter. I don't care, because someone else has to maintain the
> code I am just using :)
Hello Klaus,
The following patch (untested!) ought to do what you want. I
re-indented i386_intel_operand, so there are a few extra lines in the
patch. Can you test it out please?
--- binutils-current/gas/config/tc-i386.c~ Tue Jul 20 23:41:31 1999
+++ binutils-current/gas/config/tc-i386.c Tue Aug 3 08:38:14 1999
@@ -40,6 +40,10 @@
#define REGISTER_WARNINGS 1
#endif
+#ifndef INFER_ADDR_PREFIX
+#define INFER_ADDR_PREFIX 1
+#endif
+
#ifndef SCALE1_WHEN_NO_INDEX
/* Specifying a scale factor besides 1 when there is no index is
futile. eg. `mov (%ebx,2),%al' does exactly the same as
@@ -3241,71 +3245,71 @@ i386_intel_operand (operand_string, got_
case SHORT:
case NONE_FOUND:
- /* Should be register or immediate */
- if (is_digit_char (*op_string)
- && strchr (op_string, '[') == 0)
- {
- if (!i386_immediate (op_string))
- return 0;
- }
- else if (*op_string == REGISTER_PREFIX
- || (allow_naked_reg
- && i386_is_reg (op_string)))
- {
-
- register const reg_entry * r;
- char *end_op;
+ /* Should be register or immediate */
+ if (is_digit_char (*op_string)
+ && strchr (op_string, '[') == 0)
+ {
+ if (!i386_immediate (op_string))
+ return 0;
+ }
+ else if (*op_string == REGISTER_PREFIX
+ || (allow_naked_reg
+ && i386_is_reg (op_string)))
+ {
- r = parse_register (op_string, &end_op);
- if (r == NULL)
- return 0;
+ register const reg_entry * r;
+ char *end_op;
- /* Check for a segment override by searching for ':' after a
- segment register. */
- op_string = end_op;
- if (is_space_char (*op_string))
- ++op_string;
- if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
- {
- switch (r->reg_num)
- {
- case 0:
- i.seg[i.mem_operands] = &es;
- break;
- case 1:
- i.seg[i.mem_operands] = &cs;
- break;
- case 2:
- i.seg[i.mem_operands] = &ss;
- break;
- case 3:
- i.seg[i.mem_operands] = &ds;
- break;
- case 4:
- i.seg[i.mem_operands] = &fs;
- break;
- case 5:
- i.seg[i.mem_operands] = &gs;
- break;
- }
+ r = parse_register (op_string, &end_op);
+ if (r == NULL)
+ return 0;
+
+ /* Check for a segment override by searching for ':' after a
+ segment register. */
+ op_string = end_op;
+ if (is_space_char (*op_string))
+ ++op_string;
+ if (*op_string == ':' && (r->reg_type & (SReg2 | SReg3)))
+ {
+ switch (r->reg_num)
+ {
+ case 0:
+ i.seg[i.mem_operands] = &es;
+ break;
+ case 1:
+ i.seg[i.mem_operands] = &cs;
+ break;
+ case 2:
+ i.seg[i.mem_operands] = &ss;
+ break;
+ case 3:
+ i.seg[i.mem_operands] = &ds;
+ break;
+ case 4:
+ i.seg[i.mem_operands] = &fs;
+ break;
+ case 5:
+ i.seg[i.mem_operands] = &gs;
+ break;
+ }
- }
- i.types[this_operand] |= r->reg_type & ~BaseIndex;
- i.regs[this_operand] = r;
- i.reg_operands++;
- }
+ }
+ i.types[this_operand] |= r->reg_type & ~BaseIndex;
+ i.regs[this_operand] = r;
+ i.reg_operands++;
+ }
- else
- {
+ else
+ {
- if (!i386_intel_memory_operand (op_string))
- return 0;
+ if (!i386_intel_memory_operand (op_string))
+ return 0;
- i.mem_operands++;
- }
- break;
+ i.mem_operands++;
+ }
+ break;
- } /* end switch */
+ } /* end switch */
/* Special case for (%dx) while doing input/output op. */
if (i.base_reg
&& i.base_reg->reg_type == (Reg16 | InOutPortReg)
@@ -3313,42 +3317,68 @@ i386_intel_operand (operand_string, got_
&& i.log2_scale_factor == 0
&& i.seg[i.mem_operands] == 0
&& (i.types[this_operand] & Disp) == 0)
- {
- i.types[this_operand] = InOutPortReg;
- return 1;
- }
+ {
+ i.types[this_operand] = InOutPortReg;
+ return 1;
+ }
/* Make sure the memory operand we've been dealt is valid. */
if (flag_16bit_code ^ (i.prefix[ADDR_PREFIX] != 0))
{
+#if INFER_ADDR_PREFIX
+ try16:
+#endif
if ((i.base_reg
&& ((i.base_reg->reg_type & (Reg16|BaseIndex))
- != (Reg16|BaseIndex)))
- || (i.index_reg
- && (((i.index_reg->reg_type & (Reg16|BaseIndex))
- != (Reg16|BaseIndex))
- || ! (i.base_reg
- && i.base_reg->reg_num < 6
- && i.index_reg->reg_num >= 6
- && i.log2_scale_factor == 0))))
- {
- as_bad (_("`%s' is not a valid %s bit base/index expression"),
- operand_string, "16");
- return 0;
- }
+ != (Reg16|BaseIndex)))
+ || (i.index_reg
+ && (((i.index_reg->reg_type & (Reg16|BaseIndex))
+ != (Reg16|BaseIndex))
+ || ! (i.base_reg
+ && i.base_reg->reg_num < 6
+ && i.index_reg->reg_num >= 6
+ && i.log2_scale_factor == 0))))
+ {
+ if (i.prefix[ADDR_PREFIX] != 0)
+ {
+ as_bad (_("`%s' is not a valid %s bit base/index expression"),
+ operand_string, "16");
+ return 0;
+ }
+#if INFER_ADDR_PREFIX
+ else
+ {
+ i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
+ goto try32;
+ }
+#endif
+ }
}
- else
+ else
+ {
+#if INFER_ADDR_PREFIX
+ try32:
+#endif
+ if ((i.base_reg
+ && (i.base_reg->reg_type & Reg32) == 0)
+ || (i.index_reg
+ && ((i.index_reg->reg_type & (Reg32|BaseIndex))
+ != (Reg32|BaseIndex))))
{
- if ((i.base_reg
- && (i.base_reg->reg_type & Reg32) == 0)
- || (i.index_reg
- && ((i.index_reg->reg_type & (Reg32|BaseIndex))
- != (Reg32|BaseIndex))))
+ if (i.prefix[ADDR_PREFIX] != 0)
{
as_bad (_("`%s' is not a valid %s bit base/index expression"),
operand_string, "32");
return 0;
}
+#if INFER_ADDR_PREFIX
+ else
+ {
+ i.prefix[ADDR_PREFIX] = ADDR_PREFIX_OPCODE;
+ goto try16;
+ }
+#endif
}
+ }
return 1;
}