mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-09-25 00:14:38 +08:00
Fri Jun 5 23:27:04 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
* config/tc-i386.c (mode_from_disp_size): Disp16 is mode 2. (i386_operand): Simplify checks for valid base/index combinations. Disallow `in 4(%dx),%al'. * config/tc-i386.c (struct _i386_insn): Make regs, base_reg, and index_reg const. (add_prefix): Change parameter from char to int. * config/tc-i386.h (Ugh): Define opcode modifier. * config/tc-i386.c (md_assemble): Print warnings for Ugh insns. * config/tc-i386.c (md_assemble): Rewrite MATCH and CONSISTENT_REGISTER_MATCH macros to check register types more thoroughly. Check for illegal suffix/operand combinations when matching insns with operands. Handle new `s' suffix, and associated FloatMF opcode modifier for float insns with memory operands. * config/tc-i386.h (FloatMF): Define new opcode modifier. (No_sSuf, No_bSuf, No_wSuf, No_lSuf): Likewise. (SHORT_OPCODE_SUFFIX, LONG_OPCODE_SUFFIX): Define. * config/tc-i386.c: Rename WORD_PREFIX_OPCODE to DATA_PREFIX_OPCODE throughout. * config/tc-i386.c (REGISTER_WARNINGS): Define. (md_assemble): Rewrite suffix/register operand checking code to be more thorough. Remove Abs8,16,32. Change occurrences of Mem to AnyMem, the better to grep. (pi): Remove Abs. (i386_operand): Don't set Mem bits in i.types[this_operand] when given a memory operand. Don't set Abs bits either. (type_names): Remove Mem*, Abs*. * config/tc-i386.h (Mem8, Mem16, Mem32, Abs8, Abs16, Abs32): Don't define opcode_modifiers as these cases are handled by Disp8, Disp16, Disp32 and suffix checks. (COMES_IN_BOTH_DIRECTIONS): Remove. (FloatR): Define. It's OK to share the bit with ReverseRegRegmem. * config/tc-i386.c (md_assemble): Don't emit operand size prefix if IgnoreDataSize modifier given. Remove ShortformW modifier test. Add test for ShortForm in W base_opcode modification. Merge Seg2ShortForm and Seg3ShortForm code. * config/tc-i386.h (ShortFormW): Remove. (IgnoreDataSize): Define.
This commit is contained in:
@ -1,3 +1,49 @@
|
|||||||
|
Fri Jun 5 23:27:04 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
|
||||||
|
|
||||||
|
* config/tc-i386.c (mode_from_disp_size): Disp16 is mode 2.
|
||||||
|
(i386_operand): Simplify checks for valid base/index combinations.
|
||||||
|
Disallow `in 4(%dx),%al'.
|
||||||
|
|
||||||
|
* config/tc-i386.c (struct _i386_insn): Make regs, base_reg, and
|
||||||
|
index_reg const.
|
||||||
|
(add_prefix): Change parameter from char to int.
|
||||||
|
|
||||||
|
* config/tc-i386.h (Ugh): Define opcode modifier.
|
||||||
|
* config/tc-i386.c (md_assemble): Print warnings for Ugh insns.
|
||||||
|
|
||||||
|
* config/tc-i386.c (md_assemble): Rewrite MATCH and
|
||||||
|
CONSISTENT_REGISTER_MATCH macros to check register types more
|
||||||
|
thoroughly. Check for illegal suffix/operand combinations
|
||||||
|
when matching insns with operands. Handle new `s' suffix, and
|
||||||
|
associated FloatMF opcode modifier for float insns with memory
|
||||||
|
operands.
|
||||||
|
* config/tc-i386.h (FloatMF): Define new opcode modifier.
|
||||||
|
(No_sSuf, No_bSuf, No_wSuf, No_lSuf): Likewise.
|
||||||
|
(SHORT_OPCODE_SUFFIX, LONG_OPCODE_SUFFIX): Define.
|
||||||
|
* config/tc-i386.c: Rename WORD_PREFIX_OPCODE to
|
||||||
|
DATA_PREFIX_OPCODE throughout.
|
||||||
|
|
||||||
|
* config/tc-i386.c (REGISTER_WARNINGS): Define.
|
||||||
|
(md_assemble): Rewrite suffix/register operand checking code to be
|
||||||
|
more thorough. Remove Abs8,16,32. Change occurrences of Mem to
|
||||||
|
AnyMem, the better to grep.
|
||||||
|
(pi): Remove Abs.
|
||||||
|
(i386_operand): Don't set Mem bits in i.types[this_operand] when
|
||||||
|
given a memory operand. Don't set Abs bits either.
|
||||||
|
(type_names): Remove Mem*, Abs*.
|
||||||
|
* config/tc-i386.h (Mem8, Mem16, Mem32, Abs8, Abs16, Abs32): Don't
|
||||||
|
define opcode_modifiers as these cases are handled by Disp8,
|
||||||
|
Disp16, Disp32 and suffix checks.
|
||||||
|
(COMES_IN_BOTH_DIRECTIONS): Remove.
|
||||||
|
(FloatR): Define. It's OK to share the bit with ReverseRegRegmem.
|
||||||
|
|
||||||
|
* config/tc-i386.c (md_assemble): Don't emit operand size prefix
|
||||||
|
if IgnoreDataSize modifier given. Remove ShortformW modifier
|
||||||
|
test. Add test for ShortForm in W base_opcode modification.
|
||||||
|
Merge Seg2ShortForm and Seg3ShortForm code.
|
||||||
|
* config/tc-i386.h (ShortFormW): Remove.
|
||||||
|
(IgnoreDataSize): Define.
|
||||||
|
|
||||||
Fri Jun 5 10:50:53 1998 Nick Clifton <nickc@cygnus.com>
|
Fri Jun 5 10:50:53 1998 Nick Clifton <nickc@cygnus.com>
|
||||||
|
|
||||||
* config/tc-d30v.c (md_assemble): Store previous segment state
|
* config/tc-d30v.c (md_assemble): Store previous segment state
|
||||||
|
@ -38,6 +38,10 @@
|
|||||||
#define TC_RELOC(X,Y) (Y)
|
#define TC_RELOC(X,Y) (Y)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef REGISTER_WARNINGS
|
||||||
|
#define REGISTER_WARNINGS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef SCALE1_WHEN_NO_INDEX
|
#ifndef SCALE1_WHEN_NO_INDEX
|
||||||
/* Specifying a scale factor besides 1 when there is no index is
|
/* Specifying a scale factor besides 1 when there is no index is
|
||||||
futile. eg. `mov (%ebx,2),%al' does exactly the same as
|
futile. eg. `mov (%ebx,2),%al' does exactly the same as
|
||||||
@ -52,7 +56,7 @@ static int fits_in_unsigned_byte PARAMS ((long));
|
|||||||
static int fits_in_unsigned_word PARAMS ((long));
|
static int fits_in_unsigned_word PARAMS ((long));
|
||||||
static int fits_in_signed_word PARAMS ((long));
|
static int fits_in_signed_word PARAMS ((long));
|
||||||
static int smallest_imm_type PARAMS ((long));
|
static int smallest_imm_type PARAMS ((long));
|
||||||
static int add_prefix PARAMS ((unsigned char));
|
static int add_prefix PARAMS ((unsigned int));
|
||||||
static void set_16bit_code_flag PARAMS ((int));
|
static void set_16bit_code_flag PARAMS ((int));
|
||||||
#ifdef BFD_ASSEMBLER
|
#ifdef BFD_ASSEMBLER
|
||||||
static bfd_reloc_code_real_type reloc
|
static bfd_reloc_code_real_type reloc
|
||||||
@ -66,8 +70,10 @@ struct _i386_insn
|
|||||||
{
|
{
|
||||||
/* TM holds the template for the insn were currently assembling. */
|
/* TM holds the template for the insn were currently assembling. */
|
||||||
template tm;
|
template tm;
|
||||||
|
|
||||||
/* SUFFIX holds the opcode suffix (e.g. 'l' for 'movl') if given. */
|
/* SUFFIX holds the opcode suffix (e.g. 'l' for 'movl') if given. */
|
||||||
char suffix;
|
char suffix;
|
||||||
|
|
||||||
/* Operands are coded with OPERANDS, TYPES, DISPS, IMMS, and REGS. */
|
/* Operands are coded with OPERANDS, TYPES, DISPS, IMMS, and REGS. */
|
||||||
|
|
||||||
/* OPERANDS gives the number of given operands. */
|
/* OPERANDS gives the number of given operands. */
|
||||||
@ -97,12 +103,12 @@ struct _i386_insn
|
|||||||
expressionS *imms[MAX_OPERANDS];
|
expressionS *imms[MAX_OPERANDS];
|
||||||
|
|
||||||
/* Register operands (if given) for each operand. */
|
/* Register operands (if given) for each operand. */
|
||||||
reg_entry *regs[MAX_OPERANDS];
|
const reg_entry *regs[MAX_OPERANDS];
|
||||||
|
|
||||||
/* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode
|
/* BASE_REG, INDEX_REG, and LOG2_SCALE_FACTOR are used to encode
|
||||||
the base index byte below. */
|
the base index byte below. */
|
||||||
reg_entry *base_reg;
|
const reg_entry *base_reg;
|
||||||
reg_entry *index_reg;
|
const reg_entry *index_reg;
|
||||||
unsigned int log2_scale_factor;
|
unsigned int log2_scale_factor;
|
||||||
|
|
||||||
/* SEG gives the seg_entries of this insn. They are zero unless
|
/* SEG gives the seg_entries of this insn. They are zero unless
|
||||||
@ -115,7 +121,7 @@ struct _i386_insn
|
|||||||
unsigned char prefix[MAX_PREFIXES];
|
unsigned char prefix[MAX_PREFIXES];
|
||||||
|
|
||||||
/* RM and BI are the modrm byte and the base index byte where the
|
/* RM and BI are the modrm byte and the base index byte where the
|
||||||
addressing modes of this insn are encoded. */
|
addressing modes of this insn are encoded. */
|
||||||
|
|
||||||
modrm_byte rm;
|
modrm_byte rm;
|
||||||
base_index_byte bi;
|
base_index_byte bi;
|
||||||
@ -363,7 +369,7 @@ static INLINE unsigned long
|
|||||||
mode_from_disp_size (t)
|
mode_from_disp_size (t)
|
||||||
unsigned long t;
|
unsigned long t;
|
||||||
{
|
{
|
||||||
return (t & Disp8) ? 1 : (t & Disp32) ? 2 : 0;
|
return (t & Disp8) ? 1 : (t & (Disp16|Disp32)) ? 2 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -436,13 +442,16 @@ smallest_imm_type (num)
|
|||||||
added. */
|
added. */
|
||||||
static int
|
static int
|
||||||
add_prefix (prefix)
|
add_prefix (prefix)
|
||||||
unsigned char prefix;
|
unsigned int prefix;
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
int q;
|
int q;
|
||||||
|
|
||||||
switch (prefix)
|
switch (prefix)
|
||||||
{
|
{
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
|
||||||
case CS_PREFIX_OPCODE:
|
case CS_PREFIX_OPCODE:
|
||||||
case DS_PREFIX_OPCODE:
|
case DS_PREFIX_OPCODE:
|
||||||
case ES_PREFIX_OPCODE:
|
case ES_PREFIX_OPCODE:
|
||||||
@ -468,8 +477,9 @@ add_prefix (prefix)
|
|||||||
q = ADDR_PREFIX;
|
q = ADDR_PREFIX;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WORD_PREFIX_OPCODE:
|
case DATA_PREFIX_OPCODE:
|
||||||
q = DATA_PREFIX;
|
q = DATA_PREFIX;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.prefix[q])
|
if (i.prefix[q])
|
||||||
@ -702,7 +712,7 @@ pi (line, x)
|
|||||||
fprintf (stdout, "%s\n", x->regs[i]->reg_name);
|
fprintf (stdout, "%s\n", x->regs[i]->reg_name);
|
||||||
if (x->types[i] & Imm)
|
if (x->types[i] & Imm)
|
||||||
pe (x->imms[i]);
|
pe (x->imms[i]);
|
||||||
if (x->types[i] & (Disp | Abs))
|
if (x->types[i] & Disp)
|
||||||
pe (x->disps[i]);
|
pe (x->disps[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -776,27 +786,21 @@ type_names[] =
|
|||||||
{ Imm8S, "i8s" },
|
{ Imm8S, "i8s" },
|
||||||
{ Imm16, "i16" },
|
{ Imm16, "i16" },
|
||||||
{ Imm32, "i32" },
|
{ Imm32, "i32" },
|
||||||
{ Mem8, "Mem8" },
|
{ Imm1, "i1" },
|
||||||
{ Mem16, "Mem16" },
|
|
||||||
{ Mem32, "Mem32" },
|
|
||||||
{ BaseIndex, "BaseIndex" },
|
{ BaseIndex, "BaseIndex" },
|
||||||
{ Abs8, "Abs8" },
|
|
||||||
{ Abs16, "Abs16" },
|
|
||||||
{ Abs32, "Abs32" },
|
|
||||||
{ Disp8, "d8" },
|
{ Disp8, "d8" },
|
||||||
{ Disp16, "d16" },
|
{ Disp16, "d16" },
|
||||||
{ Disp32, "d32" },
|
{ Disp32, "d32" },
|
||||||
{ SReg2, "SReg2" },
|
|
||||||
{ SReg3, "SReg3" },
|
|
||||||
{ Acc, "Acc" },
|
|
||||||
{ InOutPortReg, "InOutPortReg" },
|
{ InOutPortReg, "InOutPortReg" },
|
||||||
{ ShiftCount, "ShiftCount" },
|
{ ShiftCount, "ShiftCount" },
|
||||||
{ Imm1, "i1" },
|
|
||||||
{ Control, "control reg" },
|
{ Control, "control reg" },
|
||||||
{ Test, "test reg" },
|
{ Test, "test reg" },
|
||||||
{ Debug, "debug reg" },
|
{ Debug, "debug reg" },
|
||||||
{ FloatReg, "FReg" },
|
{ FloatReg, "FReg" },
|
||||||
{ FloatAcc, "FAcc" },
|
{ FloatAcc, "FAcc" },
|
||||||
|
{ SReg2, "SReg2" },
|
||||||
|
{ SReg3, "SReg3" },
|
||||||
|
{ Acc, "Acc" },
|
||||||
{ JumpAbsolute, "Jump Absolute" },
|
{ JumpAbsolute, "Jump Absolute" },
|
||||||
{ RegMMX, "rMMX" },
|
{ RegMMX, "rMMX" },
|
||||||
{ EsSeg, "es" },
|
{ EsSeg, "es" },
|
||||||
@ -961,7 +965,8 @@ md_assemble (line)
|
|||||||
/* add prefix, checking for repeated prefixes */
|
/* add prefix, checking for repeated prefixes */
|
||||||
switch (add_prefix (prefix->prefix_code))
|
switch (add_prefix (prefix->prefix_code))
|
||||||
{
|
{
|
||||||
case 0: return;
|
case 0:
|
||||||
|
return;
|
||||||
case 2:
|
case 2:
|
||||||
expecting_string_instruction = prefix->prefix_name;
|
expecting_string_instruction = prefix->prefix_name;
|
||||||
break;
|
break;
|
||||||
@ -990,6 +995,10 @@ md_assemble (line)
|
|||||||
case DWORD_OPCODE_SUFFIX:
|
case DWORD_OPCODE_SUFFIX:
|
||||||
case WORD_OPCODE_SUFFIX:
|
case WORD_OPCODE_SUFFIX:
|
||||||
case BYTE_OPCODE_SUFFIX:
|
case BYTE_OPCODE_SUFFIX:
|
||||||
|
case SHORT_OPCODE_SUFFIX:
|
||||||
|
#if LONG_OPCODE_SUFFIX != DWORD_OPCODE_SUFFIX
|
||||||
|
case LONG_OPCODE_SUFFIX:
|
||||||
|
#endif
|
||||||
token_start[last_index] = '\0';
|
token_start[last_index] = '\0';
|
||||||
current_templates = (templates *) hash_find (op_hash, token_start);
|
current_templates = (templates *) hash_find (op_hash, token_start);
|
||||||
token_start[last_index] = last_char;
|
token_start[last_index] = last_char;
|
||||||
@ -1005,8 +1014,8 @@ md_assemble (line)
|
|||||||
RESTORE_END_STRING (l);
|
RESTORE_END_STRING (l);
|
||||||
|
|
||||||
/* check for rep/repne without a string instruction */
|
/* check for rep/repne without a string instruction */
|
||||||
if (expecting_string_instruction &&
|
if (expecting_string_instruction
|
||||||
!(current_templates->start->opcode_modifier & IsString))
|
&& !(current_templates->start->opcode_modifier & IsString))
|
||||||
{
|
{
|
||||||
as_bad (_("expecting string instruction after `%s'"),
|
as_bad (_("expecting string instruction after `%s'"),
|
||||||
expecting_string_instruction);
|
expecting_string_instruction);
|
||||||
@ -1112,42 +1121,46 @@ md_assemble (line)
|
|||||||
making sure the overlap of the given operands types is consistent
|
making sure the overlap of the given operands types is consistent
|
||||||
with the template operand types. */
|
with the template operand types. */
|
||||||
|
|
||||||
#define MATCH(overlap,given_type) \
|
#define MATCH(overlap, given, template) \
|
||||||
(overlap \
|
((overlap) \
|
||||||
&& ((overlap & (JumpAbsolute|BaseIndex|Mem8)) \
|
&& (((overlap) & (JumpAbsolute|BaseIndex)) \
|
||||||
== (given_type & (JumpAbsolute|BaseIndex|Mem8))))
|
== ((given) & (JumpAbsolute|BaseIndex))))
|
||||||
|
|
||||||
|
|
||||||
|
/* If given types r0 and r1 are registers they must be of the same type
|
||||||
|
unless the expected operand type register overlap is null.
|
||||||
|
Note that Acc in a template matches every size of reg. */
|
||||||
|
#define CONSISTENT_REGISTER_MATCH(m0, g0, t0, m1, g1, t1) \
|
||||||
|
( ((g0) & Reg) == 0 || ((g1) & Reg) == 0 || \
|
||||||
|
((g0) & Reg) == ((g1) & Reg) || \
|
||||||
|
((((m0) & Acc) ? Reg : (t0)) & (((m1) & Acc) ? Reg : (t1)) & Reg) == 0 )
|
||||||
|
|
||||||
/* If m0 and m1 are register matches they must be consistent
|
|
||||||
with the expected operand types t0 and t1.
|
|
||||||
That is, if both m0 & m1 are register matches
|
|
||||||
i.e. ( ((m0 & (Reg)) && (m1 & (Reg)) ) ?
|
|
||||||
then, either 1. or 2. must be true:
|
|
||||||
1. the expected operand type register overlap is null:
|
|
||||||
(t0 & t1 & Reg) == 0
|
|
||||||
AND
|
|
||||||
the given register overlap is null:
|
|
||||||
(m0 & m1 & Reg) == 0
|
|
||||||
2. the expected operand type register overlap == the given
|
|
||||||
operand type overlap: (t0 & t1 & m0 & m1 & Reg).
|
|
||||||
*/
|
|
||||||
#define CONSISTENT_REGISTER_MATCH(m0, m1, t0, t1) \
|
|
||||||
( ((m0 & (Reg)) && (m1 & (Reg))) ? \
|
|
||||||
( ((t0 & t1 & (Reg)) == 0 && (m0 & m1 & (Reg)) == 0) || \
|
|
||||||
((t0 & t1) & (m0 & m1) & (Reg)) \
|
|
||||||
) : 1)
|
|
||||||
{
|
{
|
||||||
register unsigned int overlap0, overlap1;
|
register unsigned int overlap0, overlap1;
|
||||||
expressionS *exp;
|
expressionS *exp;
|
||||||
unsigned int overlap2;
|
unsigned int overlap2;
|
||||||
unsigned int found_reverse_match;
|
unsigned int found_reverse_match;
|
||||||
|
int suffix_check;
|
||||||
|
|
||||||
|
overlap0 = 0;
|
||||||
|
overlap1 = 0;
|
||||||
|
overlap2 = 0;
|
||||||
|
found_reverse_match = 0;
|
||||||
|
suffix_check = (i.suffix == BYTE_OPCODE_SUFFIX
|
||||||
|
? No_bSuf
|
||||||
|
: (i.suffix == WORD_OPCODE_SUFFIX
|
||||||
|
? No_wSuf
|
||||||
|
: (i.suffix == SHORT_OPCODE_SUFFIX
|
||||||
|
? No_sSuf
|
||||||
|
: (i.suffix == LONG_OPCODE_SUFFIX ? No_lSuf : 0))));
|
||||||
|
|
||||||
overlap0 = overlap1 = overlap2 = found_reverse_match = 0;
|
|
||||||
for (t = current_templates->start;
|
for (t = current_templates->start;
|
||||||
t < current_templates->end;
|
t < current_templates->end;
|
||||||
t++)
|
t++)
|
||||||
{
|
{
|
||||||
/* must have right number of operands */
|
/* Must have right number of operands, and must not have
|
||||||
if (i.operands != t->operands)
|
disallowed suffix. */
|
||||||
|
if (i.operands != t->operands || (t->opcode_modifier & suffix_check))
|
||||||
continue;
|
continue;
|
||||||
else if (!t->operands)
|
else if (!t->operands)
|
||||||
break; /* 0 operands always matches */
|
break; /* 0 operands always matches */
|
||||||
@ -1156,50 +1169,55 @@ md_assemble (line)
|
|||||||
switch (t->operands)
|
switch (t->operands)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
if (!MATCH (overlap0, i.types[0]))
|
if (!MATCH (overlap0, i.types[0], t->operand_types[0]))
|
||||||
continue;
|
continue;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
overlap1 = i.types[1] & t->operand_types[1];
|
overlap1 = i.types[1] & t->operand_types[1];
|
||||||
if (!MATCH (overlap0, i.types[0]) ||
|
if (!MATCH (overlap0, i.types[0], t->operand_types[0])
|
||||||
!MATCH (overlap1, i.types[1]) ||
|
|| !MATCH (overlap1, i.types[1], t->operand_types[1])
|
||||||
!CONSISTENT_REGISTER_MATCH (overlap0, overlap1,
|
|| !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
|
||||||
t->operand_types[0],
|
t->operand_types[0],
|
||||||
t->operand_types[1]))
|
overlap1, i.types[1],
|
||||||
|
t->operand_types[1]))
|
||||||
{
|
{
|
||||||
|
|
||||||
/* check if other direction is valid ... */
|
/* check if other direction is valid ... */
|
||||||
if (!(t->opcode_modifier & COMES_IN_BOTH_DIRECTIONS))
|
if ((t->opcode_modifier & (D|FloatD)) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* try reversing direction of operands */
|
/* try reversing direction of operands */
|
||||||
overlap0 = i.types[0] & t->operand_types[1];
|
overlap0 = i.types[0] & t->operand_types[1];
|
||||||
overlap1 = i.types[1] & t->operand_types[0];
|
overlap1 = i.types[1] & t->operand_types[0];
|
||||||
if (!MATCH (overlap0, i.types[0]) ||
|
if (!MATCH (overlap0, i.types[0], t->operand_types[1])
|
||||||
!MATCH (overlap1, i.types[1]) ||
|
|| !MATCH (overlap1, i.types[1], t->operand_types[0])
|
||||||
!CONSISTENT_REGISTER_MATCH (overlap0, overlap1,
|
|| !CONSISTENT_REGISTER_MATCH (overlap0, i.types[0],
|
||||||
t->operand_types[1],
|
t->operand_types[1],
|
||||||
t->operand_types[0]))
|
overlap1, i.types[1],
|
||||||
|
t->operand_types[0]))
|
||||||
{
|
{
|
||||||
/* does not match either direction */
|
/* does not match either direction */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* found a reverse match here -- slip through */
|
/* found_reverse_match holds which of D or FloatDR
|
||||||
/* found_reverse_match holds which of D or FloatD we've found */
|
we've found. */
|
||||||
found_reverse_match = t->opcode_modifier & COMES_IN_BOTH_DIRECTIONS;
|
found_reverse_match = t->opcode_modifier & (D|FloatDR);
|
||||||
} /* endif: not forward match */
|
break;
|
||||||
/* found either forward/reverse 2 operand match here */
|
}
|
||||||
|
/* found a forward 2 operand match here */
|
||||||
if (t->operands == 3)
|
if (t->operands == 3)
|
||||||
{
|
{
|
||||||
|
/* Here we make use of the fact that there are no
|
||||||
|
reverse match 3 operand instructions, and all 3
|
||||||
|
operand instructions only need to be checked for
|
||||||
|
register consistency between operands 2 and 3. */
|
||||||
overlap2 = i.types[2] & t->operand_types[2];
|
overlap2 = i.types[2] & t->operand_types[2];
|
||||||
if (!MATCH (overlap2, i.types[2]) ||
|
if (!MATCH (overlap2, i.types[2], t->operand_types[2])
|
||||||
!CONSISTENT_REGISTER_MATCH (overlap0, overlap2,
|
|| !CONSISTENT_REGISTER_MATCH (overlap1, i.types[1],
|
||||||
t->operand_types[0],
|
t->operand_types[1],
|
||||||
t->operand_types[2]) ||
|
overlap2, i.types[2],
|
||||||
!CONSISTENT_REGISTER_MATCH (overlap1, overlap2,
|
t->operand_types[2]))
|
||||||
t->operand_types[1],
|
|
||||||
t->operand_types[2]))
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* found either forward/reverse 2 or 3 operand match here:
|
/* found either forward/reverse 2 or 3 operand match here:
|
||||||
@ -1216,23 +1234,23 @@ md_assemble (line)
|
|||||||
|
|
||||||
/* Copy the template we found. */
|
/* Copy the template we found. */
|
||||||
i.tm = *t;
|
i.tm = *t;
|
||||||
if (i.tm.opcode_modifier & FWait)
|
|
||||||
if (! add_prefix (FWAIT_OPCODE))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (found_reverse_match)
|
if (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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i.tm.opcode_modifier & FWait)
|
||||||
|
if (! add_prefix (FWAIT_OPCODE))
|
||||||
|
return;
|
||||||
|
|
||||||
/* Check string instruction segment overrides */
|
/* Check string instruction segment overrides */
|
||||||
if ((i.tm.opcode_modifier & IsString) != 0 && i.mem_operands != 0)
|
if ((i.tm.opcode_modifier & IsString) != 0 && i.mem_operands != 0)
|
||||||
{
|
{
|
||||||
int mem_op = (i.types[0] & Mem) ? 0 : 1;
|
int mem_op = (i.types[0] & AnyMem) ? 0 : 1;
|
||||||
if ((i.tm.operand_types[mem_op] & EsSeg) != 0)
|
if ((i.tm.operand_types[mem_op] & EsSeg) != 0)
|
||||||
{
|
{
|
||||||
if (i.seg[0] != (seg_entry *) 0 && i.seg[0] != (seg_entry *) &es)
|
if (i.seg[0] != NULL && i.seg[0] != &es)
|
||||||
{
|
{
|
||||||
as_bad (_("`%s' operand %d must use `%%es' segment"),
|
as_bad (_("`%s' operand %d must use `%%es' segment"),
|
||||||
i.tm.name,
|
i.tm.name,
|
||||||
@ -1247,7 +1265,7 @@ md_assemble (line)
|
|||||||
}
|
}
|
||||||
else if ((i.tm.operand_types[mem_op + 1] & EsSeg) != 0)
|
else if ((i.tm.operand_types[mem_op + 1] & EsSeg) != 0)
|
||||||
{
|
{
|
||||||
if (i.seg[1] != (seg_entry *) 0 && i.seg[1] != (seg_entry *) &es)
|
if (i.seg[1] != NULL && i.seg[1] != &es)
|
||||||
{
|
{
|
||||||
as_bad (_("`%s' operand %d must use `%%es' segment"),
|
as_bad (_("`%s' operand %d must use `%%es' segment"),
|
||||||
i.tm.name,
|
i.tm.name,
|
||||||
@ -1257,69 +1275,130 @@ md_assemble (line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the matched instruction specifies an explicit opcode suffix,
|
/* If matched instruction specifies an explicit opcode suffix, use
|
||||||
use it - and make sure none has already been specified. */
|
it. */
|
||||||
if (i.tm.opcode_modifier & (Data16|Data32))
|
if (i.tm.opcode_modifier & (Data16|Data32))
|
||||||
{
|
{
|
||||||
if (i.suffix)
|
|
||||||
{
|
|
||||||
as_bad (_("extraneous opcode suffix given"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (i.tm.opcode_modifier & Data16)
|
if (i.tm.opcode_modifier & Data16)
|
||||||
i.suffix = WORD_OPCODE_SUFFIX;
|
i.suffix = WORD_OPCODE_SUFFIX;
|
||||||
else
|
else
|
||||||
i.suffix = DWORD_OPCODE_SUFFIX;
|
i.suffix = DWORD_OPCODE_SUFFIX;
|
||||||
}
|
}
|
||||||
|
else if (i.reg_operands)
|
||||||
/* If there's no opcode suffix we try to invent one based on register
|
|
||||||
operands. */
|
|
||||||
if (!i.suffix && i.reg_operands)
|
|
||||||
{
|
{
|
||||||
/* We take i.suffix from the LAST register operand specified. This
|
/* If there's no opcode suffix we try to invent one based on
|
||||||
assumes that the last register operands is the destination register
|
register operands. */
|
||||||
operand. */
|
if (!i.suffix)
|
||||||
int op;
|
|
||||||
for (op = 0; op < MAX_OPERANDS; op++)
|
|
||||||
if (i.types[op] & Reg)
|
|
||||||
{
|
|
||||||
i.suffix = ((i.types[op] & Reg8) ? BYTE_OPCODE_SUFFIX :
|
|
||||||
(i.types[op] & Reg16) ? WORD_OPCODE_SUFFIX :
|
|
||||||
DWORD_OPCODE_SUFFIX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (i.suffix != 0
|
|
||||||
&& i.reg_operands != 0
|
|
||||||
&& (i.types[i.operands - 1] & Reg) != 0)
|
|
||||||
{
|
|
||||||
int bad;
|
|
||||||
|
|
||||||
/* If the last operand is a register, make sure it is
|
|
||||||
compatible with the suffix. */
|
|
||||||
|
|
||||||
bad = 0;
|
|
||||||
switch (i.suffix)
|
|
||||||
{
|
{
|
||||||
default:
|
/* We take i.suffix from the last register operand specified,
|
||||||
abort ();
|
Destination register type is more significant than source
|
||||||
case BYTE_OPCODE_SUFFIX:
|
register type. */
|
||||||
/* If this is an eight bit register, it's OK. If it's the
|
int op;
|
||||||
16 or 32 bit version of an eight bit register, we will
|
for (op = i.operands; --op >= 0; )
|
||||||
just use the low portion, and that's OK too. */
|
if (i.types[op] & Reg)
|
||||||
if ((i.types[i.operands - 1] & Reg8) == 0
|
{
|
||||||
&& i.regs[i.operands - 1]->reg_num >= 4)
|
i.suffix = ((i.types[op] & Reg8) ? BYTE_OPCODE_SUFFIX :
|
||||||
bad = 1;
|
(i.types[op] & Reg16) ? WORD_OPCODE_SUFFIX :
|
||||||
break;
|
DWORD_OPCODE_SUFFIX);
|
||||||
case WORD_OPCODE_SUFFIX:
|
break;
|
||||||
case DWORD_OPCODE_SUFFIX:
|
}
|
||||||
/* We don't insist on the presence or absence of the e
|
|
||||||
prefix on the register, but we reject eight bit
|
|
||||||
registers. */
|
|
||||||
if ((i.types[i.operands - 1] & Reg8) != 0)
|
|
||||||
bad = 1;
|
|
||||||
}
|
}
|
||||||
if (bad)
|
else if (i.suffix == BYTE_OPCODE_SUFFIX)
|
||||||
as_bad (_("register does not match opcode suffix"));
|
{
|
||||||
|
int op;
|
||||||
|
for (op = i.operands; --op >= 0; )
|
||||||
|
{
|
||||||
|
/* If this is an eight bit register, it's OK. If it's
|
||||||
|
the 16 or 32 bit version of an eight bit register,
|
||||||
|
we will just use the low portion, and that's OK too. */
|
||||||
|
if (i.types[op] & Reg8)
|
||||||
|
continue;
|
||||||
|
if ((i.types[op] & WordReg) && i.regs[op]->reg_num < 4
|
||||||
|
#if 0
|
||||||
|
/* Check that the template allows eight bit regs
|
||||||
|
This kills insns such as `orb $1,%edx', which
|
||||||
|
maybe should be allowed. */
|
||||||
|
&& (i.tm.operand_types[op] & (Reg8|InOutPortReg))
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
#if REGISTER_WARNINGS
|
||||||
|
if ((i.tm.operand_types[op] & InOutPortReg) == 0)
|
||||||
|
as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),
|
||||||
|
(i.regs[op] - (i.types[op] & Reg16 ? 8 : 16))->reg_name,
|
||||||
|
i.regs[op]->reg_name,
|
||||||
|
i.suffix);
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* Any other register is bad */
|
||||||
|
if (i.types[op] & (Reg | RegMMX | Control | Debug | Test
|
||||||
|
| FloatReg | FloatAcc | SReg2 | SReg3))
|
||||||
|
{
|
||||||
|
as_bad (_("`%%%s' not allowed with `%s%c'"),
|
||||||
|
i.regs[op]->reg_name,
|
||||||
|
i.tm.name,
|
||||||
|
i.suffix);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (i.suffix == DWORD_OPCODE_SUFFIX)
|
||||||
|
{
|
||||||
|
int op;
|
||||||
|
for (op = i.operands; --op >= 0; )
|
||||||
|
/* Reject eight bit registers, except where the template
|
||||||
|
requires them. (eg. movzb) */
|
||||||
|
if ((i.types[op] & Reg8) != 0
|
||||||
|
&& (i.tm.operand_types[op] & (Reg16|Reg32|Acc)) != 0)
|
||||||
|
{
|
||||||
|
as_bad (_("`%%%s' not allowed with `%s%c'"),
|
||||||
|
i.regs[op]->reg_name,
|
||||||
|
i.tm.name,
|
||||||
|
i.suffix);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if REGISTER_WARNINGS
|
||||||
|
/* Warn if the e prefix on a general reg is missing. */
|
||||||
|
else if ((i.types[op] & Reg16) != 0
|
||||||
|
&& (i.tm.operand_types[op] & (Reg32|Acc)) != 0)
|
||||||
|
{
|
||||||
|
as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),
|
||||||
|
(i.regs[op] + 8)->reg_name,
|
||||||
|
i.regs[op]->reg_name,
|
||||||
|
i.suffix);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (i.suffix == WORD_OPCODE_SUFFIX)
|
||||||
|
{
|
||||||
|
int op;
|
||||||
|
for (op = i.operands; --op >= 0; )
|
||||||
|
/* Reject eight bit registers, except where the template
|
||||||
|
requires them. (eg. movzb) */
|
||||||
|
if ((i.types[op] & Reg8) != 0
|
||||||
|
&& (i.tm.operand_types[op] & (Reg16|Reg32|Acc)) != 0)
|
||||||
|
{
|
||||||
|
as_bad (_("`%%%s' not allowed with `%s%c'"),
|
||||||
|
i.regs[op]->reg_name,
|
||||||
|
i.tm.name,
|
||||||
|
i.suffix);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if REGISTER_WARNINGS
|
||||||
|
/* Warn if the e prefix on a general reg is present. */
|
||||||
|
else if ((i.types[op] & Reg32) != 0
|
||||||
|
&& (i.tm.operand_types[op] & (Reg16|Acc)) != 0)
|
||||||
|
{
|
||||||
|
as_warn (_("using `%%%s' instead of `%%%s' due to `%c' suffix"),
|
||||||
|
(i.regs[op] - 8)->reg_name,
|
||||||
|
i.regs[op]->reg_name,
|
||||||
|
i.suffix);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make still unresolved immediate matches conform to size of immediate
|
/* Make still unresolved immediate matches conform to size of immediate
|
||||||
@ -1377,18 +1456,32 @@ md_assemble (line)
|
|||||||
{
|
{
|
||||||
/* Select between byte and word/dword operations. */
|
/* Select between byte and word/dword operations. */
|
||||||
if (i.tm.opcode_modifier & W)
|
if (i.tm.opcode_modifier & W)
|
||||||
i.tm.base_opcode |= W;
|
|
||||||
/* Now select between word & dword operations via the operand
|
|
||||||
size prefix. */
|
|
||||||
if ((i.suffix == WORD_OPCODE_SUFFIX) ^ flag_16bit_code)
|
|
||||||
{
|
{
|
||||||
unsigned char prefix = WORD_PREFIX_OPCODE;
|
if (i.tm.opcode_modifier & ShortForm)
|
||||||
|
i.tm.base_opcode |= 8;
|
||||||
|
else
|
||||||
|
i.tm.base_opcode |= 1;
|
||||||
|
}
|
||||||
|
/* Now select between word & dword operations via the operand
|
||||||
|
size prefix, except for instructions that will ignore this
|
||||||
|
prefix anyway. */
|
||||||
|
if ((i.suffix == DWORD_OPCODE_SUFFIX
|
||||||
|
|| i.suffix == LONG_OPCODE_SUFFIX) == flag_16bit_code
|
||||||
|
&& !(i.tm.opcode_modifier & IgnoreDataSize))
|
||||||
|
{
|
||||||
|
unsigned int prefix = DATA_PREFIX_OPCODE;
|
||||||
if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */
|
if (i.tm.opcode_modifier & JumpByte) /* jcxz, loop */
|
||||||
prefix = ADDR_PREFIX_OPCODE;
|
prefix = ADDR_PREFIX_OPCODE;
|
||||||
|
|
||||||
if (! add_prefix (prefix))
|
if (! add_prefix (prefix))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/* Size floating point instruction. */
|
||||||
|
if (i.suffix == LONG_OPCODE_SUFFIX)
|
||||||
|
{
|
||||||
|
if (i.tm.opcode_modifier & FloatMF)
|
||||||
|
i.tm.base_opcode ^= 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For insns with operands there are more diddles to do to the opcode. */
|
/* For insns with operands there are more diddles to do to the opcode. */
|
||||||
@ -1427,14 +1520,24 @@ md_assemble (line)
|
|||||||
unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1;
|
unsigned int op = (i.types[0] & (Reg | FloatReg)) ? 0 : 1;
|
||||||
/* Register goes in low 3 bits of opcode. */
|
/* Register goes in low 3 bits of opcode. */
|
||||||
i.tm.base_opcode |= i.regs[op]->reg_num;
|
i.tm.base_opcode |= i.regs[op]->reg_num;
|
||||||
}
|
if ((i.tm.opcode_modifier & Ugh) != 0)
|
||||||
else if (i.tm.opcode_modifier & ShortFormW)
|
{
|
||||||
{
|
/* Warn about some common errors, but press on regardless.
|
||||||
/* Short form with 0x8 width bit. Register is always dest. operand */
|
The first case can be generated by gcc (<= 2.8.1). */
|
||||||
i.tm.base_opcode |= i.regs[1]->reg_num;
|
if (i.operands == 2)
|
||||||
if (i.suffix == WORD_OPCODE_SUFFIX ||
|
{
|
||||||
i.suffix == DWORD_OPCODE_SUFFIX)
|
/* reversed arguments on faddp, fsubp, etc. */
|
||||||
i.tm.base_opcode |= 0x8;
|
as_warn (_("translating to `%s %%%s,%%%s'"), i.tm.name,
|
||||||
|
i.regs[1]->reg_name,
|
||||||
|
i.regs[0]->reg_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* extraneous `l' suffix on fp insn */
|
||||||
|
as_warn (_("translating to `%s %%%s'"), i.tm.name,
|
||||||
|
i.regs[0]->reg_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (i.tm.opcode_modifier & Modrm)
|
else if (i.tm.opcode_modifier & Modrm)
|
||||||
{
|
{
|
||||||
@ -1468,7 +1571,7 @@ md_assemble (line)
|
|||||||
were given in the reverse order. */
|
were given in the reverse order. */
|
||||||
if (i.tm.opcode_modifier & ReverseRegRegmem)
|
if (i.tm.opcode_modifier & ReverseRegRegmem)
|
||||||
{
|
{
|
||||||
reg_entry *tmp = i.regs[source];
|
const reg_entry *tmp = i.regs[source];
|
||||||
i.regs[source] = i.regs[dest];
|
i.regs[source] = i.regs[dest];
|
||||||
i.regs[dest] = tmp;
|
i.regs[dest] = tmp;
|
||||||
}
|
}
|
||||||
@ -1495,9 +1598,9 @@ md_assemble (line)
|
|||||||
if (i.mem_operands)
|
if (i.mem_operands)
|
||||||
{
|
{
|
||||||
unsigned int fake_zero_displacement = 0;
|
unsigned int fake_zero_displacement = 0;
|
||||||
unsigned int op = ((i.types[0] & Mem)
|
unsigned int op = ((i.types[0] & AnyMem)
|
||||||
? 0
|
? 0
|
||||||
: (i.types[1] & Mem) ? 1 : 2);
|
: (i.types[1] & AnyMem) ? 1 : 2);
|
||||||
|
|
||||||
default_seg = &ds;
|
default_seg = &ds;
|
||||||
|
|
||||||
@ -1617,25 +1720,16 @@ md_assemble (line)
|
|||||||
if (i.rm.mode != 3)
|
if (i.rm.mode != 3)
|
||||||
uses_mem_addrmode = 1;
|
uses_mem_addrmode = 1;
|
||||||
}
|
}
|
||||||
else if (i.tm.opcode_modifier & Seg2ShortForm)
|
else if (i.tm.opcode_modifier & (Seg2ShortForm | Seg3ShortForm))
|
||||||
{
|
{
|
||||||
if (i.tm.base_opcode == POP_SEG_SHORT && i.regs[0]->reg_num == 1)
|
if (i.tm.base_opcode == POP_SEG_SHORT && i.regs[0]->reg_num == 1)
|
||||||
{
|
{
|
||||||
as_bad (_("you can't `pop %%cs' on the 386."));
|
as_bad (_("you can't `pop %%cs'"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i.tm.base_opcode |= (i.regs[0]->reg_num << 3);
|
i.tm.base_opcode |= (i.regs[0]->reg_num << 3);
|
||||||
}
|
}
|
||||||
else if (i.tm.opcode_modifier & Seg3ShortForm)
|
else if ((i.tm.base_opcode & ~(D|W)) == MOV_AX_DISP32)
|
||||||
{
|
|
||||||
/* 'push %fs' is 0x0fa0; 'pop %fs' is 0x0fa1.
|
|
||||||
'push %gs' is 0x0fa8; 'pop %fs' is 0x0fa9.
|
|
||||||
So, only if i.regs[0]->reg_num == 5 (%gs) do we need
|
|
||||||
to change the opcode. */
|
|
||||||
if (i.regs[0]->reg_num == 5)
|
|
||||||
i.tm.base_opcode |= 0x08;
|
|
||||||
}
|
|
||||||
else if ((i.tm.base_opcode & ~DW) == MOV_AX_DISP32)
|
|
||||||
{
|
{
|
||||||
/* This is a special non-modrm instruction
|
/* This is a special non-modrm instruction
|
||||||
that addresses memory with a 32-bit displacement mode anyway,
|
that addresses memory with a 32-bit displacement mode anyway,
|
||||||
@ -1671,6 +1765,11 @@ md_assemble (line)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ((i.tm.opcode_modifier & Ugh) != 0)
|
||||||
|
{
|
||||||
|
/* UnixWare fsub no args is alias for fsubp, fadd -> faddp, etc */
|
||||||
|
as_warn (_("translating to `%sp'"), i.tm.name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle conversion of 'int $3' --> special int3 insn. */
|
/* Handle conversion of 'int $3' --> special int3 insn. */
|
||||||
@ -1738,7 +1837,7 @@ md_assemble (line)
|
|||||||
{
|
{
|
||||||
if (flag_16bit_code)
|
if (flag_16bit_code)
|
||||||
{
|
{
|
||||||
FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE);
|
FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
|
||||||
insn_size += 1;
|
insn_size += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1763,24 +1862,23 @@ md_assemble (line)
|
|||||||
{
|
{
|
||||||
int size = (i.tm.opcode_modifier & JumpByte) ? 1 : 4;
|
int size = (i.tm.opcode_modifier & JumpByte) ? 1 : 4;
|
||||||
unsigned long n = i.disps[0]->X_add_number;
|
unsigned long n = i.disps[0]->X_add_number;
|
||||||
unsigned char *q;
|
|
||||||
|
|
||||||
if (size == 1) /* then this is a loop or jecxz type instruction */
|
if (size == 1) /* then this is a loop or jecxz type instruction */
|
||||||
{
|
{
|
||||||
if (i.prefix[ADDR_PREFIX])
|
if (i.prefix[ADDR_PREFIX])
|
||||||
{
|
{
|
||||||
FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
|
FRAG_APPEND_1_CHAR (ADDR_PREFIX_OPCODE);
|
||||||
i.prefixes -= 1;
|
|
||||||
insn_size += 1;
|
insn_size += 1;
|
||||||
|
i.prefixes -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i.prefixes != 0)
|
if (i.prefixes != 0)
|
||||||
as_warn (_("skipping prefixes on this instruction"));
|
as_warn (_("skipping prefixes on this instruction"));
|
||||||
|
|
||||||
if ((size == 4) && (flag_16bit_code))
|
if (size == 4 && flag_16bit_code)
|
||||||
{
|
{
|
||||||
FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE);
|
FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
|
||||||
insn_size += 1;
|
insn_size += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1805,8 +1903,8 @@ md_assemble (line)
|
|||||||
md_number_to_chars (p, (valueT) n, size);
|
md_number_to_chars (p, (valueT) n, size);
|
||||||
if (size == 1 && !fits_in_signed_byte (n))
|
if (size == 1 && !fits_in_signed_byte (n))
|
||||||
{
|
{
|
||||||
as_bad (_("loop/jecx only takes byte displacement; %lu shortened to %d"),
|
as_bad (_("`%s' only takes byte displacement; %lu shortened to %d"),
|
||||||
n, *p);
|
i.tm.name, n, *p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1823,7 +1921,7 @@ md_assemble (line)
|
|||||||
|
|
||||||
if (flag_16bit_code)
|
if (flag_16bit_code)
|
||||||
{
|
{
|
||||||
FRAG_APPEND_1_CHAR (WORD_PREFIX_OPCODE);
|
FRAG_APPEND_1_CHAR (DATA_PREFIX_OPCODE);
|
||||||
insn_size += 1;
|
insn_size += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1900,8 +1998,9 @@ md_assemble (line)
|
|||||||
| i.rm.reg << 3
|
| i.rm.reg << 3
|
||||||
| i.rm.mode << 6),
|
| i.rm.mode << 6),
|
||||||
1);
|
1);
|
||||||
/* If i.rm.regmem == ESP (4) && i.rm.mode != Mode 3 (Register mode)
|
/* If i.rm.regmem == ESP (4)
|
||||||
==> need second modrm byte. */
|
&& i.rm.mode != (Register mode)
|
||||||
|
==> need second modrm byte. */
|
||||||
if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING
|
if (i.rm.regmem == ESCAPE_TO_TWO_BYTE_ADDRESSING
|
||||||
&& i.rm.mode != 3)
|
&& i.rm.mode != 3)
|
||||||
{
|
{
|
||||||
@ -1925,7 +2024,7 @@ md_assemble (line)
|
|||||||
{
|
{
|
||||||
if (i.disps[n]->X_op == O_constant)
|
if (i.disps[n]->X_op == O_constant)
|
||||||
{
|
{
|
||||||
if (i.types[n] & (Disp8 | Abs8))
|
if (i.types[n] & Disp8)
|
||||||
{
|
{
|
||||||
p = frag_more (1);
|
p = frag_more (1);
|
||||||
insn_size += 1;
|
insn_size += 1;
|
||||||
@ -1933,7 +2032,7 @@ md_assemble (line)
|
|||||||
(valueT) i.disps[n]->X_add_number,
|
(valueT) i.disps[n]->X_add_number,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
else if (i.types[n] & (Disp16 | Abs16))
|
else if (i.types[n] & Disp16)
|
||||||
{
|
{
|
||||||
p = frag_more (2);
|
p = frag_more (2);
|
||||||
insn_size += 2;
|
insn_size += 2;
|
||||||
@ -1942,7 +2041,7 @@ md_assemble (line)
|
|||||||
2);
|
2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* Disp32|Abs32 */
|
{ /* Disp32 */
|
||||||
p = frag_more (4);
|
p = frag_more (4);
|
||||||
insn_size += 4;
|
insn_size += 4;
|
||||||
md_number_to_chars (p,
|
md_number_to_chars (p,
|
||||||
@ -2223,21 +2322,6 @@ i386_operand (operand_string)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine type of memory operand from opcode_suffix;
|
|
||||||
no opcode suffix implies general memory references. */
|
|
||||||
switch (i.suffix)
|
|
||||||
{
|
|
||||||
case BYTE_OPCODE_SUFFIX:
|
|
||||||
i.types[this_operand] |= Mem8;
|
|
||||||
break;
|
|
||||||
case WORD_OPCODE_SUFFIX:
|
|
||||||
i.types[this_operand] |= Mem16;
|
|
||||||
break;
|
|
||||||
case DWORD_OPCODE_SUFFIX:
|
|
||||||
default:
|
|
||||||
i.types[this_operand] |= Mem32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for base index form. We detect the base index form by
|
/* Check for base index form. We detect the base index form by
|
||||||
looking for an ')' at the end of the operand, searching
|
looking for an ')' at the end of the operand, searching
|
||||||
for the '(' matching it, and finding a REGISTER_PREFIX or ','
|
for the '(' matching it, and finding a REGISTER_PREFIX or ','
|
||||||
@ -2483,13 +2567,14 @@ i386_operand (operand_string)
|
|||||||
input_line_pointer);
|
input_line_pointer);
|
||||||
RESTORE_END_STRING (displacement_string_end);
|
RESTORE_END_STRING (displacement_string_end);
|
||||||
input_line_pointer = save_input_line_pointer;
|
input_line_pointer = save_input_line_pointer;
|
||||||
#if 0 /* this is handled in expr */
|
|
||||||
|
#if 0 /* this is handled in expr. */
|
||||||
if (exp->X_op == O_absent)
|
if (exp->X_op == O_absent)
|
||||||
{
|
{
|
||||||
/* missing expr becomes absolute 0 */
|
/* missing expr becomes absolute 0 */
|
||||||
as_bad (_("missing or invalid displacement `%s' taken as 0"),
|
as_bad (_("missing or invalid displacement `%s' taken as 0"),
|
||||||
operand_string);
|
operand_string);
|
||||||
i.types[this_operand] |= (Disp | Abs);
|
i.types[this_operand] |= Disp;
|
||||||
exp->X_op = O_constant;
|
exp->X_op = O_constant;
|
||||||
exp->X_add_number = 0;
|
exp->X_add_number = 0;
|
||||||
exp->X_add_symbol = (symbolS *) 0;
|
exp->X_add_symbol = (symbolS *) 0;
|
||||||
@ -2519,24 +2604,25 @@ i386_operand (operand_string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Special case for (%dx) while doing input/output op. */
|
/* Special case for (%dx) while doing input/output op. */
|
||||||
if (i.base_reg &&
|
if (i.base_reg
|
||||||
i.base_reg->reg_type == (Reg16 | InOutPortReg) &&
|
&& i.base_reg->reg_type == (Reg16 | InOutPortReg)
|
||||||
i.index_reg == 0 &&
|
&& i.index_reg == 0
|
||||||
i.log2_scale_factor == 0 &&
|
&& i.log2_scale_factor == 0
|
||||||
i.seg[i.mem_operands] == 0)
|
&& i.seg[i.mem_operands] == 0
|
||||||
|
&& (i.types[this_operand] & Disp) == 0)
|
||||||
{
|
{
|
||||||
i.types[this_operand] = InOutPortReg;
|
i.types[this_operand] = InOutPortReg;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/* Make sure the memory operand we've been dealt is valid. */
|
/* Make sure the memory operand we've been dealt is valid. */
|
||||||
if ((i.base_reg && (i.base_reg->reg_type & BaseIndex) == 0)
|
if ((i.base_reg
|
||||||
|| (i.index_reg && ((i.index_reg->reg_type & BaseIndex) == 0
|
&& (i.base_reg->reg_type & Reg32) == 0)
|
||||||
|| i.index_reg->reg_num == ESP_REG_NUM))
|
|| (i.index_reg
|
||||||
|| (i.base_reg && i.index_reg
|
&& ((i.index_reg->reg_type & (Reg32|BaseIndex))
|
||||||
&& (i.base_reg->reg_type & i.index_reg->reg_type & Reg) == 0))
|
!= (Reg32|BaseIndex))))
|
||||||
{
|
{
|
||||||
as_bad (_("`%s' is not a valid base/index expression"),
|
as_bad (_("`%s' is not a valid %s bit base/index expression"),
|
||||||
operand_string);
|
operand_string, "32");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
i.mem_operands++;
|
i.mem_operands++;
|
||||||
@ -2574,8 +2660,8 @@ md_estimate_size_before_relax (fragP, segment)
|
|||||||
|
|
||||||
old_fr_fix = fragP->fr_fix;
|
old_fr_fix = fragP->fr_fix;
|
||||||
opcode = (unsigned char *) fragP->fr_opcode;
|
opcode = (unsigned char *) fragP->fr_opcode;
|
||||||
/* We've already got fragP->fr_subtype right; all we have to do is check
|
/* We've already got fragP->fr_subtype right; all we have to do is
|
||||||
for un-relaxable symbols. */
|
check for un-relaxable symbols. */
|
||||||
if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
|
if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
|
||||||
{
|
{
|
||||||
/* symbol is undefined in this segment */
|
/* symbol is undefined in this segment */
|
||||||
@ -2585,7 +2671,7 @@ md_estimate_size_before_relax (fragP, segment)
|
|||||||
opcode[0] = 0xe9; /* dword disp jmp */
|
opcode[0] = 0xe9; /* dword disp jmp */
|
||||||
fragP->fr_fix += 4;
|
fragP->fr_fix += 4;
|
||||||
fix_new (fragP, old_fr_fix, 4,
|
fix_new (fragP, old_fr_fix, 4,
|
||||||
fragP->fr_symbol,
|
fragP->fr_symbol,
|
||||||
fragP->fr_offset, 1,
|
fragP->fr_offset, 1,
|
||||||
(GOT_symbol && /* Not quite right - we should switch on
|
(GOT_symbol && /* Not quite right - we should switch on
|
||||||
presence of @PLT, but I cannot see how
|
presence of @PLT, but I cannot see how
|
||||||
@ -2677,14 +2763,14 @@ md_convert_frag (abfd, sec, fragP)
|
|||||||
case ENCODE_RELAX_STATE (COND_JUMP, WORD):
|
case ENCODE_RELAX_STATE (COND_JUMP, WORD):
|
||||||
opcode[1] = TWO_BYTE_OPCODE_ESCAPE;
|
opcode[1] = TWO_BYTE_OPCODE_ESCAPE;
|
||||||
opcode[2] = opcode[0] + 0x10;
|
opcode[2] = opcode[0] + 0x10;
|
||||||
opcode[0] = WORD_PREFIX_OPCODE;
|
opcode[0] = DATA_PREFIX_OPCODE;
|
||||||
extension = 4; /* 3 opcode + 2 displacement */
|
extension = 4; /* 3 opcode + 2 displacement */
|
||||||
where_to_put_displacement = &opcode[3];
|
where_to_put_displacement = &opcode[3];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENCODE_RELAX_STATE (UNCOND_JUMP, WORD):
|
case ENCODE_RELAX_STATE (UNCOND_JUMP, WORD):
|
||||||
opcode[1] = 0xe9;
|
opcode[1] = 0xe9;
|
||||||
opcode[0] = WORD_PREFIX_OPCODE;
|
opcode[0] = DATA_PREFIX_OPCODE;
|
||||||
extension = 3; /* 2 opcode + 2 displacement */
|
extension = 3; /* 2 opcode + 2 displacement */
|
||||||
where_to_put_displacement = &opcode[2];
|
where_to_put_displacement = &opcode[2];
|
||||||
break;
|
break;
|
||||||
@ -3153,7 +3239,7 @@ tc_gen_reloc (section, fixp)
|
|||||||
arelent *rel;
|
arelent *rel;
|
||||||
bfd_reloc_code_real_type code;
|
bfd_reloc_code_real_type code;
|
||||||
|
|
||||||
switch(fixp->fx_r_type)
|
switch (fixp->fx_r_type)
|
||||||
{
|
{
|
||||||
case BFD_RELOC_386_PLT32:
|
case BFD_RELOC_386_PLT32:
|
||||||
case BFD_RELOC_386_GOT32:
|
case BFD_RELOC_386_GOT32:
|
||||||
@ -3177,7 +3263,10 @@ tc_gen_reloc (section, fixp)
|
|||||||
fixp->fx_size);
|
fixp->fx_size);
|
||||||
else
|
else
|
||||||
as_bad (_("Can not do %d byte relocation"), fixp->fx_size);
|
as_bad (_("Can not do %d byte relocation"), fixp->fx_size);
|
||||||
|
code = BFD_RELOC_32;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#undef MAP
|
#undef MAP
|
||||||
#undef F
|
#undef F
|
||||||
|
@ -195,10 +195,12 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag));
|
|||||||
/* index_base_byte.base for no base register addressing */
|
/* index_base_byte.base for no base register addressing */
|
||||||
#define NO_BASE_REGISTER EBP_REG_NUM
|
#define NO_BASE_REGISTER EBP_REG_NUM
|
||||||
|
|
||||||
/* these are the att as opcode suffixes, making movl --> mov, for example */
|
/* these are the opcode suffixes, making movl --> mov, for example */
|
||||||
#define DWORD_OPCODE_SUFFIX 'l'
|
#define DWORD_OPCODE_SUFFIX 'l'
|
||||||
#define WORD_OPCODE_SUFFIX 'w'
|
#define WORD_OPCODE_SUFFIX 'w'
|
||||||
#define BYTE_OPCODE_SUFFIX 'b'
|
#define BYTE_OPCODE_SUFFIX 'b'
|
||||||
|
#define SHORT_OPCODE_SUFFIX 's'
|
||||||
|
#define LONG_OPCODE_SUFFIX 'l'
|
||||||
|
|
||||||
/* modrm.mode = REGMEM_FIELD_HAS_REG when a register is in there */
|
/* modrm.mode = REGMEM_FIELD_HAS_REG when a register is in there */
|
||||||
#define REGMEM_FIELD_HAS_REG 0x3/* always = 0x3 */
|
#define REGMEM_FIELD_HAS_REG 0x3/* always = 0x3 */
|
||||||
@ -235,44 +237,41 @@ extern int tc_coff_sizemachdep PARAMS ((fragS *frag));
|
|||||||
#define Disp8 0x200 /* 8 bit displacement */
|
#define Disp8 0x200 /* 8 bit displacement */
|
||||||
#define Disp16 0x400 /* 16 bit displacement */
|
#define Disp16 0x400 /* 16 bit displacement */
|
||||||
#define Disp32 0x800 /* 32 bit displacement */
|
#define Disp32 0x800 /* 32 bit displacement */
|
||||||
/* Mem8,16,32 are used to limit the allowed sizes of memory operands */
|
|
||||||
#define Mem8 0x1000
|
|
||||||
#define Mem16 0x2000
|
|
||||||
#define Mem32 0x4000
|
|
||||||
/* specials */
|
/* specials */
|
||||||
#define InOutPortReg 0x10000 /* register to hold in/out port addr = dx */
|
#define InOutPortReg 0x1000 /* register to hold in/out port addr = dx */
|
||||||
#define ShiftCount 0x20000 /* register to hold shift cound = cl */
|
#define ShiftCount 0x2000 /* register to hold shift cound = cl */
|
||||||
#define Control 0x40000 /* Control register */
|
#define Control 0x4000 /* Control register */
|
||||||
#define Debug 0x80000 /* Debug register */
|
#define Debug 0x8000 /* Debug register */
|
||||||
#define Test 0x100000 /* Test register */
|
#define Test 0x10000 /* Test register */
|
||||||
#define FloatReg 0x200000 /* Float register */
|
#define FloatReg 0x20000 /* Float register */
|
||||||
#define FloatAcc 0x400000 /* Float stack top %st(0) */
|
#define FloatAcc 0x40000 /* Float stack top %st(0) */
|
||||||
#define SReg2 0x800000 /* 2 bit segment register */
|
#define SReg2 0x80000 /* 2 bit segment register */
|
||||||
#define SReg3 0x1000000 /* 3 bit segment register */
|
#define SReg3 0x100000 /* 3 bit segment register */
|
||||||
#define Acc 0x2000000 /* Accumulator %al or %ax or %eax */
|
#define Acc 0x200000 /* Accumulator %al or %ax or %eax */
|
||||||
#define JumpAbsolute 0x4000000
|
#define JumpAbsolute 0x400000
|
||||||
#define Abs8 0x8000000
|
#define RegMMX 0x800000 /* MMX register */
|
||||||
#define Abs16 0x10000000
|
#define EsSeg 0x1000000 /* String insn operand with fixed es segment */
|
||||||
#define Abs32 0x20000000
|
|
||||||
#define RegMMX 0x40000000 /* MMX register */
|
|
||||||
#define EsSeg 0x80000000 /* String insn operand with fixed es segment */
|
|
||||||
|
|
||||||
#define Reg (Reg8|Reg16|Reg32) /* gen'l register */
|
#define Reg (Reg8|Reg16|Reg32) /* gen'l register */
|
||||||
#define WordReg (Reg16|Reg32)
|
#define WordReg (Reg16|Reg32)
|
||||||
|
#define ImplicitRegister (InOutPortReg|ShiftCount|Acc|FloatAcc)
|
||||||
#define Imm (Imm8|Imm8S|Imm16|Imm32) /* gen'l immediate */
|
#define Imm (Imm8|Imm8S|Imm16|Imm32) /* gen'l immediate */
|
||||||
#define Disp (Disp8|Disp16|Disp32) /* General displacement */
|
#define Disp (Disp8|Disp16|Disp32) /* General displacement */
|
||||||
#define Mem (Mem8|Mem16|Mem32|Disp|BaseIndex) /* General memory */
|
#define AnyMem (Disp|BaseIndex) /* General memory */
|
||||||
#define WordMem (Mem16|Mem32|Disp|BaseIndex)
|
/* The following aliases are defined because the opcode table
|
||||||
#define ByteMem (Mem8|Disp|BaseIndex)
|
carefully specifies the allowed memory types for each instruction.
|
||||||
#define ImplicitRegister (InOutPortReg|ShiftCount|Acc|FloatAcc)
|
At the moment we can only tell a memory reference size by the
|
||||||
#define Abs (Abs8|Abs16|Abs32)
|
instruction suffix, so there's not much point in defining Mem8,
|
||||||
|
Mem16, Mem32 and Mem64 opcode modifiers - We might as well just use
|
||||||
#define Byte (Reg8|Imm8|Imm8S)
|
the suffix directly to check memory operands. */
|
||||||
#define Word (Reg16|Imm16)
|
#define LLongMem AnyMem /* 64 bits (or more) */
|
||||||
#define DWord (Reg32|Imm32)
|
#define LongMem AnyMem /* 32 bit memory ref */
|
||||||
|
#define ShortMem AnyMem /* 16 bit memory ref */
|
||||||
|
#define WordMem AnyMem /* 16 or 32 bit memory ref */
|
||||||
|
#define ByteMem AnyMem /* 8 bit memory ref */
|
||||||
|
|
||||||
#define SMALLEST_DISP_TYPE(num) \
|
#define SMALLEST_DISP_TYPE(num) \
|
||||||
fits_in_signed_byte(num) ? (Disp8|Disp32|Abs8|Abs32) : (Disp32|Abs32)
|
(fits_in_signed_byte(num) ? (Disp8|Disp32) : Disp32)
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -282,7 +281,8 @@ typedef struct
|
|||||||
/* how many operands */
|
/* how many operands */
|
||||||
unsigned int operands;
|
unsigned int operands;
|
||||||
|
|
||||||
/* base_opcode is the fundamental opcode byte with a optional prefix(es). */
|
/* base_opcode is the fundamental opcode byte without optional
|
||||||
|
prefix(es). */
|
||||||
unsigned int base_opcode;
|
unsigned int base_opcode;
|
||||||
|
|
||||||
/* extension_opcode is the 3 bit extension for group <n> insns.
|
/* extension_opcode is the 3 bit extension for group <n> insns.
|
||||||
@ -297,33 +297,32 @@ typedef struct
|
|||||||
|
|
||||||
/* opcode_modifier bits: */
|
/* opcode_modifier bits: */
|
||||||
#define W 0x1 /* set if operands can be words or dwords
|
#define W 0x1 /* set if operands can be words or dwords
|
||||||
encoded the canonical way: MUST BE 0x1 */
|
encoded the canonical way */
|
||||||
#define D 0x2 /* D = 0 if Reg --> Regmem;
|
#define D 0x2 /* D = 0 if Reg --> Regmem;
|
||||||
D = 1 if Regmem --> Reg: MUST BE 0x2 */
|
D = 1 if Regmem --> Reg: MUST BE 0x2 */
|
||||||
#define Modrm 0x4
|
#define Modrm 0x4
|
||||||
#define ReverseRegRegmem 0x8
|
#define ReverseRegRegmem 0x8 /* swap reg,regmem fields for 2 reg case */
|
||||||
|
#define FloatR 0x8 /* src/dest swap for floats: MUST BE 0x8 */
|
||||||
#define ShortForm 0x10 /* register is in low 3 bits of opcode */
|
#define ShortForm 0x10 /* register is in low 3 bits of opcode */
|
||||||
#define ShortFormW 0x20 /* ShortForm and W bit is 0x8 */
|
#define FloatMF 0x20 /* FP insn memory format bit, sized by 0x4 */
|
||||||
#define Seg2ShortForm 0x40 /* encoding of load segment reg insns */
|
#define Jump 0x40 /* special case for jump insns. */
|
||||||
#define Seg3ShortForm 0x80 /* fs/gs segment register insns. */
|
#define JumpDword 0x80 /* call and jump */
|
||||||
#define Jump 0x100 /* special case for jump insns. */
|
#define JumpByte 0x100 /* loop and jecxz */
|
||||||
#define JumpInterSegment 0x200 /* special case for intersegment leaps/calls */
|
#define JumpInterSegment 0x200 /* special case for intersegment leaps/calls */
|
||||||
#define FloatD 0x400 /* direction for float insns: MUST BE 0x400 */
|
#define FloatD 0x400 /* direction for float insns: MUST BE 0x400 */
|
||||||
#define JumpByte 0x800
|
#define Seg2ShortForm 0x800 /* encoding of load segment reg insns */
|
||||||
#define JumpDword 0x1000
|
#define Seg3ShortForm 0x1000 /* fs/gs segment register insns. */
|
||||||
#define FWait 0x2000 /* instruction needs FWAIT */
|
#define Data16 0x2000 /* needs data prefix if in 32-bit mode */
|
||||||
#define Data16 0x4000 /* needs data prefix if in 32-bit mode */
|
#define Data32 0x4000 /* needs data prefix if in 16-bit mode */
|
||||||
#define Data32 0x8000 /* needs data prefix if in 16-bit mode */
|
#define IgnoreDataSize 0x8000 /* instruction ignores operand size prefix */
|
||||||
#define IsString 0x100000 /* quick test for string instructions */
|
#define No_bSuf 0x10000 /* b suffix on instruction illegal */
|
||||||
#define regKludge 0x200000 /* fake an extra reg operand for clr, imul */
|
#define No_wSuf 0x20000 /* w suffix on instruction illegal */
|
||||||
|
#define No_lSuf 0x40000 /* l suffix on instruction illegal */
|
||||||
#define DW (D|W) /* shorthand */
|
#define No_sSuf 0x80000 /* s suffix on instruction illegal */
|
||||||
|
#define FWait 0x100000 /* instruction needs FWAIT */
|
||||||
/* (opcode_modifier & COMES_IN_BOTH_DIRECTIONS) indicates that the
|
#define IsString 0x200000 /* quick test for string instructions */
|
||||||
source and destination operands can be reversed by setting either
|
#define regKludge 0x400000 /* fake an extra reg operand for clr, imul */
|
||||||
the D (for integer insns) or the FloatD (for floating insns) bit
|
#define Ugh 0x80000000 /* deprecated fp insn, gets a warning */
|
||||||
in base_opcode. */
|
|
||||||
#define COMES_IN_BOTH_DIRECTIONS (D|FloatD)
|
|
||||||
|
|
||||||
/* operand_types[i] describes the type of operand i. This is made
|
/* operand_types[i] describes the type of operand i. This is made
|
||||||
by OR'ing together all of the possible type masks. (e.g.
|
by OR'ing together all of the possible type masks. (e.g.
|
||||||
|
Reference in New Issue
Block a user