mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-19 13:53:29 +08:00
Fix Bug savannah/1825:
* config/tc-m68hc11.h (md_relax_frag): Define to support relaxations that are not pc-relative. (m68hc11_relax_frag): Declare. * config/tc-m68hc11.c (build_indexed_byte): Use a frag_var to handle the offsetable indexed addressing modes (n,r). (build_insn): Cleanup some locals. (m68hc11_relax_frag): New function imported from tc-cris.c to handle relaxation of difference between two symbols of same section. (md_convert_frag): For INDEXED_OFFSET relaxs, use the displacement only when this is a PC-relative operand and the offset is not absolute. (md_estimate_size_before_relax): Convert the INDEXED_OFFSET,UNDEF frag to INDEXED_OFFSET,STATE_BITS5 when the symbol is absolute; this will be handled by m68hc11_relax_frag.
This commit is contained in:
@ -1,3 +1,21 @@
|
|||||||
|
2002-12-01 Stephane Carrez <stcarrez@nerim.fr>
|
||||||
|
|
||||||
|
Fix Bug savannah/1825:
|
||||||
|
* config/tc-m68hc11.h (md_relax_frag): Define to support relaxations
|
||||||
|
that are not pc-relative.
|
||||||
|
(m68hc11_relax_frag): Declare.
|
||||||
|
|
||||||
|
* config/tc-m68hc11.c (build_indexed_byte): Use a frag_var to handle
|
||||||
|
the offsetable indexed addressing modes (n,r).
|
||||||
|
(build_insn): Cleanup some locals.
|
||||||
|
(m68hc11_relax_frag): New function imported from tc-cris.c to handle
|
||||||
|
relaxation of difference between two symbols of same section.
|
||||||
|
(md_convert_frag): For INDEXED_OFFSET relaxs, use the displacement
|
||||||
|
only when this is a PC-relative operand and the offset is not absolute.
|
||||||
|
(md_estimate_size_before_relax): Convert the INDEXED_OFFSET,UNDEF frag
|
||||||
|
to INDEXED_OFFSET,STATE_BITS5 when the symbol is absolute; this will
|
||||||
|
be handled by m68hc11_relax_frag.
|
||||||
|
|
||||||
2002-12-01 Stephane Carrez <stcarrez@nerim.fr>
|
2002-12-01 Stephane Carrez <stcarrez@nerim.fr>
|
||||||
|
|
||||||
* config/tc-m68hc11.c (elf_flags): Set default ABI to gcc default
|
* config/tc-m68hc11.c (elf_flags): Set default ABI to gcc default
|
||||||
|
@ -1933,14 +1933,21 @@ build_indexed_byte (op, format, move_insn)
|
|||||||
}
|
}
|
||||||
else if (op->reg1 != REG_PC)
|
else if (op->reg1 != REG_PC)
|
||||||
{
|
{
|
||||||
byte = (byte << 3) | 0xe2;
|
symbolS *sym;
|
||||||
|
offsetT off;
|
||||||
|
|
||||||
f = frag_more (1);
|
f = frag_more (1);
|
||||||
number_to_chars_bigendian (f, byte, 1);
|
number_to_chars_bigendian (f, byte, 1);
|
||||||
|
sym = op->exp.X_add_symbol;
|
||||||
f = frag_more (2);
|
off = op->exp.X_add_number;
|
||||||
fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
|
if (op->exp.X_op != O_symbol)
|
||||||
&op->exp, FALSE, BFD_RELOC_16);
|
{
|
||||||
number_to_chars_bigendian (f, 0, 2);
|
sym = make_expr_symbol (&op->exp);
|
||||||
|
off = 0;
|
||||||
|
}
|
||||||
|
frag_var (rs_machine_dependent, 2, 2,
|
||||||
|
ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_UNDF),
|
||||||
|
sym, off, f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2060,17 +2067,12 @@ build_insn (opcode, operands, nb_operands)
|
|||||||
char *f;
|
char *f;
|
||||||
long format;
|
long format;
|
||||||
int move_insn = 0;
|
int move_insn = 0;
|
||||||
fragS *frag;
|
|
||||||
int where;
|
|
||||||
|
|
||||||
/* Put the page code instruction if there is one. */
|
/* Put the page code instruction if there is one. */
|
||||||
format = opcode->format;
|
format = opcode->format;
|
||||||
|
|
||||||
frag = frag_now;
|
|
||||||
where = frag_now_fix ();
|
|
||||||
|
|
||||||
if (format & M6811_OP_BRANCH)
|
if (format & M6811_OP_BRANCH)
|
||||||
fix_new (frag, where, 1,
|
fix_new (frag_now, frag_now_fix (), 1,
|
||||||
&abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);
|
&abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);
|
||||||
|
|
||||||
if (format & OP_EXTENDED)
|
if (format & OP_EXTENDED)
|
||||||
@ -2732,6 +2734,97 @@ tc_gen_reloc (section, fixp)
|
|||||||
return reloc;
|
return reloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We need a port-specific relaxation function to cope with sym2 - sym1
|
||||||
|
relative expressions with both symbols in the same segment (but not
|
||||||
|
necessarily in the same frag as this insn), for example:
|
||||||
|
ldab sym2-(sym1-2),pc
|
||||||
|
sym1:
|
||||||
|
The offset can be 5, 9 or 16 bits long. */
|
||||||
|
|
||||||
|
long
|
||||||
|
m68hc11_relax_frag (seg, fragP, stretch)
|
||||||
|
segT seg ATTRIBUTE_UNUSED;
|
||||||
|
fragS *fragP;
|
||||||
|
long stretch ATTRIBUTE_UNUSED;
|
||||||
|
{
|
||||||
|
long growth;
|
||||||
|
offsetT aim = 0;
|
||||||
|
symbolS *symbolP;
|
||||||
|
const relax_typeS *this_type;
|
||||||
|
const relax_typeS *start_type;
|
||||||
|
relax_substateT next_state;
|
||||||
|
relax_substateT this_state;
|
||||||
|
const relax_typeS *table = TC_GENERIC_RELAX_TABLE;
|
||||||
|
|
||||||
|
/* We only have to cope with frags as prepared by
|
||||||
|
md_estimate_size_before_relax. The STATE_BITS16 case may geet here
|
||||||
|
because of the different reasons that it's not relaxable. */
|
||||||
|
switch (fragP->fr_subtype)
|
||||||
|
{
|
||||||
|
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16):
|
||||||
|
/* When we get to this state, the frag won't grow any more. */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5):
|
||||||
|
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9):
|
||||||
|
if (fragP->fr_symbol == NULL
|
||||||
|
|| S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
|
||||||
|
as_fatal (_("internal inconsistency problem in %s: fr_symbol %lx"),
|
||||||
|
__FUNCTION__, (long) fragP->fr_symbol);
|
||||||
|
symbolP = fragP->fr_symbol;
|
||||||
|
if (symbol_resolved_p (symbolP))
|
||||||
|
as_fatal (_("internal inconsistency problem in %s: resolved symbol"),
|
||||||
|
__FUNCTION__);
|
||||||
|
aim = S_GET_VALUE (symbolP);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
as_fatal (_("internal inconsistency problem in %s: fr_subtype %d"),
|
||||||
|
__FUNCTION__, fragP->fr_subtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The rest is stolen from relax_frag. There's no obvious way to
|
||||||
|
share the code, but fortunately no requirement to keep in sync as
|
||||||
|
long as fragP->fr_symbol does not have its segment changed. */
|
||||||
|
|
||||||
|
this_state = fragP->fr_subtype;
|
||||||
|
start_type = this_type = table + this_state;
|
||||||
|
|
||||||
|
if (aim < 0)
|
||||||
|
{
|
||||||
|
/* Look backwards. */
|
||||||
|
for (next_state = this_type->rlx_more; next_state;)
|
||||||
|
if (aim >= this_type->rlx_backward)
|
||||||
|
next_state = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Grow to next state. */
|
||||||
|
this_state = next_state;
|
||||||
|
this_type = table + this_state;
|
||||||
|
next_state = this_type->rlx_more;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Look forwards. */
|
||||||
|
for (next_state = this_type->rlx_more; next_state;)
|
||||||
|
if (aim <= this_type->rlx_forward)
|
||||||
|
next_state = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Grow to next state. */
|
||||||
|
this_state = next_state;
|
||||||
|
this_type = table + this_state;
|
||||||
|
next_state = this_type->rlx_more;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
growth = this_type->rlx_length - start_type->rlx_length;
|
||||||
|
if (growth != 0)
|
||||||
|
fragP->fr_subtype = this_state;
|
||||||
|
return growth;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
md_convert_frag (abfd, sec, fragP)
|
md_convert_frag (abfd, sec, fragP)
|
||||||
bfd *abfd ATTRIBUTE_UNUSED;
|
bfd *abfd ATTRIBUTE_UNUSED;
|
||||||
@ -2799,25 +2892,32 @@ md_convert_frag (abfd, sec, fragP)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5):
|
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5):
|
||||||
|
if (fragP->fr_opcode[0] == 3
|
||||||
|
&& fragP->fr_symbol != 0
|
||||||
|
&& S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
|
||||||
|
value = disp;
|
||||||
fragP->fr_opcode[0] = fragP->fr_opcode[0] << 6;
|
fragP->fr_opcode[0] = fragP->fr_opcode[0] << 6;
|
||||||
if ((fragP->fr_opcode[0] & 0x0ff) == 0x0c0)
|
fragP->fr_opcode[0] |= value & 0x1f;
|
||||||
fragP->fr_opcode[0] |= disp & 0x1f;
|
|
||||||
else
|
|
||||||
fragP->fr_opcode[0] |= value & 0x1f;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9):
|
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9):
|
||||||
|
if (fragP->fr_opcode[0] == 3
|
||||||
|
&& fragP->fr_symbol != 0
|
||||||
|
&& S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
|
||||||
|
value = disp;
|
||||||
fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3);
|
fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3);
|
||||||
fragP->fr_opcode[0] |= 0xE0;
|
fragP->fr_opcode[0] |= 0xE0;
|
||||||
fix_new (fragP, fragP->fr_fix, 1,
|
fragP->fr_opcode[0] |= (value >> 8) & 1;
|
||||||
fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_8);
|
fragP->fr_opcode[1] = value;
|
||||||
fragP->fr_fix += 1;
|
fragP->fr_fix += 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16):
|
case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16):
|
||||||
fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3);
|
fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3);
|
||||||
fragP->fr_opcode[0] |= 0xe2;
|
fragP->fr_opcode[0] |= 0xe2;
|
||||||
if ((fragP->fr_opcode[0] & 0x0ff) == 0x0fa)
|
if ((fragP->fr_opcode[0] & 0x0ff) == 0x0fa
|
||||||
|
&& fragP->fr_symbol != 0
|
||||||
|
&& S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
|
||||||
{
|
{
|
||||||
fixp = fix_new (fragP, fragP->fr_fix, 2,
|
fixp = fix_new (fragP, fragP->fr_fix, 2,
|
||||||
fragP->fr_symbol, fragP->fr_offset,
|
fragP->fr_symbol, fragP->fr_offset,
|
||||||
@ -2927,13 +3027,23 @@ md_estimate_size_before_relax (fragP, segment)
|
|||||||
case STATE_INDEXED_OFFSET:
|
case STATE_INDEXED_OFFSET:
|
||||||
assert (current_architecture & cpu6812);
|
assert (current_architecture & cpu6812);
|
||||||
|
|
||||||
/* Switch the indexed operation to 16-bit mode. */
|
if (fragP->fr_symbol
|
||||||
fragP->fr_opcode[0] = fragP->fr_opcode[0] << 3;
|
&& S_GET_SEGMENT (fragP->fr_symbol) == absolute_section)
|
||||||
fragP->fr_opcode[0] |= 0xe2;
|
{
|
||||||
fragP->fr_fix++;
|
fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_OFFSET,
|
||||||
fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
|
STATE_BITS5);
|
||||||
fragP->fr_offset, 0, BFD_RELOC_16);
|
/* Return the size of the variable part of the frag. */
|
||||||
fragP->fr_fix++;
|
return md_relax_table[fragP->fr_subtype].rlx_length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Switch the indexed operation to 16-bit mode. */
|
||||||
|
fragP->fr_opcode[0] = fragP->fr_opcode[0] << 3;
|
||||||
|
fragP->fr_opcode[0] |= 0xe2;
|
||||||
|
fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
|
||||||
|
fragP->fr_offset, 0, BFD_RELOC_16);
|
||||||
|
fragP->fr_fix += 2;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_XBCC_BRANCH:
|
case STATE_XBCC_BRANCH:
|
||||||
|
@ -93,6 +93,15 @@ extern int m68hc11_parse_long_option PARAMS ((char *));
|
|||||||
#define TC_GENERIC_RELAX_TABLE md_relax_table
|
#define TC_GENERIC_RELAX_TABLE md_relax_table
|
||||||
extern struct relax_type md_relax_table[];
|
extern struct relax_type md_relax_table[];
|
||||||
|
|
||||||
|
/* GAS only handles relaxations for pc-relative data targeting addresses
|
||||||
|
in the same segment, so we have to handle the rest on our own. */
|
||||||
|
#define md_relax_frag(SEG, FRAGP, STRETCH) \
|
||||||
|
((FRAGP)->fr_symbol != NULL \
|
||||||
|
&& S_GET_SEGMENT ((FRAGP)->fr_symbol) == (SEG) \
|
||||||
|
? relax_frag (SEG, FRAGP, STRETCH) \
|
||||||
|
: m68hc11_relax_frag (SEG, FRAGP, STRETCH))
|
||||||
|
extern long m68hc11_relax_frag PARAMS ((segT, fragS*, long));
|
||||||
|
|
||||||
#define TC_HANDLES_FX_DONE
|
#define TC_HANDLES_FX_DONE
|
||||||
|
|
||||||
#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */
|
#define DIFF_EXPR_OK /* .-foo gets turned into PC relative relocs */
|
||||||
|
Reference in New Issue
Block a user