From 7f3f1ea2a1563fdbdaac1c2dcc2d98cd53894ecc Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 24 Feb 2000 12:40:45 +0000 Subject: [PATCH] Correct intel_syntax fsub* and fdiv* handling. Oh, how I'd like to be rid of UNIXWARE_COMPAT. --- gas/ChangeLog | 10 ++++++++++ gas/config/tc-i386.c | 37 ++++++++++++++++++------------------- include/opcode/i386.h | 13 +++++++++---- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 31a424be40f..f21ef473327 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -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 diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 7d8a0e7004b..d9e4b1944e5 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -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. */ diff --git a/include/opcode/i386.h b/include/opcode/i386.h index 7bddbed4e6d..ee7554b0e80 100644 --- a/include/opcode/i386.h +++ b/include/opcode/i386.h @@ -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) -- 2.30.2