Correct intel_syntax fsub* and fdiv* handling. Oh, how I'd like to be rid

of UNIXWARE_COMPAT.
This commit is contained in:
Alan Modra 2000-02-24 12:40:45 +00:00
parent a526d7137a
commit 7f3f1ea2a1
3 changed files with 37 additions and 23 deletions

View file

@ -8,6 +8,16 @@
fake_zero_displacement code. Test i.types[n] when outputting fake_zero_displacement code. Test i.types[n] when outputting
displacements and immediates. Combine output of Disp16 with displacements and immediates. Combine output of Disp16 with
Disp32. 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.h (TC_RELOC): Delete.
* config/tc-i386.c (TC_RELOC): Delete. Replace usage of TC_RELOC * config/tc-i386.c (TC_RELOC): Delete. Replace usage of TC_RELOC

View file

@ -1268,9 +1268,7 @@ md_assemble (line)
/* All intel opcodes have reversed operands except for BOUND and ENTER */ /* All intel opcodes have reversed operands except for BOUND and ENTER */
if (intel_syntax && i.operands > 1 if (intel_syntax && i.operands > 1
&& (strcmp (mnemonic, "enter") != 0) && (strcmp (mnemonic, "enter") != 0)
&& (strcmp (mnemonic, "bound") != 0) && (strcmp (mnemonic, "bound") != 0))
&& (strncmp (mnemonic, "fsub", 4) !=0)
&& (strncmp (mnemonic, "fdiv", 4) !=0))
{ {
union i386_op temp_op; union i386_op temp_op;
unsigned int temp_type; unsigned int temp_type;
@ -1318,16 +1316,12 @@ md_assemble (line)
if (i.operands != t->operands) if (i.operands != t->operands)
continue; continue;
/* For some opcodes, don't check the suffix */ /* Check the suffix, except for some instructions in intel mode. */
if (intel_syntax) if ((t->opcode_modifier & suffix_check)
{ && !(intel_syntax
if (strcmp (t->name, "fnstcw") && t->base_opcode == 0xd9
&& strcmp (t->name, "fldcw") && (t->extension_opcode == 5 /* 0xd9,5 "fldcw" */
&& (t->opcode_modifier & suffix_check)) || t->extension_opcode == 7))) /* 0xd9,7 "f{n}stcw" */
continue;
}
/* Must not have disallowed suffix. */
else if ((t->opcode_modifier & suffix_check))
continue; continue;
else if (!t->operands) else if (!t->operands)
@ -1418,10 +1412,21 @@ md_assemble (line)
i.tm = *t; i.tm = *t;
if (found_reverse_match) 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[0] = t->operand_types[1];
i.tm.operand_types[1] = t->operand_types[0]; 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 (i.tm.opcode_modifier & FWait)
if (! add_prefix (FWAIT_OPCODE)) if (! add_prefix (FWAIT_OPCODE))
@ -1738,12 +1743,6 @@ md_assemble (line)
This is only for optimizing out unnecessary segment overrides. */ This is only for optimizing out unnecessary segment overrides. */
const seg_entry *default_seg = 0; 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 /* The imul $imm, %reg instruction is converted into
imul $imm, %reg, %reg, and the clr %reg instruction imul $imm, %reg, %reg, and the clr %reg instruction
is converted into xor %reg, %reg. */ is converted into xor %reg, %reg. */

View 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 gcc and possibly many other programs use this reversed syntax, so
we're stuck with it. we're stuck with it.
eg. `fsub %st(3),%st' results in st <- st - st(3) as expected, but 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 `fsub %st,%st(3)' results in st(3) = st - st(3), rather than
the expected st(3) <- st(3) - st ! the expected st(3) = st(3) - st
This happens with all the non-commutative arithmetic floating point This happens with all the non-commutative arithmetic floating point
operations with two register operands, where the source register is 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 #ifndef UNIXWARE_COMPAT
/* Set non-zero for broken, compatible instructions. Set to zero for /* 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 sld_FP (sld_Suf|IgnoreSize)
#define sldx_FP (sldx_Suf|IgnoreSize) #define sldx_FP (sldx_Suf|IgnoreSize)
#if UNIXWARE_COMPAT #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 #define FloatDR FloatD
#else #else
#define FloatDR (FloatD|FloatR) #define FloatDR (FloatD|FloatR)