aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2006-03-03 15:25:31 +0000
committerNick Clifton <nickc@redhat.com>2006-03-03 15:25:31 +0000
commitdf406460e9fc46e766dc418f85568062a4912bbe (patch)
tree8e1d5b1142214b245e59c01ed42f4a53510e7b07 /gas
parentb92a518e7392026b969a7547e5b876ea9413f7ff (diff)
downloadfsf-binutils-gdb-df406460e9fc46e766dc418f85568062a4912bbe.zip
fsf-binutils-gdb-df406460e9fc46e766dc418f85568062a4912bbe.tar.gz
fsf-binutils-gdb-df406460e9fc46e766dc418f85568062a4912bbe.tar.bz2
Add linker relaxation support for the AVR
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog13
-rw-r--r--gas/config/tc-avr.c42
2 files changed, 43 insertions, 12 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index b9f53e0..1347fae 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,16 @@
+2006-03-03 Bjoern Haase <bjoern.m.haase@web.de>
+
+ * config/tc-avr.c (avr_mod_hash_value): New function.
+ (md_apply_fix, exp_mod): Use BFD_RELOC_HH8_LDI and
+ BFD_RELOC_MS8_LDI for hlo8() and hhi8()
+ (md_begin): Set linkrelax variable to 1, use avr_mod_hash_value
+ instead of int avr_ldi_expression: use avr_mod_hash_value instead
+ of (int).
+ (tc_gen_reloc): Handle substractions of symbols, if possible do
+ fixups, abort otherwise.
+ * config/tc-avr.h (TC_LINKRELAX_FIXUP, TC_VALIDATE_FIX,
+ tc_fix_adjustable): Define.
+
2006-03-02 James E Wilson <wilson@specifix.com>
* config/tc-ia64.c (emit_one_bundle): For IA64_OPCODE_LAST, if we
diff --git a/gas/config/tc-avr.c b/gas/config/tc-avr.c
index 2ceaa1f..d6294f3 100644
--- a/gas/config/tc-avr.c
+++ b/gas/config/tc-avr.c
@@ -170,8 +170,8 @@ static struct exp_mod_s exp_mod[] =
{"pm_hi8", BFD_RELOC_AVR_HI8_LDI_PM, BFD_RELOC_AVR_HI8_LDI_PM_NEG, 0},
{"lo8", BFD_RELOC_AVR_LO8_LDI, BFD_RELOC_AVR_LO8_LDI_NEG, 1},
{"pm_lo8", BFD_RELOC_AVR_LO8_LDI_PM, BFD_RELOC_AVR_LO8_LDI_PM_NEG, 0},
- {"hlo8", -BFD_RELOC_AVR_LO8_LDI, -BFD_RELOC_AVR_LO8_LDI_NEG, 0},
- {"hhi8", -BFD_RELOC_AVR_HI8_LDI, -BFD_RELOC_AVR_HI8_LDI_NEG, 0},
+ {"hlo8", BFD_RELOC_AVR_HH8_LDI, BFD_RELOC_AVR_HH8_LDI_NEG, 0},
+ {"hhi8", BFD_RELOC_AVR_MS8_LDI, BFD_RELOC_AVR_MS8_LDI_NEG, 0},
};
/* A union used to store indicies into the exp_mod[] array
@@ -1081,15 +1081,11 @@ md_apply_fix (fixS *fixP, valueT * valP, segT seg)
bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value), where);
break;
- case -BFD_RELOC_AVR_LO8_LDI:
- bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value >> 16), where);
- break;
-
case BFD_RELOC_AVR_HI8_LDI:
bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value >> 8), where);
break;
- case -BFD_RELOC_AVR_HI8_LDI:
+ case BFD_RELOC_AVR_MS8_LDI:
bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (value >> 24), where);
break;
@@ -1101,15 +1097,11 @@ md_apply_fix (fixS *fixP, valueT * valP, segT seg)
bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (-value), where);
break;
- case -BFD_RELOC_AVR_LO8_LDI_NEG:
- bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (-value >> 16), where);
- break;
-
case BFD_RELOC_AVR_HI8_LDI_NEG:
bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (-value >> 8), where);
break;
- case -BFD_RELOC_AVR_HI8_LDI_NEG:
+ case BFD_RELOC_AVR_MS8_LDI_NEG:
bfd_putl16 ((bfd_vma) insn | LDI_IMMEDIATE (-value >> 24), where);
break;
@@ -1195,6 +1187,32 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED,
{
arelent *reloc;
+ if (fixp->fx_addsy && fixp->fx_subsy)
+ {
+ long value = 0;
+
+ if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
+ || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
+ {
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ "Difference of symbols in different sections is not supported");
+ return NULL;
+ }
+
+ /* We are dealing with two symbols defined in the same section.
+ Let us fix-up them here. */
+ value += S_GET_VALUE (fixp->fx_addsy);
+ value -= S_GET_VALUE (fixp->fx_subsy);
+
+ /* When fx_addsy and fx_subsy both are zero, md_apply_fix
+ only takes it's second operands for the fixup value. */
+ fixp->fx_addsy = NULL;
+ fixp->fx_subsy = NULL;
+ md_apply_fix (fixp, (valueT *) &value, NULL);
+
+ return NULL;
+ }
+
reloc = xmalloc (sizeof (arelent));
reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));