mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-09-10 23:57:03 +08:00
(PCINDEX): New macro.
(md_relax_table): No longer const. Add PCINDEX entries. (m68k_ip): For AINDX with simple symbol operand, generate a PCINDEX frag if PC is used, or do normal non-AINDX processing for address register. (m68k_init_after_args): If cpu is 68000 or 68010, fix md_relax_table to prevent relaxation of PCINDEX/BYTE mode to SHORT, since they don't support that mode. (md_convert_frag_1, case PCLEA/LONG): Add 4 to offset, not 2. Add support for new PCINDEX modes. (md_estimate_size_before_relax): Process PCINDEX/SZ_UNDEF mode. (md_convert_frag_1, case PCLEA/SHORT): Add 2 to offset. (m68k_ip, case most punctuation/AOFF): If using PC, call add_frag using PCLEA.
This commit is contained in:
@ -90,12 +90,27 @@ static struct obstack robyn;
|
|||||||
#define LONG 2
|
#define LONG 2
|
||||||
#define SZ_UNDEF 3
|
#define SZ_UNDEF 3
|
||||||
#undef BRANCH
|
#undef BRANCH
|
||||||
|
/* Case `g' except when BCC68000 is applicable. */
|
||||||
#define ABRANCH 1
|
#define ABRANCH 1
|
||||||
|
/* Coprocessor branches. */
|
||||||
#define FBRANCH 2
|
#define FBRANCH 2
|
||||||
|
/* Mode 7.2 -- program counter indirect with (16-bit) displacement,
|
||||||
|
supported on all cpus. Widens to 32-bit absolute. */
|
||||||
#define PCREL 3
|
#define PCREL 3
|
||||||
|
/* For inserting an extra jmp instruction with long offset on 68000,
|
||||||
|
for expanding conditional branches. (Not bsr or bra.) Since the
|
||||||
|
68000 doesn't support 32-bit displacements for conditional
|
||||||
|
branches, we fake it by reversing the condition and branching
|
||||||
|
around a jmp with an absolute long operand. */
|
||||||
#define BCC68000 4
|
#define BCC68000 4
|
||||||
|
/* For the DBcc "instructions". If the displacement requires 32 bits,
|
||||||
|
the branch-around-a-jump game is played here too. */
|
||||||
#define DBCC 5
|
#define DBCC 5
|
||||||
|
/* Not currently used? */
|
||||||
#define PCLEA 6
|
#define PCLEA 6
|
||||||
|
/* Mode AINDX (apc-relative) using PC, with variable target, might fit
|
||||||
|
in 16 or 8 bits. */
|
||||||
|
#define PCINDEX 7
|
||||||
|
|
||||||
struct m68k_incant
|
struct m68k_incant
|
||||||
{
|
{
|
||||||
@ -522,7 +537,7 @@ static const int n_archs = sizeof (archs) / sizeof (archs[0]);
|
|||||||
How many bytes this mode will add to the size of the frag
|
How many bytes this mode will add to the size of the frag
|
||||||
Which mode to go to if the offset won't fit in this one
|
Which mode to go to if the offset won't fit in this one
|
||||||
*/
|
*/
|
||||||
CONST relax_typeS md_relax_table[] =
|
relax_typeS md_relax_table[] =
|
||||||
{
|
{
|
||||||
{1, 1, 0, 0}, /* First entries aren't used */
|
{1, 1, 0, 0}, /* First entries aren't used */
|
||||||
{1, 1, 0, 0}, /* For no good reason except */
|
{1, 1, 0, 0}, /* For no good reason except */
|
||||||
@ -559,6 +574,11 @@ CONST relax_typeS md_relax_table[] =
|
|||||||
{0, 0, 6, 0},
|
{0, 0, 6, 0},
|
||||||
{1, 1, 0, 0},
|
{1, 1, 0, 0},
|
||||||
|
|
||||||
|
/* For, e.g., jmp pcrel indexed. */
|
||||||
|
{125, -130, 0, TAB (PCINDEX, SHORT)},
|
||||||
|
{32765, -32770, 2, TAB (PCINDEX, LONG)},
|
||||||
|
{0, 0, 4, 0},
|
||||||
|
{1, 1, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
/* These are the machine dependent pseudo-ops. These are included so
|
/* These are the machine dependent pseudo-ops. These are included so
|
||||||
@ -2309,10 +2329,16 @@ m68k_ip (instring)
|
|||||||
{
|
{
|
||||||
if (opP->reg == PC)
|
if (opP->reg == PC)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
addword (0x0170);
|
addword (0x0170);
|
||||||
opP->con1->e_exp.X_add_number += 6;
|
opP->con1->e_exp.X_add_number += 6;
|
||||||
add_fix ('l', opP->con1, 1);
|
add_fix ('l', opP->con1, 1);
|
||||||
addword (0), addword (0);
|
addword (0), addword (0);
|
||||||
|
#else
|
||||||
|
add_frag (adds (opP->con1),
|
||||||
|
offs (opP->con1),
|
||||||
|
TAB (PCLEA, SZ_UNDEF));
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2400,29 +2426,58 @@ m68k_ip (instring)
|
|||||||
/* IF its simple,
|
/* IF its simple,
|
||||||
GET US OUT OF HERE! */
|
GET US OUT OF HERE! */
|
||||||
|
|
||||||
/* Must be INDEX, with an index
|
/* Must be INDEX, with an index register. Address
|
||||||
register. Address register
|
register cannot be ZERO-PC, and either :b was
|
||||||
cannot be ZERO-PC, and either
|
forced, or we know it will fit. For a 68000 or
|
||||||
:b was forced, or we know
|
68010, force this mode anyways, because the
|
||||||
it will fit */
|
larger modes aren't supported. */
|
||||||
if (opP->mode == AINDX
|
if (opP->mode == AINDX
|
||||||
&& opP->reg != FAIL
|
&& opP->reg != FAIL
|
||||||
&& opP->reg != ZPC
|
&& opP->reg != ZPC
|
||||||
&& (siz1 == 1
|
&& (/* :b specified */
|
||||||
|
siz1 == 1
|
||||||
|
/* known to fit in 8 bits */
|
||||||
|
|| (issbyte (baseo) && !isvar (opP->con1))
|
||||||
|
/* doesn't support wider modes */
|
||||||
|| cpu_of_arch (current_architecture) < m68020
|
|| cpu_of_arch (current_architecture) < m68020
|
||||||
|| (issbyte (baseo)
|
/* simple enough to do relaxation */
|
||||||
&& !isvar (opP->con1))))
|
|| op (opP->con1) == O_symbol
|
||||||
|
))
|
||||||
|
{
|
||||||
|
if (isvar (opP->con1))
|
||||||
|
{
|
||||||
|
if (op (opP->con1) != O_symbol)
|
||||||
|
{
|
||||||
|
/* Can't handle more complex expressions
|
||||||
|
here yet. Should only wind up here
|
||||||
|
if the CPU doesn't support wider
|
||||||
|
modes or byte mode was explcitly
|
||||||
|
specified, so do a byte relocation
|
||||||
|
and let the fixup processing later
|
||||||
|
complain if it won't reach. */
|
||||||
|
nextword += baseo & 0xff;
|
||||||
|
addword (nextword);
|
||||||
|
add_fix ('B', opP->con1, 0);
|
||||||
|
}
|
||||||
|
else if (opP->reg != PC)
|
||||||
|
{
|
||||||
|
goto no_pc_relax;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
nextword += baseo & 0xff;
|
nextword += baseo & 0xff;
|
||||||
addword (nextword);
|
addword (nextword);
|
||||||
if (isvar (opP->con1))
|
add_frag (adds (opP->con1), offs (opP->con1),
|
||||||
add_fix ('B', opP->con1, 0);
|
TAB (PCINDEX, SZ_UNDEF));
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nextword |= 0x40; /* No index reg */
|
nextword |= 0x40; /* No index reg */
|
||||||
|
|
||||||
|
no_pc_relax:
|
||||||
/* It isn't simple. */
|
/* It isn't simple. */
|
||||||
nextword |= 0x100;
|
nextword |= 0x100;
|
||||||
/* If the guy specified a width, we assume that it is
|
/* If the guy specified a width, we assume that it is
|
||||||
@ -2549,7 +2604,8 @@ m68k_ip (instring)
|
|||||||
TAB (PCREL, SZ_UNDEF));
|
TAB (PCREL, SZ_UNDEF));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: /* Fall through into long */
|
/* Fall through into long */
|
||||||
|
case 3:
|
||||||
if (isvar (opP->con1))
|
if (isvar (opP->con1))
|
||||||
add_fix ('l', opP->con1, 0);
|
add_fix ('l', opP->con1, 0);
|
||||||
|
|
||||||
@ -3228,6 +3284,16 @@ reverse_8_bits (in)
|
|||||||
return out;
|
return out;
|
||||||
} /* reverse_8_bits() */
|
} /* reverse_8_bits() */
|
||||||
|
|
||||||
|
/* Cause an extra frag to be generated here, inserting up to 10 bytes
|
||||||
|
(that value is chosen in the frag_var call in md_assemble). TYPE
|
||||||
|
is the subtype of the frag to be generated; its primary type is
|
||||||
|
rs_machine_dependent.
|
||||||
|
|
||||||
|
The TYPE parameter is also used by md_convert_frag_1 and
|
||||||
|
md_estimate_size_before_relax. The appropriate type of fixup will
|
||||||
|
be emitted by md_convert_frag_1.
|
||||||
|
|
||||||
|
ADD becomes the FR_SYMBOL field of the frag, and OFF the FR_OFFSET. */
|
||||||
static void
|
static void
|
||||||
install_operand (mode, val)
|
install_operand (mode, val)
|
||||||
int mode;
|
int mode;
|
||||||
@ -3929,6 +3995,9 @@ m68k_init_after_args ()
|
|||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpu_of_arch (current_architecture) < m68020)
|
||||||
|
md_relax_table[TAB (PCINDEX, BYTE)].rlx_more = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Equal to MAX_PRECISION in atof-ieee.c */
|
/* Equal to MAX_PRECISION in atof-ieee.c */
|
||||||
@ -4137,6 +4206,7 @@ md_convert_frag_1 (fragP)
|
|||||||
if (cpu_of_arch (current_architecture) < m68020)
|
if (cpu_of_arch (current_architecture) < m68020)
|
||||||
{
|
{
|
||||||
if (fragP->fr_opcode[0] == 0x61)
|
if (fragP->fr_opcode[0] == 0x61)
|
||||||
|
/* BSR */
|
||||||
{
|
{
|
||||||
fragP->fr_opcode[0] = 0x4E;
|
fragP->fr_opcode[0] = 0x4E;
|
||||||
fragP->fr_opcode[1] = (char) 0xB9; /* JBSR with ABSL LONG offset */
|
fragP->fr_opcode[1] = (char) 0xB9; /* JBSR with ABSL LONG offset */
|
||||||
@ -4153,6 +4223,7 @@ md_convert_frag_1 (fragP)
|
|||||||
fragP->fr_fix += 4;
|
fragP->fr_fix += 4;
|
||||||
ext = 0;
|
ext = 0;
|
||||||
}
|
}
|
||||||
|
/* BRA */
|
||||||
else if (fragP->fr_opcode[0] == 0x60)
|
else if (fragP->fr_opcode[0] == 0x60)
|
||||||
{
|
{
|
||||||
fragP->fr_opcode[0] = 0x4E;
|
fragP->fr_opcode[0] = 0x4E;
|
||||||
@ -4242,18 +4313,53 @@ md_convert_frag_1 (fragP)
|
|||||||
fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
|
fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
|
||||||
fragP->fr_offset, 1, NO_RELOC);
|
fragP->fr_offset, 1, NO_RELOC);
|
||||||
fragP->fr_opcode[1] &= ~0x3F;
|
fragP->fr_opcode[1] &= ~0x3F;
|
||||||
fragP->fr_opcode[1] |= 0x3A;
|
fragP->fr_opcode[1] |= 0x3A; /* 072 - mode 7.2 */
|
||||||
ext = 2;
|
ext = 2;
|
||||||
break;
|
break;
|
||||||
case TAB (PCLEA, LONG):
|
case TAB (PCLEA, LONG):
|
||||||
subseg_change (text_section, 0);
|
subseg_change (text_section, 0);
|
||||||
fix_new (fragP, (int) (fragP->fr_fix) + 2, 4, fragP->fr_symbol,
|
fix_new (fragP, (int) (fragP->fr_fix) + 2, 4, fragP->fr_symbol,
|
||||||
fragP->fr_offset + 2, 1, NO_RELOC);
|
fragP->fr_offset + 4, 1, NO_RELOC);
|
||||||
|
/* Already set to mode 7.3; this indicates: PC indirect with
|
||||||
|
suppressed index, 32-bit displacement. */
|
||||||
*buffer_address++ = 0x01;
|
*buffer_address++ = 0x01;
|
||||||
*buffer_address++ = 0x70;
|
*buffer_address++ = 0x70;
|
||||||
fragP->fr_fix += 2;
|
fragP->fr_fix += 2;
|
||||||
ext = 4;
|
ext = 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TAB (PCINDEX, BYTE):
|
||||||
|
disp += 2;
|
||||||
|
if (!issbyte (disp))
|
||||||
|
{
|
||||||
|
as_bad ("displacement doesn't fit in one byte");
|
||||||
|
disp = 0;
|
||||||
|
}
|
||||||
|
fragP->fr_opcode[2] &= ~1;
|
||||||
|
fragP->fr_opcode[3] = disp;
|
||||||
|
ext = 0;
|
||||||
|
break;
|
||||||
|
case TAB (PCINDEX, SHORT):
|
||||||
|
subseg_change (text_section, 0);
|
||||||
|
disp += 2;
|
||||||
|
assert (issword (disp));
|
||||||
|
fragP->fr_opcode[2] |= 0x1;
|
||||||
|
fragP->fr_opcode[3] = 0x20;
|
||||||
|
fix_new (fragP, (int) (fragP->fr_fix), 2, fragP->fr_symbol,
|
||||||
|
fragP->fr_offset + 4, (fragP->fr_opcode[1] & 077) == 073,
|
||||||
|
NO_RELOC);
|
||||||
|
ext = 2;
|
||||||
|
break;
|
||||||
|
case TAB (PCINDEX, LONG):
|
||||||
|
subseg_change (text_section, 0);
|
||||||
|
disp += 2;
|
||||||
|
fix_new (fragP, (int) (fragP->fr_fix), 4, fragP->fr_symbol,
|
||||||
|
fragP->fr_offset + 6, (fragP->fr_opcode[1] & 077) == 073,
|
||||||
|
NO_RELOC);
|
||||||
|
fragP->fr_opcode[2] |= 0x1;
|
||||||
|
fragP->fr_opcode[3] = 0x30;
|
||||||
|
ext = 4;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ext)
|
if (ext)
|
||||||
@ -4484,10 +4590,22 @@ md_estimate_size_before_relax (fragP, segment)
|
|||||||
break;
|
break;
|
||||||
} /* TAB(PCLEA,SZ_UNDEF) */
|
} /* TAB(PCLEA,SZ_UNDEF) */
|
||||||
|
|
||||||
default:
|
case TAB (PCINDEX, SZ_UNDEF):
|
||||||
|
if (S_GET_SEGMENT (fragP->fr_symbol) == segment
|
||||||
|
|| cpu_of_arch (current_architecture) < m68020)
|
||||||
|
{
|
||||||
|
fragP->fr_subtype = TAB (PCINDEX, BYTE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fragP->fr_subtype = TAB (PCINDEX, LONG);
|
||||||
|
fragP->fr_var += 6;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
} /* switch on subtype looking for SZ_UNDEF's. */
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* now that SZ_UNDEF are taken care of, check others */
|
/* now that SZ_UNDEF are taken care of, check others */
|
||||||
switch (fragP->fr_subtype)
|
switch (fragP->fr_subtype)
|
||||||
|
Reference in New Issue
Block a user