(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:
Ken Raeburn
1995-04-11 01:31:08 +00:00
parent d8a1c247ae
commit 04ef74bb13

View File

@ -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)