mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-17 13:10:12 +08:00
Correct intel_syntax fsub* and fdiv* handling. Oh, how I'd like to be rid
of UNIXWARE_COMPAT.
This commit is contained in:
parent
a526d7137a
commit
7f3f1ea2a1
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user