bfd/ChangeLog
* elf32-avr.c: Add DIFF relocations for AVR. (avr_final_link_relocate): Handle the DIFF relocs. (bfd_elf_avr_diff_reloc): New. (elf32_avr_is_diff_reloc): New. (elf32_avr_adjust_diff_reloc_value): Reduce difference value. (elf32_avr_relax_delete_bytes): Recompute difference after deleting bytes. * reloc.c: Add BFD_RELOC_AVR_DIFF8/16/32 relocations gas/ChangeLog * config/tc-avr.c: Add new flag mlink-relax. (md_show_usage): Add flag and help text. (md_parse_option): Record whether link relax is turned on. (relaxable_section): New. (avr_validate_fix_sub): New. (avr_force_relocation): New. (md_apply_fix): Generate DIFF reloc. (avr_allow_local_subtract): New. * config/tc-avr.h (TC_LINKRELAX_FIXUP): Define to 0. (TC_FORCE_RELOCATION): Define. (TC_FORCE_RELOCATION_SUB_SAME): Define. (TC_VALIDATE_FIX_SUB): Define. (avr_force_relocation): Declare. (avr_validate_fix_sub): Declare. (md_allow_local_subtract): Define. (avr_allow_local_subtract): Declare. gas/testsuite/ChangeLog * gas/avr/diffreloc_withrelax.d: New testcase. * gas/avr/noreloc_withoutrelax.d: Likewise. * gas/avr/relax.s: Likewise. include/ChangeLog * elf/avr.h: Add new DIFF relocs. ld/testsuite/ChangeLog * ld-avr/norelax_diff.d: New testcase. * ld-avr/relax_diff.d: Likewise. * ld-avr/relax.s: Likewise.
This commit is contained in:
parent
9d497a19ea
commit
e4ef1b6c3f
@ -1,3 +1,15 @@
|
||||
2014-04-10 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
|
||||
|
||||
* elf32-avr.c: Add DIFF relocations for AVR.
|
||||
(avr_final_link_relocate): Handle the DIFF relocs.
|
||||
(bfd_elf_avr_diff_reloc): New.
|
||||
(elf32_avr_is_diff_reloc): New.
|
||||
(elf32_avr_adjust_diff_reloc_value): Reduce difference value.
|
||||
(elf32_avr_relax_delete_bytes): Recompute difference after deleting
|
||||
bytes.
|
||||
|
||||
* reloc.c: Add BFD_RELOC_AVR_DIFF8/16/32 relocations
|
||||
|
||||
2014-04-09 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* libcoff.h: Regenerate.
|
||||
|
182
bfd/elf32-avr.c
182
bfd/elf32-avr.c
@ -32,6 +32,15 @@ static bfd_boolean debug_relax = FALSE;
|
||||
/* Enable debugging printout at stdout with this variable. */
|
||||
static bfd_boolean debug_stubs = FALSE;
|
||||
|
||||
static bfd_reloc_status_type
|
||||
bfd_elf_avr_diff_reloc (bfd *abfd,
|
||||
arelent *reloc_entry,
|
||||
asymbol *symbol,
|
||||
void *data,
|
||||
asection *input_section,
|
||||
bfd *output_bfd,
|
||||
char **error_message);
|
||||
|
||||
/* Hash table initialization and handling. Code is taken from the hppa port
|
||||
and adapted to the needs of AVR. */
|
||||
|
||||
@ -557,6 +566,45 @@ static reloc_howto_type elf_avr_howto_table[] =
|
||||
0xffffff, /* src_mask */
|
||||
0xffffff, /* dst_mask */
|
||||
FALSE), /* pcrel_offset */
|
||||
HOWTO (R_AVR_DIFF8, /* type */
|
||||
0, /* rightshift */
|
||||
0, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
8, /* bitsize */
|
||||
FALSE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
bfd_elf_avr_diff_reloc, /* special_function */
|
||||
"R_AVR_DIFF8", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xff, /* dst_mask */
|
||||
FALSE), /* pcrel_offset */
|
||||
HOWTO (R_AVR_DIFF16, /* type */
|
||||
0, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
FALSE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
bfd_elf_avr_diff_reloc, /* special_function */
|
||||
"R_AVR_DIFF16", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
FALSE), /* pcrel_offset */
|
||||
HOWTO (R_AVR_DIFF32, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
32, /* bitsize */
|
||||
FALSE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
bfd_elf_avr_diff_reloc, /* special_function */
|
||||
"R_AVR_DIFF32", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffffffff, /* dst_mask */
|
||||
FALSE) /* pcrel_offset */
|
||||
};
|
||||
|
||||
/* Map BFD reloc types to AVR ELF reloc types. */
|
||||
@ -598,7 +646,10 @@ static const struct avr_reloc_map avr_reloc_map[] =
|
||||
{ BFD_RELOC_8, R_AVR_8 },
|
||||
{ BFD_RELOC_AVR_8_LO, R_AVR_8_LO8 },
|
||||
{ BFD_RELOC_AVR_8_HI, R_AVR_8_HI8 },
|
||||
{ BFD_RELOC_AVR_8_HLO, R_AVR_8_HLO8 }
|
||||
{ BFD_RELOC_AVR_8_HLO, R_AVR_8_HLO8 },
|
||||
{ BFD_RELOC_AVR_DIFF8, R_AVR_DIFF8 },
|
||||
{ BFD_RELOC_AVR_DIFF16, R_AVR_DIFF16 },
|
||||
{ BFD_RELOC_AVR_DIFF32, R_AVR_DIFF32 }
|
||||
};
|
||||
|
||||
/* Meant to be filled one day with the wrap around address for the
|
||||
@ -797,6 +848,22 @@ avr_get_stub_addr (bfd_vma srel,
|
||||
return 0x020000;
|
||||
}
|
||||
|
||||
/* Perform a diff relocation. Nothing to do, as the difference value is already
|
||||
written into the section's contents. */
|
||||
|
||||
static bfd_reloc_status_type
|
||||
bfd_elf_avr_diff_reloc (bfd *abfd ATTRIBUTE_UNUSED,
|
||||
arelent *reloc_entry ATTRIBUTE_UNUSED,
|
||||
asymbol *symbol ATTRIBUTE_UNUSED,
|
||||
void *data ATTRIBUTE_UNUSED,
|
||||
asection *input_section ATTRIBUTE_UNUSED,
|
||||
bfd *output_bfd ATTRIBUTE_UNUSED,
|
||||
char **error_message ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return bfd_reloc_ok;
|
||||
}
|
||||
|
||||
|
||||
/* Perform a single relocation. By default we use the standard BFD
|
||||
routines, but a few relocs, we have to do them ourselves. */
|
||||
|
||||
@ -1149,6 +1216,13 @@ avr_final_link_relocate (reloc_howto_type * howto,
|
||||
bfd_put_16 (input_bfd, (bfd_vma) srel &0x00ffff, contents);
|
||||
break;
|
||||
|
||||
case R_AVR_DIFF8:
|
||||
case R_AVR_DIFF16:
|
||||
case R_AVR_DIFF32:
|
||||
/* Nothing to do here, as contents already contains the diff value. */
|
||||
r = bfd_reloc_ok;
|
||||
break;
|
||||
|
||||
default:
|
||||
r = _bfd_final_link_relocate (howto, input_bfd, input_section,
|
||||
contents, rel->r_offset,
|
||||
@ -1457,6 +1531,104 @@ elf32_avr_object_p (bfd *abfd)
|
||||
e_set);
|
||||
}
|
||||
|
||||
/* Returns whether the relocation type passed is a diff reloc. */
|
||||
|
||||
static bfd_boolean
|
||||
elf32_avr_is_diff_reloc (Elf_Internal_Rela *irel)
|
||||
{
|
||||
return (ELF32_R_TYPE (irel->r_info) == R_AVR_DIFF8
|
||||
||ELF32_R_TYPE (irel->r_info) == R_AVR_DIFF16
|
||||
|| ELF32_R_TYPE (irel->r_info) == R_AVR_DIFF32);
|
||||
}
|
||||
|
||||
/* Reduce the diff value written in the section by count if the shrinked
|
||||
insn address happens to fall between the two symbols for which this
|
||||
diff reloc was emitted. */
|
||||
|
||||
static void
|
||||
elf32_avr_adjust_diff_reloc_value (bfd *abfd,
|
||||
struct bfd_section *isec,
|
||||
Elf_Internal_Rela *irel,
|
||||
bfd_vma symval,
|
||||
bfd_vma shrinked_insn_address,
|
||||
int count)
|
||||
{
|
||||
unsigned char *reloc_contents = NULL;
|
||||
unsigned char *isec_contents = elf_section_data (isec)->this_hdr.contents;
|
||||
if (isec_contents == NULL)
|
||||
{
|
||||
if (! bfd_malloc_and_get_section (abfd, isec, &isec_contents))
|
||||
return;
|
||||
|
||||
elf_section_data (isec)->this_hdr.contents = isec_contents;
|
||||
}
|
||||
|
||||
reloc_contents = isec_contents + irel->r_offset;
|
||||
|
||||
/* Read value written in object file. */
|
||||
bfd_vma x = 0;
|
||||
switch (ELF32_R_TYPE (irel->r_info))
|
||||
{
|
||||
case R_AVR_DIFF8:
|
||||
{
|
||||
x = *reloc_contents;
|
||||
break;
|
||||
}
|
||||
case R_AVR_DIFF16:
|
||||
{
|
||||
x = bfd_get_16 (abfd, reloc_contents);
|
||||
break;
|
||||
}
|
||||
case R_AVR_DIFF32:
|
||||
{
|
||||
x = bfd_get_32 (abfd, reloc_contents);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
BFD_FAIL();
|
||||
}
|
||||
}
|
||||
|
||||
/* For a diff reloc sym1 - sym2 the diff at assembly time (x) is written
|
||||
into the object file at the reloc offset. sym2's logical value is
|
||||
symval (<start_of_section>) + reloc addend. Compute the start and end
|
||||
addresses and check if the shrinked insn falls between sym1 and sym2. */
|
||||
|
||||
bfd_vma end_address = symval + irel->r_addend;
|
||||
bfd_vma start_address = end_address - x;
|
||||
|
||||
/* Reduce the diff value by count bytes and write it back into section
|
||||
contents. */
|
||||
|
||||
if (shrinked_insn_address >= start_address &&
|
||||
shrinked_insn_address <= end_address)
|
||||
{
|
||||
switch (ELF32_R_TYPE (irel->r_info))
|
||||
{
|
||||
case R_AVR_DIFF8:
|
||||
{
|
||||
*reloc_contents = (x - count);
|
||||
break;
|
||||
}
|
||||
case R_AVR_DIFF16:
|
||||
{
|
||||
bfd_put_16 (abfd, (x - count) & 0xFFFF, reloc_contents);
|
||||
break;
|
||||
}
|
||||
case R_AVR_DIFF32:
|
||||
{
|
||||
bfd_put_32 (abfd, (x - count) & 0xFFFFFFFF, reloc_contents);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
BFD_FAIL();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete some bytes from a section while changing the size of an instruction.
|
||||
The parameter "addr" denotes the section-relative offset pointing just
|
||||
@ -1595,6 +1767,14 @@ elf32_avr_relax_delete_bytes (bfd *abfd,
|
||||
if (symval <= shrinked_insn_address
|
||||
&& (symval + irel->r_addend) > shrinked_insn_address)
|
||||
{
|
||||
if (elf32_avr_is_diff_reloc (irel))
|
||||
{
|
||||
elf32_avr_adjust_diff_reloc_value (abfd, isec, irel,
|
||||
symval,
|
||||
shrinked_insn_address,
|
||||
count);
|
||||
}
|
||||
|
||||
irel->r_addend -= count;
|
||||
|
||||
if (debug_relax)
|
||||
|
14
bfd/reloc.c
14
bfd/reloc.c
@ -4780,7 +4780,19 @@ ENUM
|
||||
ENUMDOC
|
||||
This is a 8 bit reloc for the AVR that stores bits 16..23 of a symbol
|
||||
in .byte hlo8(symbol)
|
||||
|
||||
ENUM
|
||||
BFD_RELOC_AVR_DIFF8
|
||||
ENUMX
|
||||
BFD_RELOC_AVR_DIFF16
|
||||
ENUMX
|
||||
BFD_RELOC_AVR_DIFF32
|
||||
ENUMDOC
|
||||
AVR relocations to mark the difference of two local symbols.
|
||||
These are only needed to support linker relaxation and can be ignored
|
||||
when not relaxing. The field is set to the value of the difference
|
||||
assuming no relaxation. The relocation encodes the position of the
|
||||
second symbol so the linker can determine whether to adjust the field
|
||||
value.
|
||||
ENUM
|
||||
BFD_RELOC_RL78_NEG8
|
||||
ENUMX
|
||||
|
@ -1,3 +1,23 @@
|
||||
2014-04-10 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
|
||||
|
||||
* config/tc-avr.c: Add new flag mlink-relax.
|
||||
(md_show_usage): Add flag and help text.
|
||||
(md_parse_option): Record whether link relax is turned on.
|
||||
(relaxable_section): New.
|
||||
(avr_validate_fix_sub): New.
|
||||
(avr_force_relocation): New.
|
||||
(md_apply_fix): Generate DIFF reloc.
|
||||
(avr_allow_local_subtract): New.
|
||||
|
||||
* config/tc-avr.h (TC_LINKRELAX_FIXUP): Define to 0.
|
||||
(TC_FORCE_RELOCATION): Define.
|
||||
(TC_FORCE_RELOCATION_SUB_SAME): Define.
|
||||
(TC_VALIDATE_FIX_SUB): Define.
|
||||
(avr_force_relocation): Declare.
|
||||
(avr_validate_fix_sub): Declare.
|
||||
(md_allow_local_subtract): Define.
|
||||
(avr_allow_local_subtract): Declare.
|
||||
|
||||
2014-04-10 Andrew Bennett <andrew.bennett@imgtec.com>
|
||||
|
||||
* config/tc-mips.c (mips_cpu_info_table): Add P5600
|
||||
|
@ -338,9 +338,11 @@ struct avr_opt_s
|
||||
int all_opcodes; /* -mall-opcodes: accept all known AVR opcodes. */
|
||||
int no_skip_bug; /* -mno-skip-bug: no warnings for skipping 2-word insns. */
|
||||
int no_wrap; /* -mno-wrap: reject rjmp/rcall with 8K wrap-around. */
|
||||
int link_relax; /* -mlink-relax: generate relocations for linker
|
||||
relaxation. */
|
||||
};
|
||||
|
||||
static struct avr_opt_s avr_opt = { 0, 0, 0 };
|
||||
static struct avr_opt_s avr_opt = { 0, 0, 0, 0 };
|
||||
|
||||
const char EXP_CHARS[] = "eE";
|
||||
const char FLT_CHARS[] = "dD";
|
||||
@ -401,7 +403,8 @@ enum options
|
||||
OPTION_ALL_OPCODES = OPTION_MD_BASE + 1,
|
||||
OPTION_NO_SKIP_BUG,
|
||||
OPTION_NO_WRAP,
|
||||
OPTION_ISA_RMW
|
||||
OPTION_ISA_RMW,
|
||||
OPTION_LINK_RELAX
|
||||
};
|
||||
|
||||
struct option md_longopts[] =
|
||||
@ -411,6 +414,7 @@ struct option md_longopts[] =
|
||||
{ "mno-skip-bug", no_argument, NULL, OPTION_NO_SKIP_BUG },
|
||||
{ "mno-wrap", no_argument, NULL, OPTION_NO_WRAP },
|
||||
{ "mrmw", no_argument, NULL, OPTION_ISA_RMW },
|
||||
{ "mlink-relax", no_argument, NULL, OPTION_LINK_RELAX },
|
||||
{ NULL, no_argument, NULL, 0 }
|
||||
};
|
||||
|
||||
@ -517,6 +521,7 @@ md_show_usage (FILE *stream)
|
||||
" -mno-wrap reject rjmp/rcall instructions with 8K wrap-around\n"
|
||||
" (default for avr3, avr5)\n"
|
||||
" -mrmw accept Read-Modify-Write instructions\n"
|
||||
" -mlink-relax generate relocations for linker relaxation\n"
|
||||
));
|
||||
show_mcu_list (stream);
|
||||
}
|
||||
@ -587,6 +592,9 @@ md_parse_option (int c, char *arg)
|
||||
case OPTION_ISA_RMW:
|
||||
specified_mcu.isa |= AVR_ISA_RMW;
|
||||
return 1;
|
||||
case OPTION_LINK_RELAX:
|
||||
avr_opt.link_relax = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -637,6 +645,7 @@ md_begin (void)
|
||||
}
|
||||
|
||||
bfd_set_arch_mach (stdoutput, TARGET_ARCH, avr_mcu->mach);
|
||||
linkrelax = avr_opt.link_relax;
|
||||
}
|
||||
|
||||
/* Resolve STR as a constant expression and return the result.
|
||||
@ -1200,6 +1209,53 @@ md_pcrel_from_section (fixS *fixp, segT sec)
|
||||
return fixp->fx_frag->fr_address + fixp->fx_where;
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
relaxable_section (asection *sec)
|
||||
{
|
||||
return (sec->flags & SEC_DEBUGGING) == 0;
|
||||
}
|
||||
|
||||
/* Does whatever the xtensa port does. */
|
||||
int
|
||||
avr_validate_fix_sub (fixS *fix)
|
||||
{
|
||||
segT add_symbol_segment, sub_symbol_segment;
|
||||
|
||||
/* The difference of two symbols should be resolved by the assembler when
|
||||
linkrelax is not set. If the linker may relax the section containing
|
||||
the symbols, then an Xtensa DIFF relocation must be generated so that
|
||||
the linker knows to adjust the difference value. */
|
||||
if (!linkrelax || fix->fx_addsy == NULL)
|
||||
return 0;
|
||||
|
||||
/* Make sure both symbols are in the same segment, and that segment is
|
||||
"normal" and relaxable. If the segment is not "normal", then the
|
||||
fix is not valid. If the segment is not "relaxable", then the fix
|
||||
should have been handled earlier. */
|
||||
add_symbol_segment = S_GET_SEGMENT (fix->fx_addsy);
|
||||
if (! SEG_NORMAL (add_symbol_segment) ||
|
||||
! relaxable_section (add_symbol_segment))
|
||||
return 0;
|
||||
|
||||
sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
|
||||
return (sub_symbol_segment == add_symbol_segment);
|
||||
}
|
||||
|
||||
/* TC_FORCE_RELOCATION hook */
|
||||
|
||||
/* If linkrelax is turned on, and the symbol to relocate
|
||||
against is in a relaxable segment, don't compute the value -
|
||||
generate a relocation instead. */
|
||||
int
|
||||
avr_force_relocation (fixS *fix)
|
||||
{
|
||||
if (linkrelax && fix->fx_addsy
|
||||
&& relaxable_section (S_GET_SEGMENT (fix->fx_addsy)))
|
||||
return 1;
|
||||
|
||||
return generic_force_reloc (fix);
|
||||
}
|
||||
|
||||
/* GAS will call this for each fixup. It should store the correct
|
||||
value in the object file. */
|
||||
|
||||
@ -1223,11 +1279,47 @@ md_apply_fix (fixS *fixP, valueT * valP, segT seg)
|
||||
fixP->fx_done = 1;
|
||||
}
|
||||
}
|
||||
else if (linkrelax && fixP->fx_subsy)
|
||||
{
|
||||
/* For a subtraction relocation expression, generate one
|
||||
of the DIFF relocs, with the value being the difference.
|
||||
Note that a sym1 - sym2 expression is adjusted into a
|
||||
section_start_sym + sym4_offset_from_section_start - sym1
|
||||
expression. fixP->fx_addsy holds the section start symbol,
|
||||
fixP->fx_offset holds sym2's offset, and fixP->fx_subsy
|
||||
holds sym1. Calculate the current difference and write value,
|
||||
but leave fx_offset as is - during relaxation,
|
||||
fx_offset - value gives sym1's value */
|
||||
|
||||
switch (fixP->fx_r_type)
|
||||
{
|
||||
case BFD_RELOC_8:
|
||||
fixP->fx_r_type = BFD_RELOC_AVR_DIFF8;
|
||||
break;
|
||||
case BFD_RELOC_16:
|
||||
fixP->fx_r_type = BFD_RELOC_AVR_DIFF16;
|
||||
break;
|
||||
case BFD_RELOC_32:
|
||||
fixP->fx_r_type = BFD_RELOC_AVR_DIFF32;
|
||||
break;
|
||||
default:
|
||||
as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
|
||||
break;
|
||||
}
|
||||
|
||||
value = S_GET_VALUE (fixP->fx_addsy) +
|
||||
fixP->fx_offset - S_GET_VALUE (fixP->fx_subsy);
|
||||
|
||||
fixP->fx_subsy = NULL;
|
||||
}
|
||||
/* We don't actually support subtracting a symbol. */
|
||||
if (fixP->fx_subsy != (symbolS *) NULL)
|
||||
as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
|
||||
|
||||
/* For the DIFF relocs, write the value into the object file while still
|
||||
keeping fx_done FALSE, as both the difference (recorded in the object file)
|
||||
and the sym offset (part of fixP) are needed at link relax time */
|
||||
where = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
|
||||
switch (fixP->fx_r_type)
|
||||
{
|
||||
default:
|
||||
@ -1237,6 +1329,16 @@ md_apply_fix (fixS *fixP, valueT * valP, segT seg)
|
||||
case BFD_RELOC_AVR_13_PCREL:
|
||||
case BFD_RELOC_32:
|
||||
case BFD_RELOC_16:
|
||||
break;
|
||||
case BFD_RELOC_AVR_DIFF8:
|
||||
*where = value;
|
||||
break;
|
||||
case BFD_RELOC_AVR_DIFF16:
|
||||
bfd_putl16 ((bfd_vma) value, where);
|
||||
break;
|
||||
case BFD_RELOC_AVR_DIFF32:
|
||||
bfd_putl32 ((bfd_vma) value, where);
|
||||
break;
|
||||
case BFD_RELOC_AVR_CALL:
|
||||
break;
|
||||
}
|
||||
@ -1654,3 +1756,25 @@ tc_cfi_frame_initial_instructions (void)
|
||||
do not line up the same way as for targers that use pre-decrement. */
|
||||
cfi_add_CFA_offset (DWARF2_DEFAULT_RETURN_COLUMN, 1-return_size);
|
||||
}
|
||||
|
||||
bfd_boolean
|
||||
avr_allow_local_subtract (expressionS * left,
|
||||
expressionS * right,
|
||||
segT section)
|
||||
{
|
||||
/* If we are not in relaxation mode, subtraction is OK. */
|
||||
if (!linkrelax)
|
||||
return TRUE;
|
||||
|
||||
/* If the symbols are not in a code section then they are OK. */
|
||||
if ((section->flags & SEC_CODE) == 0)
|
||||
return TRUE;
|
||||
|
||||
if (left->X_add_symbol == right->X_add_symbol)
|
||||
return TRUE;
|
||||
|
||||
/* We have to assume that there may be instructions between the
|
||||
two symbols and that relaxation may increase the distance between
|
||||
them. */
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -112,6 +112,18 @@ extern void avr_cons_fix_new (fragS *,int, int, expressionS *,
|
||||
visible symbols can be overridden. */
|
||||
#define EXTERN_FORCE_RELOC 0
|
||||
|
||||
/* If defined, this macro allows control over whether fixups for a
|
||||
given section will be processed when the linkrelax variable is
|
||||
set. Define it to zero and handle things in md_apply_fix instead.*/
|
||||
#define TC_LINKRELAX_FIXUP(SEG) 0
|
||||
|
||||
/* If this macro returns non-zero, it guarantees that a relocation will be emitted
|
||||
even when the value can be resolved locally. Do that if linkrelax is turned on */
|
||||
#define TC_FORCE_RELOCATION(fix) avr_force_relocation (fix)
|
||||
#define TC_FORCE_RELOCATION_SUB_SAME(fix, seg) \
|
||||
(! SEG_NORMAL (seg) || avr_force_relocation (fix))
|
||||
extern int avr_force_relocation (struct fix *);
|
||||
|
||||
/* Values passed to md_apply_fix don't include the symbol value. */
|
||||
#define MD_APPLY_SYM_VALUE(FIX) 0
|
||||
|
||||
@ -169,6 +181,12 @@ extern long md_pcrel_from_section (struct fix *, segT);
|
||||
goto SKIP; \
|
||||
}
|
||||
|
||||
/* This macro is evaluated for any fixup with a fx_subsy that
|
||||
fixup_segment cannot reduce to a number. If the macro returns
|
||||
false an error will be reported. */
|
||||
#define TC_VALIDATE_FIX_SUB(fix, seg) avr_validate_fix_sub (fix)
|
||||
extern int avr_validate_fix_sub (struct fix *);
|
||||
|
||||
/* This target is buggy, and sets fix size too large. */
|
||||
#define TC_FX_SIZE_SLACK(FIX) 2
|
||||
|
||||
@ -190,3 +208,8 @@ extern long md_pcrel_from_section (struct fix *, segT);
|
||||
/* Define a hook to setup initial CFI state. */
|
||||
extern void tc_cfi_frame_initial_instructions (void);
|
||||
#define tc_cfi_frame_initial_instructions tc_cfi_frame_initial_instructions
|
||||
|
||||
/* The difference between same-section symbols may be affected by linker
|
||||
relaxation, so do not resolve such expressions in the assembler. */
|
||||
#define md_allow_local_subtract(l,r,s) avr_allow_local_subtract (l, r, s)
|
||||
extern bfd_boolean avr_allow_local_subtract (expressionS *, expressionS *, segT);
|
||||
|
@ -1,3 +1,9 @@
|
||||
2014-04-10 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
|
||||
|
||||
* gas/avr/diffreloc_withrelax.d: New testcase.
|
||||
* gas/avr/noreloc_withoutrelax.d: Likewise.
|
||||
* gas/avr/relax.s: Likewise.
|
||||
|
||||
2014-04-04 Ilya Tocar <ilya.tocar@intel.com>
|
||||
|
||||
* gas/i386/i386.exp: Run SE1 tests.
|
||||
|
16
gas/testsuite/gas/avr/diffreloc_withrelax.d
Normal file
16
gas/testsuite/gas/avr/diffreloc_withrelax.d
Normal file
@ -0,0 +1,16 @@
|
||||
#name: AVR DIFF relocs with link relax
|
||||
#as: -mmcu=avrxmega2 -mlink-relax
|
||||
#source: relax.s
|
||||
#objdump: -r
|
||||
#target: avr-*-*
|
||||
|
||||
.*: file format elf32-avr
|
||||
|
||||
RELOCATION RECORDS FOR \[.text\]:
|
||||
OFFSET TYPE VALUE
|
||||
00000000 R_AVR_CALL .text
|
||||
|
||||
|
||||
RELOCATION RECORDS FOR \[.data\]:
|
||||
OFFSET TYPE VALUE
|
||||
00000000 R_AVR_DIFF16 .text\+0x00000004
|
11
gas/testsuite/gas/avr/noreloc_withoutrelax.d
Normal file
11
gas/testsuite/gas/avr/noreloc_withoutrelax.d
Normal file
@ -0,0 +1,11 @@
|
||||
#name: AVR no DIFF relocs without link relax
|
||||
#as: -mmcu=avrxmega2
|
||||
#objdump: -r
|
||||
#source: relax.s
|
||||
#target: avr-*-*
|
||||
|
||||
.*: file format elf32-avr
|
||||
|
||||
RELOCATION RECORDS FOR \[.text\]:
|
||||
OFFSET TYPE VALUE
|
||||
00000000 R_AVR_CALL .text
|
12
gas/testsuite/gas/avr/relax.s
Normal file
12
gas/testsuite/gas/avr/relax.s
Normal file
@ -0,0 +1,12 @@
|
||||
.file "diffreloc.s"
|
||||
.section .text,"ax",@progbits
|
||||
main:
|
||||
L1:
|
||||
jmp L1
|
||||
L2:
|
||||
.global x
|
||||
.section .data
|
||||
.type x, @object
|
||||
.size x, 2
|
||||
x:
|
||||
.word L2 - L1
|
@ -1,3 +1,7 @@
|
||||
2014-04-10 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
|
||||
|
||||
* elf/avr.h: Add new DIFF relocs.
|
||||
|
||||
2014-03-05 Alan Modra <amodra@gmail.com>
|
||||
|
||||
Update copyright years.
|
||||
|
@ -80,6 +80,9 @@ START_RELOC_NUMBERS (elf_avr_reloc_type)
|
||||
RELOC_NUMBER (R_AVR_8_LO8, 27)
|
||||
RELOC_NUMBER (R_AVR_8_HI8, 28)
|
||||
RELOC_NUMBER (R_AVR_8_HLO8, 29)
|
||||
RELOC_NUMBER (R_AVR_DIFF8, 30)
|
||||
RELOC_NUMBER (R_AVR_DIFF16, 31)
|
||||
RELOC_NUMBER (R_AVR_DIFF32, 32)
|
||||
END_RELOC_NUMBERS (R_AVR_max)
|
||||
|
||||
#endif /* _ELF_AVR_H */
|
||||
|
@ -1,3 +1,9 @@
|
||||
2014-04-10 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
|
||||
|
||||
* ld-avr/norelax_diff.d: New testcase.
|
||||
* ld-avr/relax_diff.d: Likewise.
|
||||
* ld-avr/relax.s: Likewise.
|
||||
|
||||
2014-04-05 Andreas Schwab <schwab@linux-m68k.org>
|
||||
|
||||
* ld-plugin/lto.exp: Make "-Wp," prefix optional when filtering
|
||||
|
31
ld/testsuite/ld-avr/avr.exp
Normal file
31
ld/testsuite/ld-avr/avr.exp
Normal file
@ -0,0 +1,31 @@
|
||||
# Copyright 2014
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#
|
||||
# Some AVR tests
|
||||
#
|
||||
|
||||
if {![istarget avr-*-*]} {
|
||||
return
|
||||
}
|
||||
|
||||
set avr_test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
|
||||
foreach avr_test $avr_test_list {
|
||||
verbose [file rootname $avr_test]
|
||||
run_dump_test [file rootname $avr_test]
|
||||
}
|
||||
|
13
ld/testsuite/ld-avr/norelax_diff.d
Normal file
13
ld/testsuite/ld-avr/norelax_diff.d
Normal file
@ -0,0 +1,13 @@
|
||||
#name: AVR No change in behavior without relaxation
|
||||
#as: -mmcu=avrxmega2
|
||||
#ld: -mavrxmega2
|
||||
#source: relax.s
|
||||
#objdump: -s
|
||||
#target: avr-*-*
|
||||
|
||||
.*: file format elf32-avr
|
||||
|
||||
Contents of section .text:
|
||||
0000 0c940000 .*
|
||||
Contents of section .data:
|
||||
802000 0400 .*
|
12
ld/testsuite/ld-avr/relax.s
Normal file
12
ld/testsuite/ld-avr/relax.s
Normal file
@ -0,0 +1,12 @@
|
||||
.file "relax.s"
|
||||
.section .text,"ax",@progbits
|
||||
main:
|
||||
L1:
|
||||
jmp L1
|
||||
L2:
|
||||
.global x
|
||||
.section .data
|
||||
.type x, @object
|
||||
.size x, 2
|
||||
x:
|
||||
.word L2 - L1
|
14
ld/testsuite/ld-avr/relax_diff.d
Normal file
14
ld/testsuite/ld-avr/relax_diff.d
Normal file
@ -0,0 +1,14 @@
|
||||
#name: AVR Account for relaxation in label differences
|
||||
#as: -mmcu=avrxmega2 -mlink-relax
|
||||
#ld: -mavrxmega2 --relax
|
||||
#source: relax.s
|
||||
#objdump: -s
|
||||
#target: avr-*-*
|
||||
|
||||
.*: file format elf32-avr
|
||||
|
||||
Contents of section .text:
|
||||
0000 ffcf .*
|
||||
Contents of section .data:
|
||||
802000 0200 .*
|
||||
|
Loading…
x
Reference in New Issue
Block a user