Correct intel_syntax fsub* and fdiv* handling. Oh, how I'd like to be rid
authorAlan Modra <amodra@gmail.com>
Thu, 24 Feb 2000 12:40:45 +0000 (12:40 +0000)
committerAlan Modra <amodra@gmail.com>
Thu, 24 Feb 2000 12:40:45 +0000 (12:40 +0000)
of UNIXWARE_COMPAT.

gas/ChangeLog
gas/config/tc-i386.c
include/opcode/i386.h

index 31a424be40fad0b16fad923937ac2ef73455e3c7..f21ef4733274a014d3cc2ee51b62a27332acd624 100644 (file)
@@ -8,6 +8,16 @@
        fake_zero_displacement code.  Test i.types[n] when outputting
        displacements and immediates.  Combine output of Disp16 with
        Disp32.
+       (md_assemble): Don't try to fix broken UNIXWARE_COMPAT opcodes
+       when in intel mode by (not) reversing fsub and fdiv operands
+       before the template search.  This fails for single operand
+       shorthand forms of the instruction, and if UNIXWARE_COMPAT is
+       undefined.  Instead fix the base_opcode after we've found the
+       template.  Move base_opcode xor with found_reverse_match from
+       opcode output code to before this fix so we test for the correct
+       opcodes.
+       (md_assemble): Don't use strcmp when deciding to ignore the suffix
+       check in intel mode.  Instead compare opcodes.
 
        * config/tc-i386.h (TC_RELOC): Delete.
        * config/tc-i386.c (TC_RELOC): Delete.  Replace usage of TC_RELOC
index 7d8a0e7004b135fe73a4b576e23b9bf1124fdf28..d9e4b1944e5cf5823d4ff9f9ab21ceaa49a78e6c 100644 (file)
@@ -1268,9 +1268,7 @@ md_assemble (line)
     /* All intel opcodes have reversed operands except for BOUND and ENTER */
     if (intel_syntax && i.operands > 1
        && (strcmp (mnemonic, "enter") != 0)
-       && (strcmp (mnemonic, "bound") != 0)
-       && (strncmp (mnemonic, "fsub", 4) !=0)
-       && (strncmp (mnemonic, "fdiv", 4) !=0))
+       && (strcmp (mnemonic, "bound") != 0))
       {
        union i386_op temp_op;
        unsigned int temp_type;
@@ -1318,16 +1316,12 @@ md_assemble (line)
        if (i.operands != t->operands)
          continue;
 
-       /* For some opcodes, don't check the suffix */
-       if (intel_syntax)
-         {
-           if (strcmp (t->name, "fnstcw")
-               && strcmp (t->name, "fldcw")
-               && (t->opcode_modifier & suffix_check))
-             continue;
-         }
-       /* Must not have disallowed suffix. */
-       else if ((t->opcode_modifier & suffix_check))
+       /* Check the suffix, except for some instructions in intel mode.  */
+       if ((t->opcode_modifier & suffix_check)
+           && !(intel_syntax
+                && t->base_opcode == 0xd9
+                && (t->extension_opcode == 5   /* 0xd9,5 "fldcw"  */
+                    || t->extension_opcode == 7))) /* 0xd9,7 "f{n}stcw"  */
          continue;
 
        else if (!t->operands)
@@ -1418,10 +1412,21 @@ md_assemble (line)
     i.tm = *t;
     if (found_reverse_match)
       {
+       /* If we found a reverse match we must alter the opcode
+          direction bit.  found_reverse_match holds bits to change
+          (different for int & float insns).  */
+
+       i.tm.base_opcode ^= found_reverse_match;
+
        i.tm.operand_types[0] = t->operand_types[1];
        i.tm.operand_types[1] = t->operand_types[0];
       }
 
+    /* Undo UNIXWARE_COMPAT brokenness when in Intel mode.  See i386.h  */
+     if (UNIXWARE_COMPAT
+        && intel_syntax
+        && (i.tm.base_opcode & 0xfffffde0) == 0xdce0)
+       i.tm.base_opcode ^= FloatR;
 
     if (i.tm.opcode_modifier & FWait)
       if (! add_prefix (FWAIT_OPCODE))
@@ -1738,12 +1743,6 @@ md_assemble (line)
           This is only for optimizing out unnecessary segment overrides.  */
        const seg_entry *default_seg = 0;
 
-       /* If we found a reverse match we must alter the opcode
-          direction bit.  found_reverse_match holds bits to change
-          (different for int & float insns).  */
-
-       i.tm.base_opcode ^= found_reverse_match;
-
        /* The imul $imm, %reg instruction is converted into
           imul $imm, %reg, %reg, and the clr %reg instruction
           is converted into xor %reg, %reg.  */
index 7bddbed4e6d5d3e51f8124407df8b29cbe21d9b5..ee7554b0e80eb743cdd253639de65489a13a4ce7 100644 (file)
@@ -23,13 +23,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
    gcc and possibly many other programs use this reversed syntax, so
    we're stuck with it.
 
-   eg. `fsub %st(3),%st' results in st <- st - st(3) as expected, but
-   `fsub %st,%st(3)' results in st(3) <- st - st(3), rather than
-   the expected st(3) <- st(3) - st !
+   eg. `fsub %st(3),%st' results in st = st - st(3) as expected, but
+   `fsub %st,%st(3)' results in st(3) = st - st(3), rather than
+   the expected st(3) = st(3) - st
 
    This happens with all the non-commutative arithmetic floating point
    operations with two register operands, where the source register is
-   %st, and destination register is %st(i).  Look for FloatDR below.  */
+   %st, and destination register is %st(i).  See FloatDR below.
+
+   The affected opcode map is dceX, dcfX, deeX, defX.  */
 
 #ifndef UNIXWARE_COMPAT
 /* Set non-zero for broken, compatible instructions.  Set to zero for
@@ -64,6 +66,9 @@ static const template i386_optab[] = {
 #define sld_FP (sld_Suf|IgnoreSize)
 #define sldx_FP (sldx_Suf|IgnoreSize)
 #if UNIXWARE_COMPAT
+/* Someone forgot that the FloatR bit reverses the operation when not
+   equal to the FloatD bit.  ie. Changing only FloatD results in the
+   destination being swapped *and* the direction being reversed.  */
 #define FloatDR FloatD
 #else
 #define FloatDR (FloatD|FloatR)