aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog72
-rw-r--r--bfd/bfd-in2.h16
-rw-r--r--bfd/elf32-frv.c2629
-rw-r--r--bfd/libbfd.h16
-rw-r--r--bfd/reloc.c32
-rw-r--r--cpu/ChangeLog14
-rw-r--r--cpu/frv.cpu59
-rw-r--r--cpu/frv.opc667
-rw-r--r--gas/ChangeLog13
-rw-r--r--gas/cgen.c3
-rw-r--r--gas/config/tc-frv.c118
-rw-r--r--include/elf/ChangeLog7
-rw-r--r--include/elf/frv.h18
-rw-r--r--include/opcode/ChangeLog6
-rw-r--r--include/opcode/cgen.h3
-rw-r--r--ld/testsuite/ChangeLog60
-rw-r--r--ld/testsuite/ld-frv/fdpic-pie-1.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-pie-2.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-pie-6.d2
-rw-r--r--ld/testsuite/ld-frv/fdpic-pie-7.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-pie-8.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-shared-1.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-shared-2.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-shared-3.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-shared-4.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-shared-5.d2
-rw-r--r--ld/testsuite/ld-frv/fdpic-shared-6.d2
-rw-r--r--ld/testsuite/ld-frv/fdpic-shared-7.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-shared-8.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-shared-local-2.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-shared-local-8.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-static-1.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-static-2.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-static-6.d2
-rw-r--r--ld/testsuite/ld-frv/fdpic-static-7.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic-static-8.d4
-rw-r--r--ld/testsuite/ld-frv/fdpic.exp7
-rw-r--r--ld/testsuite/ld-frv/tls-1-dep.s7
-rw-r--r--ld/testsuite/ld-frv/tls-1-shared.lds3
-rw-r--r--ld/testsuite/ld-frv/tls-1.s85
-rw-r--r--ld/testsuite/ld-frv/tls-2.s183
-rw-r--r--ld/testsuite/ld-frv/tls-3.s20
-rw-r--r--ld/testsuite/ld-frv/tls-dynamic-1.d71
-rw-r--r--ld/testsuite/ld-frv/tls-dynamic-2.d200
-rw-r--r--ld/testsuite/ld-frv/tls-dynamic-3.d27
-rw-r--r--ld/testsuite/ld-frv/tls-initial-shared-2.d235
-rw-r--r--ld/testsuite/ld-frv/tls-pie-1.d71
-rw-r--r--ld/testsuite/ld-frv/tls-pie-3.d27
-rw-r--r--ld/testsuite/ld-frv/tls-relax-dynamic-1.d67
-rw-r--r--ld/testsuite/ld-frv/tls-relax-dynamic-2.d149
-rw-r--r--ld/testsuite/ld-frv/tls-relax-dynamic-3.d27
-rw-r--r--ld/testsuite/ld-frv/tls-relax-initial-shared-2.d214
-rw-r--r--ld/testsuite/ld-frv/tls-relax-pie-1.d67
-rw-r--r--ld/testsuite/ld-frv/tls-relax-pie-3.d27
-rw-r--r--ld/testsuite/ld-frv/tls-relax-shared-1.d73
-rw-r--r--ld/testsuite/ld-frv/tls-relax-shared-2.d264
-rw-r--r--ld/testsuite/ld-frv/tls-relax-shared-3.d27
-rw-r--r--ld/testsuite/ld-frv/tls-relax-static-1.d62
-rw-r--r--ld/testsuite/ld-frv/tls-relax-static-3.d26
-rw-r--r--ld/testsuite/ld-frv/tls-shared-1-fail.d4
-rw-r--r--ld/testsuite/ld-frv/tls-shared-1.d73
-rw-r--r--ld/testsuite/ld-frv/tls-shared-2.d264
-rw-r--r--ld/testsuite/ld-frv/tls-shared-3.d27
-rw-r--r--ld/testsuite/ld-frv/tls-static-1.d70
-rw-r--r--ld/testsuite/ld-frv/tls-static-3.d26
-rw-r--r--ld/testsuite/ld-frv/tls.exp62
-rw-r--r--opcodes/ChangeLog11
-rw-r--r--opcodes/frv-asm.c665
-rw-r--r--opcodes/frv-desc.c28
-rw-r--r--opcodes/frv-desc.h41
-rw-r--r--opcodes/frv-dis.c22
-rw-r--r--opcodes/frv-ibld.c54
-rw-r--r--opcodes/frv-opc.c12
-rw-r--r--opcodes/frv-opc.h1
74 files changed, 6466 insertions, 638 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 783865b..b03f981 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,75 @@
+2005-01-25 Alexandre Oliva <aoliva@redhat.com>
+
+ 2004-12-10 Alexandre Oliva <aoliva@redhat.com>
+ * elf32-frv.c (elf32_frv_relocate_section): Force local binding
+ for TLSMOFF.
+ * reloc.c: Add R_FRV_TLSMOFF.
+ * elf32-frv.c (elf32_frv_howto_table): Likewise.
+ (frv_reloc_map, frv_reloc_type_lookup): Map it.
+ (elf32_frv_relocate_section): Handle it.
+ (elf32_frv_check_relocs): Likewise.
+ * libbfd.h, bfd-in2.h: Rebuilt.
+ 2004-11-26 Alexandre Oliva <aoliva@redhat.com>
+ * elf32-frv.c (_frvfdpic_emit_got_relocs_plt_entries): Don't crash
+ when given an undefweak TLS symbol. Fix constant TLS PLT entries
+ such that they return the constant in gr9.
+ (_frvfdpic_relax_tls_entries): Don't crash for undefweak TLS
+ symbols.
+ (_frvfdpic_size_got_plt): Set _cooked_size of dynamic sections.
+ too, such that they shrink on relaxation.
+ (elf32_frvfdpic_finish_dynamic_sections): Check __ROFIXUP_END__ as
+ marking the position right past the _GLOBAL_OFFSET_TABLE_ value.
+ (_frvfdpic_assign_plt_entries): Shrink constant TLS PLT entries
+ if we can guarantee the use of 16-bit constants.
+ 2004-11-10 Alexandre Oliva <aoliva@redhat.com>
+ Introduce TLS support for FR-V FDPIC.
+ * reloc.c: Add TLS relocations.
+ * elf32-frv.c (elf32_frv_howto_table): Add TLS relocations.
+ (elf32_frv_rel_tlsdesc_value_howto): New.
+ (elf32_frv_rel_tlsoff_howto): New.
+ (frv_reloc_map): Add new mappings.
+ (struct frvfdpic_elf_link_hash_table): Add pointer to summary
+ reloc information.
+ (frvfdpic_dynamic_got_plt_info): New.
+ (frvfdpic_plt_tls_ret_offset): New.
+ (ELF_DYNAMIC_INTERPRETER, DEFAULT_STACK_SIZE): Move earlier.
+ (struct _frvfdpic_dynamic_got_info): Likewise. Add TLS members.
+ (struct _frvfdpic_dynamic_got_plt_info): Likewise.
+ (FRVFDPIC_SYM_LOCAL): Regard symbols defined in the absolute
+ section as local.
+ (struct frvfdpic_relocs_info): Add TLS fields.
+ (frvfdpic_relocs_info_hash): Warning clean up.
+ (frvfdpic_relocs_info_find): Initialize tlsplt_entry.
+ (frvfdpic_pic_merge_early_relocs_info): Merge TLS fields.
+ (FRVFDPIC_TLS_BIAS): Define.
+ (tls_biased_base): New.
+ (_frvfdpic_emit_got_relocs_plt_entries): Deal with TLS
+ relocations.
+ (frv_reloc_type_lookup): Likewise.
+ (frvfdpic_info_to_howto_rel): Likewise.
+ (elf32_frv_relocate_section): Likewise.
+ (_frv_create_got_section): Create the PLT section here.
+ (elf32_frvfdpic_create_dynamic_sections): Not here.
+ (_frvfdpic_count_nontls_entries): Move out of...
+ (_frvfdpic_count_got_plt_entries): ... here.
+ (_frvfdpic_count_tls_entries): Likewise. Add TLS support.
+ (_frvfdpic_count_relocs_fixups): Likewise. Add relaxation
+ support.
+ (_frvfdpic_relax_tls_entries): New.
+ (_frvfdpic_compute_got_alloc_data): Add TLS support.
+ (_frvfdpic_get_tlsdesc_entry): New.
+ (_frvfdpic_assign_got_entries): Add TLS support.
+ (_frvfdpic_assign_plt_entries): Likewise.
+ (_frvfdpic_reset_got_plt_entries): New.
+ (_frvfdpic_size_got_plt): Move out of...
+ (elf32_frvfdpic_size_dynamic_sections): ... here.
+ (_frvfdpic_relax_got_plt_entries): New.
+ (elf32_frvfdpic_relax_section): New.
+ (elf32_frvfdpic_finish_dynamic_sections): Add TLS sanity check.
+ (elf32_frv_check_relocs): Add TLS support.
+ (bfd_elf32_bfd_relax_section): Define for FDPIC.
+ * libbfd.h, bfd-in2.h: Rebuilt.
+
2005-01-25 Alan Modra <amodra@bigpond.net.au>
* elf.c (_bfd_elf_get_dynamic_reloc_upper_bound): Only include
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 70f105b..6c783a0 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -2409,6 +2409,22 @@ to compensate for the borrow when the low bits are added. */
BFD_RELOC_FRV_GOTOFF12,
BFD_RELOC_FRV_GOTOFFHI,
BFD_RELOC_FRV_GOTOFFLO,
+ BFD_RELOC_FRV_GETTLSOFF,
+ BFD_RELOC_FRV_TLSDESC_VALUE,
+ BFD_RELOC_FRV_GOTTLSDESC12,
+ BFD_RELOC_FRV_GOTTLSDESCHI,
+ BFD_RELOC_FRV_GOTTLSDESCLO,
+ BFD_RELOC_FRV_TLSMOFF12,
+ BFD_RELOC_FRV_TLSMOFFHI,
+ BFD_RELOC_FRV_TLSMOFFLO,
+ BFD_RELOC_FRV_GOTTLSOFF12,
+ BFD_RELOC_FRV_GOTTLSOFFHI,
+ BFD_RELOC_FRV_GOTTLSOFFLO,
+ BFD_RELOC_FRV_TLSOFF,
+ BFD_RELOC_FRV_TLSDESC_RELAX,
+ BFD_RELOC_FRV_GETTLSOFF_RELAX,
+ BFD_RELOC_FRV_TLSOFF_RELAX,
+ BFD_RELOC_FRV_TLSMOFF,
/* This is a 24bit GOT-relative reloc for the mn10300. */
diff --git a/bfd/elf32-frv.c b/bfd/elf32-frv.c
index 9564671..f97e0b7 100644
--- a/bfd/elf32-frv.c
+++ b/bfd/elf32-frv.c
@@ -1,5 +1,5 @@
/* FRV-specific support for 32-bit ELF.
- Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -350,7 +350,7 @@ static reloc_howto_type elf32_frv_howto_table [] =
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
- /* The 32-bit address of the canonical descriptor of a function. */
+ /* The 64-bit descriptor of a function. */
HOWTO (R_FRV_FUNCDESC_VALUE, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
@@ -461,6 +461,265 @@ static reloc_howto_type elf32_frv_howto_table [] =
0xffff, /* dst_mask */
FALSE), /* pcrel_offset */
+ /* A 24-bit pc-relative relocation referencing the TLS PLT entry for
+ a thread-local symbol. If the symbol number is 0, it refers to
+ the module. */
+ HOWTO (R_FRV_GETTLSOFF, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 26, /* bitsize */
+ TRUE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_GETTLSOFF", /* name */
+ FALSE, /* partial_inplace */
+ 0x7e03ffff, /* src_mask */
+ 0x7e03ffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* A 64-bit TLS descriptor for a symbol. This relocation is only
+ valid as a REL, dynamic relocation. */
+ HOWTO (R_FRV_TLSDESC_VALUE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_TLSDESC_VALUE", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 12-bit signed operand with the GOT offset for the TLS
+ descriptor of the symbol. */
+ HOWTO (R_FRV_GOTTLSDESC12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_GOTTLSDESC12", /* name */
+ FALSE, /* partial_inplace */
+ 0xfff, /* src_mask */
+ 0xfff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The upper 16 bits of the GOT offset for the TLS descriptor of the
+ symbol. */
+ HOWTO (R_FRV_GOTTLSDESCHI, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_GOTTLSDESCHI", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The lower 16 bits of the GOT offset for the TLS descriptor of the
+ symbol. */
+ HOWTO (R_FRV_GOTTLSDESCLO, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_GOTTLSDESCLO", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 12-bit signed operand with the offset from the module base
+ address to the thread-local symbol address. */
+ HOWTO (R_FRV_TLSMOFF12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_TLSMOFF12", /* name */
+ FALSE, /* partial_inplace */
+ 0xfff, /* src_mask */
+ 0xfff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The upper 16 bits of the offset from the module base address to
+ the thread-local symbol address. */
+ HOWTO (R_FRV_TLSMOFFHI, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_TLSMOFFHI", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The lower 16 bits of the offset from the module base address to
+ the thread-local symbol address. */
+ HOWTO (R_FRV_TLSMOFFLO, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_TLSMOFFLO", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 12-bit signed operand with the GOT offset for the TLSOFF entry
+ for a symbol. */
+ HOWTO (R_FRV_GOTTLSOFF12, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 12, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_GOTTLSOFF12", /* name */
+ FALSE, /* partial_inplace */
+ 0xfff, /* src_mask */
+ 0xfff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The upper 16 bits of the GOT offset for the TLSOFF entry for a
+ symbol. */
+ HOWTO (R_FRV_GOTTLSOFFHI, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_GOTTLSOFFHI", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The lower 16 bits of the GOT offset for the TLSOFF entry for a
+ symbol. */
+ HOWTO (R_FRV_GOTTLSOFFLO, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_GOTTLSOFFLO", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* The 32-bit offset from the thread pointer (not the module base
+ address) to a thread-local symbol. */
+ HOWTO (R_FRV_TLSOFF, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_TLSOFF", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* An annotation for linker relaxation, that denotes the
+ symbol+addend whose TLS descriptor is referenced by the sum of
+ the two input registers of an ldd instruction. */
+ HOWTO (R_FRV_TLSDESC_RELAX, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_TLSDESC_RELAX", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* An annotation for linker relaxation, that denotes the
+ symbol+addend whose TLS resolver entry point is given by the sum
+ of the two register operands of an calll instruction. */
+ HOWTO (R_FRV_GETTLSOFF_RELAX, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_GETTLSOFF_RELAX", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* An annotation for linker relaxation, that denotes the
+ symbol+addend whose TLS offset GOT entry is given by the sum of
+ the two input registers of an ld instruction. */
+ HOWTO (R_FRV_TLSOFF_RELAX, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 0, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_TLSOFF_RELAX", /* name */
+ FALSE, /* partial_inplace */
+ 0, /* src_mask */
+ 0, /* dst_mask */
+ FALSE), /* pcrel_offset */
+
+ /* A 32-bit offset from the module base address to
+ the thread-local symbol address. */
+ HOWTO (R_FRV_TLSMOFF, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_dont, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_TLSMOFF", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE), /* pcrel_offset */
};
/* GNU extension to record C++ vtable hierarchy. */
@@ -542,6 +801,50 @@ static reloc_howto_type elf32_frv_rel_funcdesc_value_howto =
0xffffffff, /* dst_mask */
FALSE); /* pcrel_offset */
+static reloc_howto_type elf32_frv_rel_tlsdesc_value_howto =
+ /* A 64-bit TLS descriptor for a symbol. The first word resolves to
+ an entry point, and the second resolves to a special argument.
+ If the symbol turns out to be in static TLS, the entry point is a
+ return instruction, and the special argument is the TLS offset
+ for the symbol. If it's in dynamic TLS, the entry point is a TLS
+ offset resolver, and the special argument is a pointer to a data
+ structure allocated by the dynamic loader, containing the GOT
+ address for the offset resolver, the module id, the offset within
+ the module, and anything else the TLS offset resolver might need
+ to determine the TLS offset for the symbol in the running
+ thread. */
+ HOWTO (R_FRV_TLSDESC_VALUE, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 64, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_bitfield, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_FRV_TLSDESC_VALUE", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE); /* pcrel_offset */
+
+static reloc_howto_type elf32_frv_rel_tlsoff_howto =
+ /* The 32-bit offset from the thread pointer (not the module base
+ address) to a thread-local symbol. */
+ HOWTO (R_FRV_TLSOFF, /* 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_generic_reloc, /* special_function */
+ "R_FRV_TLSOFF", /* name */
+ TRUE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ FALSE); /* pcrel_offset */
+
+
/* Map BFD reloc types to FRV ELF reloc types. */
#if 0
@@ -578,6 +881,22 @@ static const struct frv_reloc_map frv_reloc_map [] =
{ BFD_RELOC_FRV_GOTOFF12, R_FRV_GOTOFF12 },
{ BFD_RELOC_FRV_GOTOFFHI, R_FRV_GOTOFFHI },
{ BFD_RELOC_FRV_GOTOFFLO, R_FRV_GOTOFFLO },
+ { BFD_RELOC_FRV_GETTLSOFF, R_FRV_GETTLSOFF },
+ { BFD_RELOC_FRV_TLSDESC_VALUE, R_FRV_TLSDESC_VALUE },
+ { BFD_RELOC_FRV_GOTTLSDESC12, R_FRV_GOTTLSDESC12 },
+ { BFD_RELOC_FRV_GOTTLSDESCHI, R_FRV_GOTTLSDESCHI },
+ { BFD_RELOC_FRV_GOTTLSDESCLO, R_FRV_GOTTLSDESCLO },
+ { BFD_RELOC_FRV_TLSMOFF12, R_FRV_TLSMOFF12 },
+ { BFD_RELOC_FRV_TLSMOFFHI, R_FRV_TLSMOFFHI },
+ { BFD_RELOC_FRV_TLSMOFFLO, R_FRV_TLSMOFFLO },
+ { BFD_RELOC_FRV_GOTTLSOFF12, R_FRV_GOTTLSOFF12 },
+ { BFD_RELOC_FRV_GOTTLSOFFHI, R_FRV_GOTTLSOFFHI },
+ { BFD_RELOC_FRV_GOTTLSOFFLO, R_FRV_GOTTLSOFFLO },
+ { BFD_RELOC_FRV_TLSOFF, R_FRV_TLSOFF },
+ { BFD_RELOC_FRV_TLSDESC_RELAX, R_FRV_TLSDESC_RELAX },
+ { BFD_RELOC_FRV_GETTLSOFF_RELAX, R_FRV_GETTLSOFF_RELAX },
+ { BFD_RELOC_FRV_TLSOFF_RELAX, R_FRV_TLSOFF_RELAX },
+ { BFD_RELOC_FRV_TLSMOFF, R_FRV_TLSMOFF },
{ BFD_RELOC_VTABLE_INHERIT, R_FRV_GNU_VTINHERIT },
{ BFD_RELOC_VTABLE_ENTRY, R_FRV_GNU_VTENTRY },
};
@@ -605,11 +924,16 @@ struct frvfdpic_elf_link_hash_table
/* GOT base offset. */
bfd_vma got0;
/* Location of the first non-lazy PLT entry, i.e., the number of
- bytes taken by lazy PLT entries. */
+ bytes taken by lazy PLT entries. If locally-bound TLS
+ descriptors require a ret instruction, it will be placed at this
+ offset. */
bfd_vma plt0;
/* A hash table holding information about which symbols were
referenced with which PIC-related relocations. */
struct htab *relocs_info;
+ /* Summary reloc information collected by
+ _frvfdpic_count_got_plt_entries. */
+ struct _frvfdpic_dynamic_got_info *g;
};
/* Get the FRV ELF linker hash table from a link_info structure. */
@@ -633,6 +957,96 @@ struct frvfdpic_elf_link_hash_table
(frvfdpic_hash_table (info)->got0)
#define frvfdpic_plt_initial_offset(info) \
(frvfdpic_hash_table (info)->plt0)
+#define frvfdpic_dynamic_got_plt_info(info) \
+ (frvfdpic_hash_table (info)->g)
+
+/* Currently it's the same, but if some day we have a reason to change
+ it, we'd better be using a different macro.
+
+ FIXME: if there's any TLS PLT entry that uses local-exec or
+ initial-exec models, we could use the ret at the end of any of them
+ instead of adding one more. */
+#define frvfdpic_plt_tls_ret_offset(info) \
+ (frvfdpic_plt_initial_offset (info))
+
+/* The name of the dynamic interpreter. This is put in the .interp
+ section. */
+
+#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
+
+#define DEFAULT_STACK_SIZE 0x20000
+
+/* This structure is used to collect the number of entries present in
+ each addressable range of the got. */
+struct _frvfdpic_dynamic_got_info
+{
+ /* Several bits of information about the current link. */
+ struct bfd_link_info *info;
+ /* Total GOT size needed for GOT entries within the 12-, 16- or 32-bit
+ ranges. */
+ bfd_vma got12, gotlos, gothilo;
+ /* Total GOT size needed for function descriptor entries within the 12-,
+ 16- or 32-bit ranges. */
+ bfd_vma fd12, fdlos, fdhilo;
+ /* Total GOT size needed by function descriptor entries referenced
+ in PLT entries, that would be profitable to place in offsets
+ close to the PIC register. */
+ bfd_vma fdplt;
+ /* Total PLT size needed by lazy PLT entries. */
+ bfd_vma lzplt;
+ /* Total GOT size needed for TLS descriptor entries within the 12-,
+ 16- or 32-bit ranges. */
+ bfd_vma tlsd12, tlsdlos, tlsdhilo;
+ /* Total GOT size needed by TLS descriptors referenced in PLT
+ entries, that would be profitable to place in offers close to the
+ PIC register. */
+ bfd_vma tlsdplt;
+ /* Total PLT size needed by TLS lazy PLT entries. */
+ bfd_vma tlslzplt;
+ /* Number of relocations carried over from input object files. */
+ unsigned long relocs;
+ /* Number of fixups introduced by relocations in input object files. */
+ unsigned long fixups;
+ /* The number of fixups that reference the ret instruction added to
+ the PLT for locally-resolved TLS descriptors. */
+ unsigned long tls_ret_refs;
+};
+
+/* This structure is used to assign offsets to got entries, function
+ descriptors, plt entries and lazy plt entries. */
+
+struct _frvfdpic_dynamic_got_plt_info
+{
+ /* Summary information collected with _frvfdpic_count_got_plt_entries. */
+ struct _frvfdpic_dynamic_got_info g;
+
+ /* For each addressable range, we record a MAX (positive) and MIN
+ (negative) value. CUR is used to assign got entries, and it's
+ incremented from an initial positive value to MAX, then from MIN
+ to FDCUR (unless FDCUR wraps around first). FDCUR is used to
+ assign function descriptors, and it's decreased from an initial
+ non-positive value to MIN, then from MAX down to CUR (unless CUR
+ wraps around first). All of MIN, MAX, CUR and FDCUR always point
+ to even words. ODD, if non-zero, indicates an odd word to be
+ used for the next got entry, otherwise CUR is used and
+ incremented by a pair of words, wrapping around when it reaches
+ MAX. FDCUR is decremented (and wrapped) before the next function
+ descriptor is chosen. FDPLT indicates the number of remaining
+ slots that can be used for function descriptors used only by PLT
+ entries.
+
+ TMAX, TMIN and TCUR are used to assign TLS descriptors. TCUR
+ starts as MAX, and grows up to TMAX, then wraps around to TMIN
+ and grows up to MIN. TLSDPLT indicates the number of remaining
+ slots that can be used for TLS descriptors used only by TLS PLT
+ entries. */
+ struct _frvfdpic_dynamic_got_alloc_data
+ {
+ bfd_signed_vma max, cur, odd, fdcur, min;
+ bfd_signed_vma tmax, tcur, tmin;
+ bfd_vma fdplt, tlsdplt;
+ } got12, gotlos, gothilo;
+};
/* Create an FRV ELF linker hash table. */
@@ -661,7 +1075,15 @@ frvfdpic_elf_link_hash_table_create (bfd *abfd)
its function descriptor must be assigned by the dynamic linker. */
#define FRVFDPIC_SYM_LOCAL(INFO, H) \
(_bfd_elf_symbol_refs_local_p ((H), (INFO), 1) \
- || ! elf_hash_table (INFO)->dynamic_sections_created)
+ || ! elf_hash_table (INFO)->dynamic_sections_created \
+ /* These two additional alternatives are needed for TLS
+ relocations, that use *ABS*+offset relocations to refer to the
+ TLS section of the local module. FIXME: At some point during
+ linking, the definition section ceases to be regarded as the
+ absolute section, and starts being regarded as the undefined
+ section. */ \
+ || bfd_is_abs_section ((H)->root.u.def.section) \
+ || bfd_is_und_section ((H)->root.u.def.section))
#define FRVFDPIC_FUNCDESC_LOCAL(INFO, H) \
((H)->dynindx == -1 || ! elf_hash_table (INFO)->dynamic_sections_created)
@@ -707,6 +1129,24 @@ struct frvfdpic_relocs_info
unsigned fdgoff12:1;
unsigned fdgofflos:1;
unsigned fdgoffhilo:1;
+ /* Whether a GETTLSOFF relocation references symbol+addend. */
+ unsigned tlsplt:1;
+ /* FIXME: we should probably add tlspltdesc, tlspltoff and
+ tlspltimm, to tell what kind of TLS PLT entry we're generating.
+ We might instead just pre-compute flags telling whether the
+ object is suitable for local exec, initial exec or general
+ dynamic addressing, and use that all over the place. We could
+ also try to do a better job of merging TLSOFF and TLSDESC entries
+ in main executables, but perhaps we can get rid of TLSDESC
+ entirely in them instead. */
+ /* Whether a GOTTLSDESC relocation references symbol+addend. */
+ unsigned tlsdesc12:1;
+ unsigned tlsdesclos:1;
+ unsigned tlsdeschilo:1;
+ /* Whether a GOTTLSOFF relocation references symbol+addend. */
+ unsigned tlsoff12:1;
+ unsigned tlsofflos:1;
+ unsigned tlsoffhilo:1;
/* Whether symbol+addend is referenced with GOTOFF12, GOTOFFLO or
GOTOFFHI relocations. The addend doesn't really matter, since we
envision that this will only be used to check whether the symbol
@@ -736,9 +1176,10 @@ struct frvfdpic_relocs_info
needed for this symbol. */
unsigned done:1;
- /* The number of R_FRV_32, R_FRV_FUNCDESC and R_FRV_FUNCDESC_VALUE
- relocations referencing the symbol. */
- unsigned relocs32, relocsfd, relocsfdv;
+ /* The number of R_FRV_32, R_FRV_FUNCDESC, R_FRV_FUNCDESC_VALUE and
+ R_FRV_TLSDESC_VALUE, R_FRV_TLSOFF relocations referencing
+ symbol+addend. */
+ unsigned relocs32, relocsfd, relocsfdv, relocstlsd, relocstlsoff;
/* The number of .rofixups entries and dynamic relocations allocated
for this symbol, minus any that might have already been used. */
@@ -754,6 +1195,10 @@ struct frvfdpic_relocs_info
non-lazy and lazy, respectively. If unassigned, should be
(bfd_vma)-1. */
bfd_vma plt_entry, lzplt_entry;
+ /* The offsets of the GOT entries for TLS offset and TLS descriptor. */
+ bfd_signed_vma tlsoff_entry, tlsdesc_entry;
+ /* The offset of the TLS offset PLT entry. */
+ bfd_vma tlsplt_entry;
};
/* Compute a hash with the key fields of an frvfdpic_relocs_info entry. */
@@ -763,7 +1208,7 @@ frvfdpic_relocs_info_hash (const void *entry_)
const struct frvfdpic_relocs_info *entry = entry_;
return (entry->symndx == -1
- ? entry->d.h->root.root.hash
+ ? (long)entry->d.h->root.root.hash
: entry->symndx + entry->d.abfd->id * 257) + entry->addend;
}
@@ -807,6 +1252,7 @@ frvfdpic_relocs_info_find (struct htab *ht,
(*loc)->addend = entry->addend;
(*loc)->plt_entry = (bfd_vma)-1;
(*loc)->lzplt_entry = (bfd_vma)-1;
+ (*loc)->tlsplt_entry = (bfd_vma)-1;
return *loc;
}
@@ -866,6 +1312,13 @@ frvfdpic_pic_merge_early_relocs_info (struct frvfdpic_relocs_info *e2,
e2->fdgoff12 |= e1->fdgoff12;
e2->fdgofflos |= e1->fdgofflos;
e2->fdgoffhilo |= e1->fdgoffhilo;
+ e2->tlsplt |= e1->tlsplt;
+ e2->tlsdesc12 |= e1->tlsdesc12;
+ e2->tlsdesclos |= e1->tlsdesclos;
+ e2->tlsdeschilo |= e1->tlsdeschilo;
+ e2->tlsoff12 |= e1->tlsoff12;
+ e2->tlsofflos |= e1->tlsofflos;
+ e2->tlsoffhilo |= e1->tlsoffhilo;
e2->gotoff |= e1->gotoff;
e2->call |= e1->call;
e2->sym |= e1->sym;
@@ -884,6 +1337,8 @@ frvfdpic_pic_merge_early_relocs_info (struct frvfdpic_relocs_info *e2,
e2->relocs32 += e1->relocs32;
e2->relocsfd += e1->relocsfd;
e2->relocsfdv += e1->relocsfdv;
+ e2->relocstlsd += e1->relocstlsd;
+ e2->relocstlsoff += e1->relocstlsoff;
e2->fixups += e1->fixups;
e2->dynrelocs += e1->dynrelocs;
@@ -898,6 +1353,14 @@ frvfdpic_pic_merge_early_relocs_info (struct frvfdpic_relocs_info *e2,
e2->plt_entry = e1->plt_entry;
if (e1->lzplt_entry < e2->lzplt_entry)
e2->lzplt_entry = e1->lzplt_entry;
+
+ if (abs (e1->tlsoff_entry) < abs (e2->tlsoff_entry))
+ e2->tlsoff_entry = e1->tlsoff_entry;
+ if (abs (e1->tlsdesc_entry) < abs (e2->tlsdesc_entry))
+ e2->tlsdesc_entry = e1->tlsdesc_entry;
+
+ if (e1->tlsplt_entry < e2->tlsplt_entry)
+ t2->tlsplt_entry = t1->tlsplt_entry;
#endif
}
@@ -1011,6 +1474,21 @@ _frvfdpic_osec_readonly_p (bfd *output_bfd, asection *osec)
return ! (elf_tdata (output_bfd)->phdr[seg].p_flags & PF_W);
}
+#define FRVFDPIC_TLS_BIAS (2048 - 16)
+
+/* Return the base VMA address which should be subtracted from real addresses
+ when resolving TLSMOFF relocation.
+ This is PT_TLS segment p_vaddr, plus the 2048-16 bias. */
+
+static bfd_vma
+tls_biased_base (struct bfd_link_info *info)
+{
+ /* If tls_sec is NULL, we should have signalled an error already. */
+ if (elf_hash_table (info)->tls_sec == NULL)
+ return FRVFDPIC_TLS_BIAS;
+ return elf_hash_table (info)->tls_sec->vma + FRVFDPIC_TLS_BIAS;
+}
+
/* Generate relocations for GOT entries, function descriptors, and
code for PLT and lazy PLT entries. */
@@ -1030,7 +1508,8 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry,
return TRUE;
entry->done = 1;
- if (entry->got_entry || entry->fdgot_entry || entry->fd_entry)
+ if (entry->got_entry || entry->fdgot_entry || entry->fd_entry
+ || entry->tlsoff_entry || entry->tlsdesc_entry)
{
/* If the symbol is dynamic, consider it for dynamic
relocations, otherwise decay to section + offset. */
@@ -1364,11 +1843,12 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry,
| ((entry->fd_entry >> 16)
& (((bfd_vma)1 << 16) - 1)),
plt_code);
+ plt_code += 4;
bfd_put_32 (output_bfd,
0x9cf40000
| (entry->fd_entry & (((bfd_vma)1 << 16) - 1)),
plt_code);
- plt_code += 8;
+ plt_code += 4;
}
/* ldd @(gr14,gr15),gr14 */
bfd_put_32 (output_bfd, 0x9c08e14f, plt_code);
@@ -1412,6 +1892,372 @@ _frvfdpic_emit_got_relocs_plt_entries (struct frvfdpic_relocs_info *entry,
}
}
+ /* Generate relocation for GOT entry holding the TLS offset. */
+ if (entry->tlsoff_entry)
+ {
+ int idx = dynindx;
+ bfd_vma ad = addend;
+
+ if (entry->symndx != -1
+ || FRVFDPIC_SYM_LOCAL (info, entry->d.h))
+ {
+ /* If the symbol is dynamic but binds locally, use
+ section+offset. */
+ if (sec)
+ {
+ if (entry->symndx == -1)
+ ad += entry->d.h->root.u.def.value;
+ else
+ ad += sym->st_value;
+ ad += sec->output_offset;
+ if (sec->output_section
+ && elf_section_data (sec->output_section))
+ idx = elf_section_data (sec->output_section)->dynindx;
+ else
+ idx = 0;
+ }
+ }
+
+ /* *ABS*+addend is special for TLS relocations, use only the
+ addend. */
+ if (info->executable
+ && idx == 0
+ && (bfd_is_abs_section (sec)
+ || bfd_is_und_section (sec)))
+ ;
+ /* If we're linking an executable, we can entirely omit the
+ dynamic relocation if the symbol is local to this module. */
+ else if (info->executable
+ && (entry->symndx != -1
+ || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
+ {
+ if (sec)
+ ad += sec->output_section->vma - tls_biased_base (info);
+ }
+ else
+ {
+ if (idx == 0
+ && (bfd_is_abs_section (sec)
+ || bfd_is_und_section (sec)))
+ {
+ idx = elf_section_data (elf_hash_table (info)->tls_sec)->dynindx;
+ ad += FRVFDPIC_TLS_BIAS;
+ }
+ _frvfdpic_add_dyn_reloc (output_bfd, frvfdpic_gotrel_section (info),
+ _bfd_elf_section_offset
+ (output_bfd, info,
+ frvfdpic_got_section (info),
+ frvfdpic_got_initial_offset (info)
+ + entry->tlsoff_entry)
+ + frvfdpic_got_section (info)
+ ->output_section->vma
+ + frvfdpic_got_section (info)
+ ->output_offset,
+ R_FRV_TLSOFF, idx, ad, entry);
+ }
+
+ bfd_put_32 (output_bfd, ad,
+ frvfdpic_got_section (info)->contents
+ + frvfdpic_got_initial_offset (info)
+ + entry->tlsoff_entry);
+ }
+
+ if (entry->tlsdesc_entry)
+ {
+ int idx = dynindx;
+ bfd_vma ad = addend;
+
+ /* If the symbol is dynamic but binds locally, use
+ section+offset. */
+ if (sec && (entry->symndx != -1
+ || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
+ {
+ if (entry->symndx == -1)
+ ad += entry->d.h->root.u.def.value;
+ else
+ ad += sym->st_value;
+ ad += sec->output_offset;
+ if (sec->output_section && elf_section_data (sec->output_section))
+ idx = elf_section_data (sec->output_section)->dynindx;
+ else
+ idx = 0;
+ }
+
+ /* If we didn't set up a TLS offset entry, but we're linking an
+ executable and the symbol binds locally, we can use the
+ module offset in the TLS descriptor in relaxations. */
+ if (info->executable && ! entry->tlsoff_entry)
+ entry->tlsoff_entry = entry->tlsdesc_entry + 4;
+
+ if (info->executable && !info->pie
+ && ((idx == 0
+ && (bfd_is_abs_section (sec)
+ || bfd_is_und_section (sec)))
+ || entry->symndx != -1
+ || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
+ {
+ /* *ABS*+addend is special for TLS relocations, use only the
+ addend for the TLS offset, and take the module id as
+ 0. */
+ if (idx == 0
+ && (bfd_is_abs_section (sec)
+ || bfd_is_und_section (sec)))
+ ;
+ /* For other TLS symbols that bind locally, add the section
+ TLS offset to the addend. */
+ else if (sec)
+ ad += sec->output_section->vma - tls_biased_base (info);
+
+ bfd_put_32 (output_bfd,
+ frvfdpic_plt_section (info)->output_section->vma
+ + frvfdpic_plt_section (info)->output_offset
+ + frvfdpic_plt_tls_ret_offset (info),
+ frvfdpic_got_section (info)->contents
+ + frvfdpic_got_initial_offset (info)
+ + entry->tlsdesc_entry);
+
+ _frvfdpic_add_rofixup (output_bfd,
+ frvfdpic_gotfixup_section (info),
+ frvfdpic_got_section (info)
+ ->output_section->vma
+ + frvfdpic_got_section (info)
+ ->output_offset
+ + frvfdpic_got_initial_offset (info)
+ + entry->tlsdesc_entry, entry);
+
+ BFD_ASSERT (frvfdpic_dynamic_got_plt_info (info)->tls_ret_refs);
+
+ /* We've used one of the reserved fixups, so discount it so
+ that we can check at the end that we've used them
+ all. */
+ frvfdpic_dynamic_got_plt_info (info)->tls_ret_refs--;
+
+ /* While at that, make sure the ret instruction makes to the
+ right location in the PLT. We could do it only when we
+ got to 0, but since the check at the end will only print
+ a warning, make sure we have the ret in place in case the
+ warning is missed. */
+ bfd_put_32 (output_bfd, 0xc03a4000,
+ frvfdpic_plt_section (info)->contents
+ + frvfdpic_plt_tls_ret_offset (info));
+ }
+ else
+ {
+ if (idx == 0
+ && (bfd_is_abs_section (sec)
+ || bfd_is_und_section (sec)))
+ {
+ idx = elf_section_data (elf_hash_table (info)->tls_sec)->dynindx;
+ ad += FRVFDPIC_TLS_BIAS;
+ }
+
+ _frvfdpic_add_dyn_reloc (output_bfd, frvfdpic_gotrel_section (info),
+ _bfd_elf_section_offset
+ (output_bfd, info,
+ frvfdpic_got_section (info),
+ frvfdpic_got_initial_offset (info)
+ + entry->tlsdesc_entry)
+ + frvfdpic_got_section (info)
+ ->output_section->vma
+ + frvfdpic_got_section (info)
+ ->output_offset,
+ R_FRV_TLSDESC_VALUE, idx, ad, entry);
+
+ bfd_put_32 (output_bfd, 0,
+ frvfdpic_got_section (info)->contents
+ + frvfdpic_got_initial_offset (info)
+ + entry->tlsdesc_entry);
+ }
+
+ bfd_put_32 (output_bfd, ad,
+ frvfdpic_got_section (info)->contents
+ + frvfdpic_got_initial_offset (info)
+ + entry->tlsdesc_entry + 4);
+ }
+
+ /* Generate code for the get-TLS-offset PLT entry. */
+ if (entry->tlsplt_entry != (bfd_vma) -1)
+ {
+ bfd_byte *plt_code = frvfdpic_plt_section (info)->contents
+ + entry->tlsplt_entry;
+
+ if (info->executable
+ && (entry->symndx != -1
+ || FRVFDPIC_SYM_LOCAL (info, entry->d.h)))
+ {
+ int idx = dynindx;
+ bfd_vma ad = addend;
+
+ /* sec may be NULL when referencing an undefweak symbol
+ while linking a static executable. */
+ if (!sec)
+ {
+ BFD_ASSERT (entry->symndx == -1
+ && entry->d.h->root.type == bfd_link_hash_undefweak);
+ }
+ else
+ {
+ if (entry->symndx == -1)
+ ad += entry->d.h->root.u.def.value;
+ else
+ ad += sym->st_value;
+ ad += sec->output_offset;
+ if (sec->output_section
+ && elf_section_data (sec->output_section))
+ idx = elf_section_data (sec->output_section)->dynindx;
+ else
+ idx = 0;
+ }
+
+ /* *ABS*+addend is special for TLS relocations, use only the
+ addend for the TLS offset, and take the module id as
+ 0. */
+ if (idx == 0
+ && (bfd_is_abs_section (sec)
+ || bfd_is_und_section (sec)))
+ ;
+ /* For other TLS symbols that bind locally, add the section
+ TLS offset to the addend. */
+ else if (sec)
+ ad += sec->output_section->vma - tls_biased_base (info);
+
+ if ((bfd_signed_vma)ad >= -(1 << (16 - 1))
+ && (bfd_signed_vma)ad < (1 << (16 - 1)))
+ {
+ /* setlos lo(ad), gr9 */
+ bfd_put_32 (output_bfd,
+ 0x92fc0000
+ | (ad
+ & (((bfd_vma)1 << 16) - 1)),
+ plt_code);
+ plt_code += 4;
+ }
+ else
+ {
+ /* sethi.p hi(ad), gr9
+ setlo lo(ad), gr9 */
+ bfd_put_32 (output_bfd,
+ 0x12f80000
+ | ((ad >> 16)
+ & (((bfd_vma)1 << 16) - 1)),
+ plt_code);
+ plt_code += 4;
+ bfd_put_32 (output_bfd,
+ 0x92f40000
+ | (ad
+ & (((bfd_vma)1 << 16) - 1)),
+ plt_code);
+ plt_code += 4;
+ }
+ /* ret */
+ bfd_put_32 (output_bfd, 0xc03a4000, plt_code);
+ }
+ else if (entry->tlsoff_entry)
+ {
+ /* Figure out what kind of PLT entry we need, depending on the
+ location of the TLS descriptor within the GOT. */
+ if (entry->tlsoff_entry >= -(1 << (12 - 1))
+ && entry->tlsoff_entry < (1 << (12 - 1)))
+ {
+ /* ldi @(gr15, tlsoff_entry), gr9 */
+ bfd_put_32 (output_bfd,
+ 0x92c8f000 | (entry->tlsoff_entry
+ & ((1 << 12) - 1)),
+ plt_code);
+ plt_code += 4;
+ }
+ else
+ {
+ if (entry->tlsoff_entry >= -(1 << (16 - 1))
+ && entry->tlsoff_entry < (1 << (16 - 1)))
+ {
+ /* setlos lo(tlsoff_entry), gr8 */
+ bfd_put_32 (output_bfd,
+ 0x90fc0000
+ | (entry->tlsoff_entry
+ & (((bfd_vma)1 << 16) - 1)),
+ plt_code);
+ plt_code += 4;
+ }
+ else
+ {
+ /* sethi.p hi(tlsoff_entry), gr8
+ setlo lo(tlsoff_entry), gr8 */
+ bfd_put_32 (output_bfd,
+ 0x10f80000
+ | ((entry->tlsoff_entry >> 16)
+ & (((bfd_vma)1 << 16) - 1)),
+ plt_code);
+ plt_code += 4;
+ bfd_put_32 (output_bfd,
+ 0x90f40000
+ | (entry->tlsoff_entry
+ & (((bfd_vma)1 << 16) - 1)),
+ plt_code);
+ plt_code += 4;
+ }
+ /* ld @(gr15,gr8),gr9 */
+ bfd_put_32 (output_bfd, 0x9008f108, plt_code);
+ plt_code += 4;
+ }
+ /* ret */
+ bfd_put_32 (output_bfd, 0xc03a4000, plt_code);
+ }
+ else
+ {
+ BFD_ASSERT (entry->tlsdesc_entry);
+
+ /* Figure out what kind of PLT entry we need, depending on the
+ location of the TLS descriptor within the GOT. */
+ if (entry->tlsdesc_entry >= -(1 << (12 - 1))
+ && entry->tlsdesc_entry < (1 << (12 - 1)))
+ {
+ /* lddi @(gr15, tlsdesc_entry), gr8 */
+ bfd_put_32 (output_bfd,
+ 0x90ccf000 | (entry->tlsdesc_entry
+ & ((1 << 12) - 1)),
+ plt_code);
+ plt_code += 4;
+ }
+ else
+ {
+ if (entry->tlsdesc_entry >= -(1 << (16 - 1))
+ && entry->tlsdesc_entry < (1 << (16 - 1)))
+ {
+ /* setlos lo(tlsdesc_entry), gr8 */
+ bfd_put_32 (output_bfd,
+ 0x90fc0000
+ | (entry->tlsdesc_entry
+ & (((bfd_vma)1 << 16) - 1)),
+ plt_code);
+ plt_code += 4;
+ }
+ else
+ {
+ /* sethi.p hi(tlsdesc_entry), gr8
+ setlo lo(tlsdesc_entry), gr8 */
+ bfd_put_32 (output_bfd,
+ 0x10f80000
+ | ((entry->tlsdesc_entry >> 16)
+ & (((bfd_vma)1 << 16) - 1)),
+ plt_code);
+ plt_code += 4;
+ bfd_put_32 (output_bfd,
+ 0x90f40000
+ | (entry->tlsdesc_entry
+ & (((bfd_vma)1 << 16) - 1)),
+ plt_code);
+ plt_code += 4;
+ }
+ /* ldd @(gr15,gr8),gr8 */
+ bfd_put_32 (output_bfd, 0x9008f148, plt_code);
+ plt_code += 4;
+ }
+ /* jmpl @(gr8,gr0) */
+ bfd_put_32 (output_bfd, 0x80308000, plt_code);
+ }
+ }
+
return TRUE;
}
@@ -1756,6 +2602,60 @@ frv_reloc_type_lookup (abfd, code)
case BFD_RELOC_FRV_GOTOFFLO:
return &elf32_frv_howto_table[ (int) R_FRV_GOTOFFLO];
+ case BFD_RELOC_FRV_GETTLSOFF:
+ return &elf32_frv_howto_table[ (int) R_FRV_GETTLSOFF];
+
+ case BFD_RELOC_FRV_TLSDESC_VALUE:
+ if (elf_elfheader (abfd)->e_type == ET_EXEC
+ || elf_elfheader (abfd)->e_type == ET_DYN)
+ return &elf32_frv_rel_tlsdesc_value_howto;
+ return &elf32_frv_howto_table[ (int) R_FRV_TLSDESC_VALUE];
+
+ case BFD_RELOC_FRV_GOTTLSDESC12:
+ return &elf32_frv_howto_table[ (int) R_FRV_GOTTLSDESC12];
+
+ case BFD_RELOC_FRV_GOTTLSDESCHI:
+ return &elf32_frv_howto_table[ (int) R_FRV_GOTTLSDESCHI];
+
+ case BFD_RELOC_FRV_GOTTLSDESCLO:
+ return &elf32_frv_howto_table[ (int) R_FRV_GOTTLSDESCLO];
+
+ case BFD_RELOC_FRV_TLSMOFF12:
+ return &elf32_frv_howto_table[ (int) R_FRV_TLSMOFF12];
+
+ case BFD_RELOC_FRV_TLSMOFFHI:
+ return &elf32_frv_howto_table[ (int) R_FRV_TLSMOFFHI];
+
+ case BFD_RELOC_FRV_TLSMOFFLO:
+ return &elf32_frv_howto_table[ (int) R_FRV_TLSMOFFLO];
+
+ case BFD_RELOC_FRV_GOTTLSOFF12:
+ return &elf32_frv_howto_table[ (int) R_FRV_GOTTLSOFF12];
+
+ case BFD_RELOC_FRV_GOTTLSOFFHI:
+ return &elf32_frv_howto_table[ (int) R_FRV_GOTTLSOFFHI];
+
+ case BFD_RELOC_FRV_GOTTLSOFFLO:
+ return &elf32_frv_howto_table[ (int) R_FRV_GOTTLSOFFLO];
+
+ case BFD_RELOC_FRV_TLSOFF:
+ if (elf_elfheader (abfd)->e_type == ET_EXEC
+ || elf_elfheader (abfd)->e_type == ET_DYN)
+ return &elf32_frv_rel_tlsoff_howto;
+ return &elf32_frv_howto_table[ (int) R_FRV_TLSOFF];
+
+ case BFD_RELOC_FRV_TLSDESC_RELAX:
+ return &elf32_frv_howto_table[ (int) R_FRV_TLSDESC_RELAX];
+
+ case BFD_RELOC_FRV_GETTLSOFF_RELAX:
+ return &elf32_frv_howto_table[ (int) R_FRV_GETTLSOFF_RELAX];
+
+ case BFD_RELOC_FRV_TLSOFF_RELAX:
+ return &elf32_frv_howto_table[ (int) R_FRV_TLSOFF_RELAX];
+
+ case BFD_RELOC_FRV_TLSMOFF:
+ return &elf32_frv_howto_table[ (int) R_FRV_TLSMOFF];
+
case BFD_RELOC_VTABLE_INHERIT:
return &elf32_frv_vtinherit_howto;
@@ -1815,6 +2715,14 @@ frvfdpic_info_to_howto_rel (bfd *abfd ATTRIBUTE_UNUSED,
cache_ptr->howto = &elf32_frv_rel_funcdesc_value_howto;
break;
+ case R_FRV_TLSDESC_VALUE:
+ cache_ptr->howto = &elf32_frv_rel_tlsdesc_value_howto;
+ break;
+
+ case R_FRV_TLSOFF:
+ cache_ptr->howto = &elf32_frv_rel_tlsoff_howto;
+ break;
+
default:
cache_ptr->howto = NULL;
break;
@@ -1886,9 +2794,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
struct elf_link_hash_entry **sym_hashes;
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
- unsigned isec_segment, got_segment, plt_segment, gprel_segment,
+ unsigned isec_segment, got_segment, plt_segment, gprel_segment, tls_segment,
check_segment[2];
int silence_segment_error = !(info->shared || info->pie);
+ unsigned long insn;
if (info->relocatable)
return TRUE;
@@ -1911,12 +2820,17 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
->output_section);
else
gprel_segment = -1;
- if (IS_FDPIC (output_bfd) && elf_hash_table (info)->dynamic_sections_created)
+ if (IS_FDPIC (output_bfd) && frvfdpic_plt_section (info))
plt_segment = _frvfdpic_osec_to_segment (output_bfd,
frvfdpic_plt_section (info)
->output_section);
else
plt_segment = -1;
+ if (elf_hash_table (info)->tls_sec)
+ tls_segment = _frvfdpic_osec_to_segment (output_bfd,
+ elf_hash_table (info)->tls_sec);
+ else
+ tls_segment = -1;
for (rel = relocs; rel < relend; rel ++)
{
@@ -1967,20 +2881,22 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
name = h->root.root.string;
if ((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && ! FRVFDPIC_SYM_LOCAL (info, h))
- {
- sec = NULL;
- relocation = 0;
- }
- else
- if (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
+ || h->root.type == bfd_link_hash_defweak))
{
- sec = h->root.u.def.section;
- relocation = (h->root.u.def.value
- + sec->output_section->vma
- + sec->output_offset);
+ if (/* TLSMOFF forces local binding. */
+ r_type != R_FRV_TLSMOFF
+ && ! FRVFDPIC_SYM_LOCAL (info, h))
+ {
+ sec = NULL;
+ relocation = 0;
+ }
+ else
+ {
+ sec = h->root.u.def.section;
+ relocation = (h->root.u.def.value
+ + sec->output_section->vma
+ + sec->output_offset);
+ }
}
else if (h->root.type == bfd_link_hash_undefweak)
{
@@ -2023,6 +2939,22 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
case R_FRV_FUNCDESC_GOTOFFLO:
case R_FRV_FUNCDESC:
case R_FRV_FUNCDESC_VALUE:
+ case R_FRV_GETTLSOFF:
+ case R_FRV_TLSDESC_VALUE:
+ case R_FRV_GOTTLSDESC12:
+ case R_FRV_GOTTLSDESCHI:
+ case R_FRV_GOTTLSDESCLO:
+ case R_FRV_TLSMOFF12:
+ case R_FRV_TLSMOFFHI:
+ case R_FRV_TLSMOFFLO:
+ case R_FRV_GOTTLSOFF12:
+ case R_FRV_GOTTLSOFFHI:
+ case R_FRV_GOTTLSOFFLO:
+ case R_FRV_TLSOFF:
+ case R_FRV_TLSDESC_RELAX:
+ case R_FRV_GETTLSOFF_RELAX:
+ case R_FRV_TLSOFF_RELAX:
+ case R_FRV_TLSMOFF:
if (h != NULL)
picrel = frvfdpic_relocs_info_for_global (frvfdpic_relocs_info
(info), input_bfd, h,
@@ -2065,6 +2997,604 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
switch (r_type)
{
+ case R_FRV_GETTLSOFF:
+ case R_FRV_TLSDESC_VALUE:
+ case R_FRV_GOTTLSDESC12:
+ case R_FRV_GOTTLSDESCHI:
+ case R_FRV_GOTTLSDESCLO:
+ case R_FRV_TLSMOFF12:
+ case R_FRV_TLSMOFFHI:
+ case R_FRV_TLSMOFFLO:
+ case R_FRV_GOTTLSOFF12:
+ case R_FRV_GOTTLSOFFHI:
+ case R_FRV_GOTTLSOFFLO:
+ case R_FRV_TLSOFF:
+ case R_FRV_TLSDESC_RELAX:
+ case R_FRV_GETTLSOFF_RELAX:
+ case R_FRV_TLSOFF_RELAX:
+ case R_FRV_TLSMOFF:
+ if (sec && (bfd_is_abs_section (sec) || bfd_is_und_section (sec)))
+ relocation += tls_biased_base (info);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Try to apply TLS relaxations. */
+ if (1)
+ switch (r_type)
+ {
+
+#define LOCAL_EXEC_P(info, picrel) \
+ ((info)->executable \
+ && (picrel->symndx != -1 || FRVFDPIC_SYM_LOCAL ((info), (picrel)->d.h)))
+#define INITIAL_EXEC_P(info, picrel) \
+ (((info)->executable || (info)->flags & DF_STATIC_TLS) \
+ && (picrel)->tlsoff_entry)
+
+#define IN_RANGE_FOR_OFST12_P(value) \
+ ((bfd_vma)((value) + 2048) < (bfd_vma)4096)
+#define IN_RANGE_FOR_SETLOS_P(value) \
+ ((bfd_vma)((value) + 32768) < (bfd_vma)65536)
+#define TLSMOFF_IN_RANGE_FOR_SETLOS_P(value, info) \
+ (IN_RANGE_FOR_SETLOS_P ((value) - tls_biased_base (info)))
+
+#define RELAX_GETTLSOFF_LOCAL_EXEC_P(info, picrel, value) \
+ (LOCAL_EXEC_P ((info), (picrel)) \
+ && TLSMOFF_IN_RANGE_FOR_SETLOS_P((value), (info)))
+#define RELAX_GETTLSOFF_INITIAL_EXEC_P(info, picrel) \
+ (INITIAL_EXEC_P ((info), (picrel)) \
+ && IN_RANGE_FOR_OFST12_P ((picrel)->tlsoff_entry))
+
+#define RELAX_TLSDESC_LOCAL_EXEC_P(info, picrel, value) \
+ (LOCAL_EXEC_P ((info), (picrel)))
+#define RELAX_TLSDESC_INITIAL_EXEC_P(info, picrel) \
+ (INITIAL_EXEC_P ((info), (picrel)))
+
+#define RELAX_GOTTLSOFF_LOCAL_EXEC_P(info, picrel, value) \
+ (LOCAL_EXEC_P ((info), (picrel)) \
+ && TLSMOFF_IN_RANGE_FOR_SETLOS_P((value), (info)))
+
+ case R_FRV_GETTLSOFF:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this a call instruction? */
+ if ((insn & (unsigned long)0x01fc0000) != 0x003c0000)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_GETTLSOFF not applied to a call instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (RELAX_GETTLSOFF_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend))
+ {
+ /* Replace the call instruction (except the packing bit)
+ with setlos #tlsmofflo(symbol+offset), gr9. */
+ insn &= (unsigned long)0x80000000;
+ insn |= (unsigned long)0x12fc0000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_TLSMOFFLO;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ else if (RELAX_GETTLSOFF_INITIAL_EXEC_P (info, picrel))
+ {
+ /* Replace the call instruction (except the packing bit)
+ with ldi @(gr15, #gottlsoff12(symbol+addend)), gr9. */
+ insn &= (unsigned long)0x80000000;
+ insn |= (unsigned long)0x12c8f000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_GOTTLSOFF12;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ break;
+
+ case R_FRV_GOTTLSDESC12:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this an lddi instruction? */
+ if ((insn & (unsigned long)0x01fc0000) != 0x00cc0000)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_GOTTLSDESC12 not applied to an lddi instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (RELAX_TLSDESC_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend)
+ && TLSMOFF_IN_RANGE_FOR_SETLOS_P (relocation + rel->r_addend,
+ info))
+ {
+ /* Replace lddi @(grB, #gottlsdesc12(symbol+offset), grC
+ with setlos #tlsmofflo(symbol+offset), gr<C+1>.
+ Preserve the packing bit. */
+ insn = (insn & (unsigned long)0x80000000)
+ | ((insn + (unsigned long)0x02000000)
+ & (unsigned long)0x7e000000);
+ insn |= (unsigned long)0x00fc0000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_TLSMOFFLO;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ else if (RELAX_TLSDESC_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend))
+ {
+ /* Replace lddi @(grB, #gottlsdesc12(symbol+offset), grC
+ with sethi #tlsmoffhi(symbol+offset), gr<C+1>.
+ Preserve the packing bit. */
+ insn = (insn & (unsigned long)0x80000000)
+ | ((insn + (unsigned long)0x02000000)
+ & (unsigned long)0x7e000000);
+ insn |= (unsigned long)0x00f80000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_TLSMOFFHI;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ else if (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel))
+ {
+ /* Replace lddi @(grB, #gottlsdesc12(symbol+offset), grC
+ with ldi @(grB, #gottlsoff12(symbol+offset),
+ gr<C+1>. Preserve the packing bit. If gottlsoff12
+ overflows, we'll error out, but that's sort-of ok,
+ since we'd started with gottlsdesc12, that's actually
+ more demanding. Compiling with -fPIE instead of
+ -fpie would fix it; linking with --relax should fix
+ it as well. */
+ insn = (insn & (unsigned long)0x80cbf000)
+ | ((insn + (unsigned long)0x02000000)
+ & (unsigned long)0x7e000000);
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_GOTTLSOFF12;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ break;
+
+ case R_FRV_GOTTLSDESCHI:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this a sethi instruction? */
+ if ((insn & (unsigned long)0x01ff0000) != 0x00f80000)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_GOTTLSDESCHI not applied to a sethi instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (RELAX_TLSDESC_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend)
+ || (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel)
+ && IN_RANGE_FOR_SETLOS_P (picrel->tlsoff_entry)))
+ {
+ /* Replace sethi with a nop. Preserve the packing bit. */
+ insn &= (unsigned long)0x80000000;
+ insn |= (unsigned long)0x00880000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ /* Nothing to relocate. */
+ continue;
+ }
+
+ else if (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel))
+ {
+ /* Simply decay GOTTLSDESC to GOTTLSOFF. */
+ r_type = R_FRV_GOTTLSOFFHI;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ break;
+
+ case R_FRV_GOTTLSDESCLO:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this a setlo or setlos instruction? */
+ if ((insn & (unsigned long)0x01f70000) != 0x00f40000)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_GOTTLSDESCLO"
+ " not applied to a setlo or setlos instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (RELAX_TLSDESC_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend)
+ || (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel)
+ && IN_RANGE_FOR_OFST12_P (picrel->tlsoff_entry)))
+ {
+ /* Replace setlo/setlos with a nop. Preserve the
+ packing bit. */
+ insn &= (unsigned long)0x80000000;
+ insn |= (unsigned long)0x00880000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ /* Nothing to relocate. */
+ continue;
+ }
+
+ else if (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel))
+ {
+ /* If the corresponding sethi (if it exists) decayed
+ to a nop, make sure this becomes (or already is) a
+ setlos, not setlo. */
+ if (IN_RANGE_FOR_SETLOS_P (picrel->tlsoff_entry))
+ {
+ insn |= (unsigned long)0x00080000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+ }
+
+ /* Simply decay GOTTLSDESC to GOTTLSOFF. */
+ r_type = R_FRV_GOTTLSOFFLO;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ break;
+
+ case R_FRV_TLSDESC_RELAX:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this an ldd instruction? */
+ if ((insn & (unsigned long)0x01fc0fc0) != 0x00080140)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_TLSDESC_RELAX not applied to an ldd instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (RELAX_TLSDESC_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend)
+ && TLSMOFF_IN_RANGE_FOR_SETLOS_P (relocation + rel->r_addend,
+ info))
+ {
+ /* Replace ldd #tlsdesc(symbol+offset)@(grB, grA), grC
+ with setlos #tlsmofflo(symbol+offset), gr<C+1>.
+ Preserve the packing bit. */
+ insn = (insn & (unsigned long)0x80000000)
+ | ((insn + (unsigned long)0x02000000)
+ & (unsigned long)0x7e000000);
+ insn |= (unsigned long)0x00fc0000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_TLSMOFFLO;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ else if (RELAX_TLSDESC_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend))
+ {
+ /* Replace ldd #tlsdesc(symbol+offset)@(grB, grA), grC
+ with sethi #tlsmoffhi(symbol+offset), gr<C+1>.
+ Preserve the packing bit. */
+ insn = (insn & (unsigned long)0x80000000)
+ | ((insn + (unsigned long)0x02000000)
+ & (unsigned long)0x7e000000);
+ insn |= (unsigned long)0x00f80000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_TLSMOFFHI;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ else if (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel)
+ && IN_RANGE_FOR_OFST12_P (picrel->tlsoff_entry))
+ {
+ /* Replace ldd #tlsdesc(symbol+offset)@(grB, grA), grC
+ with ldi @(grB, #gottlsoff12(symbol+offset), gr<C+1>.
+ Preserve the packing bit. */
+ insn = (insn & (unsigned long)0x8003f000)
+ | (unsigned long)0x00c80000
+ | ((insn + (unsigned long)0x02000000)
+ & (unsigned long)0x7e000000);
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_GOTTLSOFF12;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ else if (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel))
+ {
+ /* Replace ldd #tlsdesc(symbol+offset)@(grB, grA), grC
+ with ld #tlsoff(symbol+offset)@(grB, grA), gr<C+1>.
+ Preserve the packing bit. */
+ insn = (insn & (unsigned long)0x81ffffbf)
+ | ((insn + (unsigned long)0x02000000)
+ & (unsigned long)0x7e000000);
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ /* #tlsoff(symbol+offset) is just a relaxation
+ annotation, so there's nothing left to
+ relocate. */
+ continue;
+ }
+
+ break;
+
+ case R_FRV_GETTLSOFF_RELAX:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this a calll or callil instruction? */
+ if ((insn & (unsigned long)0x7ff80fc0) != 0x02300000)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_GETTLSOFF_RELAX"
+ " not applied to a calll instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (RELAX_TLSDESC_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend)
+ && TLSMOFF_IN_RANGE_FOR_SETLOS_P (relocation + rel->r_addend,
+ info))
+ {
+ /* Replace calll with a nop. Preserve the packing bit. */
+ insn &= (unsigned long)0x80000000;
+ insn |= (unsigned long)0x00880000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ /* Nothing to relocate. */
+ continue;
+ }
+
+ else if (RELAX_TLSDESC_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend))
+ {
+ /* Replace calll with setlo #tlsmofflo(symbol+offset), gr9.
+ Preserve the packing bit. */
+ insn &= (unsigned long)0x80000000;
+ insn |= (unsigned long)0x12f40000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_TLSMOFFLO;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ else if (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel))
+ {
+ /* Replace calll with a nop. Preserve the packing bit. */
+ insn &= (unsigned long)0x80000000;
+ insn |= (unsigned long)0x00880000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ /* Nothing to relocate. */
+ continue;
+ }
+
+ break;
+
+ case R_FRV_GOTTLSOFF12:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this an ldi instruction? */
+ if ((insn & (unsigned long)0x01fc0000) != 0x00c80000)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_GOTTLSOFF12 not applied to an ldi instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (RELAX_GOTTLSOFF_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend))
+ {
+ /* Replace ldi @(grB, #gottlsoff12(symbol+offset), grC
+ with setlos #tlsmofflo(symbol+offset), grC.
+ Preserve the packing bit. */
+ insn &= (unsigned long)0xfe000000;
+ insn |= (unsigned long)0x00fc0000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_TLSMOFFLO;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ break;
+
+ case R_FRV_GOTTLSOFFHI:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this a sethi instruction? */
+ if ((insn & (unsigned long)0x01ff0000) != 0x00f80000)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_GOTTLSOFFHI not applied to a sethi instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (RELAX_GOTTLSOFF_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend)
+ || (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel)
+ && IN_RANGE_FOR_OFST12_P (picrel->tlsoff_entry)))
+ {
+ /* Replace sethi with a nop. Preserve the packing bit. */
+ insn &= (unsigned long)0x80000000;
+ insn |= (unsigned long)0x00880000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ /* Nothing to relocate. */
+ continue;
+ }
+
+ break;
+
+ case R_FRV_GOTTLSOFFLO:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this a setlo or setlos instruction? */
+ if ((insn & (unsigned long)0x01f70000) != 0x00f40000)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_GOTTLSOFFLO"
+ " not applied to a setlo or setlos instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (RELAX_GOTTLSOFF_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend)
+ || (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel)
+ && IN_RANGE_FOR_OFST12_P (picrel->tlsoff_entry)))
+ {
+ /* Replace setlo/setlos with a nop. Preserve the
+ packing bit. */
+ insn &= (unsigned long)0x80000000;
+ insn |= (unsigned long)0x00880000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ /* Nothing to relocate. */
+ continue;
+ }
+
+ break;
+
+ case R_FRV_TLSOFF_RELAX:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this an ld instruction? */
+ if ((insn & (unsigned long)0x01fc0fc0) != 0x00080100)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_TLSOFF_RELAX not applied to an ld instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (RELAX_GOTTLSOFF_LOCAL_EXEC_P (info, picrel,
+ relocation + rel->r_addend))
+ {
+ /* Replace ld #gottlsoff(symbol+offset)@(grB, grA), grC
+ with setlos #tlsmofflo(symbol+offset), grC.
+ Preserve the packing bit. */
+ insn &= (unsigned long)0xfe000000;
+ insn |= (unsigned long)0x00fc0000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_TLSMOFFLO;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ else if (RELAX_TLSDESC_INITIAL_EXEC_P (info, picrel)
+ && IN_RANGE_FOR_OFST12_P (picrel->tlsoff_entry))
+ {
+ /* Replace ld #tlsoff(symbol+offset)@(grB, grA), grC
+ with ldi @(grB, #gottlsoff12(symbol+offset), grC.
+ Preserve the packing bit. */
+ insn = (insn & (unsigned long)0xfe03f000)
+ | (unsigned long)0x00c80000;;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ r_type = R_FRV_GOTTLSOFF12;
+ howto = elf32_frv_howto_table + r_type;
+ rel->r_info = ELF32_R_INFO (r_symndx, r_type);
+ }
+
+ break;
+
+ case R_FRV_TLSMOFFHI:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this a sethi instruction? */
+ if ((insn & (unsigned long)0x01ff0000) != 0x00f80000)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_TLSMOFFHI not applied to a sethi instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (TLSMOFF_IN_RANGE_FOR_SETLOS_P (relocation + rel->r_addend,
+ info))
+ {
+ /* Replace sethi with a nop. Preserve the packing bit. */
+ insn &= (unsigned long)0x80000000;
+ insn |= (unsigned long)0x00880000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+
+ /* Nothing to relocate. */
+ continue;
+ }
+
+ break;
+
+ case R_FRV_TLSMOFFLO:
+ insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+ /* Is this a setlo or setlos instruction? */
+ if ((insn & (unsigned long)0x01f70000) != 0x00f40000)
+ {
+ r = info->callbacks->warning
+ (info,
+ _("R_FRV_TLSMOFFLO"
+ " not applied to a setlo or setlos instruction"),
+ name, input_bfd, input_section, rel->r_offset);
+ return FALSE;
+ }
+
+ if (TLSMOFF_IN_RANGE_FOR_SETLOS_P (relocation + rel->r_addend,
+ info))
+ /* If the corresponding sethi (if it exists) decayed
+ to a nop, make sure this becomes (or already is) a
+ setlos, not setlo. */
+ {
+ insn |= (unsigned long)0x00080000;
+ bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
+ }
+
+ break;
+
+#if 0 /* There's nothing to relax in these. */
+ case R_FRV_TLSDESC_VALUE:
+ case R_FRV_TLSOFF:
+ case R_FRV_TLSMOFF12:
+ case R_FRV_TLSMOFFHI:
+ case R_FRV_TLSMOFFLO:
+ case R_FRV_TLSMOFF:
+#endif
+ default:
+ break;
+ }
+
+ switch (r_type)
+ {
case R_FRV_LABEL24:
check_segment[0] = isec_segment;
if (! IS_FDPIC (output_bfd))
@@ -2408,6 +3938,76 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
: (unsigned)-1;
break;
+ case R_FRV_GETTLSOFF:
+ relocation = frvfdpic_plt_section (info)->output_section->vma
+ + frvfdpic_plt_section (info)->output_offset
+ + picrel->tlsplt_entry;
+ BFD_ASSERT (picrel->tlsplt_entry != (bfd_vma)-1
+ && picrel->tlsdesc_entry);
+ check_segment[0] = isec_segment;
+ check_segment[1] = plt_segment;
+ break;
+
+ case R_FRV_GOTTLSDESC12:
+ case R_FRV_GOTTLSDESCHI:
+ case R_FRV_GOTTLSDESCLO:
+ BFD_ASSERT (picrel->tlsdesc_entry);
+ relocation = picrel->tlsdesc_entry;
+ check_segment[0] = tls_segment;
+ check_segment[1] = sec
+ && ! bfd_is_abs_section (sec)
+ && ! bfd_is_und_section (sec)
+ ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section)
+ : tls_segment;
+ break;
+
+ case R_FRV_TLSMOFF12:
+ case R_FRV_TLSMOFFHI:
+ case R_FRV_TLSMOFFLO:
+ case R_FRV_TLSMOFF:
+ check_segment[0] = tls_segment;
+ if (! sec)
+ check_segment[1] = -1;
+ else if (bfd_is_abs_section (sec)
+ || bfd_is_und_section (sec))
+ {
+ relocation = 0;
+ check_segment[1] = tls_segment;
+ }
+ else if (sec->output_section)
+ {
+ relocation -= tls_biased_base (info);
+ check_segment[1] =
+ _frvfdpic_osec_to_segment (output_bfd, sec->output_section);
+ }
+ break;
+
+ case R_FRV_GOTTLSOFF12:
+ case R_FRV_GOTTLSOFFHI:
+ case R_FRV_GOTTLSOFFLO:
+ BFD_ASSERT (picrel->tlsoff_entry);
+ relocation = picrel->tlsoff_entry;
+ check_segment[0] = tls_segment;
+ check_segment[1] = sec
+ && ! bfd_is_abs_section (sec)
+ && ! bfd_is_und_section (sec)
+ ? _frvfdpic_osec_to_segment (output_bfd, sec->output_section)
+ : tls_segment;
+ break;
+
+ case R_FRV_TLSDESC_VALUE:
+ case R_FRV_TLSOFF:
+ /* These shouldn't be present in input object files. */
+ check_segment[0] = check_segment[1] = isec_segment;
+ break;
+
+ case R_FRV_TLSDESC_RELAX:
+ case R_FRV_GETTLSOFF_RELAX:
+ case R_FRV_TLSOFF_RELAX:
+ /* These are just annotations for relaxation, nothing to do
+ here. */
+ continue;
+
default:
check_segment[0] = isec_segment;
check_segment[1] = sec
@@ -2452,6 +4052,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
switch (r_type)
{
case R_FRV_GOTOFFHI:
+ case R_FRV_TLSMOFFHI:
/* We need the addend to be applied before we shift the
value right. */
relocation += rel->r_addend;
@@ -2459,6 +4060,8 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
case R_FRV_GOTHI:
case R_FRV_FUNCDESC_GOTHI:
case R_FRV_FUNCDESC_GOTOFFHI:
+ case R_FRV_GOTTLSOFFHI:
+ case R_FRV_GOTTLSDESCHI:
relocation >>= 16;
/* Fall through. */
@@ -2466,6 +4069,9 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
case R_FRV_FUNCDESC_GOTLO:
case R_FRV_GOTOFFLO:
case R_FRV_FUNCDESC_GOTOFFLO:
+ case R_FRV_GOTTLSOFFLO:
+ case R_FRV_GOTTLSDESCLO:
+ case R_FRV_TLSMOFFLO:
relocation &= 0xffff;
break;
@@ -2494,11 +4100,19 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
case R_FRV_FUNCDESC_GOTOFF12:
case R_FRV_FUNCDESC_GOTOFFHI:
case R_FRV_FUNCDESC_GOTOFFLO:
+ case R_FRV_GETTLSOFF:
+ case R_FRV_GOTTLSDESC12:
+ case R_FRV_GOTTLSDESCHI:
+ case R_FRV_GOTTLSDESCLO:
+ case R_FRV_GOTTLSOFF12:
+ case R_FRV_GOTTLSOFFHI:
+ case R_FRV_GOTTLSOFFLO:
/* Note that we only want GOTOFFHI, not GOTOFFLO or GOTOFF12
here, since we do want to apply the addend to the others.
Note that we've applied the addend to GOTOFFHI before we
shifted it right. */
case R_FRV_GOTOFFHI:
+ case R_FRV_TLSMOFFHI:
relocation -= rel->r_addend;
break;
@@ -2512,7 +4126,7 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
else if (r_type == R_FRV_LO16)
r = elf32_frv_relocate_lo16 (input_bfd, rel, contents, relocation);
- else if (r_type == R_FRV_LABEL24)
+ else if (r_type == R_FRV_LABEL24 || r_type == R_FRV_GETTLSOFF)
r = elf32_frv_relocate_label24 (input_bfd, input_section, rel,
contents, relocation);
@@ -2532,6 +4146,10 @@ elf32_frv_relocate_section (output_bfd, info, input_bfd, input_section,
r = elf32_frv_relocate_gprelhi (info, input_bfd, input_section, rel,
contents, relocation);
+ else if (r_type == R_FRV_TLSOFF
+ || r_type == R_FRV_TLSDESC_VALUE)
+ r = bfd_reloc_notsupported;
+
else
r = frv_final_link_relocate (howto, input_bfd, input_section, contents,
rel, relocation);
@@ -2705,7 +4323,7 @@ _frvfdpic_link_omit_section_dynsym (bfd *output_bfd ATTRIBUTE_UNUSED,
static bfd_boolean
_frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
{
- flagword flags;
+ flagword flags, pltflags;
asection *s;
struct elf_link_hash_entry *h;
struct bfd_link_hash_entry *bh;
@@ -2726,6 +4344,7 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
| SEC_LINKER_CREATED);
+ pltflags = flags;
s = bfd_make_section (abfd, ".got");
if (s == NULL
@@ -2757,6 +4376,7 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
h = (struct elf_link_hash_entry *) bh;
h->def_regular = 1;
h->type = STT_OBJECT;
+ /* h->other = STV_HIDDEN; */ /* Should we? */
/* Machine-specific: we want the symbol for executables as
well. */
@@ -2774,7 +4394,8 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
if (IS_FDPIC (abfd))
{
frvfdpic_got_section (info) = s;
- frvfdpic_relocs_info (info) = htab_try_create (1, frvfdpic_relocs_info_hash,
+ frvfdpic_relocs_info (info) = htab_try_create (1,
+ frvfdpic_relocs_info_hash,
frvfdpic_relocs_info_eq,
(htab_del) NULL);
if (! frvfdpic_relocs_info (info))
@@ -2816,33 +4437,22 @@ _frv_create_got_section (bfd *abfd, struct bfd_link_info *info)
h = (struct elf_link_hash_entry *) bh;
h->def_regular = 1;
h->type = STT_OBJECT;
+ /* h->other = STV_HIDDEN; */ /* Should we? */
/* Machine-specific: we want the symbol for executables as well. */
if (IS_FDPIC (abfd) && ! bfd_elf_link_record_dynamic_symbol (info, h))
return FALSE;
- return TRUE;
-}
+ if (!IS_FDPIC (abfd))
+ return TRUE;
-/* Make sure the got and plt sections exist, and that our pointers in
- the link hash table point to them. */
+ /* FDPIC supports Thread Local Storage, and this may require a
+ procedure linkage table for TLS PLT entries. */
-static bfd_boolean
-elf32_frvfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
-{
/* This is mostly copied from
elflink.c:_bfd_elf_create_dynamic_sections(). */
- flagword flags, pltflags;
- asection *s;
- const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-
- /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
- .rel[a].bss sections. */
-
- flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
- | SEC_LINKER_CREATED);
- pltflags = flags;
+ flags = pltflags;
pltflags |= SEC_CODE;
if (bed->plt_not_loaded)
pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
@@ -2871,6 +4481,7 @@ elf32_frvfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
h = (struct elf_link_hash_entry *) bh;
h->def_regular = 1;
h->type = STT_OBJECT;
+ /* h->other = STV_HIDDEN; */ /* Should we? */
if (! info->executable
&& ! bfd_elf_link_record_dynamic_symbol (info, h))
@@ -2886,7 +4497,29 @@ elf32_frvfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
/* FRV-specific: remember it. */
frvfdpic_pltrel_section (info) = s;
- /* FRV-specific: we want to create the GOT in the FRV way. */
+ return TRUE;
+}
+
+/* Make sure the got and plt sections exist, and that our pointers in
+ the link hash table point to them. */
+
+static bfd_boolean
+elf32_frvfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
+{
+ /* This is mostly copied from
+ elflink.c:_bfd_elf_create_dynamic_sections(). */
+ flagword flags;
+ asection *s;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+ flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED);
+
+ /* We need to create .plt, .rel[a].plt, .got, .got.plt, .dynbss, and
+ .rel[a].bss sections. */
+
+ /* FRV-specific: we want to create the GOT and the PLT in the FRV
+ way. */
if (! _frv_create_got_section (abfd, info))
return FALSE;
@@ -2935,49 +4568,16 @@ elf32_frvfdpic_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
return TRUE;
}
-/* The name of the dynamic interpreter. This is put in the .interp
- section. */
+/* Compute the total GOT and PLT size required by each symbol in each
+ range. Symbols may require up to 4 words in the GOT: an entry
+ pointing to the symbol, an entry pointing to its function
+ descriptor, and a private function descriptors taking two
+ words. */
-#define ELF_DYNAMIC_INTERPRETER "/lib/ld.so.1"
-
-#define DEFAULT_STACK_SIZE 0x20000
-
-/* This structure is used to collect the number of entries present in
- each addressable range of the got. */
-struct _frvfdpic_dynamic_got_info
-{
- /* Several bits of information about the current link. */
- struct bfd_link_info *info;
- /* Total size needed for GOT entries within the 12-, 16- or 32-bit
- ranges. */
- bfd_vma got12, gotlos, gothilo;
- /* Total size needed for function descriptor entries within the 12-,
- 16- or 32-bit ranges. */
- bfd_vma fd12, fdlos, fdhilo;
- /* Total size needed function descriptor entries referenced in PLT
- entries, that would be profitable to place in offsets close to
- the PIC register. */
- bfd_vma fdplt;
- /* Total size needed by lazy PLT entries. */
- bfd_vma lzplt;
- /* Number of relocations carried over from input object files. */
- unsigned long relocs;
- /* Number of fixups introduced by relocations in input object files. */
- unsigned long fixups;
-};
-
-/* Compute the total GOT size required by each symbol in each range.
- Symbols may require up to 4 words in the GOT: an entry pointing to
- the symbol, an entry pointing to its function descriptor, and a
- private function descriptors taking two words. */
-
-static int
-_frvfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
+static void
+_frvfdpic_count_nontls_entries (struct frvfdpic_relocs_info *entry,
+ struct _frvfdpic_dynamic_got_info *dinfo)
{
- struct frvfdpic_relocs_info *entry = *entryp;
- struct _frvfdpic_dynamic_got_info *dinfo = dinfo_;
- unsigned relocs = 0, fixups = 0;
-
/* Allocate space for a GOT entry pointing to the symbol. */
if (entry->got12)
dinfo->got12 += 4;
@@ -3031,9 +4631,82 @@ _frvfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
if (entry->lazyplt)
dinfo->lzplt += 8;
+}
+
+/* Compute the total GOT size required by each TLS symbol in each
+ range. Symbols may require up to 5 words in the GOT: an entry
+ holding the TLS offset for the symbol, and an entry with a full TLS
+ descriptor taking 4 words. */
+
+static void
+_frvfdpic_count_tls_entries (struct frvfdpic_relocs_info *entry,
+ struct _frvfdpic_dynamic_got_info *dinfo,
+ bfd_boolean subtract)
+{
+ const int l = subtract ? -1 : 1;
+
+ /* Allocate space for a GOT entry with the TLS offset of the
+ symbol. */
+ if (entry->tlsoff12)
+ dinfo->got12 += 4 * l;
+ else if (entry->tlsofflos)
+ dinfo->gotlos += 4 * l;
+ else if (entry->tlsoffhilo)
+ dinfo->gothilo += 4 * l;
+ else
+ entry->relocstlsoff -= l;
+ entry->relocstlsoff += l;
+
+ /* If there's any TLSOFF relocation, mark the output file as not
+ suitable for dlopening. This mark will remain even if we relax
+ all such relocations, but this is not a problem, since we'll only
+ do so for executables, and we definitely don't want anyone
+ dlopening executables. */
+ if (entry->relocstlsoff)
+ dinfo->info->flags |= DF_STATIC_TLS;
+
+ /* Allocate space for a TLS descriptor. */
+ if (entry->tlsdesc12)
+ dinfo->tlsd12 += 8 * l;
+ else if (entry->tlsdesclos)
+ dinfo->tlsdlos += 8 * l;
+ else if (entry->tlsplt)
+ dinfo->tlsdplt += 8 * l;
+ else if (entry->tlsdeschilo)
+ dinfo->tlsdhilo += 8 * l;
+ else
+ entry->relocstlsd -= l;
+ entry->relocstlsd += l;
+}
+
+/* Compute the number of dynamic relocations and fixups that a symbol
+ requires, and add (or subtract) from the grand and per-symbol
+ totals. */
+
+static void
+_frvfdpic_count_relocs_fixups (struct frvfdpic_relocs_info *entry,
+ struct _frvfdpic_dynamic_got_info *dinfo,
+ bfd_boolean subtract)
+{
+ bfd_vma relocs = 0, fixups = 0, tlsrets = 0;
if (!dinfo->info->executable || dinfo->info->pie)
- relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv;
+ {
+ relocs = entry->relocs32 + entry->relocsfd + entry->relocsfdv
+ + entry->relocstlsd;
+
+ /* In the executable, TLS relocations to symbols that bind
+ locally (including those that resolve to global TLS offsets)
+ are resolved immediately, without any need for fixups or
+ dynamic relocations. In shared libraries, however, we must
+ emit dynamic relocations even for local symbols, because we
+ don't know the module id the library is going to get at
+ run-time, nor its TLS base offset. */
+ if (!dinfo->info->executable
+ || (entry->symndx == -1
+ && ! FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h)))
+ relocs += entry->relocstlsoff;
+ }
else
{
if (entry->symndx != -1 || FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h))
@@ -3041,9 +4714,14 @@ _frvfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
if (entry->symndx != -1
|| entry->d.h->root.type != bfd_link_hash_undefweak)
fixups += entry->relocs32 + 2 * entry->relocsfdv;
+ fixups += entry->relocstlsd;
+ tlsrets += entry->relocstlsd;
}
else
- relocs += entry->relocs32 + entry->relocsfdv;
+ {
+ relocs += entry->relocs32 + entry->relocsfdv
+ + entry->relocstlsoff + entry->relocstlsd;
+ }
if (entry->symndx != -1
|| FRVFDPIC_FUNCDESC_LOCAL (dinfo->info, entry->d.h))
@@ -3056,42 +4734,159 @@ _frvfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
relocs += entry->relocsfd;
}
+ if (subtract)
+ {
+ relocs = - relocs;
+ fixups = - fixups;
+ tlsrets = - tlsrets;
+ }
+
entry->dynrelocs += relocs;
entry->fixups += fixups;
dinfo->relocs += relocs;
dinfo->fixups += fixups;
+ dinfo->tls_ret_refs += tlsrets;
+}
- return 1;
+/* Look for opportunities to relax TLS relocations. We can assume
+ we're linking the main executable or a static-tls library, since
+ otherwise we wouldn't have got here. When relaxing, we have to
+ first undo any previous accounting of TLS uses of fixups, dynamic
+ relocations, GOT and PLT entries. */
+
+static void
+_frvfdpic_relax_tls_entries (struct frvfdpic_relocs_info *entry,
+ struct _frvfdpic_dynamic_got_info *dinfo,
+ bfd_boolean relaxing)
+{
+ bfd_boolean changed = ! relaxing;
+
+ BFD_ASSERT (dinfo->info->executable
+ || (dinfo->info->flags & DF_STATIC_TLS));
+
+ if (entry->tlsdesc12 || entry->tlsdesclos || entry->tlsdeschilo)
+ {
+ if (! changed)
+ {
+ _frvfdpic_count_relocs_fixups (entry, dinfo, TRUE);
+ _frvfdpic_count_tls_entries (entry, dinfo, TRUE);
+ changed = TRUE;
+ }
+
+ /* When linking an executable, we can always decay GOTTLSDESC to
+ TLSMOFF, if the symbol is local, or GOTTLSOFF, otherwise.
+ When linking a static-tls shared library, using TLSMOFF is
+ not an option, but we can still use GOTTLSOFF. When decaying
+ to GOTTLSOFF, we must keep the GOT entry in range. We know
+ it has to fit because we'll be trading the 4 words of hte TLS
+ descriptor for a single word in the same range. */
+ if (! dinfo->info->executable
+ || (entry->symndx == -1
+ && ! FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h)))
+ {
+ entry->tlsoff12 |= entry->tlsdesc12;
+ entry->tlsofflos |= entry->tlsdesclos;
+ entry->tlsoffhilo |= entry->tlsdeschilo;
+ }
+
+ entry->tlsdesc12 = entry->tlsdesclos = entry->tlsdeschilo = 0;
+ }
+
+ /* We can only decay TLSOFFs or call #gettlsoff to TLSMOFF in the
+ main executable. We have to check whether the symbol's TLSOFF is
+ in range for a setlos. For symbols with a hash entry, we can
+ determine exactly what to do; for others locals, we don't have
+ addresses handy, so we use the size of the TLS section as an
+ approximation. If we get it wrong, we'll retain a GOT entry
+ holding the TLS offset (without dynamic relocations or fixups),
+ but we'll still optimize away the loads from it. Since TLS sizes
+ are generally very small, it's probably not worth attempting to
+ do better than this. */
+ if ((entry->tlsplt
+ || entry->tlsoff12 || entry->tlsofflos || entry->tlsoffhilo)
+ && dinfo->info->executable && relaxing
+ && ((entry->symndx == -1
+ && FRVFDPIC_SYM_LOCAL (dinfo->info, entry->d.h)
+ /* The above may hold for an undefweak TLS symbol, so make
+ sure we don't have this case before accessing def.value
+ and def.section. */
+ && (entry->d.h->root.type == bfd_link_hash_undefweak
+ || (bfd_vma)(entry->d.h->root.u.def.value
+ + (entry->d.h->root.u.def.section
+ ->output_section->vma)
+ + entry->d.h->root.u.def.section->output_offset
+ + entry->addend
+ - tls_biased_base (dinfo->info)
+ + 32768) < (bfd_vma)65536))
+ || (entry->symndx != -1
+ && (elf_hash_table (dinfo->info)->tls_sec->size
+ + abs (entry->addend) < 32768 + FRVFDPIC_TLS_BIAS))))
+ {
+ if (! changed)
+ {
+ _frvfdpic_count_relocs_fixups (entry, dinfo, TRUE);
+ _frvfdpic_count_tls_entries (entry, dinfo, TRUE);
+ changed = TRUE;
+ }
+
+ entry->tlsplt =
+ entry->tlsoff12 = entry->tlsofflos = entry->tlsoffhilo = 0;
+ }
+
+ /* We can decay `call #gettlsoff' to a ldi #tlsoff if we already
+ have a #gottlsoff12 relocation for this entry, or if we can fit
+ one more in the 12-bit (and 16-bit) ranges. */
+ if (entry->tlsplt
+ && (entry->tlsoff12
+ || (relaxing
+ && dinfo->got12 + dinfo->fd12 + dinfo->tlsd12 <= 4096 - 12 - 4
+ && (dinfo->got12 + dinfo->fd12 + dinfo->tlsd12
+ + dinfo->gotlos + dinfo->fdlos + dinfo->tlsdlos
+ <= 65536 - 12 - 4))))
+ {
+ if (! changed)
+ {
+ _frvfdpic_count_relocs_fixups (entry, dinfo, TRUE);
+ _frvfdpic_count_tls_entries (entry, dinfo, TRUE);
+ changed = TRUE;
+ }
+
+ entry->tlsoff12 = 1;
+ entry->tlsplt = 0;
+ }
+
+ if (changed)
+ {
+ _frvfdpic_count_tls_entries (entry, dinfo, FALSE);
+ _frvfdpic_count_relocs_fixups (entry, dinfo, FALSE);
+ }
+
+ return;
}
-/* This structure is used to assign offsets to got entries, function
- descriptors, plt entries and lazy plt entries. */
+/* Compute the total GOT and PLT size required by each symbol in each range. *
+ Symbols may require up to 4 words in the GOT: an entry pointing to
+ the symbol, an entry pointing to its function descriptor, and a
+ private function descriptors taking two words. */
-struct _frvfdpic_dynamic_got_plt_info
+static int
+_frvfdpic_count_got_plt_entries (void **entryp, void *dinfo_)
{
- /* Summary information collected with _frvfdpic_count_got_plt_entries. */
- struct _frvfdpic_dynamic_got_info g;
+ struct frvfdpic_relocs_info *entry = *entryp;
+ struct _frvfdpic_dynamic_got_info *dinfo = dinfo_;
- /* For each addressable range, we record a MAX (positive) and MIN
- (negative) value. CUR is used to assign got entries, and it's
- incremented from an initial positive value to MAX, then from MIN
- to FDCUR (unless FDCUR wraps around first). FDCUR is used to
- assign function descriptors, and it's decreased from an initial
- non-positive value to MIN, then from MAX down to CUR (unless CUR
- wraps around first). All of MIN, MAX, CUR and FDCUR always point
- to even words. ODD, if non-zero, indicates an odd word to be
- used for the next got entry, otherwise CUR is used and
- incremented by a pair of words, wrapping around when it reaches
- MAX. FDCUR is decremented (and wrapped) before the next function
- descriptor is chosen. FDPLT indicates the number of remaining
- slots that can be used for function descriptors used only by PLT
- entries. */
- struct _frvfdpic_dynamic_got_alloc_data
- {
- bfd_signed_vma max, cur, odd, fdcur, min;
- bfd_vma fdplt;
- } got12, gotlos, gothilo;
-};
+ _frvfdpic_count_nontls_entries (entry, dinfo);
+
+ if (dinfo->info->executable || (dinfo->info->flags & DF_STATIC_TLS))
+ _frvfdpic_relax_tls_entries (entry, dinfo, FALSE);
+ else
+ {
+ _frvfdpic_count_tls_entries (entry, dinfo, FALSE);
+ _frvfdpic_count_relocs_fixups (entry, dinfo, FALSE);
+ }
+
+ return 1;
+}
/* Determine the positive and negative ranges to be used by each
offset range in the GOT. FDCUR and CUR, that must be aligned to a
@@ -3111,9 +4906,12 @@ _frvfdpic_compute_got_alloc_data (struct _frvfdpic_dynamic_got_alloc_data *gad,
bfd_vma got,
bfd_vma fd,
bfd_vma fdplt,
+ bfd_vma tlsd,
+ bfd_vma tlsdplt,
bfd_vma wrap)
{
bfd_signed_vma wrapmin = -wrap;
+ const bfd_vma tdescsz = 8;
/* Start at the given initial points. */
gad->fdcur = fdcur;
@@ -3158,48 +4956,109 @@ _frvfdpic_compute_got_alloc_data (struct _frvfdpic_dynamic_got_alloc_data *gad,
if (gad->min < wrapmin)
{
gad->max += wrapmin - gad->min;
- gad->min = wrapmin;
+ gad->tmin = gad->min = wrapmin;
}
+
+ /* If GOT entries took too much space, wrap some of them around.
+ This may well cause gad->min to become lower than wrapmin. This
+ will cause a relocation overflow later on, so we don't have to
+ report it here . */
+ if ((bfd_vma) gad->max > wrap)
+ {
+ gad->min -= gad->max - wrap;
+ gad->max = wrap;
+ }
+
+ /* Add TLS descriptors. */
+ gad->tmax = gad->max + tlsd;
+ gad->tmin = gad->min;
+ gad->tlsdplt = 0;
+
+ /* If TLS descriptors took too much space, wrap an integral number
+ of them around. */
+ if ((bfd_vma) gad->tmax > wrap)
+ {
+ bfd_vma wrapsize = gad->tmax - wrap;
+
+ wrapsize += tdescsz / 2;
+ wrapsize &= ~ tdescsz / 2;
+
+ gad->tmin -= wrapsize;
+ gad->tmax -= wrapsize;
+ }
+
/* If there is space left and we have function descriptors
referenced in PLT entries that could take advantage of shorter
- offsets, place them here. */
- else if (fdplt && gad->min > wrapmin)
+ offsets, place them now. */
+ if (fdplt && gad->tmin > wrapmin)
{
bfd_vma fds;
- if ((bfd_vma) (gad->min - wrapmin) < fdplt)
- fds = gad->min - wrapmin;
+
+ if ((bfd_vma) (gad->tmin - wrapmin) < fdplt)
+ fds = gad->tmin - wrapmin;
else
fds = fdplt;
fdplt -= fds;
gad->min -= fds;
+ gad->tmin -= fds;
gad->fdplt += fds;
}
- /* If GOT entries took too much space, wrap some of them around.
- This may well cause gad->min to become lower than wrapmin. This
- will cause a relocation overflow later on, so we don't have to
- report it here . */
- if ((bfd_vma) gad->max > wrap)
- {
- gad->min -= gad->max - wrap;
- gad->max = wrap;
- }
/* If there is more space left, try to place some more function
descriptors for PLT entries. */
- else if (fdplt && (bfd_vma) gad->max < wrap)
+ if (fdplt && (bfd_vma) gad->tmax < wrap)
{
bfd_vma fds;
- if ((bfd_vma) (wrap - gad->max) < fdplt)
- fds = wrap - gad->max;
+
+ if ((bfd_vma) (wrap - gad->tmax) < fdplt)
+ fds = wrap - gad->tmax;
else
fds = fdplt;
fdplt -= fds;
gad->max += fds;
+ gad->tmax += fds;
gad->fdplt += fds;
}
+ /* If there is space left and we have TLS descriptors referenced in
+ PLT entries that could take advantage of shorter offsets, place
+ them now. */
+ if (tlsdplt && gad->tmin > wrapmin)
+ {
+ bfd_vma tlsds;
+
+ if ((bfd_vma) (gad->tmin - wrapmin) < tlsdplt)
+ tlsds = (gad->tmin - wrapmin) & ~ (tdescsz / 2);
+ else
+ tlsds = tlsdplt;
+
+ tlsdplt -= tlsds;
+ gad->tmin -= tlsds;
+ gad->tlsdplt += tlsds;
+ }
+
+ /* If there is more space left, try to place some more TLS
+ descriptors for PLT entries. Although we could try to fit an
+ additional TLS descriptor with half of it just before before the
+ wrap point and another right past the wrap point, this might
+ cause us to run out of space for the next region, so don't do
+ it. */
+ if (tlsdplt && (bfd_vma) gad->tmax < wrap - tdescsz / 2)
+ {
+ bfd_vma tlsds;
+
+ if ((bfd_vma) (wrap - gad->tmax) < tlsdplt)
+ tlsds = (wrap - gad->tmax) & ~ (tdescsz / 2);
+ else
+ tlsds = tlsdplt;
+
+ tlsdplt -= tlsds;
+ gad->tmax += tlsds;
+ gad->tlsdplt += tlsds;
+ }
+
/* If odd was initially computed as an offset past the wrap point,
wrap it around. */
if (odd > gad->max)
@@ -3212,6 +5071,11 @@ _frvfdpic_compute_got_alloc_data (struct _frvfdpic_dynamic_got_alloc_data *gad,
if (gad->cur == gad->max)
gad->cur = gad->min;
+ /* Ditto for _frvfdpic_get_tlsdesc_entry(). */
+ gad->tcur = gad->max;
+ if (gad->tcur == gad->tmax)
+ gad->tcur = gad->tmin;
+
return odd;
}
@@ -3257,6 +5121,24 @@ _frvfdpic_get_fd_entry (struct _frvfdpic_dynamic_got_alloc_data *gad)
return gad->fdcur -= 8;
}
+/* Compute the location of the next TLS descriptor entry in the GOT,
+ given the allocation data for a range. */
+inline static bfd_signed_vma
+_frvfdpic_get_tlsdesc_entry (struct _frvfdpic_dynamic_got_alloc_data *gad)
+{
+ bfd_signed_vma ret;
+
+ ret = gad->tcur;
+
+ gad->tcur += 8;
+
+ /* If we're at the top of the region, wrap around to the bottom. */
+ if (gad->tcur == gad->tmax)
+ gad->tcur = gad->tmin;
+
+ return ret;
+}
+
/* Assign GOT offsets for every GOT entry and function descriptor.
Doing everything in a single pass is tricky. */
@@ -3302,6 +5184,35 @@ _frvfdpic_assign_got_entries (void **entryp, void *info_)
else if (entry->privfd)
entry->fd_entry = _frvfdpic_get_fd_entry (&dinfo->gothilo);
+ if (entry->tlsoff12)
+ entry->tlsoff_entry = _frvfdpic_get_got_entry (&dinfo->got12);
+ else if (entry->tlsofflos)
+ entry->tlsoff_entry = _frvfdpic_get_got_entry (&dinfo->gotlos);
+ else if (entry->tlsoffhilo)
+ entry->tlsoff_entry = _frvfdpic_get_got_entry (&dinfo->gothilo);
+
+ if (entry->tlsdesc12)
+ entry->tlsdesc_entry = _frvfdpic_get_tlsdesc_entry (&dinfo->got12);
+ else if (entry->tlsplt && dinfo->got12.tlsdplt)
+ {
+ dinfo->got12.tlsdplt -= 8;
+ entry->tlsdesc_entry = _frvfdpic_get_tlsdesc_entry (&dinfo->got12);
+ }
+ else if (entry->tlsdesclos)
+ entry->tlsdesc_entry = _frvfdpic_get_tlsdesc_entry (&dinfo->gotlos);
+ else if (entry->tlsplt && dinfo->gotlos.tlsdplt)
+ {
+ dinfo->gotlos.tlsdplt -= 8;
+ entry->tlsdesc_entry = _frvfdpic_get_tlsdesc_entry (&dinfo->gotlos);
+ }
+ else if (entry->tlsplt)
+ {
+ dinfo->gothilo.tlsdplt -= 8;
+ entry->tlsdesc_entry = _frvfdpic_get_tlsdesc_entry (&dinfo->gothilo);
+ }
+ else if (entry->tlsdeschilo)
+ entry->tlsdesc_entry = _frvfdpic_get_tlsdesc_entry (&dinfo->gothilo);
+
return 1;
}
@@ -3315,6 +5226,10 @@ _frvfdpic_assign_plt_entries (void **entryp, void *info_)
struct frvfdpic_relocs_info *entry = *entryp;
struct _frvfdpic_dynamic_got_plt_info *dinfo = info_;
+#if 1
+ if (entry->privfd)
+ BFD_ASSERT (entry->fd_entry);
+#else
/* If this symbol requires a local function descriptor, allocate
one. */
if (entry->privfd && entry->fd_entry == 0)
@@ -3336,6 +5251,7 @@ _frvfdpic_assign_plt_entries (void **entryp, void *info_)
dinfo->gothilo.fdplt -= 8;
}
}
+#endif
if (entry->plt)
{
@@ -3371,6 +5287,79 @@ _frvfdpic_assign_plt_entries (void **entryp, void *info_)
dinfo->g.lzplt += 4;
}
+ if (entry->tlsplt)
+ {
+ int size;
+
+ entry->tlsplt_entry
+ = frvfdpic_plt_section (dinfo->g.info)->size;
+
+ if (dinfo->g.info->executable
+ && (entry->symndx != -1
+ || FRVFDPIC_SYM_LOCAL (dinfo->g.info, entry->d.h)))
+ {
+ if ((bfd_signed_vma)entry->addend >= -(1 << (16 - 1))
+ /* FIXME: here we use the size of the TLS section
+ as an upper bound for the value of the TLS
+ symbol, because we may not know the exact value
+ yet. If we get it wrong, we'll just waste a
+ word in the PLT, and we should never get even
+ close to 32 KiB of TLS anyway. */
+ && elf_hash_table (dinfo->g.info)->tls_sec
+ && (elf_hash_table (dinfo->g.info)->tls_sec->size
+ + (bfd_signed_vma)(entry->addend) <= (1 << (16 - 1))))
+ size = 8;
+ else
+ size = 12;
+ }
+ else if (entry->tlsoff_entry)
+ {
+ if (entry->tlsoff_entry >= -(1 << (12 - 1))
+ && entry->tlsoff_entry < (1 << (12 - 1)))
+ size = 8;
+ else if (entry->tlsoff_entry >= -(1 << (16 - 1))
+ && entry->tlsoff_entry < (1 << (16 - 1)))
+ size = 12;
+ else
+ size = 16;
+ }
+ else
+ {
+ BFD_ASSERT (entry->tlsdesc_entry);
+
+ if (entry->tlsdesc_entry >= -(1 << (12 - 1))
+ && entry->tlsdesc_entry < (1 << (12 - 1)))
+ size = 8;
+ else if (entry->tlsdesc_entry >= -(1 << (16 - 1))
+ && entry->tlsdesc_entry < (1 << (16 - 1)))
+ size = 12;
+ else
+ size = 16;
+ }
+
+ frvfdpic_plt_section (dinfo->g.info)->size += size;
+ }
+
+ return 1;
+}
+
+/* Cancel out any effects of calling _frvfdpic_assign_got_entries and
+ _frvfdpic_assign_plt_entries. */
+
+static int
+_frvfdpic_reset_got_plt_entries (void **entryp, void *ignore ATTRIBUTE_UNUSED)
+{
+ struct frvfdpic_relocs_info *entry = *entryp;
+
+ entry->got_entry = 0;
+ entry->fdgot_entry = 0;
+ entry->fd_entry = 0;
+ entry->plt_entry = (bfd_vma)-1;
+ entry->lzplt_entry = (bfd_vma)-1;
+ entry->tlsoff_entry = 0;
+ entry->tlsdesc_entry = 0;
+ entry->tlsplt_entry = (bfd_vma)-1;
+
return 1;
}
@@ -3430,100 +5419,92 @@ _frvfdpic_resolve_final_relocs_info (void **entryp, void *p)
return 1;
}
-/* Set the sizes of the dynamic sections. */
+/* Compute the total size of the GOT, the PLT, the dynamic relocations
+ section and the rofixup section. Assign locations for GOT and PLT
+ entries. */
static bfd_boolean
-elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
- struct bfd_link_info *info)
+_frvfdpic_size_got_plt (bfd *output_bfd,
+ struct _frvfdpic_dynamic_got_plt_info *gpinfop)
{
- bfd *dynobj;
- asection *s;
- struct _frvfdpic_dynamic_got_plt_info gpinfo;
bfd_signed_vma odd;
- bfd_vma limit;
+ bfd_vma limit, tlslimit;
+ struct bfd_link_info *info = gpinfop->g.info;
+ bfd *dynobj = elf_hash_table (info)->dynobj;
- dynobj = elf_hash_table (info)->dynobj;
- BFD_ASSERT (dynobj != NULL);
-
- if (elf_hash_table (info)->dynamic_sections_created)
- {
- /* Set the contents of the .interp section to the interpreter. */
- if (info->executable)
- {
- s = bfd_get_section_by_name (dynobj, ".interp");
- BFD_ASSERT (s != NULL);
- s->size = sizeof ELF_DYNAMIC_INTERPRETER;
- s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
- }
- }
-
- memset (&gpinfo, 0, sizeof (gpinfo));
- gpinfo.g.info = info;
-
- for (;;)
- {
- htab_t relocs = frvfdpic_relocs_info (info);
-
- htab_traverse (relocs, _frvfdpic_resolve_final_relocs_info, &relocs);
-
- if (relocs == frvfdpic_relocs_info (info))
- break;
- }
-
- htab_traverse (frvfdpic_relocs_info (info), _frvfdpic_count_got_plt_entries,
- &gpinfo.g);
+ memcpy (frvfdpic_dynamic_got_plt_info (info), &gpinfop->g,
+ sizeof (gpinfop->g));
odd = 12;
/* Compute the total size taken by entries in the 12-bit and 16-bit
ranges, to tell how many PLT function descriptors we can bring
into the 12-bit range without causing the 16-bit range to
overflow. */
- limit = odd + gpinfo.g.got12 + gpinfo.g.gotlos
- + gpinfo.g.fd12 + gpinfo.g.fdlos;
+ limit = odd + gpinfop->g.got12 + gpinfop->g.gotlos
+ + gpinfop->g.fd12 + gpinfop->g.fdlos
+ + gpinfop->g.tlsd12 + gpinfop->g.tlsdlos;
if (limit < (bfd_vma)1 << 16)
limit = ((bfd_vma)1 << 16) - limit;
else
limit = 0;
- if (gpinfo.g.fdplt < limit)
- limit = gpinfo.g.fdplt;
+ if (gpinfop->g.fdplt < limit)
+ {
+ tlslimit = (limit - gpinfop->g.fdplt) & ~ (bfd_vma) 8;
+ limit = gpinfop->g.fdplt;
+ }
+ else
+ tlslimit = 0;
+ if (gpinfop->g.tlsdplt < tlslimit)
+ tlslimit = gpinfop->g.tlsdplt;
/* Determine the ranges of GOT offsets that we can use for each
range of addressing modes. */
- odd = _frvfdpic_compute_got_alloc_data (&gpinfo.got12,
+ odd = _frvfdpic_compute_got_alloc_data (&gpinfop->got12,
0,
odd,
16,
- gpinfo.g.got12,
- gpinfo.g.fd12,
+ gpinfop->g.got12,
+ gpinfop->g.fd12,
limit,
+ gpinfop->g.tlsd12,
+ tlslimit,
(bfd_vma)1 << (12-1));
- odd = _frvfdpic_compute_got_alloc_data (&gpinfo.gotlos,
- gpinfo.got12.min,
+ odd = _frvfdpic_compute_got_alloc_data (&gpinfop->gotlos,
+ gpinfop->got12.tmin,
odd,
- gpinfo.got12.max,
- gpinfo.g.gotlos,
- gpinfo.g.fdlos,
- gpinfo.g.fdplt - gpinfo.got12.fdplt,
+ gpinfop->got12.tmax,
+ gpinfop->g.gotlos,
+ gpinfop->g.fdlos,
+ gpinfop->g.fdplt
+ - gpinfop->got12.fdplt,
+ gpinfop->g.tlsdlos,
+ gpinfop->g.tlsdplt
+ - gpinfop->got12.tlsdplt,
(bfd_vma)1 << (16-1));
- odd = _frvfdpic_compute_got_alloc_data (&gpinfo.gothilo,
- gpinfo.gotlos.min,
+ odd = _frvfdpic_compute_got_alloc_data (&gpinfop->gothilo,
+ gpinfop->gotlos.tmin,
odd,
- gpinfo.gotlos.max,
- gpinfo.g.gothilo,
- gpinfo.g.fdhilo,
- gpinfo.g.fdplt - gpinfo.got12.fdplt
- - gpinfo.gotlos.fdplt,
+ gpinfop->gotlos.tmax,
+ gpinfop->g.gothilo,
+ gpinfop->g.fdhilo,
+ gpinfop->g.fdplt
+ - gpinfop->got12.fdplt
+ - gpinfop->gotlos.fdplt,
+ gpinfop->g.tlsdhilo,
+ gpinfop->g.tlsdplt
+ - gpinfop->got12.tlsdplt
+ - gpinfop->gotlos.tlsdplt,
(bfd_vma)1 << (32-1));
/* Now assign (most) GOT offsets. */
htab_traverse (frvfdpic_relocs_info (info), _frvfdpic_assign_got_entries,
- &gpinfo);
+ gpinfop);
- frvfdpic_got_section (info)->size = gpinfo.gothilo.max
- - gpinfo.gothilo.min
+ frvfdpic_got_section (info)->size = gpinfop->gothilo.tmax
+ - gpinfop->gothilo.tmin
/* If an odd word is the last word of the GOT, we don't need this
word to be part of the GOT. */
- - (odd + 4 == gpinfo.gothilo.max ? 4 : 0);
+ - (odd + 4 == gpinfop->gothilo.tmax ? 4 : 0);
if (frvfdpic_got_section (info)->size == 0)
frvfdpic_got_section (info)->flags |= SEC_EXCLUDE;
else if (frvfdpic_got_section (info)->size == 12
@@ -3532,7 +5513,10 @@ elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
frvfdpic_got_section (info)->flags |= SEC_EXCLUDE;
frvfdpic_got_section (info)->size = 0;
}
- else
+ /* This will be non-NULL during relaxation. The assumption is that
+ the size of one of these sections will never grow, only shrink,
+ so we can use the larger buffer we allocated before. */
+ else if (frvfdpic_got_section (info)->contents == NULL)
{
frvfdpic_got_section (info)->contents =
(bfd_byte *) bfd_zalloc (dynobj,
@@ -3541,17 +5525,17 @@ elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
return FALSE;
}
- if (elf_hash_table (info)->dynamic_sections_created)
+ if (frvfdpic_gotrel_section (info))
/* Subtract the number of lzplt entries, since those will generate
relocations in the pltrel section. */
frvfdpic_gotrel_section (info)->size =
- (gpinfo.g.relocs - gpinfo.g.lzplt / 8)
+ (gpinfop->g.relocs - gpinfop->g.lzplt / 8)
* get_elf_backend_data (output_bfd)->s->sizeof_rel;
else
- BFD_ASSERT (gpinfo.g.relocs == 0);
+ BFD_ASSERT (gpinfop->g.relocs == 0);
if (frvfdpic_gotrel_section (info)->size == 0)
frvfdpic_gotrel_section (info)->flags |= SEC_EXCLUDE;
- else
+ else if (frvfdpic_gotrel_section (info)->contents == NULL)
{
frvfdpic_gotrel_section (info)->contents =
(bfd_byte *) bfd_zalloc (dynobj,
@@ -3560,10 +5544,10 @@ elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
return FALSE;
}
- frvfdpic_gotfixup_section (info)->size = (gpinfo.g.fixups + 1) * 4;
+ frvfdpic_gotfixup_section (info)->size = (gpinfop->g.fixups + 1) * 4;
if (frvfdpic_gotfixup_section (info)->size == 0)
frvfdpic_gotfixup_section (info)->flags |= SEC_EXCLUDE;
- else
+ else if (frvfdpic_gotfixup_section (info)->contents == NULL)
{
frvfdpic_gotfixup_section (info)->contents =
(bfd_byte *) bfd_zalloc (dynobj,
@@ -3572,13 +5556,14 @@ elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
return FALSE;
}
- if (elf_hash_table (info)->dynamic_sections_created)
+ if (frvfdpic_pltrel_section (info))
{
frvfdpic_pltrel_section (info)->size =
- gpinfo.g.lzplt / 8 * get_elf_backend_data (output_bfd)->s->sizeof_rel;
+ gpinfop->g.lzplt / 8
+ * get_elf_backend_data (output_bfd)->s->sizeof_rel;
if (frvfdpic_pltrel_section (info)->size == 0)
frvfdpic_pltrel_section (info)->flags |= SEC_EXCLUDE;
- else
+ else if (frvfdpic_pltrel_section (info)->contents == NULL)
{
frvfdpic_pltrel_section (info)->contents =
(bfd_byte *) bfd_zalloc (dynobj,
@@ -3593,40 +5578,45 @@ elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
call the resolver. Since _frvfdpic_assign_got_entries didn't
account for them, our block size is 4 bytes smaller than the real
block size. */
- if (elf_hash_table (info)->dynamic_sections_created)
+ if (frvfdpic_plt_section (info))
{
- frvfdpic_plt_section (info)->size = gpinfo.g.lzplt
- + ((gpinfo.g.lzplt + (FRVFDPIC_LZPLT_BLOCK_SIZE - 4) - 8)
+ frvfdpic_plt_section (info)->size = gpinfop->g.lzplt
+ + ((gpinfop->g.lzplt + (FRVFDPIC_LZPLT_BLOCK_SIZE - 4) - 8)
/ (FRVFDPIC_LZPLT_BLOCK_SIZE - 4) * 4);
}
/* Reset it, such that _frvfdpic_assign_plt_entries() can use it to
actually assign lazy PLT entries addresses. */
- gpinfo.g.lzplt = 0;
+ gpinfop->g.lzplt = 0;
/* Save information that we're going to need to generate GOT and PLT
entries. */
- frvfdpic_got_initial_offset (info) = -gpinfo.gothilo.min;
+ frvfdpic_got_initial_offset (info) = -gpinfop->gothilo.tmin;
if (get_elf_backend_data (output_bfd)->want_got_sym)
elf_hash_table (info)->hgot->root.u.def.value
- += frvfdpic_got_initial_offset (info);
+ = frvfdpic_got_initial_offset (info);
- if (elf_hash_table (info)->dynamic_sections_created)
+ if (frvfdpic_plt_section (info))
frvfdpic_plt_initial_offset (info) =
frvfdpic_plt_section (info)->size;
+ /* Allocate a ret statement at plt_initial_offset, to be used by
+ locally-resolved TLS descriptors. */
+ if (gpinfop->g.tls_ret_refs)
+ frvfdpic_plt_section (info)->size += 4;
+
htab_traverse (frvfdpic_relocs_info (info), _frvfdpic_assign_plt_entries,
- &gpinfo);
+ gpinfop);
/* Allocate the PLT section contents only after
_frvfdpic_assign_plt_entries has a chance to add the size of the
non-lazy PLT entries. */
- if (elf_hash_table (info)->dynamic_sections_created)
+ if (frvfdpic_plt_section (info))
{
if (frvfdpic_plt_section (info)->size == 0)
frvfdpic_plt_section (info)->flags |= SEC_EXCLUDE;
- else
+ else if (frvfdpic_plt_section (info)->contents == NULL)
{
frvfdpic_plt_section (info)->contents =
(bfd_byte *) bfd_zalloc (dynobj,
@@ -3636,6 +5626,57 @@ elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
}
}
+ return TRUE;
+}
+
+/* Set the sizes of the dynamic sections. */
+
+static bfd_boolean
+elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
+ struct bfd_link_info *info)
+{
+ bfd *dynobj;
+ asection *s;
+ struct _frvfdpic_dynamic_got_plt_info gpinfo;
+
+ dynobj = elf_hash_table (info)->dynobj;
+ BFD_ASSERT (dynobj != NULL);
+
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ /* Set the contents of the .interp section to the interpreter. */
+ if (info->executable)
+ {
+ s = bfd_get_section_by_name (dynobj, ".interp");
+ BFD_ASSERT (s != NULL);
+ s->size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
+ }
+ }
+
+ memset (&gpinfo, 0, sizeof (gpinfo));
+ gpinfo.g.info = info;
+
+ for (;;)
+ {
+ htab_t relocs = frvfdpic_relocs_info (info);
+
+ htab_traverse (relocs, _frvfdpic_resolve_final_relocs_info, &relocs);
+
+ if (relocs == frvfdpic_relocs_info (info))
+ break;
+ }
+
+ htab_traverse (frvfdpic_relocs_info (info), _frvfdpic_count_got_plt_entries,
+ &gpinfo.g);
+
+ /* Allocate space to save the summary information, we're going to
+ use it if we're doing relaxations. */
+ frvfdpic_dynamic_got_plt_info (info) = bfd_alloc (dynobj, sizeof (gpinfo.g));
+
+ if (!_frvfdpic_size_got_plt (output_bfd, &gpinfo))
+ return FALSE;
+
if (elf_hash_table (info)->dynamic_sections_created)
{
if (frvfdpic_got_section (info)->size)
@@ -3691,6 +5732,7 @@ elf32_frvfdpic_always_size_sections (bfd *output_bfd,
h = (struct elf_link_hash_entry *) bh;
h->def_regular = 1;
h->type = STT_OBJECT;
+ /* This one must NOT be hidden. */
}
/* Create a stack section, and set its alignment. */
@@ -3704,6 +5746,81 @@ elf32_frvfdpic_always_size_sections (bfd *output_bfd,
return TRUE;
}
+/* Look for opportunities to relax TLS relocations. We can assume
+ we're linking the main executable or a static-tls library, since
+ otherwise we wouldn't have got here. */
+
+static int
+_frvfdpic_relax_got_plt_entries (void **entryp, void *dinfo_)
+{
+ struct frvfdpic_relocs_info *entry = *entryp;
+ struct _frvfdpic_dynamic_got_info *dinfo = dinfo_;
+
+ _frvfdpic_relax_tls_entries (entry, dinfo, TRUE);
+
+ return 1;
+}
+
+static bfd_boolean
+elf32_frvfdpic_relax_section (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
+ struct bfd_link_info *info, bfd_boolean *again)
+{
+ struct _frvfdpic_dynamic_got_plt_info gpinfo;
+
+ /* If we return early, we didn't change anything. */
+ *again = FALSE;
+
+ /* We'll do our thing when requested to relax the GOT section. */
+ if (sec != frvfdpic_got_section (info))
+ return TRUE;
+
+ /* We can only relax when linking the main executable or a library
+ that can't be dlopened. */
+ if (! info->executable && ! (info->flags & DF_STATIC_TLS))
+ return TRUE;
+
+ /* If there isn't a TLS section for this binary, we can't do
+ anything about its TLS relocations (it probably doesn't have
+ any. */
+ if (elf_hash_table (info)->tls_sec == NULL)
+ return TRUE;
+
+ memset (&gpinfo, 0, sizeof (gpinfo));
+ memcpy (&gpinfo.g, frvfdpic_dynamic_got_plt_info (info), sizeof (gpinfo.g));
+
+ /* Now look for opportunities to relax, adjusting the GOT usage
+ as needed. */
+ htab_traverse (frvfdpic_relocs_info (info),
+ _frvfdpic_relax_got_plt_entries,
+ &gpinfo.g);
+
+ /* If we changed anything, reset and re-assign GOT and PLT entries. */
+ if (memcmp (frvfdpic_dynamic_got_plt_info (info),
+ &gpinfo.g, sizeof (gpinfo.g)) != 0)
+ {
+ /* Clear GOT and PLT assignments. */
+ htab_traverse (frvfdpic_relocs_info (info),
+ _frvfdpic_reset_got_plt_entries,
+ NULL);
+
+ /* The owner of the TLS section is the output bfd. There should
+ be a better way to get to it. */
+ if (!_frvfdpic_size_got_plt (elf_hash_table (info)->tls_sec->owner,
+ &gpinfo))
+ return FALSE;
+
+ /* Repeat until we don't make any further changes. We could fail to
+ introduce changes in a round if, for example, the 12-bit range is
+ full, but we later release some space by getting rid of TLS
+ descriptors in it. We have to repeat the whole process because
+ we might have changed the size of a section processed before this
+ one. */
+ *again = TRUE;
+ }
+
+ return TRUE;
+}
+
static bfd_boolean
elf32_frvfdpic_modify_segment_map (bfd *output_bfd,
struct bfd_link_info *info)
@@ -3771,6 +5888,10 @@ elf32_frvfdpic_finish_dynamic_sections (bfd *output_bfd,
dynobj = elf_hash_table (info)->dynobj;
+ if (frvfdpic_dynamic_got_plt_info (info))
+ {
+ BFD_ASSERT (frvfdpic_dynamic_got_plt_info (info)->tls_ret_refs == 0);
+ }
if (frvfdpic_got_section (info))
{
BFD_ASSERT (frvfdpic_gotrel_section (info)->size
@@ -3783,6 +5904,7 @@ elf32_frvfdpic_finish_dynamic_sections (bfd *output_bfd,
bfd_vma got_value = hgot->root.u.def.value
+ hgot->root.u.def.section->output_section->vma
+ hgot->root.u.def.section->output_offset;
+ struct bfd_link_hash_entry *hend;
_frvfdpic_add_rofixup (output_bfd, frvfdpic_gotfixup_section (info),
got_value, 0);
@@ -3790,26 +5912,45 @@ elf32_frvfdpic_finish_dynamic_sections (bfd *output_bfd,
if (frvfdpic_gotfixup_section (info)->size
!= (frvfdpic_gotfixup_section (info)->reloc_count * 4))
{
+ error:
(*_bfd_error_handler)
("LINKER BUG: .rofixup section size mismatch");
return FALSE;
}
+
+ hend = bfd_link_hash_lookup (info->hash, "__ROFIXUP_END__",
+ FALSE, FALSE, TRUE);
+ if (hend
+ && (hend->type == bfd_link_hash_defined
+ || hend->type == bfd_link_hash_defweak))
+ {
+ bfd_vma value =
+ frvfdpic_gotfixup_section (info)->output_section->vma
+ + frvfdpic_gotfixup_section (info)->output_offset
+ + frvfdpic_gotfixup_section (info)->size
+ - hend->u.def.section->output_section->vma
+ - hend->u.def.section->output_offset;
+ BFD_ASSERT (hend->u.def.value == value);
+ if (hend->u.def.value != value)
+ goto error;
+ }
}
}
- if (elf_hash_table (info)->dynamic_sections_created)
+ if (frvfdpic_pltrel_section (info))
{
BFD_ASSERT (frvfdpic_pltrel_section (info)->size
== (frvfdpic_pltrel_section (info)->reloc_count
* sizeof (Elf32_External_Rel)));
}
- sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
if (elf_hash_table (info)->dynamic_sections_created)
{
Elf32_External_Dyn * dyncon;
Elf32_External_Dyn * dynconend;
+ sdyn = bfd_get_section_by_name (dynobj, ".dynamic");
+
BFD_ASSERT (sdyn != NULL);
dyncon = (Elf32_External_Dyn *) sdyn->contents;
@@ -4082,6 +6223,15 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
switch (ELF32_R_TYPE (rel->r_info))
{
+ case R_FRV_GETTLSOFF:
+ case R_FRV_TLSDESC_VALUE:
+ case R_FRV_GOTTLSDESC12:
+ case R_FRV_GOTTLSDESCHI:
+ case R_FRV_GOTTLSDESCLO:
+ case R_FRV_GOTTLSOFF12:
+ case R_FRV_GOTTLSOFFHI:
+ case R_FRV_GOTTLSOFFLO:
+ case R_FRV_TLSOFF:
case R_FRV_GOT12:
case R_FRV_GOTHI:
case R_FRV_GOTLO:
@@ -4096,6 +6246,10 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
case R_FRV_FUNCDESC_GOTOFFLO:
case R_FRV_FUNCDESC:
case R_FRV_FUNCDESC_VALUE:
+ case R_FRV_TLSMOFF12:
+ case R_FRV_TLSMOFFHI:
+ case R_FRV_TLSMOFFLO:
+ case R_FRV_TLSMOFF:
if (! IS_FDPIC (abfd))
goto bad_reloc;
/* Fall through. */
@@ -4206,6 +6360,45 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
picrel->relocsfd++;
break;
+ case R_FRV_GETTLSOFF:
+ picrel->tlsplt = 1;
+ break;
+
+ case R_FRV_TLSDESC_VALUE:
+ picrel->relocstlsd++;
+ goto bad_reloc;
+
+ case R_FRV_GOTTLSDESC12:
+ picrel->tlsdesc12 = 1;
+ break;
+
+ case R_FRV_GOTTLSDESCHI:
+ case R_FRV_GOTTLSDESCLO:
+ picrel->tlsdeschilo = 1;
+ break;
+
+ case R_FRV_TLSMOFF12:
+ case R_FRV_TLSMOFFHI:
+ case R_FRV_TLSMOFFLO:
+ case R_FRV_TLSMOFF:
+ break;
+
+ case R_FRV_GOTTLSOFF12:
+ picrel->tlsoff12 = 1;
+ info->flags |= DF_STATIC_TLS;
+ break;
+
+ case R_FRV_GOTTLSOFFHI:
+ case R_FRV_GOTTLSOFFLO:
+ picrel->tlsoffhilo = 1;
+ info->flags |= DF_STATIC_TLS;
+ break;
+
+ case R_FRV_TLSOFF:
+ picrel->relocstlsoff++;
+ info->flags |= DF_STATIC_TLS;
+ goto bad_reloc;
+
/* This relocation describes the C++ object vtable hierarchy.
Reconstruct it for later use during GC. */
case R_FRV_GNU_VTINHERIT:
@@ -4228,6 +6421,9 @@ elf32_frv_check_relocs (abfd, info, sec, relocs)
case R_FRV_GPREL32:
case R_FRV_GPRELHI:
case R_FRV_GPRELLO:
+ case R_FRV_TLSDESC_RELAX:
+ case R_FRV_GETTLSOFF_RELAX:
+ case R_FRV_TLSOFF_RELAX:
break;
default:
@@ -4806,6 +7002,9 @@ frv_elf_print_private_bfd_data (abfd, ptr)
#undef elf_backend_size_dynamic_sections
#define elf_backend_size_dynamic_sections \
elf32_frvfdpic_size_dynamic_sections
+#undef bfd_elf32_bfd_relax_section
+#define bfd_elf32_bfd_relax_section \
+ elf32_frvfdpic_relax_section
#undef elf_backend_finish_dynamic_symbol
#define elf_backend_finish_dynamic_symbol \
elf32_frvfdpic_finish_dynamic_symbol
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 0905522..a454115 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -948,6 +948,22 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_FRV_GOTOFF12",
"BFD_RELOC_FRV_GOTOFFHI",
"BFD_RELOC_FRV_GOTOFFLO",
+ "BFD_RELOC_FRV_GETTLSOFF",
+ "BFD_RELOC_FRV_TLSDESC_VALUE",
+ "BFD_RELOC_FRV_GOTTLSDESC12",
+ "BFD_RELOC_FRV_GOTTLSDESCHI",
+ "BFD_RELOC_FRV_GOTTLSDESCLO",
+ "BFD_RELOC_FRV_TLSMOFF12",
+ "BFD_RELOC_FRV_TLSMOFFHI",
+ "BFD_RELOC_FRV_TLSMOFFLO",
+ "BFD_RELOC_FRV_GOTTLSOFF12",
+ "BFD_RELOC_FRV_GOTTLSOFFHI",
+ "BFD_RELOC_FRV_GOTTLSOFFLO",
+ "BFD_RELOC_FRV_TLSOFF",
+ "BFD_RELOC_FRV_TLSDESC_RELAX",
+ "BFD_RELOC_FRV_GETTLSOFF_RELAX",
+ "BFD_RELOC_FRV_TLSOFF_RELAX",
+ "BFD_RELOC_FRV_TLSMOFF",
"BFD_RELOC_MN10300_GOTOFF24",
"BFD_RELOC_MN10300_GOT32",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 8898d87..49d7938 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -2162,6 +2162,38 @@ ENUMX
BFD_RELOC_FRV_GOTOFFHI
ENUMX
BFD_RELOC_FRV_GOTOFFLO
+ENUMX
+ BFD_RELOC_FRV_GETTLSOFF
+ENUMX
+ BFD_RELOC_FRV_TLSDESC_VALUE
+ENUMX
+ BFD_RELOC_FRV_GOTTLSDESC12
+ENUMX
+ BFD_RELOC_FRV_GOTTLSDESCHI
+ENUMX
+ BFD_RELOC_FRV_GOTTLSDESCLO
+ENUMX
+ BFD_RELOC_FRV_TLSMOFF12
+ENUMX
+ BFD_RELOC_FRV_TLSMOFFHI
+ENUMX
+ BFD_RELOC_FRV_TLSMOFFLO
+ENUMX
+ BFD_RELOC_FRV_GOTTLSOFF12
+ENUMX
+ BFD_RELOC_FRV_GOTTLSOFFHI
+ENUMX
+ BFD_RELOC_FRV_GOTTLSOFFLO
+ENUMX
+ BFD_RELOC_FRV_TLSOFF
+ENUMX
+ BFD_RELOC_FRV_TLSDESC_RELAX
+ENUMX
+ BFD_RELOC_FRV_GETTLSOFF_RELAX
+ENUMX
+ BFD_RELOC_FRV_TLSOFF_RELAX
+ENUMX
+ BFD_RELOC_FRV_TLSMOFF
ENUMDOC
Fujitsu Frv Relocations.
COMMENT
diff --git a/cpu/ChangeLog b/cpu/ChangeLog
index ddbce32..859aa2a 100644
--- a/cpu/ChangeLog
+++ b/cpu/ChangeLog
@@ -1,3 +1,17 @@
+2005-01-25 Alexandre Oliva <aoliva@redhat.com>
+
+ 2004-11-10 Alexandre Oliva <aoliva@redhat.com>
+ * frv.cpu: Add support for TLS annotations in loads and calll.
+ * frv.opc (parse_symbolic_address): New.
+ (parse_ldd_annotation): New.
+ (parse_call_annotation): New.
+ (parse_ld_annotation): New.
+ (parse_ulo16, parse_uslo16): Use parse_symbolic_address.
+ Introduce TLS relocations.
+ (parse_d12, parse_s12, parse_u12): Likewise.
+ (parse_uhi16): Likewise. Fix constant checking on 64-bit host.
+ (parse_call_label, print_at): New.
+
2004-12-21 Mikael Starvik <starvik@axis.com>
* cris.cpu (cris-set-mem): Correct integral write semantics.
diff --git a/cpu/frv.cpu b/cpu/frv.cpu
index 720322d..8f00c00 100644
--- a/cpu/frv.cpu
+++ b/cpu/frv.cpu
@@ -2081,6 +2081,22 @@
(dnf f-LI-off "null field" (RESERVED) 25 1)
(dnf f-LI-on "null field" (RESERVED) 25 1)
+
+; Relocation annotations.
+(dsh h-reloc-ann "relocation annotation" () (register BI))
+(dnf f-reloc-ann "relocation annotation" () 0 0)
+
+(define-pmacro (dann xname xcomment xmode xparse xprint)
+ (define-operand
+ (name xname)
+ (comment xcomment)
+ (type h-reloc-ann)
+ (index f-reloc-ann)
+ (mode xmode)
+ (handlers (parse xparse) (print xprint))
+ )
+ )
+
; Enums.
@@ -3156,7 +3172,6 @@
(dnop ae "all entries indicator" (HASH-PREFIX) h-uint f-ae)
(dnop label16 "18 bit pc relative address" () h-iaddr f-label16)
-(dnop label24 "26 bit pc relative address" () h-iaddr f-label24)
(dnop LRAE "Load Real Address E flag" () h-uint f-LRAE)
(dnop LRAD "Load Real Address D flag" () h-uint f-LRAD)
@@ -3278,6 +3293,16 @@
(handlers (parse "uhi16") (print "hi"))
)
+(define-operand
+ (name label24)
+ (comment "26 bit pc relative address")
+ (attrs)
+ (type h-iaddr)
+ (index f-label24)
+ (mode SI)
+ (handlers (parse "call_label"))
+)
+
; operands representing hardware
;
(dnop psr_esr "PSR.ESR bit" (SEM-ONLY) h-psr_esr f-nil)
@@ -4295,12 +4320,12 @@
(fr500 (unit u-integer)) (fr550 (unit u-integer)))
)
-(define-pmacro (load-gr-r name mode op ope comment)
+(define-pmacro (load-gr-r name mode op ope comment ann)
(dni name
(comment)
((UNIT LOAD) (FR550-MAJOR I-3) (FR500-MAJOR I-2)
(FR400-MAJOR I-2) (FR450-MAJOR I-2))
- (.str name "$pack @($GRi,$GRj),$GRk")
+ (.str name "$pack " ann "($GRi,$GRj),$GRk")
(+ pack GRk op GRi ope GRj)
(set GRk (c-call mode (.str "@cpu@_read_mem_" mode) pc (add GRi GRj)))
((fr400 (unit u-gr-load)) (fr450 (unit u-gr-load))
@@ -4308,11 +4333,13 @@
)
)
-(load-gr-r ldsb QI OP_02 OPE1_00 "Load signed byte")
-(load-gr-r ldub UQI OP_02 OPE1_01 "Load unsigned byte")
-(load-gr-r ldsh HI OP_02 OPE1_02 "Load signed half")
-(load-gr-r lduh UHI OP_02 OPE1_03 "Load unsigned half")
-(load-gr-r ld SI OP_02 OPE1_04 "Load word")
+(dann ldann "ld annotation" SI "ld_annotation" "at")
+
+(load-gr-r ldsb QI OP_02 OPE1_00 "Load signed byte" "@")
+(load-gr-r ldub UQI OP_02 OPE1_01 "Load unsigned byte" "@")
+(load-gr-r ldsh HI OP_02 OPE1_02 "Load signed half" "@")
+(load-gr-r lduh UHI OP_02 OPE1_03 "Load unsigned half" "@")
+(load-gr-r ld SI OP_02 OPE1_04 "Load word" "$ldann")
(define-pmacro (load-fr-r name mode op ope comment)
(dni name
@@ -4414,12 +4441,12 @@
)
(define-pmacro (load-double-r-r
- name not_gr mode op ope regtype attr profile comment)
+ name not_gr mode op ope regtype attr profile comment ann)
(dni name
(comment)
((UNIT LOAD) (FR550-MAJOR I-3) (FR500-MAJOR I-2)
(FR400-MAJOR I-2) (FR450-MAJOR I-2) attr)
- (.str name "$pack @($GRi,$GRj),$" regtype "doublek")
+ (.str name "$pack " ann "($GRi,$GRj),$" regtype "doublek")
(+ pack (.sym regtype doublek) op GRi ope GRj)
(sequence ((WI address))
(load-double-semantics not_gr mode regtype address GRj))
@@ -4427,16 +4454,18 @@
)
)
+(dann lddann "ldd annotation" SI "ldd_annotation" "at")
+
(load-double-r-r ldd 0 DI OP_02 OPE1_05 GR NA
((fr400 (unit u-gr-load)) (fr450 (unit u-gr-load))
(fr500 (unit u-gr-load)) (fr550 (unit u-gr-load)))
- "Load double word")
+ "Load double word" "$lddann")
(load-double-r-r lddf 1 DF OP_02 OPE1_0B FR FR-ACCESS
((fr400 (unit u-fr-load)) (fr450 (unit u-fr-load))
(fr500 (unit u-fr-load)) (fr550 (unit u-fr-load)))
- "Load double float")
+ "Load double float" "@")
(load-double-r-r lddc 1 DI OP_02 OPE1_0E CPR (MACH frv) ()
- "Load coprocessor double")
+ "Load coprocessor double" "@")
(define-pmacro (ne-load-double-r-r
name not_gr mode op ope regtype size is_float attr profile
@@ -6128,11 +6157,13 @@
(fr500 (unit u-branch)) (fr550 (unit u-branch)))
)
+(dann callann "call annotation" SI "call_annotation" "at")
+
(dni calll
"call and link"
((UNIT I0) (FR500-MAJOR I-5) (FR550-MAJOR I-6)
(FR400-MAJOR I-5) (FR450-MAJOR I-5))
- "calll$pack @($GRi,$GRj)"
+ "calll$pack $callann($GRi,$GRj)"
(+ pack (misc-null-1) (LI-on) OP_0C GRi (misc-null-2) GRj)
(jump-and-link-semantics GRi GRj LI)
((fr400 (unit u-branch)) (fr450 (unit u-branch))
diff --git a/cpu/frv.opc b/cpu/frv.opc
index 46985b6..298252a 100644
--- a/cpu/frv.opc
+++ b/cpu/frv.opc
@@ -970,6 +970,146 @@ static const char * parse_A1
static const char * parse_A
PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long));
+inline static const char *
+parse_symbolic_address (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ int opinfo,
+ enum cgen_parse_operand_result *resultp,
+ bfd_vma *valuep)
+{
+ enum cgen_parse_operand_result result_type;
+ const char *errmsg = (* cd->parse_operand_fn)
+ (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
+ &result_type, valuep);
+
+ if (errmsg == NULL
+ && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
+ return "symbolic expression required";
+
+ if (resultp)
+ *resultp = result_type;
+
+ return errmsg;
+}
+
+static const char *
+parse_ldd_annotation (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ long *valuep)
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#' || **strp == '%')
+ {
+ if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
+ {
+ *strp += 9;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSDESC_RELAX,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ if (valuep)
+ *valuep = value;
+ ++*strp;
+ if (errmsg)
+ return errmsg;
+ }
+ }
+
+ while (**strp == ' ' || **strp == '\t')
+ ++*strp;
+
+ if (**strp != '@')
+ return "missing `@'";
+
+ ++*strp;
+
+ return NULL;
+}
+
+static const char *
+parse_call_annotation (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ long *valuep)
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#' || **strp == '%')
+ {
+ if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GETTLSOFF_RELAX,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ if (valuep)
+ *valuep = value;
+ ++*strp;
+ if (errmsg)
+ return errmsg;
+ }
+ }
+
+ while (**strp == ' ' || **strp == '\t')
+ ++*strp;
+
+ if (**strp != '@')
+ return "missing `@'";
+
+ ++*strp;
+
+ return NULL;
+}
+
+static const char *
+parse_ld_annotation (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ long *valuep)
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#' || **strp == '%')
+ {
+ if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
+ {
+ *strp += 8;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSOFF_RELAX,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ if (valuep)
+ *valuep = value;
+ ++*strp;
+ if (errmsg)
+ return errmsg;
+ }
+ }
+
+ while (**strp == ' ' || **strp == '\t')
+ ++*strp;
+
+ if (**strp != '@')
+ return "missing `@'";
+
+ ++*strp;
+
+ return NULL;
+}
+
static const char *
parse_ulo16 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
@@ -1000,73 +1140,96 @@ parse_ulo16 (cd, strp, opindex, valuep)
if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
{
*strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPRELLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
{
*strp += 7;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
{
*strp += 15;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
{
*strp += 10;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_GOTOFFLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFFLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
{
*strp += 18;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESCLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFFLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFFLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
@@ -1104,73 +1267,96 @@ parse_uslo16 (cd, strp, opindex, valuep)
else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
{
*strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPRELLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
{
*strp += 7;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
{
*strp += 15;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
{
*strp += 10;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_GOTOFFLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFFLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
{
*strp += 18;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESCLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFFLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFFLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
@@ -1201,80 +1387,110 @@ parse_uhi16 (cd, strp, opindex, valuep)
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
+ {
+ /* If bfd_vma is wider than 32 bits, but we have a sign-
+ or zero-extension, truncate it. */
+ if (value >= - ((bfd_vma)1 << 31)
+ || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
+ value &= (((bfd_vma)1 << 16) << 16) - 1;
+ value >>= 16;
+ }
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
{
*strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPRELHI,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
{
*strp += 7;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTHI,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTHI,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
{
*strp += 15;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTHI,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTHI,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
{
*strp += 10;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_GOTOFFHI,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFFHI,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
{
*strp += 18;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESCHI,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFFHI,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFFHI,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
*valuep = value;
return errmsg;
}
@@ -1352,8 +1568,9 @@ parse_d12 (cd, strp, opindex, valuep)
if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
{
*strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPREL12,
+ &result_type, &value);
if (**strp != ')')
return "missing `)'";
++*strp;
@@ -1363,8 +1580,9 @@ parse_d12 (cd, strp, opindex, valuep)
else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
{
*strp += 7;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOT12,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
@@ -1374,9 +1592,9 @@ parse_d12 (cd, strp, opindex, valuep)
else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
{
*strp += 15;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOT12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOT12,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
@@ -1386,9 +1604,9 @@ parse_d12 (cd, strp, opindex, valuep)
else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
{
*strp += 10;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_GOTOFF12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFF12,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
@@ -1398,9 +1616,45 @@ parse_d12 (cd, strp, opindex, valuep)
else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
{
*strp += 18;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESC12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFF12,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
@@ -1423,74 +1677,109 @@ parse_s12 (cd, strp, opindex, valuep)
bfd_vma value;
/* Check for small data reference. */
- if ((**strp == '#' || **strp == '%')
- && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
- {
- *strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
- &result_type, &value);
- if (**strp != ')')
- return "missing `)'";
- ++*strp;
- *valuep = value;
- return errmsg;
- }
- else if ((**strp == '#' || **strp == '%')
- && strncasecmp (*strp + 1, "got12(", 6) == 0)
- {
- *strp += 7;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
- &result_type, &value);
- if (**strp != ')')
- return "missing ')'";
- ++*strp;
- *valuep = value;
- return errmsg;
- }
- else if ((**strp == '#' || **strp == '%')
- && strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
- {
- *strp += 15;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOT12,
- &result_type, &value);
- if (**strp != ')')
- return "missing ')'";
- ++*strp;
- *valuep = value;
- return errmsg;
- }
- else if ((**strp == '#' || **strp == '%')
- && strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
- {
- *strp += 10;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTOFF12,
- &result_type, &value);
- if (**strp != ')')
- return "missing ')'";
- ++*strp;
- *valuep = value;
- return errmsg;
- }
- else if ((**strp == '#' || **strp == '%')
- && strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
- {
- *strp += 18;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
- &result_type, &value);
- if (**strp != ')')
- return "missing ')'";
- ++*strp;
- *valuep = value;
- return errmsg;
- }
- else
+ if (**strp == '#' || **strp == '%')
{
- if (**strp == '#')
- ++*strp;
- return cgen_parse_signed_integer (cd, strp, opindex, valuep);
+ if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
+ {
+ *strp += 9;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPREL12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
+ {
+ *strp += 7;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOT12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
+ {
+ *strp += 15;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOT12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
+ {
+ *strp += 10;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
+ {
+ *strp += 18;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESC12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
}
+
+ if (**strp == '#')
+ ++*strp;
+ return cgen_parse_signed_integer (cd, strp, opindex, valuep);
}
static const char *
@@ -1509,8 +1798,9 @@ parse_u12 (cd, strp, opindex, valuep)
&& strncasecmp (*strp + 1, "gprel12(", 8) == 0)
{
*strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPRELU12,
+ &result_type, &value);
if (**strp != ')')
return "missing `)'";
++*strp;
@@ -1588,6 +1878,38 @@ parse_even_register (cd, strP, tableP, valueP)
return errmsg;
}
+
+static const char *
+parse_call_label (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ int opinfo,
+ enum cgen_parse_operand_result *resultp,
+ bfd_vma *valuep)
+{
+ const char *errmsg;
+ bfd_vma value;
+
+ /* Check for small data reference. */
+ if (opinfo == 0 && (**strp == '#' || **strp == '%'))
+ {
+ if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GETTLSOFF,
+ resultp, &value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ }
+
+ return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
+}
+
/* -- */
/* -- dis.c */
@@ -1599,6 +1921,19 @@ static void print_lo
PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
static void
+print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
+ PTR dis_info,
+ long reloc_ann ATTRIBUTE_UNUSED,
+ long value ATTRIBUTE_UNUSED,
+ bfd_vma pc ATTRIBUTE_UNUSED,
+ int length ATTRIBUTE_UNUSED
+ )
+{
+ disassemble_info *info = (disassemble_info *) dis_info;
+ (*info->fprintf_func) (info->stream, "@");
+}
+
+static void
print_spr (cd, dis_info, names, regno, attrs)
CGEN_CPU_DESC cd;
PTR dis_info;
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 8b9aa3f..5cc7c42 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,16 @@
+2005-01-25 Alexandre Oliva <aoliva@redhat.com>
+
+ * config/tc-frv.c (md_apply_fix3): Mark TLS symbols as such.
+ 2004-12-10 Alexandre Oliva <aoliva@redhat.com>
+ * config/tc-frv.c (frv_pic_ptr): Add tlsmoff support.
+ 2004-11-10 Alexandre Oliva <aoliva@redhat.com>
+ * cgen.c (gas_cgen_parse_operand): Handle
+ CGEN_PARSE_OPERAND_SYMBOLIC.
+ * config/tc-frv.c (md_cgen_lookup_reloc): Handle TLS relocations.
+ (frv_force_relocation): Likewise. Fix handling of PIC
+ relocations.
+ (md_apply_fix3): Likewise.
+
2005-01-21 Ben Elliston <bje@au.ibm.com>
* as.h: Remove #if 0'd code.
diff --git a/gas/cgen.c b/gas/cgen.c
index 384618e..4a4d988 100644
--- a/gas/cgen.c
+++ b/gas/cgen.c
@@ -372,6 +372,8 @@ gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
*resultP = CGEN_PARSE_OPERAND_RESULT_ERROR;
break;
case O_constant:
+ if (want == CGEN_PARSE_OPERAND_SYMBOLIC)
+ goto de_fault;
*valueP = exp.X_add_number;
*resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER;
break;
@@ -379,6 +381,7 @@ gas_cgen_parse_operand (cd, want, strP, opindex, opinfo, resultP, valueP)
*valueP = exp.X_add_number;
*resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER;
break;
+ de_fault:
default:
queue_fixup (opindex, opinfo, &exp);
*valueP = 0;
diff --git a/gas/config/tc-frv.c b/gas/config/tc-frv.c
index e85db95..c75018d 100644
--- a/gas/config/tc-frv.c
+++ b/gas/config/tc-frv.c
@@ -1380,12 +1380,18 @@ md_cgen_lookup_reloc (insn, operand, fixP)
case FRV_OPERAND_LABEL24:
fixP->fx_pcrel = TRUE;
+
+ if (fixP->fx_cgen.opinfo != 0)
+ return fixP->fx_cgen.opinfo;
+
return BFD_RELOC_FRV_LABEL24;
case FRV_OPERAND_UHI16:
case FRV_OPERAND_ULO16:
case FRV_OPERAND_SLO16:
-
+ case FRV_OPERAND_CALLANN:
+ case FRV_OPERAND_LDANN:
+ case FRV_OPERAND_LDDANN:
/* The relocation type should be recorded in opinfo */
if (fixP->fx_cgen.opinfo != 0)
return fixP->fx_cgen.opinfo;
@@ -1416,9 +1422,45 @@ int
frv_force_relocation (fix)
fixS * fix;
{
- if (fix->fx_r_type == BFD_RELOC_FRV_GPREL12
- || fix->fx_r_type == BFD_RELOC_FRV_GPRELU12)
- return 1;
+ switch (fix->fx_r_type < BFD_RELOC_UNUSED
+ ? fix->fx_r_type
+ : fix->fx_cgen.opinfo)
+ {
+ case BFD_RELOC_FRV_GPREL12:
+ case BFD_RELOC_FRV_GPRELU12:
+ case BFD_RELOC_FRV_GPREL32:
+ case BFD_RELOC_FRV_GPRELHI:
+ case BFD_RELOC_FRV_GPRELLO:
+ case BFD_RELOC_FRV_GOT12:
+ case BFD_RELOC_FRV_GOTHI:
+ case BFD_RELOC_FRV_GOTLO:
+ case BFD_RELOC_FRV_FUNCDESC_VALUE:
+ case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
+ case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
+ case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
+ case BFD_RELOC_FRV_GOTOFF12:
+ case BFD_RELOC_FRV_GOTOFFHI:
+ case BFD_RELOC_FRV_GOTOFFLO:
+ case BFD_RELOC_FRV_GETTLSOFF:
+ case BFD_RELOC_FRV_TLSDESC_VALUE:
+ case BFD_RELOC_FRV_GOTTLSDESC12:
+ case BFD_RELOC_FRV_GOTTLSDESCHI:
+ case BFD_RELOC_FRV_GOTTLSDESCLO:
+ case BFD_RELOC_FRV_TLSMOFF12:
+ case BFD_RELOC_FRV_TLSMOFFHI:
+ case BFD_RELOC_FRV_TLSMOFFLO:
+ case BFD_RELOC_FRV_GOTTLSOFF12:
+ case BFD_RELOC_FRV_GOTTLSOFFHI:
+ case BFD_RELOC_FRV_GOTTLSOFFLO:
+ case BFD_RELOC_FRV_TLSOFF:
+ case BFD_RELOC_FRV_TLSDESC_RELAX:
+ case BFD_RELOC_FRV_GETTLSOFF_RELAX:
+ case BFD_RELOC_FRV_TLSOFF_RELAX:
+ return 1;
+
+ default:
+ break;
+ }
return generic_force_reloc (fix);
}
@@ -1440,6 +1482,64 @@ md_apply_fix3 (fixP, valP, seg)
case BFD_RELOC_FRV_LO16:
*valP &= 0xffff;
break;
+
+ /* We need relocations for these, even if their symbols reduce
+ to constants. */
+ case BFD_RELOC_FRV_GPREL12:
+ case BFD_RELOC_FRV_GPRELU12:
+ case BFD_RELOC_FRV_GPREL32:
+ case BFD_RELOC_FRV_GPRELHI:
+ case BFD_RELOC_FRV_GPRELLO:
+ case BFD_RELOC_FRV_GOT12:
+ case BFD_RELOC_FRV_GOTHI:
+ case BFD_RELOC_FRV_GOTLO:
+ case BFD_RELOC_FRV_FUNCDESC_VALUE:
+ case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
+ case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
+ case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
+ case BFD_RELOC_FRV_GOTOFF12:
+ case BFD_RELOC_FRV_GOTOFFHI:
+ case BFD_RELOC_FRV_GOTOFFLO:
+ case BFD_RELOC_FRV_GETTLSOFF:
+ case BFD_RELOC_FRV_TLSDESC_VALUE:
+ case BFD_RELOC_FRV_GOTTLSDESC12:
+ case BFD_RELOC_FRV_GOTTLSDESCHI:
+ case BFD_RELOC_FRV_GOTTLSDESCLO:
+ case BFD_RELOC_FRV_TLSMOFF12:
+ case BFD_RELOC_FRV_TLSMOFFHI:
+ case BFD_RELOC_FRV_TLSMOFFLO:
+ case BFD_RELOC_FRV_GOTTLSOFF12:
+ case BFD_RELOC_FRV_GOTTLSOFFHI:
+ case BFD_RELOC_FRV_GOTTLSOFFLO:
+ case BFD_RELOC_FRV_TLSOFF:
+ case BFD_RELOC_FRV_TLSDESC_RELAX:
+ case BFD_RELOC_FRV_GETTLSOFF_RELAX:
+ case BFD_RELOC_FRV_TLSOFF_RELAX:
+ fixP->fx_addsy = expr_build_uconstant (0);
+ break;
+ }
+ else
+ switch (fixP->fx_cgen.opinfo)
+ {
+ case BFD_RELOC_FRV_GETTLSOFF:
+ case BFD_RELOC_FRV_TLSDESC_VALUE:
+ case BFD_RELOC_FRV_GOTTLSDESC12:
+ case BFD_RELOC_FRV_GOTTLSDESCHI:
+ case BFD_RELOC_FRV_GOTTLSDESCLO:
+ case BFD_RELOC_FRV_TLSMOFF12:
+ case BFD_RELOC_FRV_TLSMOFFHI:
+ case BFD_RELOC_FRV_TLSMOFFLO:
+ case BFD_RELOC_FRV_GOTTLSOFF12:
+ case BFD_RELOC_FRV_GOTTLSOFFHI:
+ case BFD_RELOC_FRV_GOTTLSOFFLO:
+ case BFD_RELOC_FRV_TLSOFF:
+ case BFD_RELOC_FRV_TLSDESC_RELAX:
+ case BFD_RELOC_FRV_GETTLSOFF_RELAX:
+ case BFD_RELOC_FRV_TLSOFF_RELAX:
+ /* Mark TLS symbols as such. */
+ if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ break;
}
gas_cgen_md_apply_fix3 (fixP, valP, seg);
@@ -1603,6 +1703,16 @@ frv_pic_ptr (nbytes)
as_bad ("missing ')'");
reloc_type = BFD_RELOC_FRV_FUNCDESC;
}
+ else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
+ {
+ input_line_pointer += 8;
+ expression (&exp);
+ if (*input_line_pointer == ')')
+ input_line_pointer++;
+ else
+ as_bad ("missing ')'");
+ reloc_type = BFD_RELOC_FRV_TLSMOFF;
+ }
else
expression (&exp);
diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog
index 8ecaa50..74795ee 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -1,3 +1,10 @@
+2005-01-25 Alexandre Oliva <aoliva@redhat.com>
+
+ 2004-12-10 Alexandre Oliva <aoliva@redhat.com>
+ * frv.h: Add R_FRV_TLSMOFF.
+ 2004-11-10 Alexandre Oliva <aoliva@redhat.com>
+ * frv.h: Add TLS relocations.
+
2005-01-17 Nick Clifton <nickc@redhat.com>
* sh.h (EF_SH2A_SH4_NOFPU, EF_SH2A_SH3_NOFPU, EF_SH2A_SH4,
diff --git a/include/elf/frv.h b/include/elf/frv.h
index a6b8a7d..bbd8f33 100644
--- a/include/elf/frv.h
+++ b/include/elf/frv.h
@@ -1,5 +1,5 @@
/* FRV ELF support for BFD.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
@@ -49,6 +49,22 @@ START_RELOC_NUMBERS (elf_frv_reloc_type)
RELOC_NUMBER (R_FRV_GOTOFF12, 22)
RELOC_NUMBER (R_FRV_GOTOFFHI, 23)
RELOC_NUMBER (R_FRV_GOTOFFLO, 24)
+ RELOC_NUMBER (R_FRV_GETTLSOFF, 25)
+ RELOC_NUMBER (R_FRV_TLSDESC_VALUE, 26)
+ RELOC_NUMBER (R_FRV_GOTTLSDESC12, 27)
+ RELOC_NUMBER (R_FRV_GOTTLSDESCHI, 28)
+ RELOC_NUMBER (R_FRV_GOTTLSDESCLO, 29)
+ RELOC_NUMBER (R_FRV_TLSMOFF12, 30)
+ RELOC_NUMBER (R_FRV_TLSMOFFHI, 31)
+ RELOC_NUMBER (R_FRV_TLSMOFFLO, 32)
+ RELOC_NUMBER (R_FRV_GOTTLSOFF12, 33)
+ RELOC_NUMBER (R_FRV_GOTTLSOFFHI, 34)
+ RELOC_NUMBER (R_FRV_GOTTLSOFFLO, 35)
+ RELOC_NUMBER (R_FRV_TLSOFF, 36)
+ RELOC_NUMBER (R_FRV_TLSDESC_RELAX, 37)
+ RELOC_NUMBER (R_FRV_GETTLSOFF_RELAX, 38)
+ RELOC_NUMBER (R_FRV_TLSOFF_RELAX, 39)
+ RELOC_NUMBER (R_FRV_TLSMOFF, 40)
RELOC_NUMBER (R_FRV_GNU_VTINHERIT, 200)
RELOC_NUMBER (R_FRV_GNU_VTENTRY, 201)
END_RELOC_NUMBERS(R_FRV_max)
diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog
index 1a589bd..44c7dc4 100644
--- a/include/opcode/ChangeLog
+++ b/include/opcode/ChangeLog
@@ -1,3 +1,9 @@
+2005-01-25 Alexandre Oliva <aoliva@redhat.com>
+
+ 2004-11-10 Alexandre Oliva <aoliva@redhat.com>
+ * cgen.h (enum cgen_parse_operand_type): Add
+ CGEN_PARSE_OPERAND_SYMBOLIC.
+
2005-01-21 Fred Fish <fnf@specifixinc.com>
* mips.h: Change INSN_ALIAS to INSN2_ALIAS.
diff --git a/include/opcode/cgen.h b/include/opcode/cgen.h
index 16366fd..2926f91 100644
--- a/include/opcode/cgen.h
+++ b/include/opcode/cgen.h
@@ -369,7 +369,8 @@ enum cgen_parse_operand_type
{
CGEN_PARSE_OPERAND_INIT,
CGEN_PARSE_OPERAND_INTEGER,
- CGEN_PARSE_OPERAND_ADDRESS
+ CGEN_PARSE_OPERAND_ADDRESS,
+ CGEN_PARSE_OPERAND_SYMBOLIC
};
/* Values for indicating what was parsed. */
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 7db3064..1aa1671 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -1,3 +1,63 @@
+2005-01-25 Alexandre Oliva <aoliva@redhat.com>
+
+ * ld-frv/fdpic.exp: Add -mfdpic to ASFLAGS.
+ * ld-frv/tls.exp: Likewise.
+ 2004-11-26 Alexandre Oliva <aoliva@redhat.com>
+ * ld-frv/tls-3.s: New.
+ * ld-frv/tls-static-3.d: New.
+ * ld-frv/tls-dynamic-3.d: New.
+ * ld-frv/tls-pie-3.d: New.
+ * ld-frv/tls-shared-3.d: New.
+ * ld-frv/tls-relax-static-3.d: New.
+ * ld-frv/tls-relax-dynamic-3.d: New.
+ * ld-frv/tls-relax-pie-3.d: New.
+ * ld-frv/tls-relax-shared-3.d: New.
+ * ld-frv/tls.exp: Run the new tests.
+ * ld-frv/tls-dynamic-2.d: Adjust for improved relaxation.
+ * ld-frv/tls-relax-dynamic-2.d: Likewise.
+ * ld-frv/tls-relax-initial-shared-2.d: Likewise.
+ 2004-11-10 Alexandre Oliva <aoliva@redhat.com>
+ * ld-frv/tls-1-dep.s: New.
+ * ld-frv/tls-1-shared.lds: New.
+ * ld-frv/tls-1.s: New.
+ * ld-frv/tls-2.s: New.
+ * ld-frv/tls-dynamic-1.d: New.
+ * ld-frv/tls-dynamic-2.d: New.
+ * ld-frv/tls-initial-shared-2.d: New.
+ * ld-frv/tls-pie-1.d: New.
+ * ld-frv/tls-relax-dynamic-1.d: New.
+ * ld-frv/tls-relax-dynamic-2.d: New.
+ * ld-frv/tls-relax-initial-shared-2.d: New.
+ * ld-frv/tls-relax-pie-1.d: New.
+ * ld-frv/tls-relax-shared-1.d: New.
+ * ld-frv/tls-relax-shared-2.d: New.
+ * ld-frv/tls-relax-static-1.d: New.
+ * ld-frv/tls-shared-1-fail.d: New.
+ * ld-frv/tls-shared-1.d: New.
+ * ld-frv/tls-shared-2.d: New.
+ * ld-frv/tls-static-1.d: New.
+ * ld-frv/tls.exp: New.
+ * ld-frv/fdpic-pie-1.d: Adjust for 64-bit host.
+ * ld-frv/fdpic-pie-2.d: Likewise.
+ * ld-frv/fdpic-pie-6.d: Likewise.
+ * ld-frv/fdpic-pie-7.d: Likewise.
+ * ld-frv/fdpic-pie-8.d: Likewise.
+ * ld-frv/fdpic-shared-1.d: Likewise.
+ * ld-frv/fdpic-shared-2.d: Likewise.
+ * ld-frv/fdpic-shared-3.d: Likewise.
+ * ld-frv/fdpic-shared-4.d: Likewise.
+ * ld-frv/fdpic-shared-5.d: Likewise.
+ * ld-frv/fdpic-shared-6.d: Likewise.
+ * ld-frv/fdpic-shared-7.d: Likewise.
+ * ld-frv/fdpic-shared-8.d: Likewise.
+ * ld-frv/fdpic-shared-local-2.d: Likewise.
+ * ld-frv/fdpic-shared-local-8.d: Likewise.
+ * ld-frv/fdpic-static-1.d: Likewise.
+ * ld-frv/fdpic-static-2.d: Likewise.
+ * ld-frv/fdpic-static-6.d: Likewise.
+ * ld-frv/fdpic-static-7.d: Likewise.
+ * ld-frv/fdpic-static-8.d: Likewise.
+
2005-01-17 Richard Sandiford <rsandifo@redhat.com>
* ld-mips-elf/eh-frame2-{n32,n64}.d: New tests.
diff --git a/ld/testsuite/ld-frv/fdpic-pie-1.d b/ld/testsuite/ld-frv/fdpic-pie-1.d
index 17901e8..70d2cca 100644
--- a/ld/testsuite/ld-frv/fdpic-pie-1.d
+++ b/ld/testsuite/ld-frv/fdpic-pie-1.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
35c: 80 f4 00 10 setlo 0x10,gr0
360: 80 f8 00 00 sethi hi\(0x0\),gr0
364: 80 40 ff f8 addi gr15,-8,gr0
- 368: 80 fc ff f8 setlos 0xfffffff8,gr0
+ 368: 80 fc ff f8 setlos 0xf*fffffff8,gr0
36c: 80 f4 ff f8 setlo 0xfff8,gr0
370: 80 f8 ff ff sethi 0xffff,gr0
374: 80 40 ff ec addi gr15,-20,gr0
- 378: 80 fc ff ec setlos 0xffffffec,gr0
+ 378: 80 fc ff ec setlos 0xf*ffffffec,gr0
37c: 80 f4 ff ec setlo 0xffec,gr0
380: 80 f8 ff ff sethi 0xffff,gr0
384: 80 f4 00 14 setlo 0x14,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-pie-2.d b/ld/testsuite/ld-frv/fdpic-pie-2.d
index e03af40..a6a5f8b 100644
--- a/ld/testsuite/ld-frv/fdpic-pie-2.d
+++ b/ld/testsuite/ld-frv/fdpic-pie-2.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
50c: 80 f4 00 14 setlo 0x14,gr0
510: 80 f8 00 00 sethi hi\(0x0\),gr0
514: 80 40 ff f8 addi gr15,-8,gr0
- 518: 80 fc ff f0 setlos 0xfffffff0,gr0
+ 518: 80 fc ff f0 setlos 0xf*fffffff0,gr0
51c: 80 f4 ff e8 setlo 0xffe8,gr0
520: 80 f8 ff ff sethi 0xffff,gr0
524: 80 40 ff dc addi gr15,-36,gr0
- 528: 80 fc ff dc setlos 0xffffffdc,gr0
+ 528: 80 fc ff dc setlos 0xf*ffffffdc,gr0
52c: 80 f4 ff dc setlo 0xffdc,gr0
530: 80 f8 ff ff sethi 0xffff,gr0
534: 80 f4 00 1c setlo 0x1c,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-pie-6.d b/ld/testsuite/ld-frv/fdpic-pie-6.d
index 9ad328b..9c39cc5 100644
--- a/ld/testsuite/ld-frv/fdpic-pie-6.d
+++ b/ld/testsuite/ld-frv/fdpic-pie-6.d
@@ -33,7 +33,7 @@ Disassembly of section \.text:
510: 80 f4 00 1c setlo 0x1c,gr0
514: 80 f8 00 00 sethi hi\(0x0\),gr0
518: 80 40 ff f8 addi gr15,-8,gr0
- 51c: 80 fc ff e8 setlos 0xffffffe8,gr0
+ 51c: 80 fc ff e8 setlos 0xf*ffffffe8,gr0
520: 80 f4 ff e0 setlo 0xffe0,gr0
524: 80 f8 ff ff sethi 0xffff,gr0
528: 80 f4 ff d4 setlo 0xffd4,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-pie-7.d b/ld/testsuite/ld-frv/fdpic-pie-7.d
index 8448e5d..c22c5de 100644
--- a/ld/testsuite/ld-frv/fdpic-pie-7.d
+++ b/ld/testsuite/ld-frv/fdpic-pie-7.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
35c: 80 f4 00 10 setlo 0x10,gr0
360: 80 f8 00 00 sethi hi\(0x0\),gr0
364: 80 40 ff f8 addi gr15,-8,gr0
- 368: 80 fc ff f8 setlos 0xfffffff8,gr0
+ 368: 80 fc ff f8 setlos 0xf*fffffff8,gr0
36c: 80 f4 ff f8 setlo 0xfff8,gr0
370: 80 f8 ff ff sethi 0xffff,gr0
374: 80 40 ff f0 addi gr15,-16,gr0
- 378: 80 fc ff f0 setlos 0xfffffff0,gr0
+ 378: 80 fc ff f0 setlos 0xf*fffffff0,gr0
37c: 80 f4 ff f0 setlo 0xfff0,gr0
380: 80 f8 ff ff sethi 0xffff,gr0
384: 80 f4 00 14 setlo 0x14,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-pie-8.d b/ld/testsuite/ld-frv/fdpic-pie-8.d
index 85437aa..f504016 100644
--- a/ld/testsuite/ld-frv/fdpic-pie-8.d
+++ b/ld/testsuite/ld-frv/fdpic-pie-8.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
50c: 80 f4 00 18 setlo 0x18,gr0
510: 80 f8 00 00 sethi hi\(0x0\),gr0
514: 80 40 ff f8 addi gr15,-8,gr0
- 518: 80 fc ff f0 setlos 0xfffffff0,gr0
+ 518: 80 fc ff f0 setlos 0xf*fffffff0,gr0
51c: 80 f4 ff e8 setlo 0xffe8,gr0
520: 80 f8 ff ff sethi 0xffff,gr0
524: 80 40 ff e0 addi gr15,-32,gr0
- 528: 80 fc ff e0 setlos 0xffffffe0,gr0
+ 528: 80 fc ff e0 setlos 0xf*ffffffe0,gr0
52c: 80 f4 ff e0 setlo 0xffe0,gr0
530: 80 f8 ff ff sethi 0xffff,gr0
534: 80 f4 00 20 setlo 0x20,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-shared-1.d b/ld/testsuite/ld-frv/fdpic-shared-1.d
index ad5cbc4..7d6d03d 100644
--- a/ld/testsuite/ld-frv/fdpic-shared-1.d
+++ b/ld/testsuite/ld-frv/fdpic-shared-1.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
358: 80 f4 00 10 setlo 0x10,gr0
35c: 80 f8 00 00 sethi hi\(0x0\),gr0
360: 80 40 ff f8 addi gr15,-8,gr0
- 364: 80 fc ff f8 setlos 0xfffffff8,gr0
+ 364: 80 fc ff f8 setlos 0xf*fffffff8,gr0
368: 80 f4 ff f8 setlo 0xfff8,gr0
36c: 80 f8 ff ff sethi 0xffff,gr0
370: 80 40 ff f0 addi gr15,-16,gr0
- 374: 80 fc ff f0 setlos 0xfffffff0,gr0
+ 374: 80 fc ff f0 setlos 0xf*fffffff0,gr0
378: 80 f4 ff f0 setlo 0xfff0,gr0
37c: 80 f8 ff ff sethi 0xffff,gr0
380: 80 f4 00 14 setlo 0x14,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-shared-2.d b/ld/testsuite/ld-frv/fdpic-shared-2.d
index 6cc589f..b517d7b 100644
--- a/ld/testsuite/ld-frv/fdpic-shared-2.d
+++ b/ld/testsuite/ld-frv/fdpic-shared-2.d
@@ -35,11 +35,11 @@ Disassembly of section \.text:
520: 80 f4 00 14 setlo 0x14,gr0
524: 80 f8 00 00 sethi hi\(0x0\),gr0
528: 80 40 ff f0 addi gr15,-16,gr0
- 52c: 80 fc ff e8 setlos 0xffffffe8,gr0
+ 52c: 80 fc ff e8 setlos 0xf*ffffffe8,gr0
530: 80 f4 ff e0 setlo 0xffe0,gr0
534: 80 f8 ff ff sethi 0xffff,gr0
538: 80 40 ff d8 addi gr15,-40,gr0
- 53c: 80 fc ff d8 setlos 0xffffffd8,gr0
+ 53c: 80 fc ff d8 setlos 0xf*ffffffd8,gr0
540: 80 f4 ff d8 setlo 0xffd8,gr0
544: 80 f8 ff ff sethi 0xffff,gr0
548: 80 f4 00 1c setlo 0x1c,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-shared-3.d b/ld/testsuite/ld-frv/fdpic-shared-3.d
index 638be7b..3c39d2c 100644
--- a/ld/testsuite/ld-frv/fdpic-shared-3.d
+++ b/ld/testsuite/ld-frv/fdpic-shared-3.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
3a8: 80 f4 00 14 setlo 0x14,gr0
3ac: 80 f8 00 00 sethi hi\(0x0\),gr0
3b0: 80 40 ff f8 addi gr15,-8,gr0
- 3b4: 80 fc ff e8 setlos 0xffffffe8,gr0
+ 3b4: 80 fc ff e8 setlos 0xf*ffffffe8,gr0
3b8: 80 f4 ff d8 setlo 0xffd8,gr0
3bc: 80 f8 ff ff sethi 0xffff,gr0
3c0: 80 40 ff c0 addi gr15,-64,gr0
- 3c4: 80 fc ff c0 setlos 0xffffffc0,gr0
+ 3c4: 80 fc ff c0 setlos 0xf*ffffffc0,gr0
3c8: 80 f4 ff c0 setlo 0xffc0,gr0
3cc: 80 f8 ff ff sethi 0xffff,gr0
3d0: 80 f4 00 24 setlo 0x24,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-shared-4.d b/ld/testsuite/ld-frv/fdpic-shared-4.d
index 5769e86..fa3a3c2 100644
--- a/ld/testsuite/ld-frv/fdpic-shared-4.d
+++ b/ld/testsuite/ld-frv/fdpic-shared-4.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
580: 80 f4 00 18 setlo 0x18,gr0
584: 80 f8 00 00 sethi hi\(0x0\),gr0
588: 80 40 ff f8 addi gr15,-8,gr0
- 58c: 80 fc ff f0 setlos 0xfffffff0,gr0
+ 58c: 80 fc ff f0 setlos 0xf*fffffff0,gr0
590: 80 f4 ff e8 setlo 0xffe8,gr0
594: 80 f8 ff ff sethi 0xffff,gr0
598: 80 40 ff e0 addi gr15,-32,gr0
- 59c: 80 fc ff e0 setlos 0xffffffe0,gr0
+ 59c: 80 fc ff e0 setlos 0xf*ffffffe0,gr0
5a0: 80 f4 ff e0 setlo 0xffe0,gr0
5a4: 80 f8 ff ff sethi 0xffff,gr0
5a8: 80 f4 00 14 setlo 0x14,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-shared-5.d b/ld/testsuite/ld-frv/fdpic-shared-5.d
index f7f9d31..33cbde3 100644
--- a/ld/testsuite/ld-frv/fdpic-shared-5.d
+++ b/ld/testsuite/ld-frv/fdpic-shared-5.d
@@ -33,7 +33,7 @@ Disassembly of section \.text:
4f0: 80 f4 00 18 setlo 0x18,gr0
4f4: 80 f8 00 00 sethi hi\(0x0\),gr0
4f8: 80 40 ff f8 addi gr15,-8,gr0
- 4fc: 80 fc ff e8 setlos 0xffffffe8,gr0
+ 4fc: 80 fc ff e8 setlos 0xf*ffffffe8,gr0
500: 80 f4 ff e0 setlo 0xffe0,gr0
504: 80 f8 ff ff sethi 0xffff,gr0
508: 80 f4 00 14 setlo 0x14,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-shared-6.d b/ld/testsuite/ld-frv/fdpic-shared-6.d
index 0d18336..03abbe7 100644
--- a/ld/testsuite/ld-frv/fdpic-shared-6.d
+++ b/ld/testsuite/ld-frv/fdpic-shared-6.d
@@ -33,7 +33,7 @@ Disassembly of section \.text:
3c4: 80 f4 00 1c setlo 0x1c,gr0
3c8: 80 f8 00 00 sethi hi\(0x0\),gr0
3cc: 80 40 ff f8 addi gr15,-8,gr0
- 3d0: 80 fc ff e8 setlos 0xffffffe8,gr0
+ 3d0: 80 fc ff e8 setlos 0xf*ffffffe8,gr0
3d4: 80 f4 ff e0 setlo 0xffe0,gr0
3d8: 80 f8 ff ff sethi 0xffff,gr0
3dc: 80 f4 ff d0 setlo 0xffd0,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-shared-7.d b/ld/testsuite/ld-frv/fdpic-shared-7.d
index 0a1464f..82218c3 100644
--- a/ld/testsuite/ld-frv/fdpic-shared-7.d
+++ b/ld/testsuite/ld-frv/fdpic-shared-7.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
358: 80 f4 00 10 setlo 0x10,gr0
35c: 80 f8 00 00 sethi hi\(0x0\),gr0
360: 80 40 ff f8 addi gr15,-8,gr0
- 364: 80 fc ff f8 setlos 0xfffffff8,gr0
+ 364: 80 fc ff f8 setlos 0xf*fffffff8,gr0
368: 80 f4 ff f8 setlo 0xfff8,gr0
36c: 80 f8 ff ff sethi 0xffff,gr0
370: 80 40 ff f4 addi gr15,-12,gr0
- 374: 80 fc ff f4 setlos 0xfffffff4,gr0
+ 374: 80 fc ff f4 setlos 0xf*fffffff4,gr0
378: 80 f4 ff f4 setlo 0xfff4,gr0
37c: 80 f8 ff ff sethi 0xffff,gr0
380: 80 f4 00 14 setlo 0x14,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-shared-8.d b/ld/testsuite/ld-frv/fdpic-shared-8.d
index a546165..292bba5 100644
--- a/ld/testsuite/ld-frv/fdpic-shared-8.d
+++ b/ld/testsuite/ld-frv/fdpic-shared-8.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
450: 80 f4 00 18 setlo 0x18,gr0
454: 80 f8 00 00 sethi hi\(0x0\),gr0
458: 80 40 ff f8 addi gr15,-8,gr0
- 45c: 80 fc ff f0 setlos 0xfffffff0,gr0
+ 45c: 80 fc ff f0 setlos 0xf*fffffff0,gr0
460: 80 f4 ff c8 setlo 0xffc8,gr0
464: 80 f8 ff ff sethi 0xffff,gr0
468: 80 40 ff c4 addi gr15,-60,gr0
- 46c: 80 fc ff c4 setlos 0xffffffc4,gr0
+ 46c: 80 fc ff c4 setlos 0xf*ffffffc4,gr0
470: 80 f4 ff c4 setlo 0xffc4,gr0
474: 80 f8 ff ff sethi 0xffff,gr0
478: 80 f4 00 20 setlo 0x20,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-shared-local-2.d b/ld/testsuite/ld-frv/fdpic-shared-local-2.d
index 67fa6d1..e18ced0 100644
--- a/ld/testsuite/ld-frv/fdpic-shared-local-2.d
+++ b/ld/testsuite/ld-frv/fdpic-shared-local-2.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
244: 80 f4 00 14 setlo 0x14,gr0
248: 80 f8 00 00 sethi hi\(0x0\),gr0
24c: 80 40 ff f8 addi gr15,-8,gr0
- 250: 80 fc ff d0 setlos 0xffffffd0,gr0
+ 250: 80 fc ff d0 setlos 0xf*ffffffd0,gr0
254: 80 f4 ff c8 setlo 0xffc8,gr0
258: 80 f8 ff ff sethi 0xffff,gr0
25c: 80 40 ff bc addi gr15,-68,gr0
- 260: 80 fc ff bc setlos 0xffffffbc,gr0
+ 260: 80 fc ff bc setlos 0xf*ffffffbc,gr0
264: 80 f4 ff bc setlo 0xffbc,gr0
268: 80 f8 ff ff sethi 0xffff,gr0
26c: 80 f4 00 1c setlo 0x1c,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-shared-local-8.d b/ld/testsuite/ld-frv/fdpic-shared-local-8.d
index b0aeec1..4c92b07 100644
--- a/ld/testsuite/ld-frv/fdpic-shared-local-8.d
+++ b/ld/testsuite/ld-frv/fdpic-shared-local-8.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
244: 80 f4 00 18 setlo 0x18,gr0
248: 80 f8 00 00 sethi hi\(0x0\),gr0
24c: 80 40 ff f8 addi gr15,-8,gr0
- 250: 80 fc ff f0 setlos 0xfffffff0,gr0
+ 250: 80 fc ff f0 setlos 0xf*fffffff0,gr0
254: 80 f4 ff c8 setlo 0xffc8,gr0
258: 80 f8 ff ff sethi 0xffff,gr0
25c: 80 40 ff c0 addi gr15,-64,gr0
- 260: 80 fc ff c0 setlos 0xffffffc0,gr0
+ 260: 80 fc ff c0 setlos 0xf*ffffffc0,gr0
264: 80 f4 ff c0 setlo 0xffc0,gr0
268: 80 f8 ff ff sethi 0xffff,gr0
26c: 80 f4 00 20 setlo 0x20,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-static-1.d b/ld/testsuite/ld-frv/fdpic-static-1.d
index dd3a498..7512144 100644
--- a/ld/testsuite/ld-frv/fdpic-static-1.d
+++ b/ld/testsuite/ld-frv/fdpic-static-1.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
100b0: 80 f4 00 10 setlo 0x10,gr0
100b4: 80 f8 00 00 sethi hi\(0x0\),gr0
100b8: 80 40 ff f8 addi gr15,-8,gr0
- 100bc: 80 fc ff f8 setlos 0xfffffff8,gr0
+ 100bc: 80 fc ff f8 setlos 0xf*fffffff8,gr0
100c0: 80 f4 ff f8 setlo 0xfff8,gr0
100c4: 80 f8 ff ff sethi 0xffff,gr0
100c8: 80 40 ff f0 addi gr15,-16,gr0
- 100cc: 80 fc ff f0 setlos 0xfffffff0,gr0
+ 100cc: 80 fc ff f0 setlos 0xf*fffffff0,gr0
100d0: 80 f4 ff f0 setlo 0xfff0,gr0
100d4: 80 f8 ff ff sethi 0xffff,gr0
100d8: 80 f4 00 14 setlo 0x14,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-static-2.d b/ld/testsuite/ld-frv/fdpic-static-2.d
index 26003b3..9b5a9c2 100644
--- a/ld/testsuite/ld-frv/fdpic-static-2.d
+++ b/ld/testsuite/ld-frv/fdpic-static-2.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
100b0: 80 f4 00 14 setlo 0x14,gr0
100b4: 80 f8 00 00 sethi hi\(0x0\),gr0
100b8: 80 40 ff f8 addi gr15,-8,gr0
- 100bc: 80 fc ff d0 setlos 0xffffffd0,gr0
+ 100bc: 80 fc ff d0 setlos 0xf*ffffffd0,gr0
100c0: 80 f4 ff c8 setlo 0xffc8,gr0
100c4: 80 f8 ff ff sethi 0xffff,gr0
100c8: 80 40 ff c0 addi gr15,-64,gr0
- 100cc: 80 fc ff c0 setlos 0xffffffc0,gr0
+ 100cc: 80 fc ff c0 setlos 0xf*ffffffc0,gr0
100d0: 80 f4 ff c0 setlo 0xffc0,gr0
100d4: 80 f8 ff ff sethi 0xffff,gr0
100d8: 80 f4 00 1c setlo 0x1c,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-static-6.d b/ld/testsuite/ld-frv/fdpic-static-6.d
index 54a225b..9615876 100644
--- a/ld/testsuite/ld-frv/fdpic-static-6.d
+++ b/ld/testsuite/ld-frv/fdpic-static-6.d
@@ -20,7 +20,7 @@ Disassembly of section \.text:
1001c: 80 f4 00 1c setlo 0x1c,gr0
10020: 80 f8 00 00 sethi hi\(0x0\),gr0
10024: 80 40 ff f8 addi gr15,-8,gr0
- 10028: 80 fc ff f0 setlos 0xfffffff0,gr0
+ 10028: 80 fc ff f0 setlos 0xf*fffffff0,gr0
1002c: 80 f4 ff e8 setlo 0xffe8,gr0
10030: 80 f8 ff ff sethi 0xffff,gr0
10034: 80 f4 ff 18 setlo 0xff18,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-static-7.d b/ld/testsuite/ld-frv/fdpic-static-7.d
index 0363a67..1f882c5 100644
--- a/ld/testsuite/ld-frv/fdpic-static-7.d
+++ b/ld/testsuite/ld-frv/fdpic-static-7.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
100b0: 80 f4 00 10 setlo 0x10,gr0
100b4: 80 f8 00 00 sethi hi\(0x0\),gr0
100b8: 80 40 ff f8 addi gr15,-8,gr0
- 100bc: 80 fc ff f8 setlos 0xfffffff8,gr0
+ 100bc: 80 fc ff f8 setlos 0xf*fffffff8,gr0
100c0: 80 f4 ff f8 setlo 0xfff8,gr0
100c4: 80 f8 ff ff sethi 0xffff,gr0
100c8: 80 40 ff f4 addi gr15,-12,gr0
- 100cc: 80 fc ff f4 setlos 0xfffffff4,gr0
+ 100cc: 80 fc ff f4 setlos 0xf*fffffff4,gr0
100d0: 80 f4 ff f4 setlo 0xfff4,gr0
100d4: 80 f8 ff ff sethi 0xffff,gr0
100d8: 80 f4 00 14 setlo 0x14,gr0
diff --git a/ld/testsuite/ld-frv/fdpic-static-8.d b/ld/testsuite/ld-frv/fdpic-static-8.d
index 804c56e..4f0deae 100644
--- a/ld/testsuite/ld-frv/fdpic-static-8.d
+++ b/ld/testsuite/ld-frv/fdpic-static-8.d
@@ -21,11 +21,11 @@ Disassembly of section \.text:
100b0: 80 f4 00 18 setlo 0x18,gr0
100b4: 80 f8 00 00 sethi hi\(0x0\),gr0
100b8: 80 40 ff f8 addi gr15,-8,gr0
- 100bc: 80 fc ff f0 setlos 0xfffffff0,gr0
+ 100bc: 80 fc ff f0 setlos 0xf*fffffff0,gr0
100c0: 80 f4 ff c8 setlo 0xffc8,gr0
100c4: 80 f8 ff ff sethi 0xffff,gr0
100c8: 80 40 ff c4 addi gr15,-60,gr0
- 100cc: 80 fc ff c4 setlos 0xffffffc4,gr0
+ 100cc: 80 fc ff c4 setlos 0xf*ffffffc4,gr0
100d0: 80 f4 ff c4 setlo 0xffc4,gr0
100d4: 80 f8 ff ff sethi 0xffff,gr0
100d8: 80 f4 00 20 setlo 0x20,gr0
diff --git a/ld/testsuite/ld-frv/fdpic.exp b/ld/testsuite/ld-frv/fdpic.exp
index cc43848..6cf3666 100644
--- a/ld/testsuite/ld-frv/fdpic.exp
+++ b/ld/testsuite/ld-frv/fdpic.exp
@@ -1,5 +1,5 @@
# Expect script for FRV FDPIC linker tests
-# Copyright 2003 Free Software Foundation, Inc.
+# Copyright 2003, 2004, 2005 Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -20,6 +20,10 @@ if {![istarget frv*-*-*] || ![is_elf_format]} {
return
}
+global ASFLAGS
+set saved_ASFLAGS "$ASFLAGS"
+set ASFLAGS "$ASFLAGS -mfdpic"
+
global LDFLAGS
set saved_LDFLAGS "$LDFLAGS"
set LDFLAGS "$LDFLAGS -melf32frvfd"
@@ -59,3 +63,4 @@ run_dump_test "fdpic-shared-8"
run_dump_test "fdpic-shared-local-8"
set LDFLAGS "$saved_LDFLAGS"
+set ASFLAGS "$saved_ASFLAGS"
diff --git a/ld/testsuite/ld-frv/tls-1-dep.s b/ld/testsuite/ld-frv/tls-1-dep.s
new file mode 100644
index 0000000..75daab7
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-1-dep.s
@@ -0,0 +1,7 @@
+ .section .tbss,"awT",@nobits
+ .align 4
+ .globl x
+ .type x, @tls_object
+ .size x, 4
+x:
+ .zero 4
diff --git a/ld/testsuite/ld-frv/tls-1-shared.lds b/ld/testsuite/ld-frv/tls-1-shared.lds
new file mode 100644
index 0000000..3769e01
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-1-shared.lds
@@ -0,0 +1,3 @@
+{
+ local: x; i;
+};
diff --git a/ld/testsuite/ld-frv/tls-1.s b/ld/testsuite/ld-frv/tls-1.s
new file mode 100644
index 0000000..a13c91b
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-1.s
@@ -0,0 +1,85 @@
+ .section .tbss,"awT",@nobits
+ .align 4
+ .globl i
+ .type i, @object
+ .size i, 4
+i:
+ .zero 4
+ .align 4
+ .type l, @object
+ .size l, 4
+l:
+ .zero 4
+ .text
+ .globl _start
+_start:
+ call #gettlsoff(x)
+
+ sethi.p #gottlsdeschi(x), gr14
+ setlo #gottlsdesclo(x), gr14
+ ldd #tlsdesc(x)@(gr15, gr14), gr8
+ calll #gettlsoff(x)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(x)), gr8
+ setlos #gottlsdesclo(x), gr14
+ calll #gettlsoff(x)@(gr8, gr0)
+
+ call #gettlsoff(i)
+
+ sethi.p #gottlsdeschi(i), gr14
+ setlo #gottlsdesclo(i), gr14
+ ldd #tlsdesc(i)@(gr15, gr14), gr8
+ calll #gettlsoff(i)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(i)), gr8
+ setlos #gottlsdesclo(i), gr14
+ calll #gettlsoff(i)@(gr8, gr0)
+
+ call #gettlsoff(l)
+
+ sethi.p #gottlsdeschi(l), gr14
+ setlo #gottlsdesclo(l), gr14
+ ldd #tlsdesc(l)@(gr15, gr14), gr8
+ calll #gettlsoff(l)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(l)), gr8
+ setlos #gottlsdesclo(l), gr14
+ calll #gettlsoff(l)@(gr8, gr0)
+
+ call #gettlsoff(0)
+
+ sethi.p #gottlsdeschi(0), gr14
+ setlo #gottlsdesclo(0), gr14
+ ldd #tlsdesc(0)@(gr15, gr14), gr8
+ calll #gettlsoff(0)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(0)), gr8
+ setlos #gottlsdesclo(0), gr14
+ calll #gettlsoff(0)@(gr8, gr0)
+
+ sethi.p #tlsmoffhi(l), gr8
+ setlo #tlsmofflo(l), gr8
+
+ sethi.p #tlsmoffhi(i), gr9
+ setlo #tlsmofflo(i), gr9
+
+ ldi @(gr15, #gottlsoff12(x)), gr9
+ ldi @(gr15, #gottlsoff12(i)), gr9
+ ldi @(gr15, #gottlsoff12(l)), gr9
+ ldi @(gr15, #gottlsoff12(0)), gr9
+
+ sethi.p #gottlsoffhi(x), gr14
+ setlo #gottlsofflo(x), gr14
+ ld #tlsoff(x)@(gr15, gr14), gr9
+
+ sethi.p #gottlsoffhi(i), gr14
+ setlo #gottlsofflo(i), gr14
+ ld #tlsoff(i)@(gr15, gr14), gr9
+
+ sethi.p #gottlsoffhi(l), gr14
+ setlo #gottlsofflo(l), gr14
+ ld #tlsoff(l)@(gr15, gr14), gr9
+
+ sethi.p #gottlsoffhi(0), gr14
+ setlo #gottlsofflo(0), gr14
+ ld #tlsoff(0)@(gr15, gr14), gr9
diff --git a/ld/testsuite/ld-frv/tls-2.s b/ld/testsuite/ld-frv/tls-2.s
new file mode 100644
index 0000000..f0712e3
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-2.s
@@ -0,0 +1,183 @@
+ .section .tbss,"awT",@nobits
+ .align 4
+ .type l, @object
+ .size l, 4
+l:
+ .zero 4
+ .align 4
+ .globl i
+ .type i, @object
+ .size i, 4
+i:
+ .zero 4
+ .text
+ .globl _start
+_start:
+ call #gettlsoff(l+1)
+ call #gettlsoff(l+1+4096)
+ call #gettlsoff(l+1+65536)
+
+ sethi.p #gottlsdeschi(l+2), gr14
+ setlo #gottlsdesclo(l+2), gr14
+ ldd #tlsdesc(l+2)@(gr15, gr14), gr8
+ calll #gettlsoff(l+2)@(gr8, gr0)
+
+ sethi.p #gottlsdeschi(l+2+4096), gr14
+ setlo #gottlsdesclo(l+2+4096), gr14
+ ldd #tlsdesc(l+2+4096)@(gr15, gr14), gr8
+ calll #gettlsoff(l+2+4096)@(gr8, gr0)
+
+ sethi.p #gottlsdeschi(l+2+65536), gr14
+ setlo #gottlsdesclo(l+2+65536), gr14
+ ldd #tlsdesc(l+2+65536)@(gr15, gr14), gr8
+ calll #gettlsoff(l+2+65536)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(l+3)), gr8
+ setlos #gottlsdesclo(l+3), gr14
+ calll #gettlsoff(l+3)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(l+3+4096)), gr8
+ setlos #gottlsdesclo(l+3+4096), gr14
+ calll #gettlsoff(l+3+4096)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(l+3+65536)), gr8
+ setlos #gottlsdesclo(l+3+65536), gr14
+ calll #gettlsoff(l+3+65536)@(gr8, gr0)
+
+ sethi #tlsmoffhi(l+4), gr9
+ setlo #tlsmofflo(l+4), gr9
+
+ sethi #tlsmoffhi(l+4+4096), gr9
+ setlo #tlsmofflo(l+4+4096), gr9
+
+ sethi #tlsmoffhi(l+4+65536), gr9
+ setlo #tlsmofflo(l+4+65536), gr9
+
+ call #gettlsoff(i+1)
+ call #gettlsoff(i+1+4096)
+ call #gettlsoff(i+1+65536)
+
+ sethi.p #gottlsdeschi(i+2), gr14
+ setlo #gottlsdesclo(i+2), gr14
+ ldd #tlsdesc(i+2)@(gr15, gr14), gr8
+ calll #gettlsoff(i+2)@(gr8, gr0)
+
+ sethi.p #gottlsdeschi(i+2+4096), gr14
+ setlo #gottlsdesclo(i+2+4096), gr14
+ ldd #tlsdesc(i+2+4096)@(gr15, gr14), gr8
+ calll #gettlsoff(i+2+4096)@(gr8, gr0)
+
+ sethi.p #gottlsdeschi(i+2+65536), gr14
+ setlo #gottlsdesclo(i+2+65536), gr14
+ ldd #tlsdesc(i+2+65536)@(gr15, gr14), gr8
+ calll #gettlsoff(i+2+65536)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(i+3)), gr8
+ setlos #gottlsdesclo(i+3), gr14
+ calll #gettlsoff(i+3)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(i+3+4096)), gr8
+ setlos #gottlsdesclo(i+3+4096), gr14
+ calll #gettlsoff(i+3+4096)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(i+3+65536)), gr8
+ setlos #gottlsdesclo(i+3+65536), gr14
+ calll #gettlsoff(i+3+65536)@(gr8, gr0)
+
+ sethi #tlsmoffhi(i+4), gr9
+ setlo #tlsmofflo(i+4), gr9
+
+ sethi #tlsmoffhi(i+4+4096), gr9
+ setlo #tlsmofflo(i+4+4096), gr9
+
+ sethi #tlsmoffhi(i+4+65536), gr9
+ setlo #tlsmofflo(i+4+65536), gr9
+
+ call #gettlsoff(0+1)
+ call #gettlsoff(0+1+4096)
+ call #gettlsoff(0+1+65536)
+
+ sethi.p #gottlsdeschi(0+2), gr14
+ setlo #gottlsdesclo(0+2), gr14
+ ldd #tlsdesc(0+2)@(gr15, gr14), gr8
+ calll #gettlsoff(0+2)@(gr8, gr0)
+
+ sethi.p #gottlsdeschi(0+2+4096), gr14
+ setlo #gottlsdesclo(0+2+4096), gr14
+ ldd #tlsdesc(0+2+4096)@(gr15, gr14), gr8
+ calll #gettlsoff(0+2+4096)@(gr8, gr0)
+
+ sethi.p #gottlsdeschi(0+2+65536), gr14
+ setlo #gottlsdesclo(0+2+65536), gr14
+ ldd #tlsdesc(0+2+65536)@(gr15, gr14), gr8
+ calll #gettlsoff(0+2+65536)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(0+3)), gr8
+ setlos #gottlsdesclo(0+3), gr14
+ calll #gettlsoff(0+3)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(0+3+4096)), gr8
+ setlos #gottlsdesclo(0+3+4096), gr14
+ calll #gettlsoff(0+3+4096)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(0+3+65536)), gr8
+ setlos #gottlsdesclo(0+3+65536), gr14
+ calll #gettlsoff(0+3+65536)@(gr8, gr0)
+
+ sethi #tlsmoffhi(0+4), gr9
+ setlo #tlsmofflo(0+4), gr9
+
+ sethi #tlsmoffhi(0+4+4096), gr9
+ setlo #tlsmofflo(0+4+4096), gr9
+
+ sethi #tlsmoffhi(0+4+65536), gr9
+ setlo #tlsmofflo(0+4+65536), gr9
+
+ call #gettlsoff(x+1)
+ call #gettlsoff(x+1+4096)
+ call #gettlsoff(x+1+65536)
+
+ sethi.p #gottlsdeschi(x+2), gr14
+ setlo #gottlsdesclo(x+2), gr14
+ ldd #tlsdesc(x+2)@(gr15, gr14), gr8
+ calll #gettlsoff(x+2)@(gr8, gr0)
+
+ sethi.p #gottlsdeschi(x+2+4096), gr14
+ setlo #gottlsdesclo(x+2+4096), gr14
+ ldd #tlsdesc(x+2+4096)@(gr15, gr14), gr8
+ calll #gettlsoff(x+2+4096)@(gr8, gr0)
+
+ sethi.p #gottlsdeschi(x+2+65536), gr14
+ setlo #gottlsdesclo(x+2+65536), gr14
+ ldd #tlsdesc(x+2+65536)@(gr15, gr14), gr8
+ calll #gettlsoff(x+2+65536)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(x+3)), gr8
+ setlos #gottlsdesclo(x+3), gr14
+ calll #gettlsoff(x+3)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(x+3+4096)), gr8
+ setlos #gottlsdesclo(x+3+4096), gr14
+ calll #gettlsoff(x+3+4096)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(x+3+65536)), gr8
+ setlos #gottlsdesclo(x+3+65536), gr14
+ calll #gettlsoff(x+3+65536)@(gr8, gr0)
+
+.ifdef static_tls
+ ldi @(gr15, #gottlsoff12(l+1)), gr9
+ ldi @(gr15, #gottlsoff12(l+1+65536)), gr9
+ ldi @(gr15, #gottlsoff12(i+1)), gr9
+ ldi @(gr15, #gottlsoff12(i+1+65536)), gr9
+ ldi @(gr15, #gottlsoff12(0+1)), gr9
+ ldi @(gr15, #gottlsoff12(0+1+65536)), gr9
+ ldi @(gr15, #gottlsoff12(x+1)), gr9
+ ldi @(gr15, #gottlsoff12(x+1+65536)), gr9
+
+ setlos #gottlsofflo(l+1+4096), gr8
+ ld #tlsoff(l+1+4096)@(gr15, gr8), gr9
+
+ sethi #gottlsoffhi(i+1+4096), gr8
+ setlo #gottlsofflo(i+1+4096), gr8
+ ld #tlsoff(i+1+4096)@(gr15, gr8), gr9
+.endif
diff --git a/ld/testsuite/ld-frv/tls-3.s b/ld/testsuite/ld-frv/tls-3.s
new file mode 100644
index 0000000..6dd7972
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-3.s
@@ -0,0 +1,20 @@
+ .text
+ .weak u
+ .globl _start
+_start:
+ call #gettlsoff(u)
+
+ sethi.p #gottlsdeschi(u), gr14
+ setlo #gottlsdesclo(u), gr14
+ ldd #tlsdesc(u)@(gr15, gr14), gr8
+ calll #gettlsoff(u)@(gr8, gr0)
+
+ lddi.p @(gr15, #gottlsdesc12(u)), gr8
+ setlos #gottlsdesclo(u), gr14
+ calll #gettlsoff(u)@(gr8, gr0)
+
+ ldi @(gr15, #gottlsoff12(u)), gr9
+
+ sethi.p #gottlsoffhi(u), gr14
+ setlo #gottlsofflo(u), gr14
+ ld #tlsoff(u)@(gr15, gr14), gr9
diff --git a/ld/testsuite/ld-frv/tls-dynamic-1.d b/ld/testsuite/ld-frv/tls-dynamic-1.d
new file mode 100644
index 0000000..27075d5
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-dynamic-1.d
@@ -0,0 +1,71 @@
+#name: FRV TLS relocs, dynamic linking
+#source: tls-1.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: tmpdir/tls-1-dep.so
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+000102c8 <_start>:
+ 102c8: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 102cc: 00 88 00 00 nop\.p
+ 102d0: 80 88 00 00 nop
+ 102d4: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 102d8: 80 88 00 00 nop
+ 102dc: 12 c8 f0 10 ldi\.p @\(gr15,16\),gr9
+ 102e0: 80 88 00 00 nop
+ 102e4: 80 88 00 00 nop
+ 102e8: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 102ec: 00 88 00 00 nop\.p
+ 102f0: 80 88 00 00 nop
+ 102f4: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 102f8: 80 88 00 00 nop
+ 102fc: 12 fc f8 10 setlos\.p 0xf*fffff810,gr9
+ 10300: 80 88 00 00 nop
+ 10304: 80 88 00 00 nop
+ 10308: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 1030c: 00 88 00 00 nop\.p
+ 10310: 80 88 00 00 nop
+ 10314: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 10318: 80 88 00 00 nop
+ 1031c: 12 fc f8 20 setlos\.p 0xf*fffff820,gr9
+ 10320: 80 88 00 00 nop
+ 10324: 80 88 00 00 nop
+ 10328: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 1032c: 00 88 00 00 nop\.p
+ 10330: 80 88 00 00 nop
+ 10334: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10338: 80 88 00 00 nop
+ 1033c: 12 fc 00 00 setlos\.p lo\(0x0\),gr9
+ 10340: 80 88 00 00 nop
+ 10344: 80 88 00 00 nop
+ 10348: 00 88 00 00 nop\.p
+ 1034c: 90 fc f8 20 setlos 0xf*fffff820,gr8
+ 10350: 00 88 00 00 nop\.p
+ 10354: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 10358: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 1035c: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 10360: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 10364: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10368: 00 88 00 00 nop\.p
+ 1036c: 80 88 00 00 nop
+ 10370: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 10374: 00 88 00 00 nop\.p
+ 10378: 80 88 00 00 nop
+ 1037c: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 10380: 00 88 00 00 nop\.p
+ 10384: 80 88 00 00 nop
+ 10388: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 1038c: 00 88 00 00 nop\.p
+ 10390: 80 88 00 00 nop
+ 10394: 92 fc 00 00 setlos lo\(0x0\),gr9
+Disassembly of section \.got:
+
+00014428 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 14434: ff ff f8 20 cop2 -32,cpr63,cpr32,cpr63
+ 14438: 00 00 00 00 add\.p gr0,gr0,gr0
+ 14438: R_FRV_TLSOFF x
+ 1443c: ff ff f8 10 cop2 -32,cpr63,cpr16,cpr63
+ 14440: 00 00 00 00 add\.p gr0,gr0,gr0
diff --git a/ld/testsuite/ld-frv/tls-dynamic-2.d b/ld/testsuite/ld-frv/tls-dynamic-2.d
new file mode 100644
index 0000000..986789c
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-dynamic-2.d
@@ -0,0 +1,200 @@
+#name: FRV TLS relocs with addends, dynamic linking
+#source: tls-2.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: tmpdir/tls-1-dep.so
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.plt:
+
+00010308 <\.plt>:
+ 10308: c0 3a 40 00 bralr
+ 1030c: 92 fc 08 21 setlos 0x821,gr9
+ 10310: c0 3a 40 00 bralr
+ 10314: 12 f8 00 00 sethi\.p hi\(0x0\),gr9
+ 10318: 92 f4 f8 21 setlo 0xf821,gr9
+ 1031c: c0 3a 40 00 bralr
+ 10320: 92 fc 00 01 setlos 0x1,gr9
+ 10324: c0 3a 40 00 bralr
+ 10328: 92 c8 ff bc ldi @\(gr15,-68\),gr9
+ 1032c: c0 3a 40 00 bralr
+ 10330: 92 fc f8 11 setlos 0xf*fffff811,gr9
+ 10334: c0 3a 40 00 bralr
+ 10338: 92 fc 10 01 setlos 0x1001,gr9
+ 1033c: c0 3a 40 00 bralr
+ 10340: 92 c8 ff d4 ldi @\(gr15,-44\),gr9
+ 10344: c0 3a 40 00 bralr
+ 10348: 92 fc 08 11 setlos 0x811,gr9
+ 1034c: c0 3a 40 00 bralr
+ 10350: 12 f8 00 01 sethi\.p 0x1,gr9
+ 10354: 92 f4 00 01 setlo 0x1,gr9
+ 10358: c0 3a 40 00 bralr
+ 1035c: 92 c8 ff ec ldi @\(gr15,-20\),gr9
+ 10360: c0 3a 40 00 bralr
+ 10364: 12 f8 00 00 sethi\.p hi\(0x0\),gr9
+ 10368: 92 f4 f8 11 setlo 0xf811,gr9
+ 1036c: c0 3a 40 00 bralr
+ 10370: 92 fc f8 21 setlos 0xf*fffff821,gr9
+ 10374: c0 3a 40 00 bralr
+Disassembly of section \.text:
+
+00010378 <_start>:
+ 10378: 92 fc f8 11 setlos 0xf*fffff811,gr9
+ 1037c: 92 fc 08 11 setlos 0x811,gr9
+ 10380: 92 c8 ff f4 ldi @\(gr15,-12\),gr9
+ 10384: 00 88 00 00 nop\.p
+ 10388: 80 88 00 00 nop
+ 1038c: 92 fc f8 12 setlos 0xf*fffff812,gr9
+ 10390: 80 88 00 00 nop
+ 10394: 00 88 00 00 nop\.p
+ 10398: 80 88 00 00 nop
+ 1039c: 92 fc 08 12 setlos 0x812,gr9
+ 103a0: 80 88 00 00 nop
+ 103a4: 00 88 00 00 nop\.p
+ 103a8: 80 88 00 00 nop
+ 103ac: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 103b0: 92 f4 f8 12 setlo 0xf812,gr9
+ 103b4: 12 fc f8 13 setlos\.p 0xf*fffff813,gr9
+ 103b8: 80 88 00 00 nop
+ 103bc: 80 88 00 00 nop
+ 103c0: 12 fc 08 13 setlos\.p 0x813,gr9
+ 103c4: 80 88 00 00 nop
+ 103c8: 80 88 00 00 nop
+ 103cc: 12 f8 00 00 sethi\.p hi\(0x0\),gr9
+ 103d0: 80 88 00 00 nop
+ 103d4: 92 f4 f8 13 setlo 0xf813,gr9
+ 103d8: 80 88 00 00 nop
+ 103dc: 92 fc f8 14 setlos 0xf*fffff814,gr9
+ 103e0: 80 88 00 00 nop
+ 103e4: 92 fc 08 14 setlos 0x814,gr9
+ 103e8: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 103ec: 92 f4 f8 14 setlo 0xf814,gr9
+ 103f0: 92 fc f8 21 setlos 0xf*fffff821,gr9
+ 103f4: 92 fc 08 21 setlos 0x821,gr9
+ 103f8: 92 c8 ff ac ldi @\(gr15,-84\),gr9
+ 103fc: 00 88 00 00 nop\.p
+ 10400: 80 88 00 00 nop
+ 10404: 92 fc f8 22 setlos 0xf*fffff822,gr9
+ 10408: 80 88 00 00 nop
+ 1040c: 00 88 00 00 nop\.p
+ 10410: 80 88 00 00 nop
+ 10414: 92 fc 08 22 setlos 0x822,gr9
+ 10418: 80 88 00 00 nop
+ 1041c: 00 88 00 00 nop\.p
+ 10420: 80 88 00 00 nop
+ 10424: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 10428: 92 f4 f8 22 setlo 0xf822,gr9
+ 1042c: 12 fc f8 23 setlos\.p 0xf*fffff823,gr9
+ 10430: 80 88 00 00 nop
+ 10434: 80 88 00 00 nop
+ 10438: 12 fc 08 23 setlos\.p 0x823,gr9
+ 1043c: 80 88 00 00 nop
+ 10440: 80 88 00 00 nop
+ 10444: 12 f8 00 00 sethi\.p hi\(0x0\),gr9
+ 10448: 80 88 00 00 nop
+ 1044c: 92 f4 f8 23 setlo 0xf823,gr9
+ 10450: 80 88 00 00 nop
+ 10454: 92 fc f8 24 setlos 0xf*fffff824,gr9
+ 10458: 80 88 00 00 nop
+ 1045c: 92 fc 08 24 setlos 0x824,gr9
+ 10460: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 10464: 92 f4 f8 24 setlo 0xf824,gr9
+ 10468: 92 fc 00 01 setlos 0x1,gr9
+ 1046c: 92 fc 10 01 setlos 0x1001,gr9
+ 10470: 92 c8 ff e4 ldi @\(gr15,-28\),gr9
+ 10474: 00 88 00 00 nop\.p
+ 10478: 80 88 00 00 nop
+ 1047c: 92 fc 00 02 setlos 0x2,gr9
+ 10480: 80 88 00 00 nop
+ 10484: 00 88 00 00 nop\.p
+ 10488: 80 88 00 00 nop
+ 1048c: 92 fc 10 02 setlos 0x1002,gr9
+ 10490: 80 88 00 00 nop
+ 10494: 00 88 00 00 nop\.p
+ 10498: 80 88 00 00 nop
+ 1049c: 92 f8 00 01 sethi 0x1,gr9
+ 104a0: 92 f4 00 02 setlo 0x2,gr9
+ 104a4: 12 fc 00 03 setlos\.p 0x3,gr9
+ 104a8: 80 88 00 00 nop
+ 104ac: 80 88 00 00 nop
+ 104b0: 12 fc 10 03 setlos\.p 0x1003,gr9
+ 104b4: 80 88 00 00 nop
+ 104b8: 80 88 00 00 nop
+ 104bc: 12 f8 00 01 sethi\.p 0x1,gr9
+ 104c0: 80 88 00 00 nop
+ 104c4: 92 f4 00 03 setlo 0x3,gr9
+ 104c8: 80 88 00 00 nop
+ 104cc: 92 fc 00 04 setlos 0x4,gr9
+ 104d0: 80 88 00 00 nop
+ 104d4: 92 fc 10 04 setlos 0x1004,gr9
+ 104d8: 92 f8 00 01 sethi 0x1,gr9
+ 104dc: 92 f4 00 04 setlo 0x4,gr9
+ 104e0: 92 c8 ff bc ldi @\(gr15,-68\),gr9
+ 104e4: 92 c8 ff d4 ldi @\(gr15,-44\),gr9
+ 104e8: 92 c8 ff ec ldi @\(gr15,-20\),gr9
+ 104ec: 00 88 00 00 nop\.p
+ 104f0: 80 88 00 00 nop
+ 104f4: 92 c8 f0 20 ldi @\(gr15,32\),gr9
+ 104f8: 80 88 00 00 nop
+ 104fc: 00 88 00 00 nop\.p
+ 10500: 80 88 00 00 nop
+ 10504: 92 c8 f0 1c ldi @\(gr15,28\),gr9
+ 10508: 80 88 00 00 nop
+ 1050c: 00 88 00 00 nop\.p
+ 10510: 80 88 00 00 nop
+ 10514: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+ 10518: 80 88 00 00 nop
+ 1051c: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 10520: 80 88 00 00 nop
+ 10524: 80 88 00 00 nop
+ 10528: 12 c8 f0 10 ldi\.p @\(gr15,16\),gr9
+ 1052c: 80 88 00 00 nop
+ 10530: 80 88 00 00 nop
+ 10534: 12 c8 f0 14 ldi\.p @\(gr15,20\),gr9
+ 10538: 80 88 00 00 nop
+ 1053c: 80 88 00 00 nop
+Disassembly of section \.got:
+
+000145f8 <_GLOBAL_OFFSET_TABLE_-0x60>:
+ 145f8: 00 01 03 08 cmpb\.p gr16,gr8,icc0
+ 145fc: 00 00 08 21 \*unknown\*
+ 14600: 00 01 03 08 cmpb\.p gr16,gr8,icc0
+ 14604: 00 00 f8 21 \*unknown\*
+ 14608: 00 01 03 08 cmpb\.p gr16,gr8,icc0
+ 1460c: 00 00 00 01 add\.p gr0,sp,gr0
+ 14610: 00 00 00 00 add\.p gr0,gr0,gr0
+ 14610: R_FRV_TLSDESC_VALUE x
+ 14614: 00 00 00 01 add\.p gr0,sp,gr0
+ 14618: 00 01 03 08 cmpb\.p gr16,gr8,icc0
+ 1461c: ff ff f8 11 cop2 -32,cpr63,cpr17,cpr63
+ 14620: 00 01 03 08 cmpb\.p gr16,gr8,icc0
+ 14624: 00 00 10 01 add\.p sp,sp,gr0
+ 14628: 00 00 00 00 add\.p gr0,gr0,gr0
+ 14628: R_FRV_TLSDESC_VALUE x
+ 1462c: 00 00 10 01 add\.p sp,sp,gr0
+ 14630: 00 01 03 08 cmpb\.p gr16,gr8,icc0
+ 14634: 00 00 08 11 \*unknown\*
+ 14638: 00 01 03 08 cmpb\.p gr16,gr8,icc0
+ 1463c: 00 01 00 01 add\.p gr16,sp,gr0
+ 14640: 00 00 00 00 add\.p gr0,gr0,gr0
+ 14640: R_FRV_TLSDESC_VALUE x
+ 14644: 00 01 00 01 add\.p gr16,sp,gr0
+ 14648: 00 01 03 08 cmpb\.p gr16,gr8,icc0
+ 1464c: 00 00 f8 11 \*unknown\*
+ 14650: 00 01 03 08 cmpb\.p gr16,gr8,icc0
+ 14654: ff ff f8 21 cop2 -32,cpr63,cpr33,cpr63
+
+00014658 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 14664: 00 00 00 03 add\.p gr0,gr3,gr0
+ 14664: R_FRV_TLSOFF x
+ 14668: 00 00 10 03 add\.p sp,gr3,gr0
+ 14668: R_FRV_TLSOFF x
+ 1466c: 00 01 00 03 add\.p gr16,gr3,gr0
+ 1466c: R_FRV_TLSOFF x
+ 14670: 00 01 00 02 add\.p gr16,fp,gr0
+ 14670: R_FRV_TLSOFF x
+ 14674: 00 00 10 02 add\.p sp,fp,gr0
+ 14674: R_FRV_TLSOFF x
+ 14678: 00 00 00 02 add\.p gr0,fp,gr0
+ 14678: R_FRV_TLSOFF x
diff --git a/ld/testsuite/ld-frv/tls-dynamic-3.d b/ld/testsuite/ld-frv/tls-dynamic-3.d
new file mode 100644
index 0000000..f4d3337
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-dynamic-3.d
@@ -0,0 +1,27 @@
+#name: FRV TLS undefweak relocs, dynamic linking
+#source: tls-3.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: tmpdir/tls-1-dep.so
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+00010294 <_start>:
+ 10294: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 10298: 00 88 00 00 nop\.p
+ 1029c: 80 88 00 00 nop
+ 102a0: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 102a4: 80 88 00 00 nop
+ 102a8: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 102ac: 80 88 00 00 nop
+ 102b0: 80 88 00 00 nop
+ 102b4: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 102b8: 00 88 00 00 nop\.p
+ 102bc: 80 88 00 00 nop
+ 102c0: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+Disassembly of section \.got:
+
+00014350 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 1435c: R_FRV_TLSOFF u
diff --git a/ld/testsuite/ld-frv/tls-initial-shared-2.d b/ld/testsuite/ld-frv/tls-initial-shared-2.d
new file mode 100644
index 0000000..3d276db
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-initial-shared-2.d
@@ -0,0 +1,235 @@
+#name: FRV TLS relocs with addends, shared linking with static TLS
+#source: tls-2.s
+#as: --defsym static_tls=1
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -shared tmpdir/tls-1-dep.so --version-script tls-1-shared.lds
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.plt:
+
+00000464 <\.plt>:
+ 464: 92 c8 f0 5c ldi @\(gr15,92\),gr9
+ 468: c0 3a 40 00 bralr
+ 46c: 90 cc ff e8 lddi @\(gr15,-24\),gr8
+ 470: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 474: 92 c8 f0 78 ldi @\(gr15,120\),gr9
+ 478: c0 3a 40 00 bralr
+ 47c: 90 cc ff f8 lddi @\(gr15,-8\),gr8
+ 480: 80 30 80 00 jmpl @\(gr8,gr0\)
+Disassembly of section \.text:
+
+00000484 <_start>:
+ 484: 92 c8 f0 30 ldi @\(gr15,48\),gr9
+ 488: 92 c8 f0 78 ldi @\(gr15,120\),gr9
+ 48c: 92 c8 f0 4c ldi @\(gr15,76\),gr9
+ 490: 00 88 00 00 nop\.p
+ 494: 80 88 00 00 nop
+ 498: 92 c8 f0 70 ldi @\(gr15,112\),gr9
+ 49c: 80 88 00 00 nop
+ 4a0: 00 88 00 00 nop\.p
+ 4a4: 80 88 00 00 nop
+ 4a8: 92 c8 f0 7c ldi @\(gr15,124\),gr9
+ 4ac: 80 88 00 00 nop
+ 4b0: 00 88 00 00 nop\.p
+ 4b4: 80 88 00 00 nop
+ 4b8: 92 c8 f0 8c ldi @\(gr15,140\),gr9
+ 4bc: 80 88 00 00 nop
+ 4c0: 12 c8 f0 34 ldi\.p @\(gr15,52\),gr9
+ 4c4: 80 88 00 00 nop
+ 4c8: 80 88 00 00 nop
+ 4cc: 12 c8 f0 3c ldi\.p @\(gr15,60\),gr9
+ 4d0: 80 88 00 00 nop
+ 4d4: 80 88 00 00 nop
+ 4d8: 12 c8 f0 50 ldi\.p @\(gr15,80\),gr9
+ 4dc: 80 88 00 00 nop
+ 4e0: 80 88 00 00 nop
+ 4e4: 80 88 00 00 nop
+ 4e8: 92 fc f8 14 setlos 0xf*fffff814,gr9
+ 4ec: 80 88 00 00 nop
+ 4f0: 92 fc 08 14 setlos 0x814,gr9
+ 4f4: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 4f8: 92 f4 f8 14 setlo 0xf814,gr9
+ 4fc: 92 c8 f0 54 ldi @\(gr15,84\),gr9
+ 500: 92 c8 f0 5c ldi @\(gr15,92\),gr9
+ 504: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+ 508: 00 88 00 00 nop\.p
+ 50c: 80 88 00 00 nop
+ 510: 92 c8 f0 90 ldi @\(gr15,144\),gr9
+ 514: 80 88 00 00 nop
+ 518: 00 88 00 00 nop\.p
+ 51c: 80 88 00 00 nop
+ 520: 92 c8 f0 60 ldi @\(gr15,96\),gr9
+ 524: 80 88 00 00 nop
+ 528: 00 88 00 00 nop\.p
+ 52c: 80 88 00 00 nop
+ 530: 92 c8 f0 64 ldi @\(gr15,100\),gr9
+ 534: 80 88 00 00 nop
+ 538: 12 c8 f0 58 ldi\.p @\(gr15,88\),gr9
+ 53c: 80 88 00 00 nop
+ 540: 80 88 00 00 nop
+ 544: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 548: 80 88 00 00 nop
+ 54c: 80 88 00 00 nop
+ 550: 12 c8 f0 1c ldi\.p @\(gr15,28\),gr9
+ 554: 80 88 00 00 nop
+ 558: 80 88 00 00 nop
+ 55c: 80 88 00 00 nop
+ 560: 92 fc f8 24 setlos 0xf*fffff824,gr9
+ 564: 80 88 00 00 nop
+ 568: 92 fc 08 24 setlos 0x824,gr9
+ 56c: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 570: 92 f4 f8 24 setlo 0xf824,gr9
+ 574: 92 c8 f0 24 ldi @\(gr15,36\),gr9
+ 578: fe 3f ff c1 call 47c <i\+0x46c>
+ 57c: 92 c8 f0 40 ldi @\(gr15,64\),gr9
+ 580: 00 88 00 00 nop\.p
+ 584: 80 88 00 00 nop
+ 588: 92 c8 f0 68 ldi @\(gr15,104\),gr9
+ 58c: 80 88 00 00 nop
+ 590: 00 88 00 00 nop\.p
+ 594: 80 88 00 00 nop
+ 598: 92 c8 f0 80 ldi @\(gr15,128\),gr9
+ 59c: 80 88 00 00 nop
+ 5a0: 00 88 00 00 nop\.p
+ 5a4: 80 88 00 00 nop
+ 5a8: 92 c8 f0 84 ldi @\(gr15,132\),gr9
+ 5ac: 80 88 00 00 nop
+ 5b0: 12 c8 f0 28 ldi\.p @\(gr15,40\),gr9
+ 5b4: 80 88 00 00 nop
+ 5b8: 80 88 00 00 nop
+ 5bc: 12 c8 f0 38 ldi\.p @\(gr15,56\),gr9
+ 5c0: 80 88 00 00 nop
+ 5c4: 80 88 00 00 nop
+ 5c8: 12 c8 f0 44 ldi\.p @\(gr15,68\),gr9
+ 5cc: 80 88 00 00 nop
+ 5d0: 80 88 00 00 nop
+ 5d4: 80 88 00 00 nop
+ 5d8: 92 fc 00 04 setlos 0x4,gr9
+ 5dc: 80 88 00 00 nop
+ 5e0: 92 fc 10 04 setlos 0x1004,gr9
+ 5e4: 92 f8 00 01 sethi 0x1,gr9
+ 5e8: 92 f4 00 04 setlo 0x4,gr9
+ 5ec: 92 c8 f0 2c ldi @\(gr15,44\),gr9
+ 5f0: fe 3f ff 9f call 46c <i\+0x45c>
+ 5f4: 92 c8 f0 48 ldi @\(gr15,72\),gr9
+ 5f8: 00 88 00 00 nop\.p
+ 5fc: 80 88 00 00 nop
+ 600: 92 c8 f0 6c ldi @\(gr15,108\),gr9
+ 604: 80 88 00 00 nop
+ 608: 00 88 00 00 nop\.p
+ 60c: 80 88 00 00 nop
+ 610: 92 c8 f0 74 ldi @\(gr15,116\),gr9
+ 614: 80 88 00 00 nop
+ 618: 00 88 00 00 nop\.p
+ 61c: 80 88 00 00 nop
+ 620: 92 c8 f0 88 ldi @\(gr15,136\),gr9
+ 624: 80 88 00 00 nop
+ 628: 12 c8 f0 10 ldi\.p @\(gr15,16\),gr9
+ 62c: 80 88 00 00 nop
+ 630: 80 88 00 00 nop
+ 634: 12 c8 f0 14 ldi\.p @\(gr15,20\),gr9
+ 638: 80 88 00 00 nop
+ 63c: 80 88 00 00 nop
+ 640: 12 c8 f0 20 ldi\.p @\(gr15,32\),gr9
+ 644: 80 88 00 00 nop
+ 648: 80 88 00 00 nop
+ 64c: 92 c8 f0 30 ldi @\(gr15,48\),gr9
+ 650: 92 c8 f0 4c ldi @\(gr15,76\),gr9
+ 654: 92 c8 f0 54 ldi @\(gr15,84\),gr9
+ 658: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+ 65c: 92 c8 f0 24 ldi @\(gr15,36\),gr9
+ 660: 92 c8 f0 40 ldi @\(gr15,64\),gr9
+ 664: 92 c8 f0 2c ldi @\(gr15,44\),gr9
+ 668: 92 c8 f0 48 ldi @\(gr15,72\),gr9
+ 66c: 80 88 00 00 nop
+ 670: 92 c8 f0 78 ldi @\(gr15,120\),gr9
+ 674: 80 88 00 00 nop
+ 678: 80 88 00 00 nop
+ 67c: 92 c8 f0 5c ldi @\(gr15,92\),gr9
+Disassembly of section \.got:
+
+00004718 <_GLOBAL_OFFSET_TABLE_-0x20>:
+ 4718: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4718: R_FRV_TLSDESC_VALUE \.tbss
+ 471c: 00 00 10 11 add\.p sp,gr17,gr0
+ 4720: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4720: R_FRV_TLSDESC_VALUE x
+ 4724: 00 00 10 01 add\.p sp,sp,gr0
+ 4728: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4728: R_FRV_TLSDESC_VALUE \.tbss
+ 472c: 00 00 10 01 add\.p sp,sp,gr0
+ 4730: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4730: R_FRV_TLSDESC_VALUE \.tbss
+ 4734: 00 00 17 f1 \*unknown\*
+
+00004738 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 4744: 00 00 10 13 add\.p sp,gr19,gr0
+ 4744: R_FRV_TLSOFF \.tbss
+ 4748: 00 00 00 03 add\.p gr0,gr3,gr0
+ 4748: R_FRV_TLSOFF x
+ 474c: 00 00 10 03 add\.p sp,gr3,gr0
+ 474c: R_FRV_TLSOFF x
+ 4750: 00 01 00 11 add\.p gr16,gr17,gr0
+ 4750: R_FRV_TLSOFF \.tbss
+ 4754: 00 01 00 13 add\.p gr16,gr19,gr0
+ 4754: R_FRV_TLSOFF \.tbss
+ 4758: 00 01 00 03 add\.p gr16,gr3,gr0
+ 4758: R_FRV_TLSOFF x
+ 475c: 00 00 07 f1 \*unknown\*
+ 475c: R_FRV_TLSOFF \.tbss
+ 4760: 00 00 07 f3 \*unknown\*
+ 4760: R_FRV_TLSOFF \.tbss
+ 4764: 00 00 00 01 add\.p gr0,sp,gr0
+ 4764: R_FRV_TLSOFF x
+ 4768: 00 00 00 01 add\.p gr0,sp,gr0
+ 4768: R_FRV_TLSOFF \.tbss
+ 476c: 00 00 00 03 add\.p gr0,gr3,gr0
+ 476c: R_FRV_TLSOFF \.tbss
+ 4770: 00 00 17 f3 \*unknown\*
+ 4770: R_FRV_TLSOFF \.tbss
+ 4774: 00 00 10 03 add\.p sp,gr3,gr0
+ 4774: R_FRV_TLSOFF \.tbss
+ 4778: 00 01 07 f1 \*unknown\*
+ 4778: R_FRV_TLSOFF \.tbss
+ 477c: 00 01 07 f3 \*unknown\*
+ 477c: R_FRV_TLSOFF \.tbss
+ 4780: 00 01 00 01 add\.p gr16,sp,gr0
+ 4780: R_FRV_TLSOFF x
+ 4784: 00 01 00 01 add\.p gr16,sp,gr0
+ 4784: R_FRV_TLSOFF \.tbss
+ 4788: 00 01 00 03 add\.p gr16,gr3,gr0
+ 4788: R_FRV_TLSOFF \.tbss
+ 478c: 00 00 00 11 add\.p gr0,gr17,gr0
+ 478c: R_FRV_TLSOFF \.tbss
+ 4790: 00 00 00 13 add\.p gr0,gr19,gr0
+ 4790: R_FRV_TLSOFF \.tbss
+ 4794: 00 00 10 11 add\.p sp,gr17,gr0
+ 4794: R_FRV_TLSOFF \.tbss
+ 4798: 00 00 10 12 add\.p sp,gr18,gr0
+ 4798: R_FRV_TLSOFF \.tbss
+ 479c: 00 01 00 12 add\.p gr16,gr18,gr0
+ 479c: R_FRV_TLSOFF \.tbss
+ 47a0: 00 00 07 f2 \*unknown\*
+ 47a0: R_FRV_TLSOFF \.tbss
+ 47a4: 00 00 00 02 add\.p gr0,fp,gr0
+ 47a4: R_FRV_TLSOFF x
+ 47a8: 00 00 00 02 add\.p gr0,fp,gr0
+ 47a8: R_FRV_TLSOFF \.tbss
+ 47ac: 00 00 10 02 add\.p sp,fp,gr0
+ 47ac: R_FRV_TLSOFF x
+ 47b0: 00 00 10 01 add\.p sp,sp,gr0
+ 47b0: R_FRV_TLSOFF \.tbss
+ 47b4: 00 00 10 02 add\.p sp,fp,gr0
+ 47b4: R_FRV_TLSOFF \.tbss
+ 47b8: 00 00 17 f2 \*unknown\*
+ 47b8: R_FRV_TLSOFF \.tbss
+ 47bc: 00 01 07 f2 \*unknown\*
+ 47bc: R_FRV_TLSOFF \.tbss
+ 47c0: 00 01 00 02 add\.p gr16,fp,gr0
+ 47c0: R_FRV_TLSOFF x
+ 47c4: 00 01 00 02 add\.p gr16,fp,gr0
+ 47c4: R_FRV_TLSOFF \.tbss
+ 47c8: 00 00 00 12 add\.p gr0,gr18,gr0
+ 47c8: R_FRV_TLSOFF \.tbss
diff --git a/ld/testsuite/ld-frv/tls-pie-1.d b/ld/testsuite/ld-frv/tls-pie-1.d
new file mode 100644
index 0000000..5e4b6a1
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-pie-1.d
@@ -0,0 +1,71 @@
+#name: FRV TLS relocs, pie linking
+#source: tls-1.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -pie tmpdir/tls-1-dep.so
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+000003a0 <_start>:
+ 3a0: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 3a4: 00 88 00 00 nop\.p
+ 3a8: 80 88 00 00 nop
+ 3ac: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 3b0: 80 88 00 00 nop
+ 3b4: 12 c8 f0 10 ldi\.p @\(gr15,16\),gr9
+ 3b8: 80 88 00 00 nop
+ 3bc: 80 88 00 00 nop
+ 3c0: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 3c4: 00 88 00 00 nop\.p
+ 3c8: 80 88 00 00 nop
+ 3cc: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 3d0: 80 88 00 00 nop
+ 3d4: 12 fc f8 10 setlos\.p 0xf*fffff810,gr9
+ 3d8: 80 88 00 00 nop
+ 3dc: 80 88 00 00 nop
+ 3e0: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 3e4: 00 88 00 00 nop\.p
+ 3e8: 80 88 00 00 nop
+ 3ec: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 3f0: 80 88 00 00 nop
+ 3f4: 12 fc f8 20 setlos\.p 0xf*fffff820,gr9
+ 3f8: 80 88 00 00 nop
+ 3fc: 80 88 00 00 nop
+ 400: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 404: 00 88 00 00 nop\.p
+ 408: 80 88 00 00 nop
+ 40c: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 410: 80 88 00 00 nop
+ 414: 12 fc 00 00 setlos\.p lo\(0x0\),gr9
+ 418: 80 88 00 00 nop
+ 41c: 80 88 00 00 nop
+ 420: 00 88 00 00 nop\.p
+ 424: 90 fc f8 20 setlos 0xf*fffff820,gr8
+ 428: 00 88 00 00 nop\.p
+ 42c: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 430: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 434: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 438: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 43c: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 440: 00 88 00 00 nop\.p
+ 444: 80 88 00 00 nop
+ 448: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 44c: 00 88 00 00 nop\.p
+ 450: 80 88 00 00 nop
+ 454: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 458: 00 88 00 00 nop\.p
+ 45c: 80 88 00 00 nop
+ 460: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 464: 00 88 00 00 nop\.p
+ 468: 80 88 00 00 nop
+ 46c: 92 fc 00 00 setlos lo\(0x0\),gr9
+Disassembly of section \.got:
+
+00004508 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 4514: ff ff f8 20 cop2 -32,cpr63,cpr32,cpr63
+ 4518: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4518: R_FRV_TLSOFF x
+ 451c: ff ff f8 10 cop2 -32,cpr63,cpr16,cpr63
+ 4520: 00 00 00 00 add\.p gr0,gr0,gr0
diff --git a/ld/testsuite/ld-frv/tls-pie-3.d b/ld/testsuite/ld-frv/tls-pie-3.d
new file mode 100644
index 0000000..440002b
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-pie-3.d
@@ -0,0 +1,27 @@
+#name: FRV TLS undefweak relocs, pie linking
+#source: tls-3.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -pie
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+00000324 <_start>:
+ 324: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 328: 00 88 00 00 nop\.p
+ 32c: 80 88 00 00 nop
+ 330: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 334: 80 88 00 00 nop
+ 338: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 33c: 80 88 00 00 nop
+ 340: 80 88 00 00 nop
+ 344: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 348: 00 88 00 00 nop\.p
+ 34c: 80 88 00 00 nop
+ 350: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+Disassembly of section \.got:
+
+000043d8 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 43e4: R_FRV_TLSOFF u
diff --git a/ld/testsuite/ld-frv/tls-relax-dynamic-1.d b/ld/testsuite/ld-frv/tls-relax-dynamic-1.d
new file mode 100644
index 0000000..94fdb1b
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-dynamic-1.d
@@ -0,0 +1,67 @@
+#name: FRV TLS relocs, dynamic linking with relaxation
+#source: tls-1.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: tmpdir/tls-1-dep.so --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+000102c8 <_start>:
+ 102c8: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 102cc: 00 88 00 00 nop\.p
+ 102d0: 80 88 00 00 nop
+ 102d4: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 102d8: 80 88 00 00 nop
+ 102dc: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 102e0: 80 88 00 00 nop
+ 102e4: 80 88 00 00 nop
+ 102e8: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 102ec: 00 88 00 00 nop\.p
+ 102f0: 80 88 00 00 nop
+ 102f4: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 102f8: 80 88 00 00 nop
+ 102fc: 12 fc f8 10 setlos\.p 0xf*fffff810,gr9
+ 10300: 80 88 00 00 nop
+ 10304: 80 88 00 00 nop
+ 10308: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 1030c: 00 88 00 00 nop\.p
+ 10310: 80 88 00 00 nop
+ 10314: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 10318: 80 88 00 00 nop
+ 1031c: 12 fc f8 20 setlos\.p 0xf*fffff820,gr9
+ 10320: 80 88 00 00 nop
+ 10324: 80 88 00 00 nop
+ 10328: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 1032c: 00 88 00 00 nop\.p
+ 10330: 80 88 00 00 nop
+ 10334: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10338: 80 88 00 00 nop
+ 1033c: 12 fc 00 00 setlos\.p lo\(0x0\),gr9
+ 10340: 80 88 00 00 nop
+ 10344: 80 88 00 00 nop
+ 10348: 00 88 00 00 nop\.p
+ 1034c: 90 fc f8 20 setlos 0xf*fffff820,gr8
+ 10350: 00 88 00 00 nop\.p
+ 10354: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 10358: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 1035c: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 10360: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 10364: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10368: 00 88 00 00 nop\.p
+ 1036c: 80 88 00 00 nop
+ 10370: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 10374: 00 88 00 00 nop\.p
+ 10378: 80 88 00 00 nop
+ 1037c: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 10380: 00 88 00 00 nop\.p
+ 10384: 80 88 00 00 nop
+ 10388: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 1038c: 00 88 00 00 nop\.p
+ 10390: 80 88 00 00 nop
+ 10394: 92 fc 00 00 setlos lo\(0x0\),gr9
+Disassembly of section \.got:
+
+00014428 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 14434: R_FRV_TLSOFF x
diff --git a/ld/testsuite/ld-frv/tls-relax-dynamic-2.d b/ld/testsuite/ld-frv/tls-relax-dynamic-2.d
new file mode 100644
index 0000000..c8b35e0
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-dynamic-2.d
@@ -0,0 +1,149 @@
+#name: FRV TLS relocs with addends, dynamic linking, relaxing
+#source: tls-2.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: tmpdir/tls-1-dep.so --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+00010308 <_start>:
+ 10308: 92 fc f8 11 setlos 0xf*fffff811,gr9
+ 1030c: 92 fc 08 11 setlos 0x811,gr9
+ 10310: 92 c8 f0 2c ldi @\(gr15,44\),gr9
+ 10314: 00 88 00 00 nop\.p
+ 10318: 80 88 00 00 nop
+ 1031c: 92 fc f8 12 setlos 0xf*fffff812,gr9
+ 10320: 80 88 00 00 nop
+ 10324: 00 88 00 00 nop\.p
+ 10328: 80 88 00 00 nop
+ 1032c: 92 fc 08 12 setlos 0x812,gr9
+ 10330: 80 88 00 00 nop
+ 10334: 00 88 00 00 nop\.p
+ 10338: 80 88 00 00 nop
+ 1033c: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 10340: 92 f4 f8 12 setlo 0xf812,gr9
+ 10344: 12 fc f8 13 setlos\.p 0xf*fffff813,gr9
+ 10348: 80 88 00 00 nop
+ 1034c: 80 88 00 00 nop
+ 10350: 12 fc 08 13 setlos\.p 0x813,gr9
+ 10354: 80 88 00 00 nop
+ 10358: 80 88 00 00 nop
+ 1035c: 12 f8 00 00 sethi\.p hi\(0x0\),gr9
+ 10360: 80 88 00 00 nop
+ 10364: 92 f4 f8 13 setlo 0xf813,gr9
+ 10368: 80 88 00 00 nop
+ 1036c: 92 fc f8 14 setlos 0xf*fffff814,gr9
+ 10370: 80 88 00 00 nop
+ 10374: 92 fc 08 14 setlos 0x814,gr9
+ 10378: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 1037c: 92 f4 f8 14 setlo 0xf814,gr9
+ 10380: 92 fc f8 21 setlos 0xf*fffff821,gr9
+ 10384: 92 fc 08 21 setlos 0x821,gr9
+ 10388: 92 c8 f0 14 ldi @\(gr15,20\),gr9
+ 1038c: 00 88 00 00 nop\.p
+ 10390: 80 88 00 00 nop
+ 10394: 92 fc f8 22 setlos 0xf*fffff822,gr9
+ 10398: 80 88 00 00 nop
+ 1039c: 00 88 00 00 nop\.p
+ 103a0: 80 88 00 00 nop
+ 103a4: 92 fc 08 22 setlos 0x822,gr9
+ 103a8: 80 88 00 00 nop
+ 103ac: 00 88 00 00 nop\.p
+ 103b0: 80 88 00 00 nop
+ 103b4: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 103b8: 92 f4 f8 22 setlo 0xf822,gr9
+ 103bc: 12 fc f8 23 setlos\.p 0xf*fffff823,gr9
+ 103c0: 80 88 00 00 nop
+ 103c4: 80 88 00 00 nop
+ 103c8: 12 fc 08 23 setlos\.p 0x823,gr9
+ 103cc: 80 88 00 00 nop
+ 103d0: 80 88 00 00 nop
+ 103d4: 12 f8 00 00 sethi\.p hi\(0x0\),gr9
+ 103d8: 80 88 00 00 nop
+ 103dc: 92 f4 f8 23 setlo 0xf823,gr9
+ 103e0: 80 88 00 00 nop
+ 103e4: 92 fc f8 24 setlos 0xf*fffff824,gr9
+ 103e8: 80 88 00 00 nop
+ 103ec: 92 fc 08 24 setlos 0x824,gr9
+ 103f0: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 103f4: 92 f4 f8 24 setlo 0xf824,gr9
+ 103f8: 92 fc 00 01 setlos 0x1,gr9
+ 103fc: 92 fc 10 01 setlos 0x1001,gr9
+ 10400: 92 c8 f0 24 ldi @\(gr15,36\),gr9
+ 10404: 00 88 00 00 nop\.p
+ 10408: 80 88 00 00 nop
+ 1040c: 92 fc 00 02 setlos 0x2,gr9
+ 10410: 80 88 00 00 nop
+ 10414: 00 88 00 00 nop\.p
+ 10418: 80 88 00 00 nop
+ 1041c: 92 fc 10 02 setlos 0x1002,gr9
+ 10420: 80 88 00 00 nop
+ 10424: 00 88 00 00 nop\.p
+ 10428: 80 88 00 00 nop
+ 1042c: 92 f8 00 01 sethi 0x1,gr9
+ 10430: 92 f4 00 02 setlo 0x2,gr9
+ 10434: 12 fc 00 03 setlos\.p 0x3,gr9
+ 10438: 80 88 00 00 nop
+ 1043c: 80 88 00 00 nop
+ 10440: 12 fc 10 03 setlos\.p 0x1003,gr9
+ 10444: 80 88 00 00 nop
+ 10448: 80 88 00 00 nop
+ 1044c: 12 f8 00 01 sethi\.p 0x1,gr9
+ 10450: 80 88 00 00 nop
+ 10454: 92 f4 00 03 setlo 0x3,gr9
+ 10458: 80 88 00 00 nop
+ 1045c: 92 fc 00 04 setlos 0x4,gr9
+ 10460: 80 88 00 00 nop
+ 10464: 92 fc 10 04 setlos 0x1004,gr9
+ 10468: 92 f8 00 01 sethi 0x1,gr9
+ 1046c: 92 f4 00 04 setlo 0x4,gr9
+ 10470: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+ 10474: 92 c8 f0 1c ldi @\(gr15,28\),gr9
+ 10478: 92 c8 f0 28 ldi @\(gr15,40\),gr9
+ 1047c: 00 88 00 00 nop\.p
+ 10480: 80 88 00 00 nop
+ 10484: 92 c8 f0 38 ldi @\(gr15,56\),gr9
+ 10488: 80 88 00 00 nop
+ 1048c: 00 88 00 00 nop\.p
+ 10490: 80 88 00 00 nop
+ 10494: 92 c8 f0 34 ldi @\(gr15,52\),gr9
+ 10498: 80 88 00 00 nop
+ 1049c: 00 88 00 00 nop\.p
+ 104a0: 80 88 00 00 nop
+ 104a4: 92 c8 f0 30 ldi @\(gr15,48\),gr9
+ 104a8: 80 88 00 00 nop
+ 104ac: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 104b0: 80 88 00 00 nop
+ 104b4: 80 88 00 00 nop
+ 104b8: 12 c8 f0 10 ldi\.p @\(gr15,16\),gr9
+ 104bc: 80 88 00 00 nop
+ 104c0: 80 88 00 00 nop
+ 104c4: 12 c8 f0 20 ldi\.p @\(gr15,32\),gr9
+ 104c8: 80 88 00 00 nop
+ 104cc: 80 88 00 00 nop
+Disassembly of section \.got:
+
+00014568 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 14574: 00 00 00 03 add\.p gr0,gr3,gr0
+ 14574: R_FRV_TLSOFF x
+ 14578: 00 00 10 03 add\.p sp,gr3,gr0
+ 14578: R_FRV_TLSOFF x
+ 1457c: 00 00 f8 21 \*unknown\*
+ 14580: 00 00 00 01 add\.p gr0,sp,gr0
+ 14580: R_FRV_TLSOFF x
+ 14584: 00 00 10 01 add\.p sp,sp,gr0
+ 14584: R_FRV_TLSOFF x
+ 14588: 00 01 00 03 add\.p gr16,gr3,gr0
+ 14588: R_FRV_TLSOFF x
+ 1458c: 00 01 00 01 add\.p gr16,sp,gr0
+ 14590: 00 01 00 01 add\.p gr16,sp,gr0
+ 14590: R_FRV_TLSOFF x
+ 14594: 00 00 f8 11 \*unknown\*
+ 14598: 00 01 00 02 add\.p gr16,fp,gr0
+ 14598: R_FRV_TLSOFF x
+ 1459c: 00 00 10 02 add\.p sp,fp,gr0
+ 1459c: R_FRV_TLSOFF x
+ 145a0: 00 00 00 02 add\.p gr0,fp,gr0
+ 145a0: R_FRV_TLSOFF x
diff --git a/ld/testsuite/ld-frv/tls-relax-dynamic-3.d b/ld/testsuite/ld-frv/tls-relax-dynamic-3.d
new file mode 100644
index 0000000..0043319
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-dynamic-3.d
@@ -0,0 +1,27 @@
+#name: FRV TLS undefweak relocs, dynamic linking with relaxation
+#source: tls-3.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: tmpdir/tls-1-dep.so --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+00010294 <_start>:
+ 10294: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 10298: 00 88 00 00 nop\.p
+ 1029c: 80 88 00 00 nop
+ 102a0: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 102a4: 80 88 00 00 nop
+ 102a8: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 102ac: 80 88 00 00 nop
+ 102b0: 80 88 00 00 nop
+ 102b4: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 102b8: 00 88 00 00 nop\.p
+ 102bc: 80 88 00 00 nop
+ 102c0: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+Disassembly of section \.got:
+
+00014350 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 1435c: R_FRV_TLSOFF u
diff --git a/ld/testsuite/ld-frv/tls-relax-initial-shared-2.d b/ld/testsuite/ld-frv/tls-relax-initial-shared-2.d
new file mode 100644
index 0000000..7911890
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-initial-shared-2.d
@@ -0,0 +1,214 @@
+#name: FRV TLS relocs with addends, shared linking with static TLS, relaxing
+#source: tls-2.s
+#as: --defsym static_tls=1
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -shared tmpdir/tls-1-dep.so --version-script tls-1-shared.lds --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+00000454 <_start>:
+ 454: 92 c8 f0 34 ldi @\(gr15,52\),gr9
+ 458: 92 c8 f0 44 ldi @\(gr15,68\),gr9
+ 45c: 92 c8 f0 5c ldi @\(gr15,92\),gr9
+ 460: 00 88 00 00 nop\.p
+ 464: 80 88 00 00 nop
+ 468: 92 c8 f0 7c ldi @\(gr15,124\),gr9
+ 46c: 80 88 00 00 nop
+ 470: 00 88 00 00 nop\.p
+ 474: 80 88 00 00 nop
+ 478: 92 c8 f0 84 ldi @\(gr15,132\),gr9
+ 47c: 80 88 00 00 nop
+ 480: 00 88 00 00 nop\.p
+ 484: 80 88 00 00 nop
+ 488: 92 c8 f0 94 ldi @\(gr15,148\),gr9
+ 48c: 80 88 00 00 nop
+ 490: 12 c8 f0 38 ldi\.p @\(gr15,56\),gr9
+ 494: 80 88 00 00 nop
+ 498: 80 88 00 00 nop
+ 49c: 12 c8 f0 48 ldi\.p @\(gr15,72\),gr9
+ 4a0: 80 88 00 00 nop
+ 4a4: 80 88 00 00 nop
+ 4a8: 12 c8 f0 60 ldi\.p @\(gr15,96\),gr9
+ 4ac: 80 88 00 00 nop
+ 4b0: 80 88 00 00 nop
+ 4b4: 80 88 00 00 nop
+ 4b8: 92 fc f8 14 setlos 0xf*fffff814,gr9
+ 4bc: 80 88 00 00 nop
+ 4c0: 92 fc 08 14 setlos 0x814,gr9
+ 4c4: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 4c8: 92 f4 f8 14 setlo 0xf814,gr9
+ 4cc: 92 c8 f0 64 ldi @\(gr15,100\),gr9
+ 4d0: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 4d4: 92 c8 f0 1c ldi @\(gr15,28\),gr9
+ 4d8: 00 88 00 00 nop\.p
+ 4dc: 80 88 00 00 nop
+ 4e0: 92 c8 f0 98 ldi @\(gr15,152\),gr9
+ 4e4: 80 88 00 00 nop
+ 4e8: 00 88 00 00 nop\.p
+ 4ec: 80 88 00 00 nop
+ 4f0: 92 c8 f0 6c ldi @\(gr15,108\),gr9
+ 4f4: 80 88 00 00 nop
+ 4f8: 00 88 00 00 nop\.p
+ 4fc: 80 88 00 00 nop
+ 500: 92 c8 f0 70 ldi @\(gr15,112\),gr9
+ 504: 80 88 00 00 nop
+ 508: 12 c8 f0 68 ldi\.p @\(gr15,104\),gr9
+ 50c: 80 88 00 00 nop
+ 510: 80 88 00 00 nop
+ 514: 12 c8 f0 10 ldi\.p @\(gr15,16\),gr9
+ 518: 80 88 00 00 nop
+ 51c: 80 88 00 00 nop
+ 520: 12 c8 f0 20 ldi\.p @\(gr15,32\),gr9
+ 524: 80 88 00 00 nop
+ 528: 80 88 00 00 nop
+ 52c: 80 88 00 00 nop
+ 530: 92 fc f8 24 setlos 0xf*fffff824,gr9
+ 534: 80 88 00 00 nop
+ 538: 92 fc 08 24 setlos 0x824,gr9
+ 53c: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 540: 92 f4 f8 24 setlo 0xf824,gr9
+ 544: 92 c8 f0 28 ldi @\(gr15,40\),gr9
+ 548: 92 c8 f0 4c ldi @\(gr15,76\),gr9
+ 54c: 92 c8 f0 50 ldi @\(gr15,80\),gr9
+ 550: 00 88 00 00 nop\.p
+ 554: 80 88 00 00 nop
+ 558: 92 c8 f0 74 ldi @\(gr15,116\),gr9
+ 55c: 80 88 00 00 nop
+ 560: 00 88 00 00 nop\.p
+ 564: 80 88 00 00 nop
+ 568: 92 c8 f0 88 ldi @\(gr15,136\),gr9
+ 56c: 80 88 00 00 nop
+ 570: 00 88 00 00 nop\.p
+ 574: 80 88 00 00 nop
+ 578: 92 c8 f0 8c ldi @\(gr15,140\),gr9
+ 57c: 80 88 00 00 nop
+ 580: 12 c8 f0 2c ldi\.p @\(gr15,44\),gr9
+ 584: 80 88 00 00 nop
+ 588: 80 88 00 00 nop
+ 58c: 12 c8 f0 3c ldi\.p @\(gr15,60\),gr9
+ 590: 80 88 00 00 nop
+ 594: 80 88 00 00 nop
+ 598: 12 c8 f0 54 ldi\.p @\(gr15,84\),gr9
+ 59c: 80 88 00 00 nop
+ 5a0: 80 88 00 00 nop
+ 5a4: 80 88 00 00 nop
+ 5a8: 92 fc 00 04 setlos 0x4,gr9
+ 5ac: 80 88 00 00 nop
+ 5b0: 92 fc 10 04 setlos 0x1004,gr9
+ 5b4: 92 f8 00 01 sethi 0x1,gr9
+ 5b8: 92 f4 00 04 setlo 0x4,gr9
+ 5bc: 92 c8 f0 30 ldi @\(gr15,48\),gr9
+ 5c0: 92 c8 f0 40 ldi @\(gr15,64\),gr9
+ 5c4: 92 c8 f0 58 ldi @\(gr15,88\),gr9
+ 5c8: 00 88 00 00 nop\.p
+ 5cc: 80 88 00 00 nop
+ 5d0: 92 c8 f0 78 ldi @\(gr15,120\),gr9
+ 5d4: 80 88 00 00 nop
+ 5d8: 00 88 00 00 nop\.p
+ 5dc: 80 88 00 00 nop
+ 5e0: 92 c8 f0 80 ldi @\(gr15,128\),gr9
+ 5e4: 80 88 00 00 nop
+ 5e8: 00 88 00 00 nop\.p
+ 5ec: 80 88 00 00 nop
+ 5f0: 92 c8 f0 90 ldi @\(gr15,144\),gr9
+ 5f4: 80 88 00 00 nop
+ 5f8: 12 c8 f0 14 ldi\.p @\(gr15,20\),gr9
+ 5fc: 80 88 00 00 nop
+ 600: 80 88 00 00 nop
+ 604: 12 c8 f0 18 ldi\.p @\(gr15,24\),gr9
+ 608: 80 88 00 00 nop
+ 60c: 80 88 00 00 nop
+ 610: 12 c8 f0 24 ldi\.p @\(gr15,36\),gr9
+ 614: 80 88 00 00 nop
+ 618: 80 88 00 00 nop
+ 61c: 92 c8 f0 34 ldi @\(gr15,52\),gr9
+ 620: 92 c8 f0 5c ldi @\(gr15,92\),gr9
+ 624: 92 c8 f0 64 ldi @\(gr15,100\),gr9
+ 628: 92 c8 f0 1c ldi @\(gr15,28\),gr9
+ 62c: 92 c8 f0 28 ldi @\(gr15,40\),gr9
+ 630: 92 c8 f0 50 ldi @\(gr15,80\),gr9
+ 634: 92 c8 f0 30 ldi @\(gr15,48\),gr9
+ 638: 92 c8 f0 58 ldi @\(gr15,88\),gr9
+ 63c: 80 88 00 00 nop
+ 640: 92 c8 f0 44 ldi @\(gr15,68\),gr9
+ 644: 80 88 00 00 nop
+ 648: 80 88 00 00 nop
+ 64c: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+Disassembly of section \.got:
+
+000046e8 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 46f4: 00 00 10 11 add\.p sp,gr17,gr0
+ 46f4: R_FRV_TLSOFF \.tbss
+ 46f8: 00 00 10 13 add\.p sp,gr19,gr0
+ 46f8: R_FRV_TLSOFF \.tbss
+ 46fc: 00 00 00 03 add\.p gr0,gr3,gr0
+ 46fc: R_FRV_TLSOFF x
+ 4700: 00 00 10 03 add\.p sp,gr3,gr0
+ 4700: R_FRV_TLSOFF x
+ 4704: 00 01 00 11 add\.p gr16,gr17,gr0
+ 4704: R_FRV_TLSOFF \.tbss
+ 4708: 00 01 00 13 add\.p gr16,gr19,gr0
+ 4708: R_FRV_TLSOFF \.tbss
+ 470c: 00 01 00 03 add\.p gr16,gr3,gr0
+ 470c: R_FRV_TLSOFF x
+ 4710: 00 00 07 f1 \*unknown\*
+ 4710: R_FRV_TLSOFF \.tbss
+ 4714: 00 00 07 f3 \*unknown\*
+ 4714: R_FRV_TLSOFF \.tbss
+ 4718: 00 00 00 01 add\.p gr0,sp,gr0
+ 4718: R_FRV_TLSOFF x
+ 471c: 00 00 00 01 add\.p gr0,sp,gr0
+ 471c: R_FRV_TLSOFF \.tbss
+ 4720: 00 00 00 03 add\.p gr0,gr3,gr0
+ 4720: R_FRV_TLSOFF \.tbss
+ 4724: 00 00 17 f3 \*unknown\*
+ 4724: R_FRV_TLSOFF \.tbss
+ 4728: 00 00 10 01 add\.p sp,sp,gr0
+ 4728: R_FRV_TLSOFF x
+ 472c: 00 00 10 01 add\.p sp,sp,gr0
+ 472c: R_FRV_TLSOFF \.tbss
+ 4730: 00 00 10 03 add\.p sp,gr3,gr0
+ 4730: R_FRV_TLSOFF \.tbss
+ 4734: 00 00 17 f1 \*unknown\*
+ 4734: R_FRV_TLSOFF \.tbss
+ 4738: 00 01 07 f1 \*unknown\*
+ 4738: R_FRV_TLSOFF \.tbss
+ 473c: 00 01 07 f3 \*unknown\*
+ 473c: R_FRV_TLSOFF \.tbss
+ 4740: 00 01 00 01 add\.p gr16,sp,gr0
+ 4740: R_FRV_TLSOFF x
+ 4744: 00 01 00 01 add\.p gr16,sp,gr0
+ 4744: R_FRV_TLSOFF \.tbss
+ 4748: 00 01 00 03 add\.p gr16,gr3,gr0
+ 4748: R_FRV_TLSOFF \.tbss
+ 474c: 00 00 00 11 add\.p gr0,gr17,gr0
+ 474c: R_FRV_TLSOFF \.tbss
+ 4750: 00 00 00 13 add\.p gr0,gr19,gr0
+ 4750: R_FRV_TLSOFF \.tbss
+ 4754: 00 00 10 12 add\.p sp,gr18,gr0
+ 4754: R_FRV_TLSOFF \.tbss
+ 4758: 00 01 00 12 add\.p gr16,gr18,gr0
+ 4758: R_FRV_TLSOFF \.tbss
+ 475c: 00 00 07 f2 \*unknown\*
+ 475c: R_FRV_TLSOFF \.tbss
+ 4760: 00 00 00 02 add\.p gr0,fp,gr0
+ 4760: R_FRV_TLSOFF x
+ 4764: 00 00 00 02 add\.p gr0,fp,gr0
+ 4764: R_FRV_TLSOFF \.tbss
+ 4768: 00 00 10 02 add\.p sp,fp,gr0
+ 4768: R_FRV_TLSOFF x
+ 476c: 00 00 10 02 add\.p sp,fp,gr0
+ 476c: R_FRV_TLSOFF \.tbss
+ 4770: 00 00 17 f2 \*unknown\*
+ 4770: R_FRV_TLSOFF \.tbss
+ 4774: 00 01 07 f2 \*unknown\*
+ 4774: R_FRV_TLSOFF \.tbss
+ 4778: 00 01 00 02 add\.p gr16,fp,gr0
+ 4778: R_FRV_TLSOFF x
+ 477c: 00 01 00 02 add\.p gr16,fp,gr0
+ 477c: R_FRV_TLSOFF \.tbss
+ 4780: 00 00 00 12 add\.p gr0,gr18,gr0
+ 4780: R_FRV_TLSOFF \.tbss
diff --git a/ld/testsuite/ld-frv/tls-relax-pie-1.d b/ld/testsuite/ld-frv/tls-relax-pie-1.d
new file mode 100644
index 0000000..3979080
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-pie-1.d
@@ -0,0 +1,67 @@
+#name: FRV TLS relocs, pie linking with relaxation
+#source: tls-1.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -pie tmpdir/tls-1-dep.so --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+000003a0 <_start>:
+ 3a0: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 3a4: 00 88 00 00 nop\.p
+ 3a8: 80 88 00 00 nop
+ 3ac: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 3b0: 80 88 00 00 nop
+ 3b4: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 3b8: 80 88 00 00 nop
+ 3bc: 80 88 00 00 nop
+ 3c0: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 3c4: 00 88 00 00 nop\.p
+ 3c8: 80 88 00 00 nop
+ 3cc: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 3d0: 80 88 00 00 nop
+ 3d4: 12 fc f8 10 setlos\.p 0xf*fffff810,gr9
+ 3d8: 80 88 00 00 nop
+ 3dc: 80 88 00 00 nop
+ 3e0: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 3e4: 00 88 00 00 nop\.p
+ 3e8: 80 88 00 00 nop
+ 3ec: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 3f0: 80 88 00 00 nop
+ 3f4: 12 fc f8 20 setlos\.p 0xf*fffff820,gr9
+ 3f8: 80 88 00 00 nop
+ 3fc: 80 88 00 00 nop
+ 400: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 404: 00 88 00 00 nop\.p
+ 408: 80 88 00 00 nop
+ 40c: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 410: 80 88 00 00 nop
+ 414: 12 fc 00 00 setlos\.p lo\(0x0\),gr9
+ 418: 80 88 00 00 nop
+ 41c: 80 88 00 00 nop
+ 420: 00 88 00 00 nop\.p
+ 424: 90 fc f8 20 setlos 0xf*fffff820,gr8
+ 428: 00 88 00 00 nop\.p
+ 42c: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 430: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 434: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 438: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 43c: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 440: 00 88 00 00 nop\.p
+ 444: 80 88 00 00 nop
+ 448: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 44c: 00 88 00 00 nop\.p
+ 450: 80 88 00 00 nop
+ 454: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 458: 00 88 00 00 nop\.p
+ 45c: 80 88 00 00 nop
+ 460: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 464: 00 88 00 00 nop\.p
+ 468: 80 88 00 00 nop
+ 46c: 92 fc 00 00 setlos lo\(0x0\),gr9
+Disassembly of section \.got:
+
+00004508 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 4514: R_FRV_TLSOFF x
diff --git a/ld/testsuite/ld-frv/tls-relax-pie-3.d b/ld/testsuite/ld-frv/tls-relax-pie-3.d
new file mode 100644
index 0000000..e83d317
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-pie-3.d
@@ -0,0 +1,27 @@
+#name: FRV TLS undefweak relocs, pie linking with relaxation
+#source: tls-3.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -pie --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+00000324 <_start>:
+ 324: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 328: 00 88 00 00 nop\.p
+ 32c: 80 88 00 00 nop
+ 330: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 334: 80 88 00 00 nop
+ 338: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 33c: 80 88 00 00 nop
+ 340: 80 88 00 00 nop
+ 344: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 348: 00 88 00 00 nop\.p
+ 34c: 80 88 00 00 nop
+ 350: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+Disassembly of section \.got:
+
+000043d8 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 43e4: R_FRV_TLSOFF u
diff --git a/ld/testsuite/ld-frv/tls-relax-shared-1.d b/ld/testsuite/ld-frv/tls-relax-shared-1.d
new file mode 100644
index 0000000..6aafd23
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-shared-1.d
@@ -0,0 +1,73 @@
+#name: FRV TLS relocs, shared linking with relaxation
+#source: tls-1.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -shared tmpdir/tls-1-dep.so --version-script tls-1-shared.lds --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+00000354 <_start>:
+ 354: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 358: 00 88 00 00 nop\.p
+ 35c: 80 88 00 00 nop
+ 360: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 364: 80 88 00 00 nop
+ 368: 12 c8 f0 10 ldi\.p @\(gr15,16\),gr9
+ 36c: 80 88 00 00 nop
+ 370: 80 88 00 00 nop
+ 374: 92 c8 f0 14 ldi @\(gr15,20\),gr9
+ 378: 00 88 00 00 nop\.p
+ 37c: 80 88 00 00 nop
+ 380: 92 c8 f0 14 ldi @\(gr15,20\),gr9
+ 384: 80 88 00 00 nop
+ 388: 12 c8 f0 14 ldi\.p @\(gr15,20\),gr9
+ 38c: 80 88 00 00 nop
+ 390: 80 88 00 00 nop
+ 394: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 398: 00 88 00 00 nop\.p
+ 39c: 80 88 00 00 nop
+ 3a0: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 3a4: 80 88 00 00 nop
+ 3a8: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 3ac: 80 88 00 00 nop
+ 3b0: 80 88 00 00 nop
+ 3b4: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+ 3b8: 00 88 00 00 nop\.p
+ 3bc: 80 88 00 00 nop
+ 3c0: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+ 3c4: 80 88 00 00 nop
+ 3c8: 12 c8 f0 18 ldi\.p @\(gr15,24\),gr9
+ 3cc: 80 88 00 00 nop
+ 3d0: 80 88 00 00 nop
+ 3d4: 00 88 00 00 nop\.p
+ 3d8: 90 fc f8 20 setlos 0xf*fffff820,gr8
+ 3dc: 00 88 00 00 nop\.p
+ 3e0: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 3e4: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 3e8: 92 c8 f0 14 ldi @\(gr15,20\),gr9
+ 3ec: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 3f0: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+ 3f4: 00 88 00 00 nop\.p
+ 3f8: 80 88 00 00 nop
+ 3fc: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 400: 00 88 00 00 nop\.p
+ 404: 80 88 00 00 nop
+ 408: 92 c8 f0 14 ldi @\(gr15,20\),gr9
+ 40c: 00 88 00 00 nop\.p
+ 410: 80 88 00 00 nop
+ 414: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 418: 00 88 00 00 nop\.p
+ 41c: 80 88 00 00 nop
+ 420: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+Disassembly of section \.got:
+
+000044b8 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 44c4: 00 00 00 10 add\.p gr0,gr16,gr0
+ 44c4: R_FRV_TLSOFF \.tbss
+ \.\.\.
+ 44c8: R_FRV_TLSOFF x
+ 44cc: R_FRV_TLSOFF \.tbss
+ 44d0: 00 00 07 f0 \*unknown\*
+ 44d0: R_FRV_TLSOFF \.tbss
diff --git a/ld/testsuite/ld-frv/tls-relax-shared-2.d b/ld/testsuite/ld-frv/tls-relax-shared-2.d
new file mode 100644
index 0000000..49cfea7
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-shared-2.d
@@ -0,0 +1,264 @@
+#name: FRV TLS relocs with addends, shared linking, relaxing
+#source: tls-2.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -shared tmpdir/tls-1-dep.so --version-script tls-1-shared.lds --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.plt:
+
+00000454 <\.plt>:
+ 454: 90 cc f0 10 lddi @\(gr15,16\),gr8
+ 458: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 45c: 90 cc f0 30 lddi @\(gr15,48\),gr8
+ 460: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 464: 90 cc f0 40 lddi @\(gr15,64\),gr8
+ 468: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 46c: 90 cc f0 50 lddi @\(gr15,80\),gr8
+ 470: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 474: 90 cc f0 58 lddi @\(gr15,88\),gr8
+ 478: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 47c: 90 cc f0 68 lddi @\(gr15,104\),gr8
+ 480: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 484: 90 cc ff a8 lddi @\(gr15,-88\),gr8
+ 488: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 48c: 90 cc ff b0 lddi @\(gr15,-80\),gr8
+ 490: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 494: 90 cc ff c8 lddi @\(gr15,-56\),gr8
+ 498: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 49c: 90 cc ff d8 lddi @\(gr15,-40\),gr8
+ 4a0: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 4a4: 90 cc ff e0 lddi @\(gr15,-32\),gr8
+ 4a8: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 4ac: 90 cc ff f0 lddi @\(gr15,-16\),gr8
+ 4b0: 80 30 80 00 jmpl @\(gr8,gr0\)
+Disassembly of section \.text:
+
+000004b4 <_start>:
+ 4b4: fe 3f ff f0 call 474 <i\+0x464>
+ 4b8: fe 3f ff f5 call 48c <i\+0x47c>
+ 4bc: fe 3f ff fa call 4a4 <i\+0x494>
+ 4c0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 4c4: 9c f4 00 98 setlo 0x98,gr14
+ 4c8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 4cc: 82 30 80 00 calll @\(gr8,gr0\)
+ 4d0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 4d4: 9c f4 00 a8 setlo 0xa8,gr14
+ 4d8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 4dc: 82 30 80 00 calll @\(gr8,gr0\)
+ 4e0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 4e4: 9c f4 00 c0 setlo 0xc0,gr14
+ 4e8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 4ec: 82 30 80 00 calll @\(gr8,gr0\)
+ 4f0: 10 cc f0 60 lddi\.p @\(gr15,96\),gr8
+ 4f4: 9c fc 00 60 setlos 0x60,gr14
+ 4f8: 82 30 80 00 calll @\(gr8,gr0\)
+ 4fc: 10 cc ff b8 lddi\.p @\(gr15,-72\),gr8
+ 500: 9c fc ff b8 setlos 0xf*ffffffb8,gr14
+ 504: 82 30 80 00 calll @\(gr8,gr0\)
+ 508: 10 cc ff e8 lddi\.p @\(gr15,-24\),gr8
+ 50c: 9c fc ff e8 setlos 0xf*ffffffe8,gr14
+ 510: 82 30 80 00 calll @\(gr8,gr0\)
+ 514: 80 88 00 00 nop
+ 518: 92 fc f8 14 setlos 0xf*fffff814,gr9
+ 51c: 80 88 00 00 nop
+ 520: 92 fc 08 14 setlos 0x814,gr9
+ 524: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 528: 92 f4 f8 14 setlo 0xf814,gr9
+ 52c: fe 3f ff e0 call 4ac <i\+0x49c>
+ 530: fe 3f ff c9 call 454 <i\+0x444>
+ 534: fe 3f ff ca call 45c <i\+0x44c>
+ 538: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 53c: 9c f4 00 c8 setlo 0xc8,gr14
+ 540: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 544: 82 30 80 00 calll @\(gr8,gr0\)
+ 548: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 54c: 9c f4 00 78 setlo 0x78,gr14
+ 550: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 554: 82 30 80 00 calll @\(gr8,gr0\)
+ 558: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 55c: 9c f4 00 88 setlo 0x88,gr14
+ 560: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 564: 82 30 80 00 calll @\(gr8,gr0\)
+ 568: 10 cc ff f8 lddi\.p @\(gr15,-8\),gr8
+ 56c: 9c fc ff f8 setlos 0xf*fffffff8,gr14
+ 570: 82 30 80 00 calll @\(gr8,gr0\)
+ 574: 10 cc f0 18 lddi\.p @\(gr15,24\),gr8
+ 578: 9c fc 00 18 setlos 0x18,gr14
+ 57c: 82 30 80 00 calll @\(gr8,gr0\)
+ 580: 10 cc f0 38 lddi\.p @\(gr15,56\),gr8
+ 584: 9c fc 00 38 setlos 0x38,gr14
+ 588: 82 30 80 00 calll @\(gr8,gr0\)
+ 58c: 80 88 00 00 nop
+ 590: 92 fc f8 24 setlos 0xf*fffff824,gr9
+ 594: 80 88 00 00 nop
+ 598: 92 fc 08 24 setlos 0x824,gr9
+ 59c: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 5a0: 92 f4 f8 24 setlo 0xf824,gr9
+ 5a4: fe 3f ff b0 call 464 <i\+0x454>
+ 5a8: fe 3f ff b5 call 47c <i\+0x46c>
+ 5ac: fe 3f ff ba call 494 <i\+0x484>
+ 5b0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 5b4: 9c f4 00 90 setlo 0x90,gr14
+ 5b8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 5bc: 82 30 80 00 calll @\(gr8,gr0\)
+ 5c0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 5c4: 9c f4 00 a0 setlo 0xa0,gr14
+ 5c8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 5cc: 82 30 80 00 calll @\(gr8,gr0\)
+ 5d0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 5d4: 9c f4 00 b8 setlo 0xb8,gr14
+ 5d8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 5dc: 82 30 80 00 calll @\(gr8,gr0\)
+ 5e0: 10 cc f0 48 lddi\.p @\(gr15,72\),gr8
+ 5e4: 9c fc 00 48 setlos 0x48,gr14
+ 5e8: 82 30 80 00 calll @\(gr8,gr0\)
+ 5ec: 10 cc ff a0 lddi\.p @\(gr15,-96\),gr8
+ 5f0: 9c fc ff a0 setlos 0xf*ffffffa0,gr14
+ 5f4: 82 30 80 00 calll @\(gr8,gr0\)
+ 5f8: 10 cc ff d0 lddi\.p @\(gr15,-48\),gr8
+ 5fc: 9c fc ff d0 setlos 0xf*ffffffd0,gr14
+ 600: 82 30 80 00 calll @\(gr8,gr0\)
+ 604: 80 88 00 00 nop
+ 608: 92 fc 00 04 setlos 0x4,gr9
+ 60c: 80 88 00 00 nop
+ 610: 92 fc 10 04 setlos 0x1004,gr9
+ 614: 92 f8 00 01 sethi 0x1,gr9
+ 618: 92 f4 00 04 setlo 0x4,gr9
+ 61c: fe 3f ff 94 call 46c <i\+0x45c>
+ 620: fe 3f ff 99 call 484 <i\+0x474>
+ 624: fe 3f ff 9e call 49c <i\+0x48c>
+ 628: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 62c: 9c f4 00 b0 setlo 0xb0,gr14
+ 630: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 634: 82 30 80 00 calll @\(gr8,gr0\)
+ 638: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 63c: 9c f4 00 80 setlo 0x80,gr14
+ 640: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 644: 82 30 80 00 calll @\(gr8,gr0\)
+ 648: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 64c: 9c f4 00 70 setlo 0x70,gr14
+ 650: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 654: 82 30 80 00 calll @\(gr8,gr0\)
+ 658: 10 cc f0 20 lddi\.p @\(gr15,32\),gr8
+ 65c: 9c fc 00 20 setlos 0x20,gr14
+ 660: 82 30 80 00 calll @\(gr8,gr0\)
+ 664: 10 cc f0 28 lddi\.p @\(gr15,40\),gr8
+ 668: 9c fc 00 28 setlos 0x28,gr14
+ 66c: 82 30 80 00 calll @\(gr8,gr0\)
+ 670: 10 cc ff c0 lddi\.p @\(gr15,-64\),gr8
+ 674: 9c fc ff c0 setlos 0xf*ffffffc0,gr14
+ 678: 82 30 80 00 calll @\(gr8,gr0\)
+Disassembly of section \.got:
+
+00004700 <_GLOBAL_OFFSET_TABLE_-0x60>:
+ 4700: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4700: R_FRV_TLSDESC_VALUE \.tbss
+ 4704: 00 00 17 f3 \*unknown\*
+ 4708: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4708: R_FRV_TLSDESC_VALUE x
+ 470c: 00 00 10 01 add\.p sp,sp,gr0
+ 4710: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4710: R_FRV_TLSDESC_VALUE \.tbss
+ 4714: 00 00 10 01 add\.p sp,sp,gr0
+ 4718: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4718: R_FRV_TLSDESC_VALUE \.tbss
+ 471c: 00 00 10 03 add\.p sp,gr3,gr0
+ 4720: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4720: R_FRV_TLSDESC_VALUE x
+ 4724: 00 01 00 03 add\.p gr16,gr3,gr0
+ 4728: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4728: R_FRV_TLSDESC_VALUE \.tbss
+ 472c: 00 01 07 f1 \*unknown\*
+ 4730: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4730: R_FRV_TLSDESC_VALUE \.tbss
+ 4734: 00 01 07 f3 \*unknown\*
+ 4738: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4738: R_FRV_TLSDESC_VALUE x
+ 473c: 00 01 00 01 add\.p gr16,sp,gr0
+ 4740: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4740: R_FRV_TLSDESC_VALUE \.tbss
+ 4744: 00 01 00 01 add\.p gr16,sp,gr0
+ 4748: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4748: R_FRV_TLSDESC_VALUE \.tbss
+ 474c: 00 01 00 03 add\.p gr16,gr3,gr0
+ 4750: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4750: R_FRV_TLSDESC_VALUE \.tbss
+ 4754: 00 00 00 11 add\.p gr0,gr17,gr0
+ 4758: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4758: R_FRV_TLSDESC_VALUE \.tbss
+ 475c: 00 00 00 13 add\.p gr0,gr19,gr0
+
+00004760 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 4770: R_FRV_TLSDESC_VALUE \.tbss
+ 4774: 00 00 10 11 add\.p sp,gr17,gr0
+ 4778: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4778: R_FRV_TLSDESC_VALUE \.tbss
+ 477c: 00 00 10 13 add\.p sp,gr19,gr0
+ 4780: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4780: R_FRV_TLSDESC_VALUE x
+ 4784: 00 00 00 03 add\.p gr0,gr3,gr0
+ 4788: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4788: R_FRV_TLSDESC_VALUE x
+ 478c: 00 00 10 03 add\.p sp,gr3,gr0
+ 4790: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4790: R_FRV_TLSDESC_VALUE \.tbss
+ 4794: 00 01 00 11 add\.p gr16,gr17,gr0
+ 4798: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4798: R_FRV_TLSDESC_VALUE \.tbss
+ 479c: 00 01 00 13 add\.p gr16,gr19,gr0
+ 47a0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47a0: R_FRV_TLSDESC_VALUE \.tbss
+ 47a4: 00 00 07 f1 \*unknown\*
+ 47a8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47a8: R_FRV_TLSDESC_VALUE \.tbss
+ 47ac: 00 00 07 f3 \*unknown\*
+ 47b0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47b0: R_FRV_TLSDESC_VALUE x
+ 47b4: 00 00 00 01 add\.p gr0,sp,gr0
+ 47b8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47b8: R_FRV_TLSDESC_VALUE \.tbss
+ 47bc: 00 00 00 01 add\.p gr0,sp,gr0
+ 47c0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47c0: R_FRV_TLSDESC_VALUE \.tbss
+ 47c4: 00 00 00 03 add\.p gr0,gr3,gr0
+ 47c8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47c8: R_FRV_TLSDESC_VALUE \.tbss
+ 47cc: 00 00 17 f1 \*unknown\*
+ 47d0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47d0: R_FRV_TLSDESC_VALUE x
+ 47d4: 00 01 00 02 add\.p gr16,fp,gr0
+ 47d8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47d8: R_FRV_TLSDESC_VALUE \.tbss
+ 47dc: 00 00 10 12 add\.p sp,gr18,gr0
+ 47e0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47e0: R_FRV_TLSDESC_VALUE x
+ 47e4: 00 00 10 02 add\.p sp,fp,gr0
+ 47e8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47e8: R_FRV_TLSDESC_VALUE \.tbss
+ 47ec: 00 01 00 12 add\.p gr16,gr18,gr0
+ 47f0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47f0: R_FRV_TLSDESC_VALUE \.tbss
+ 47f4: 00 00 07 f2 \*unknown\*
+ 47f8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47f8: R_FRV_TLSDESC_VALUE \.tbss
+ 47fc: 00 00 00 02 add\.p gr0,fp,gr0
+ 4800: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4800: R_FRV_TLSDESC_VALUE \.tbss
+ 4804: 00 00 17 f2 \*unknown\*
+ 4808: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4808: R_FRV_TLSDESC_VALUE \.tbss
+ 480c: 00 00 10 02 add\.p sp,fp,gr0
+ 4810: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4810: R_FRV_TLSDESC_VALUE x
+ 4814: 00 00 00 02 add\.p gr0,fp,gr0
+ 4818: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4818: R_FRV_TLSDESC_VALUE \.tbss
+ 481c: 00 01 07 f2 \*unknown\*
+ 4820: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4820: R_FRV_TLSDESC_VALUE \.tbss
+ 4824: 00 01 00 02 add\.p gr16,fp,gr0
+ 4828: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4828: R_FRV_TLSDESC_VALUE \.tbss
+ 482c: 00 00 00 12 add\.p gr0,gr18,gr0
diff --git a/ld/testsuite/ld-frv/tls-relax-shared-3.d b/ld/testsuite/ld-frv/tls-relax-shared-3.d
new file mode 100644
index 0000000..216e4ff
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-shared-3.d
@@ -0,0 +1,27 @@
+#name: FRV TLS undefweak relocs, shared linking with relaxation
+#source: tls-3.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -shared --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+000002f4 <_start>:
+ 2f4: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 2f8: 00 88 00 00 nop\.p
+ 2fc: 80 88 00 00 nop
+ 300: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 304: 80 88 00 00 nop
+ 308: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 30c: 80 88 00 00 nop
+ 310: 80 88 00 00 nop
+ 314: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 318: 00 88 00 00 nop\.p
+ 31c: 80 88 00 00 nop
+ 320: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+Disassembly of section \.got:
+
+000043a8 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 43b4: R_FRV_TLSOFF u
diff --git a/ld/testsuite/ld-frv/tls-relax-static-1.d b/ld/testsuite/ld-frv/tls-relax-static-1.d
new file mode 100644
index 0000000..45038e7
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-static-1.d
@@ -0,0 +1,62 @@
+#name: FRV TLS relocs, static linking with relaxation
+#source: tls-1.s
+#objdump: -D -j .text -j .got -j .plt
+#ld: -static tmpdir/tls-1-dep.o --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+000100b4 <_start>:
+ 100b4: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 100b8: 00 88 00 00 nop\.p
+ 100bc: 80 88 00 00 nop
+ 100c0: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 100c4: 80 88 00 00 nop
+ 100c8: 12 fc f8 10 setlos\.p 0xf*fffff810,gr9
+ 100cc: 80 88 00 00 nop
+ 100d0: 80 88 00 00 nop
+ 100d4: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 100d8: 00 88 00 00 nop\.p
+ 100dc: 80 88 00 00 nop
+ 100e0: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 100e4: 80 88 00 00 nop
+ 100e8: 12 fc f8 20 setlos\.p 0xf*fffff820,gr9
+ 100ec: 80 88 00 00 nop
+ 100f0: 80 88 00 00 nop
+ 100f4: 92 fc f8 30 setlos 0xf*fffff830,gr9
+ 100f8: 00 88 00 00 nop\.p
+ 100fc: 80 88 00 00 nop
+ 10100: 92 fc f8 30 setlos 0xf*fffff830,gr9
+ 10104: 80 88 00 00 nop
+ 10108: 12 fc f8 30 setlos\.p 0xf*fffff830,gr9
+ 1010c: 80 88 00 00 nop
+ 10110: 80 88 00 00 nop
+ 10114: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10118: 00 88 00 00 nop\.p
+ 1011c: 80 88 00 00 nop
+ 10120: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10124: 80 88 00 00 nop
+ 10128: 12 fc 00 00 setlos\.p lo\(0x0\),gr9
+ 1012c: 80 88 00 00 nop
+ 10130: 80 88 00 00 nop
+ 10134: 00 88 00 00 nop\.p
+ 10138: 90 fc f8 30 setlos 0xf*fffff830,gr8
+ 1013c: 00 88 00 00 nop\.p
+ 10140: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 10144: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 10148: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 1014c: 92 fc f8 30 setlos 0xf*fffff830,gr9
+ 10150: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10154: 00 88 00 00 nop\.p
+ 10158: 80 88 00 00 nop
+ 1015c: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 10160: 00 88 00 00 nop\.p
+ 10164: 80 88 00 00 nop
+ 10168: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 1016c: 00 88 00 00 nop\.p
+ 10170: 80 88 00 00 nop
+ 10174: 92 fc f8 30 setlos 0xf*fffff830,gr9
+ 10178: 00 88 00 00 nop\.p
+ 1017c: 80 88 00 00 nop
+ 10180: 92 fc 00 00 setlos lo\(0x0\),gr9
diff --git a/ld/testsuite/ld-frv/tls-relax-static-3.d b/ld/testsuite/ld-frv/tls-relax-static-3.d
new file mode 100644
index 0000000..f4ce45f
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-relax-static-3.d
@@ -0,0 +1,26 @@
+#name: FRV TLS undefweak relocs, static linking with relaxation
+#source: tls-3.s
+#objdump: -D -j .text -j .got -j .plt
+#ld: -static --relax
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+00010094 <_start>:
+ 10094: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10098: 00 88 00 00 nop\.p
+ 1009c: 80 88 00 00 nop
+ 100a0: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 100a4: 80 88 00 00 nop
+ 100a8: 12 fc 00 00 setlos\.p lo\(0x0\),gr9
+ 100ac: 80 88 00 00 nop
+ 100b0: 80 88 00 00 nop
+ 100b4: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 100b8: 00 88 00 00 nop\.p
+ 100bc: 80 88 00 00 nop
+ 100c0: 92 fc 00 00 setlos lo\(0x0\),gr9
+Disassembly of section \.got:
+
+000140c8 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
diff --git a/ld/testsuite/ld-frv/tls-shared-1-fail.d b/ld/testsuite/ld-frv/tls-shared-1-fail.d
new file mode 100644
index 0000000..511d094
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-shared-1-fail.d
@@ -0,0 +1,4 @@
+#name: FRV TLS relocs, shared linking
+#source: tls-1.s
+#ld: -shared tmpdir/tls-1-dep.so
+#error: different segments
diff --git a/ld/testsuite/ld-frv/tls-shared-1.d b/ld/testsuite/ld-frv/tls-shared-1.d
new file mode 100644
index 0000000..aabd072
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-shared-1.d
@@ -0,0 +1,73 @@
+#name: FRV TLS relocs, shared linking with local binding
+#source: tls-1.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -shared tmpdir/tls-1-dep.so --version-script tls-1-shared.lds
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+00000354 <_start>:
+ 354: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 358: 00 88 00 00 nop\.p
+ 35c: 80 88 00 00 nop
+ 360: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 364: 80 88 00 00 nop
+ 368: 12 c8 f0 10 ldi\.p @\(gr15,16\),gr9
+ 36c: 80 88 00 00 nop
+ 370: 80 88 00 00 nop
+ 374: 92 c8 f0 14 ldi @\(gr15,20\),gr9
+ 378: 00 88 00 00 nop\.p
+ 37c: 80 88 00 00 nop
+ 380: 92 c8 f0 14 ldi @\(gr15,20\),gr9
+ 384: 80 88 00 00 nop
+ 388: 12 c8 f0 14 ldi\.p @\(gr15,20\),gr9
+ 38c: 80 88 00 00 nop
+ 390: 80 88 00 00 nop
+ 394: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 398: 00 88 00 00 nop\.p
+ 39c: 80 88 00 00 nop
+ 3a0: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 3a4: 80 88 00 00 nop
+ 3a8: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 3ac: 80 88 00 00 nop
+ 3b0: 80 88 00 00 nop
+ 3b4: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+ 3b8: 00 88 00 00 nop\.p
+ 3bc: 80 88 00 00 nop
+ 3c0: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+ 3c4: 80 88 00 00 nop
+ 3c8: 12 c8 f0 18 ldi\.p @\(gr15,24\),gr9
+ 3cc: 80 88 00 00 nop
+ 3d0: 80 88 00 00 nop
+ 3d4: 00 88 00 00 nop\.p
+ 3d8: 90 fc f8 20 setlos 0xf*fffff820,gr8
+ 3dc: 00 88 00 00 nop\.p
+ 3e0: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 3e4: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 3e8: 92 c8 f0 14 ldi @\(gr15,20\),gr9
+ 3ec: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 3f0: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+ 3f4: 00 88 00 00 nop\.p
+ 3f8: 80 88 00 00 nop
+ 3fc: 92 c8 f0 10 ldi @\(gr15,16\),gr9
+ 400: 00 88 00 00 nop\.p
+ 404: 80 88 00 00 nop
+ 408: 92 c8 f0 14 ldi @\(gr15,20\),gr9
+ 40c: 00 88 00 00 nop\.p
+ 410: 80 88 00 00 nop
+ 414: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 418: 00 88 00 00 nop\.p
+ 41c: 80 88 00 00 nop
+ 420: 92 c8 f0 18 ldi @\(gr15,24\),gr9
+Disassembly of section \.got:
+
+000044b8 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 44c4: 00 00 00 10 add\.p gr0,gr16,gr0
+ 44c4: R_FRV_TLSOFF \.tbss
+ \.\.\.
+ 44c8: R_FRV_TLSOFF x
+ 44cc: R_FRV_TLSOFF \.tbss
+ 44d0: 00 00 07 f0 \*unknown\*
+ 44d0: R_FRV_TLSOFF \.tbss
diff --git a/ld/testsuite/ld-frv/tls-shared-2.d b/ld/testsuite/ld-frv/tls-shared-2.d
new file mode 100644
index 0000000..14d8462
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-shared-2.d
@@ -0,0 +1,264 @@
+#name: FRV TLS relocs with addends, shared linking
+#source: tls-2.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -shared tmpdir/tls-1-dep.so --version-script tls-1-shared.lds
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.plt:
+
+00000454 <\.plt>:
+ 454: 90 cc f0 10 lddi @\(gr15,16\),gr8
+ 458: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 45c: 90 cc f0 30 lddi @\(gr15,48\),gr8
+ 460: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 464: 90 cc f0 40 lddi @\(gr15,64\),gr8
+ 468: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 46c: 90 cc f0 50 lddi @\(gr15,80\),gr8
+ 470: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 474: 90 cc f0 58 lddi @\(gr15,88\),gr8
+ 478: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 47c: 90 cc f0 68 lddi @\(gr15,104\),gr8
+ 480: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 484: 90 cc ff a8 lddi @\(gr15,-88\),gr8
+ 488: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 48c: 90 cc ff b0 lddi @\(gr15,-80\),gr8
+ 490: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 494: 90 cc ff c8 lddi @\(gr15,-56\),gr8
+ 498: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 49c: 90 cc ff d8 lddi @\(gr15,-40\),gr8
+ 4a0: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 4a4: 90 cc ff e0 lddi @\(gr15,-32\),gr8
+ 4a8: 80 30 80 00 jmpl @\(gr8,gr0\)
+ 4ac: 90 cc ff f0 lddi @\(gr15,-16\),gr8
+ 4b0: 80 30 80 00 jmpl @\(gr8,gr0\)
+Disassembly of section \.text:
+
+000004b4 <_start>:
+ 4b4: fe 3f ff f0 call 474 <i\+0x464>
+ 4b8: fe 3f ff f5 call 48c <i\+0x47c>
+ 4bc: fe 3f ff fa call 4a4 <i\+0x494>
+ 4c0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 4c4: 9c f4 00 98 setlo 0x98,gr14
+ 4c8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 4cc: 82 30 80 00 calll @\(gr8,gr0\)
+ 4d0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 4d4: 9c f4 00 a8 setlo 0xa8,gr14
+ 4d8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 4dc: 82 30 80 00 calll @\(gr8,gr0\)
+ 4e0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 4e4: 9c f4 00 c0 setlo 0xc0,gr14
+ 4e8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 4ec: 82 30 80 00 calll @\(gr8,gr0\)
+ 4f0: 10 cc f0 60 lddi\.p @\(gr15,96\),gr8
+ 4f4: 9c fc 00 60 setlos 0x60,gr14
+ 4f8: 82 30 80 00 calll @\(gr8,gr0\)
+ 4fc: 10 cc ff b8 lddi\.p @\(gr15,-72\),gr8
+ 500: 9c fc ff b8 setlos 0xf*ffffffb8,gr14
+ 504: 82 30 80 00 calll @\(gr8,gr0\)
+ 508: 10 cc ff e8 lddi\.p @\(gr15,-24\),gr8
+ 50c: 9c fc ff e8 setlos 0xf*ffffffe8,gr14
+ 510: 82 30 80 00 calll @\(gr8,gr0\)
+ 514: 80 88 00 00 nop
+ 518: 92 fc f8 14 setlos 0xf*fffff814,gr9
+ 51c: 80 88 00 00 nop
+ 520: 92 fc 08 14 setlos 0x814,gr9
+ 524: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 528: 92 f4 f8 14 setlo 0xf814,gr9
+ 52c: fe 3f ff e0 call 4ac <i\+0x49c>
+ 530: fe 3f ff c9 call 454 <i\+0x444>
+ 534: fe 3f ff ca call 45c <i\+0x44c>
+ 538: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 53c: 9c f4 00 c8 setlo 0xc8,gr14
+ 540: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 544: 82 30 80 00 calll @\(gr8,gr0\)
+ 548: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 54c: 9c f4 00 78 setlo 0x78,gr14
+ 550: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 554: 82 30 80 00 calll @\(gr8,gr0\)
+ 558: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 55c: 9c f4 00 88 setlo 0x88,gr14
+ 560: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 564: 82 30 80 00 calll @\(gr8,gr0\)
+ 568: 10 cc ff f8 lddi\.p @\(gr15,-8\),gr8
+ 56c: 9c fc ff f8 setlos 0xf*fffffff8,gr14
+ 570: 82 30 80 00 calll @\(gr8,gr0\)
+ 574: 10 cc f0 18 lddi\.p @\(gr15,24\),gr8
+ 578: 9c fc 00 18 setlos 0x18,gr14
+ 57c: 82 30 80 00 calll @\(gr8,gr0\)
+ 580: 10 cc f0 38 lddi\.p @\(gr15,56\),gr8
+ 584: 9c fc 00 38 setlos 0x38,gr14
+ 588: 82 30 80 00 calll @\(gr8,gr0\)
+ 58c: 80 88 00 00 nop
+ 590: 92 fc f8 24 setlos 0xf*fffff824,gr9
+ 594: 80 88 00 00 nop
+ 598: 92 fc 08 24 setlos 0x824,gr9
+ 59c: 92 f8 00 00 sethi hi\(0x0\),gr9
+ 5a0: 92 f4 f8 24 setlo 0xf824,gr9
+ 5a4: fe 3f ff b0 call 464 <i\+0x454>
+ 5a8: fe 3f ff b5 call 47c <i\+0x46c>
+ 5ac: fe 3f ff ba call 494 <i\+0x484>
+ 5b0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 5b4: 9c f4 00 90 setlo 0x90,gr14
+ 5b8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 5bc: 82 30 80 00 calll @\(gr8,gr0\)
+ 5c0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 5c4: 9c f4 00 a0 setlo 0xa0,gr14
+ 5c8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 5cc: 82 30 80 00 calll @\(gr8,gr0\)
+ 5d0: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 5d4: 9c f4 00 b8 setlo 0xb8,gr14
+ 5d8: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 5dc: 82 30 80 00 calll @\(gr8,gr0\)
+ 5e0: 10 cc f0 48 lddi\.p @\(gr15,72\),gr8
+ 5e4: 9c fc 00 48 setlos 0x48,gr14
+ 5e8: 82 30 80 00 calll @\(gr8,gr0\)
+ 5ec: 10 cc ff a0 lddi\.p @\(gr15,-96\),gr8
+ 5f0: 9c fc ff a0 setlos 0xf*ffffffa0,gr14
+ 5f4: 82 30 80 00 calll @\(gr8,gr0\)
+ 5f8: 10 cc ff d0 lddi\.p @\(gr15,-48\),gr8
+ 5fc: 9c fc ff d0 setlos 0xf*ffffffd0,gr14
+ 600: 82 30 80 00 calll @\(gr8,gr0\)
+ 604: 80 88 00 00 nop
+ 608: 92 fc 00 04 setlos 0x4,gr9
+ 60c: 80 88 00 00 nop
+ 610: 92 fc 10 04 setlos 0x1004,gr9
+ 614: 92 f8 00 01 sethi 0x1,gr9
+ 618: 92 f4 00 04 setlo 0x4,gr9
+ 61c: fe 3f ff 94 call 46c <i\+0x45c>
+ 620: fe 3f ff 99 call 484 <i\+0x474>
+ 624: fe 3f ff 9e call 49c <i\+0x48c>
+ 628: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 62c: 9c f4 00 b0 setlo 0xb0,gr14
+ 630: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 634: 82 30 80 00 calll @\(gr8,gr0\)
+ 638: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 63c: 9c f4 00 80 setlo 0x80,gr14
+ 640: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 644: 82 30 80 00 calll @\(gr8,gr0\)
+ 648: 1c f8 00 00 sethi\.p hi\(0x0\),gr14
+ 64c: 9c f4 00 70 setlo 0x70,gr14
+ 650: 90 08 f1 4e ldd @\(gr15,gr14\),gr8
+ 654: 82 30 80 00 calll @\(gr8,gr0\)
+ 658: 10 cc f0 20 lddi\.p @\(gr15,32\),gr8
+ 65c: 9c fc 00 20 setlos 0x20,gr14
+ 660: 82 30 80 00 calll @\(gr8,gr0\)
+ 664: 10 cc f0 28 lddi\.p @\(gr15,40\),gr8
+ 668: 9c fc 00 28 setlos 0x28,gr14
+ 66c: 82 30 80 00 calll @\(gr8,gr0\)
+ 670: 10 cc ff c0 lddi\.p @\(gr15,-64\),gr8
+ 674: 9c fc ff c0 setlos 0xf*ffffffc0,gr14
+ 678: 82 30 80 00 calll @\(gr8,gr0\)
+Disassembly of section \.got:
+
+00004700 <_GLOBAL_OFFSET_TABLE_-0x60>:
+ 4700: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4700: R_FRV_TLSDESC_VALUE \.tbss
+ 4704: 00 00 17 f3 \*unknown\*
+ 4708: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4708: R_FRV_TLSDESC_VALUE x
+ 470c: 00 00 10 01 add\.p sp,sp,gr0
+ 4710: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4710: R_FRV_TLSDESC_VALUE \.tbss
+ 4714: 00 00 10 01 add\.p sp,sp,gr0
+ 4718: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4718: R_FRV_TLSDESC_VALUE \.tbss
+ 471c: 00 00 10 03 add\.p sp,gr3,gr0
+ 4720: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4720: R_FRV_TLSDESC_VALUE x
+ 4724: 00 01 00 03 add\.p gr16,gr3,gr0
+ 4728: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4728: R_FRV_TLSDESC_VALUE \.tbss
+ 472c: 00 01 07 f1 \*unknown\*
+ 4730: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4730: R_FRV_TLSDESC_VALUE \.tbss
+ 4734: 00 01 07 f3 \*unknown\*
+ 4738: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4738: R_FRV_TLSDESC_VALUE x
+ 473c: 00 01 00 01 add\.p gr16,sp,gr0
+ 4740: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4740: R_FRV_TLSDESC_VALUE \.tbss
+ 4744: 00 01 00 01 add\.p gr16,sp,gr0
+ 4748: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4748: R_FRV_TLSDESC_VALUE \.tbss
+ 474c: 00 01 00 03 add\.p gr16,gr3,gr0
+ 4750: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4750: R_FRV_TLSDESC_VALUE \.tbss
+ 4754: 00 00 00 11 add\.p gr0,gr17,gr0
+ 4758: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4758: R_FRV_TLSDESC_VALUE \.tbss
+ 475c: 00 00 00 13 add\.p gr0,gr19,gr0
+
+00004760 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 4770: R_FRV_TLSDESC_VALUE \.tbss
+ 4774: 00 00 10 11 add\.p sp,gr17,gr0
+ 4778: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4778: R_FRV_TLSDESC_VALUE \.tbss
+ 477c: 00 00 10 13 add\.p sp,gr19,gr0
+ 4780: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4780: R_FRV_TLSDESC_VALUE x
+ 4784: 00 00 00 03 add\.p gr0,gr3,gr0
+ 4788: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4788: R_FRV_TLSDESC_VALUE x
+ 478c: 00 00 10 03 add\.p sp,gr3,gr0
+ 4790: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4790: R_FRV_TLSDESC_VALUE \.tbss
+ 4794: 00 01 00 11 add\.p gr16,gr17,gr0
+ 4798: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4798: R_FRV_TLSDESC_VALUE \.tbss
+ 479c: 00 01 00 13 add\.p gr16,gr19,gr0
+ 47a0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47a0: R_FRV_TLSDESC_VALUE \.tbss
+ 47a4: 00 00 07 f1 \*unknown\*
+ 47a8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47a8: R_FRV_TLSDESC_VALUE \.tbss
+ 47ac: 00 00 07 f3 \*unknown\*
+ 47b0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47b0: R_FRV_TLSDESC_VALUE x
+ 47b4: 00 00 00 01 add\.p gr0,sp,gr0
+ 47b8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47b8: R_FRV_TLSDESC_VALUE \.tbss
+ 47bc: 00 00 00 01 add\.p gr0,sp,gr0
+ 47c0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47c0: R_FRV_TLSDESC_VALUE \.tbss
+ 47c4: 00 00 00 03 add\.p gr0,gr3,gr0
+ 47c8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47c8: R_FRV_TLSDESC_VALUE \.tbss
+ 47cc: 00 00 17 f1 \*unknown\*
+ 47d0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47d0: R_FRV_TLSDESC_VALUE x
+ 47d4: 00 01 00 02 add\.p gr16,fp,gr0
+ 47d8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47d8: R_FRV_TLSDESC_VALUE \.tbss
+ 47dc: 00 00 10 12 add\.p sp,gr18,gr0
+ 47e0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47e0: R_FRV_TLSDESC_VALUE x
+ 47e4: 00 00 10 02 add\.p sp,fp,gr0
+ 47e8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47e8: R_FRV_TLSDESC_VALUE \.tbss
+ 47ec: 00 01 00 12 add\.p gr16,gr18,gr0
+ 47f0: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47f0: R_FRV_TLSDESC_VALUE \.tbss
+ 47f4: 00 00 07 f2 \*unknown\*
+ 47f8: 00 00 00 00 add\.p gr0,gr0,gr0
+ 47f8: R_FRV_TLSDESC_VALUE \.tbss
+ 47fc: 00 00 00 02 add\.p gr0,fp,gr0
+ 4800: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4800: R_FRV_TLSDESC_VALUE \.tbss
+ 4804: 00 00 17 f2 \*unknown\*
+ 4808: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4808: R_FRV_TLSDESC_VALUE \.tbss
+ 480c: 00 00 10 02 add\.p sp,fp,gr0
+ 4810: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4810: R_FRV_TLSDESC_VALUE x
+ 4814: 00 00 00 02 add\.p gr0,fp,gr0
+ 4818: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4818: R_FRV_TLSDESC_VALUE \.tbss
+ 481c: 00 01 07 f2 \*unknown\*
+ 4820: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4820: R_FRV_TLSDESC_VALUE \.tbss
+ 4824: 00 01 00 02 add\.p gr16,fp,gr0
+ 4828: 00 00 00 00 add\.p gr0,gr0,gr0
+ 4828: R_FRV_TLSDESC_VALUE \.tbss
+ 482c: 00 00 00 12 add\.p gr0,gr18,gr0
diff --git a/ld/testsuite/ld-frv/tls-shared-3.d b/ld/testsuite/ld-frv/tls-shared-3.d
new file mode 100644
index 0000000..d1a74c8
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-shared-3.d
@@ -0,0 +1,27 @@
+#name: FRV TLS undefweak relocs, shared linking
+#source: tls-3.s
+#objdump: -DR -j .text -j .got -j .plt
+#ld: -shared
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+000002f4 <_start>:
+ 2f4: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 2f8: 00 88 00 00 nop\.p
+ 2fc: 80 88 00 00 nop
+ 300: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 304: 80 88 00 00 nop
+ 308: 12 c8 f0 0c ldi\.p @\(gr15,12\),gr9
+ 30c: 80 88 00 00 nop
+ 310: 80 88 00 00 nop
+ 314: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+ 318: 00 88 00 00 nop\.p
+ 31c: 80 88 00 00 nop
+ 320: 92 c8 f0 0c ldi @\(gr15,12\),gr9
+Disassembly of section \.got:
+
+000043a8 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 43b4: R_FRV_TLSOFF u
diff --git a/ld/testsuite/ld-frv/tls-static-1.d b/ld/testsuite/ld-frv/tls-static-1.d
new file mode 100644
index 0000000..75b4011
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-static-1.d
@@ -0,0 +1,70 @@
+#name: FRV TLS relocs, static linking
+#source: tls-1.s
+#objdump: -D -j .text -j .got -j .plt
+#ld: -static tmpdir/tls-1-dep.o
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+000100b4 <_start>:
+ 100b4: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 100b8: 00 88 00 00 nop\.p
+ 100bc: 80 88 00 00 nop
+ 100c0: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 100c4: 80 88 00 00 nop
+ 100c8: 12 fc f8 10 setlos\.p 0xf*fffff810,gr9
+ 100cc: 80 88 00 00 nop
+ 100d0: 80 88 00 00 nop
+ 100d4: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 100d8: 00 88 00 00 nop\.p
+ 100dc: 80 88 00 00 nop
+ 100e0: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 100e4: 80 88 00 00 nop
+ 100e8: 12 fc f8 20 setlos\.p 0xf*fffff820,gr9
+ 100ec: 80 88 00 00 nop
+ 100f0: 80 88 00 00 nop
+ 100f4: 92 fc f8 30 setlos 0xf*fffff830,gr9
+ 100f8: 00 88 00 00 nop\.p
+ 100fc: 80 88 00 00 nop
+ 10100: 92 fc f8 30 setlos 0xf*fffff830,gr9
+ 10104: 80 88 00 00 nop
+ 10108: 12 fc f8 30 setlos\.p 0xf*fffff830,gr9
+ 1010c: 80 88 00 00 nop
+ 10110: 80 88 00 00 nop
+ 10114: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10118: 00 88 00 00 nop\.p
+ 1011c: 80 88 00 00 nop
+ 10120: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10124: 80 88 00 00 nop
+ 10128: 12 fc 00 00 setlos\.p lo\(0x0\),gr9
+ 1012c: 80 88 00 00 nop
+ 10130: 80 88 00 00 nop
+ 10134: 00 88 00 00 nop\.p
+ 10138: 90 fc f8 30 setlos 0xf*fffff830,gr8
+ 1013c: 00 88 00 00 nop\.p
+ 10140: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 10144: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 10148: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 1014c: 92 fc f8 30 setlos 0xf*fffff830,gr9
+ 10150: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10154: 00 88 00 00 nop\.p
+ 10158: 80 88 00 00 nop
+ 1015c: 92 fc f8 10 setlos 0xf*fffff810,gr9
+ 10160: 00 88 00 00 nop\.p
+ 10164: 80 88 00 00 nop
+ 10168: 92 fc f8 20 setlos 0xf*fffff820,gr9
+ 1016c: 00 88 00 00 nop\.p
+ 10170: 80 88 00 00 nop
+ 10174: 92 fc f8 30 setlos 0xf*fffff830,gr9
+ 10178: 00 88 00 00 nop\.p
+ 1017c: 80 88 00 00 nop
+ 10180: 92 fc 00 00 setlos lo\(0x0\),gr9
+Disassembly of section \.got:
+
+00014190 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
+ 1419c: ff ff f8 30 cop2 -32,cpr63,cpr48,cpr63
+ 141a0: ff ff f8 10 cop2 -32,cpr63,cpr16,cpr63
+ 141a4: ff ff f8 20 cop2 -32,cpr63,cpr32,cpr63
+ 141a8: 00 00 00 00 add\.p gr0,gr0,gr0
diff --git a/ld/testsuite/ld-frv/tls-static-3.d b/ld/testsuite/ld-frv/tls-static-3.d
new file mode 100644
index 0000000..3a678b3
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls-static-3.d
@@ -0,0 +1,26 @@
+#name: FRV TLS undefweak relocs, static linking
+#source: tls-3.s
+#objdump: -D -j .text -j .got -j .plt
+#ld: -static
+
+.*: file format elf.*frv.*
+
+Disassembly of section \.text:
+
+00010094 <_start>:
+ 10094: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 10098: 00 88 00 00 nop\.p
+ 1009c: 80 88 00 00 nop
+ 100a0: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 100a4: 80 88 00 00 nop
+ 100a8: 12 fc 00 00 setlos\.p lo\(0x0\),gr9
+ 100ac: 80 88 00 00 nop
+ 100b0: 80 88 00 00 nop
+ 100b4: 92 fc 00 00 setlos lo\(0x0\),gr9
+ 100b8: 00 88 00 00 nop\.p
+ 100bc: 80 88 00 00 nop
+ 100c0: 92 fc 00 00 setlos lo\(0x0\),gr9
+Disassembly of section \.got:
+
+000140c8 <_GLOBAL_OFFSET_TABLE_>:
+ \.\.\.
diff --git a/ld/testsuite/ld-frv/tls.exp b/ld/testsuite/ld-frv/tls.exp
new file mode 100644
index 0000000..a6c2603
--- /dev/null
+++ b/ld/testsuite/ld-frv/tls.exp
@@ -0,0 +1,62 @@
+# Expect script for FRV FDPIC TLS linker tests
+# Copyright 2003, 2004, 2005 Free Software Foundation, Inc.
+#
+# This file 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+
+if {![istarget frv*-*-*] || ![is_elf_format]} {
+ return
+}
+
+global ASFLAGS
+set saved_ASFLAGS "$ASFLAGS"
+set ASFLAGS "$ASFLAGS -mfdpic"
+
+global LDFLAGS
+set saved_LDFLAGS "$LDFLAGS"
+set LDFLAGS "$LDFLAGS -melf32frvfd"
+
+run_ld_link_tests [list [list "tls-1-dep" "$LDFLAGS -shared" "" "tls-1-dep.s" [list] "tls-1-dep.so" ""]]
+run_dump_test "tls-static-1"
+run_dump_test "tls-dynamic-1"
+run_dump_test "tls-pie-1"
+run_dump_test "tls-shared-1-fail"
+run_dump_test "tls-shared-1"
+
+run_dump_test "tls-relax-static-1"
+run_dump_test "tls-relax-dynamic-1"
+run_dump_test "tls-relax-pie-1"
+run_dump_test "tls-relax-shared-1"
+
+run_dump_test "tls-dynamic-2"
+run_dump_test "tls-shared-2"
+run_dump_test "tls-initial-shared-2"
+
+run_dump_test "tls-relax-dynamic-2"
+run_dump_test "tls-relax-shared-2"
+run_dump_test "tls-relax-initial-shared-2"
+
+run_dump_test "tls-static-3"
+run_dump_test "tls-dynamic-3"
+run_dump_test "tls-pie-3"
+run_dump_test "tls-shared-3"
+
+run_dump_test "tls-relax-static-3"
+run_dump_test "tls-relax-dynamic-3"
+run_dump_test "tls-relax-pie-3"
+run_dump_test "tls-relax-shared-3"
+
+set LDFLAGS "$saved_LDFLAGS"
+set ASFLAGS "$saved_ASFLAGS"
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 02e2553..b91673f 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,14 @@
+2005-01-25 Alexandre Oliva <aoliva@redhat.com>
+
+ 2004-11-10 Alexandre Oliva <aoliva@redhat.com>
+ * frv-asm.c: Rebuilt.
+ * frv-desc.c: Rebuilt.
+ * frv-desc.h: Rebuilt.
+ * frv-dis.c: Rebuilt.
+ * frv-ibld.c: Rebuilt.
+ * frv-opc.c: Rebuilt.
+ * frv-opc.h: Rebuilt.
+
2005-01-24 Andrew Cagney <cagney@gnu.org>
* configure: Regenerate, ../gettext.m4 was updated.
diff --git a/opcodes/frv-asm.c b/opcodes/frv-asm.c
index 98df36b..52d3bc1 100644
--- a/opcodes/frv-asm.c
+++ b/opcodes/frv-asm.c
@@ -73,6 +73,146 @@ static const char * parse_A1
static const char * parse_A
PARAMS ((CGEN_CPU_DESC, const char **, int, long *, long));
+inline static const char *
+parse_symbolic_address (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ int opinfo,
+ enum cgen_parse_operand_result *resultp,
+ bfd_vma *valuep)
+{
+ enum cgen_parse_operand_result result_type;
+ const char *errmsg = (* cd->parse_operand_fn)
+ (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
+ &result_type, valuep);
+
+ if (errmsg == NULL
+ && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
+ return "symbolic expression required";
+
+ if (resultp)
+ *resultp = result_type;
+
+ return errmsg;
+}
+
+static const char *
+parse_ldd_annotation (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ long *valuep)
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#' || **strp == '%')
+ {
+ if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
+ {
+ *strp += 9;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSDESC_RELAX,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ if (valuep)
+ *valuep = value;
+ ++*strp;
+ if (errmsg)
+ return errmsg;
+ }
+ }
+
+ while (**strp == ' ' || **strp == '\t')
+ ++*strp;
+
+ if (**strp != '@')
+ return "missing `@'";
+
+ ++*strp;
+
+ return NULL;
+}
+
+static const char *
+parse_call_annotation (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ long *valuep)
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#' || **strp == '%')
+ {
+ if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GETTLSOFF_RELAX,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ if (valuep)
+ *valuep = value;
+ ++*strp;
+ if (errmsg)
+ return errmsg;
+ }
+ }
+
+ while (**strp == ' ' || **strp == '\t')
+ ++*strp;
+
+ if (**strp != '@')
+ return "missing `@'";
+
+ ++*strp;
+
+ return NULL;
+}
+
+static const char *
+parse_ld_annotation (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ long *valuep)
+{
+ const char *errmsg;
+ enum cgen_parse_operand_result result_type;
+ bfd_vma value;
+
+ if (**strp == '#' || **strp == '%')
+ {
+ if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
+ {
+ *strp += 8;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSOFF_RELAX,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ if (valuep)
+ *valuep = value;
+ ++*strp;
+ if (errmsg)
+ return errmsg;
+ }
+ }
+
+ while (**strp == ' ' || **strp == '\t')
+ ++*strp;
+
+ if (**strp != '@')
+ return "missing `@'";
+
+ ++*strp;
+
+ return NULL;
+}
+
static const char *
parse_ulo16 (cd, strp, opindex, valuep)
CGEN_CPU_DESC cd;
@@ -103,73 +243,96 @@ parse_ulo16 (cd, strp, opindex, valuep)
if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
{
*strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPRELLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
{
*strp += 7;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
{
*strp += 15;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
{
*strp += 10;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_GOTOFFLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFFLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
{
*strp += 18;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESCLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFFLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFFLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
@@ -207,73 +370,96 @@ parse_uslo16 (cd, strp, opindex, valuep)
else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
{
*strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPRELLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
{
*strp += 7;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
{
*strp += 15;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
{
*strp += 10;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_GOTOFFLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFFLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
{
*strp += 18;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESCLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFFLO,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFFLO,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value &= 0xffff;
*valuep = value;
return errmsg;
}
@@ -304,80 +490,110 @@ parse_uhi16 (cd, strp, opindex, valuep)
++*strp;
if (errmsg == NULL
&& result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
+ {
+ /* If bfd_vma is wider than 32 bits, but we have a sign-
+ or zero-extension, truncate it. */
+ if (value >= - ((bfd_vma)1 << 31)
+ || value <= ((bfd_vma)1 << 31) - (bfd_vma)1)
+ value &= (((bfd_vma)1 << 16) << 16) - 1;
+ value >>= 16;
+ }
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
{
*strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPRELHI,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
{
*strp += 7;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTHI,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTHI,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
{
*strp += 15;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTHI,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTHI,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
{
*strp += 10;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_GOTOFFHI,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFFHI,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
*valuep = value;
return errmsg;
}
else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
{
*strp += 18;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESCHI,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFFHI,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFFHI,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
- if (errmsg == NULL
- && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
- value >>= 16;
*valuep = value;
return errmsg;
}
@@ -455,8 +671,9 @@ parse_d12 (cd, strp, opindex, valuep)
if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
{
*strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPREL12,
+ &result_type, &value);
if (**strp != ')')
return "missing `)'";
++*strp;
@@ -466,8 +683,9 @@ parse_d12 (cd, strp, opindex, valuep)
else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
{
*strp += 7;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOT12,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
@@ -477,9 +695,9 @@ parse_d12 (cd, strp, opindex, valuep)
else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
{
*strp += 15;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOT12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOT12,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
@@ -489,9 +707,9 @@ parse_d12 (cd, strp, opindex, valuep)
else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
{
*strp += 10;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_GOTOFF12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFF12,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
@@ -501,9 +719,45 @@ parse_d12 (cd, strp, opindex, valuep)
else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
{
*strp += 18;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESC12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFF12,
+ &result_type, &value);
if (**strp != ')')
return "missing ')'";
++*strp;
@@ -526,74 +780,109 @@ parse_s12 (cd, strp, opindex, valuep)
bfd_vma value;
/* Check for small data reference. */
- if ((**strp == '#' || **strp == '%')
- && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
- {
- *strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
- &result_type, &value);
- if (**strp != ')')
- return "missing `)'";
- ++*strp;
- *valuep = value;
- return errmsg;
- }
- else if ((**strp == '#' || **strp == '%')
- && strncasecmp (*strp + 1, "got12(", 6) == 0)
- {
- *strp += 7;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOT12,
- &result_type, &value);
- if (**strp != ')')
- return "missing ')'";
- ++*strp;
- *valuep = value;
- return errmsg;
- }
- else if ((**strp == '#' || **strp == '%')
- && strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
- {
- *strp += 15;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOT12,
- &result_type, &value);
- if (**strp != ')')
- return "missing ')'";
- ++*strp;
- *valuep = value;
- return errmsg;
- }
- else if ((**strp == '#' || **strp == '%')
- && strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
- {
- *strp += 10;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GOTOFF12,
- &result_type, &value);
- if (**strp != ')')
- return "missing ')'";
- ++*strp;
- *valuep = value;
- return errmsg;
- }
- else if ((**strp == '#' || **strp == '%')
- && strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
- {
- *strp += 18;
- errmsg = cgen_parse_address (cd, strp, opindex,
- BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
- &result_type, &value);
- if (**strp != ')')
- return "missing ')'";
- ++*strp;
- *valuep = value;
- return errmsg;
- }
- else
+ if (**strp == '#' || **strp == '%')
{
- if (**strp == '#')
- ++*strp;
- return cgen_parse_signed_integer (cd, strp, opindex, valuep);
+ if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
+ {
+ *strp += 9;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPREL12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
+ {
+ *strp += 7;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOT12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
+ {
+ *strp += 15;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOT12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
+ {
+ *strp += 10;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
+ {
+ *strp += 18;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
+ {
+ *strp += 14;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSDESC12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_TLSMOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
+ {
+ *strp += 13;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GOTTLSOFF12,
+ &result_type, &value);
+ if (**strp != ')')
+ return "missing ')'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
}
+
+ if (**strp == '#')
+ ++*strp;
+ return cgen_parse_signed_integer (cd, strp, opindex, valuep);
}
static const char *
@@ -612,8 +901,9 @@ parse_u12 (cd, strp, opindex, valuep)
&& strncasecmp (*strp + 1, "gprel12(", 8) == 0)
{
*strp += 9;
- errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
- &result_type, &value);
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GPRELU12,
+ &result_type, &value);
if (**strp != ')')
return "missing `)'";
++*strp;
@@ -691,6 +981,38 @@ parse_even_register (cd, strP, tableP, valueP)
return errmsg;
}
+
+static const char *
+parse_call_label (CGEN_CPU_DESC cd,
+ const char **strp,
+ int opindex,
+ int opinfo,
+ enum cgen_parse_operand_result *resultp,
+ bfd_vma *valuep)
+{
+ const char *errmsg;
+ bfd_vma value;
+
+ /* Check for small data reference. */
+ if (opinfo == 0 && (**strp == '#' || **strp == '%'))
+ {
+ if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
+ {
+ *strp += 11;
+ errmsg = parse_symbolic_address (cd, strp, opindex,
+ BFD_RELOC_FRV_GETTLSOFF,
+ resultp, &value);
+ if (**strp != ')')
+ return "missing `)'";
+ ++*strp;
+ *valuep = value;
+ return errmsg;
+ }
+ }
+
+ return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
+}
+
/* -- */
const char * frv_cgen_parse_operand
@@ -878,6 +1200,9 @@ frv_cgen_parse_operand (cd, opindex, strp, fields)
case FRV_OPERAND_AE :
errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_AE, &fields->f_ae);
break;
+ case FRV_OPERAND_CALLANN :
+ errmsg = parse_call_annotation (cd, strp, FRV_OPERAND_CALLANN, &fields->f_reloc_ann);
+ break;
case FRV_OPERAND_CCOND :
errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_CCOND, &fields->f_ccond);
break;
@@ -912,10 +1237,16 @@ frv_cgen_parse_operand (cd, opindex, strp, fields)
case FRV_OPERAND_LABEL24 :
{
bfd_vma value;
- errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL24, 0, NULL, & value);
+ errmsg = parse_call_label (cd, strp, FRV_OPERAND_LABEL24, 0, NULL, & value);
fields->f_label24 = value;
}
break;
+ case FRV_OPERAND_LDANN :
+ errmsg = parse_ld_annotation (cd, strp, FRV_OPERAND_LDANN, &fields->f_reloc_ann);
+ break;
+ case FRV_OPERAND_LDDANN :
+ errmsg = parse_ldd_annotation (cd, strp, FRV_OPERAND_LDDANN, &fields->f_reloc_ann);
+ break;
case FRV_OPERAND_LOCK :
errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LOCK, &fields->f_lock);
break;
diff --git a/opcodes/frv-desc.c b/opcodes/frv-desc.c
index 91f8cca..af49bd0 100644
--- a/opcodes/frv-desc.c
+++ b/opcodes/frv-desc.c
@@ -1825,6 +1825,7 @@ const CGEN_HW_ENTRY frv_cgen_hw_table[] =
{ "h-uint", HW_H_UINT, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
{ "h-addr", HW_H_ADDR, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
{ "h-iaddr", HW_H_IADDR, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
+ { "h-reloc-ann", HW_H_RELOC_ANN, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
{ "h-pc", HW_H_PC, CGEN_ASM_NONE, 0, { 0|A(PROFILE)|A(PC), { (1<<MACH_BASE) } } },
{ "h-psr_imple", HW_H_PSR_IMPLE, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
{ "h-psr_ver", HW_H_PSR_VER, CGEN_ASM_NONE, 0, { 0, { (1<<MACH_BASE) } } },
@@ -1989,6 +1990,7 @@ const CGEN_IFLD frv_cgen_ifld_table[] =
{ FRV_F_TLBPR_NULL, "f-TLBPR-null", 0, 32, 30, 2, { 0|A(RESERVED), { (1<<MACH_BASE) } } },
{ FRV_F_LI_OFF, "f-LI-off", 0, 32, 25, 1, { 0|A(RESERVED), { (1<<MACH_BASE) } } },
{ FRV_F_LI_ON, "f-LI-on", 0, 32, 25, 1, { 0|A(RESERVED), { (1<<MACH_BASE) } } },
+ { FRV_F_RELOC_ANN, "f-reloc-ann", 0, 32, 0, 0, { 0, { (1<<MACH_BASE) } } },
{ 0, 0, 0, 0, 0, 0, {0, {0}} }
};
@@ -2279,10 +2281,6 @@ const CGEN_OPERAND frv_cgen_operand_table[] =
{ "label16", FRV_OPERAND_LABEL16, HW_H_IADDR, 15, 16,
{ 0, { (const PTR) &frv_cgen_ifld_table[FRV_F_LABEL16] } },
{ 0|A(PCREL_ADDR), { (1<<MACH_BASE) } } },
-/* label24: 26 bit pc relative address */
- { "label24", FRV_OPERAND_LABEL24, HW_H_IADDR, 17, 24,
- { 2, { (const PTR) &FRV_F_LABEL24_MULTI_IFIELD[0] } },
- { 0|A(PCREL_ADDR)|A(VIRTUAL), { (1<<MACH_BASE) } } },
/* LRAE: Load Real Address E flag */
{ "LRAE", FRV_OPERAND_LRAE, HW_H_UINT, 5, 1,
{ 0, { (const PTR) &frv_cgen_ifld_table[FRV_F_LRAE] } },
@@ -2351,6 +2349,10 @@ const CGEN_OPERAND frv_cgen_operand_table[] =
{ "uhi16", FRV_OPERAND_UHI16, HW_H_UINT, 15, 16,
{ 0, { (const PTR) &frv_cgen_ifld_table[FRV_F_U16] } },
{ 0, { (1<<MACH_BASE) } } },
+/* label24: 26 bit pc relative address */
+ { "label24", FRV_OPERAND_LABEL24, HW_H_IADDR, 17, 24,
+ { 2, { (const PTR) &FRV_F_LABEL24_MULTI_IFIELD[0] } },
+ { 0|A(PCREL_ADDR)|A(VIRTUAL), { (1<<MACH_BASE) } } },
/* psr_esr: PSR.ESR bit */
{ "psr_esr", FRV_OPERAND_PSR_ESR, HW_H_PSR_ESR, 0, 0,
{ 0, { (const PTR) 0 } },
@@ -2383,6 +2385,18 @@ const CGEN_OPERAND frv_cgen_operand_table[] =
{ "tbr_tt", FRV_OPERAND_TBR_TT, HW_H_TBR_TT, 0, 0,
{ 0, { (const PTR) 0 } },
{ 0|A(SEM_ONLY), { (1<<MACH_BASE) } } },
+/* ldann: ld annotation */
+ { "ldann", FRV_OPERAND_LDANN, HW_H_RELOC_ANN, 0, 0,
+ { 0, { (const PTR) &frv_cgen_ifld_table[FRV_F_RELOC_ANN] } },
+ { 0, { (1<<MACH_BASE) } } },
+/* lddann: ldd annotation */
+ { "lddann", FRV_OPERAND_LDDANN, HW_H_RELOC_ANN, 0, 0,
+ { 0, { (const PTR) &frv_cgen_ifld_table[FRV_F_RELOC_ANN] } },
+ { 0, { (1<<MACH_BASE) } } },
+/* callann: call annotation */
+ { "callann", FRV_OPERAND_CALLANN, HW_H_RELOC_ANN, 0, 0,
+ { 0, { (const PTR) &frv_cgen_ifld_table[FRV_F_RELOC_ANN] } },
+ { 0, { (1<<MACH_BASE) } } },
/* sentinel */
{ 0, 0, 0, 0, 0,
{ 0, { (const PTR) 0 } },
@@ -2892,7 +2906,7 @@ static const CGEN_IBASE frv_cgen_insn_table[MAX_INSNS] =
FRV_INSN_LDUH, "lduh", "lduh", 32,
{ 0, { (1<<MACH_BASE), UNIT_LOAD, FR400_MAJOR_I_2, FR450_MAJOR_I_2, FR500_MAJOR_I_2, FR550_MAJOR_I_3 } }
},
-/* ld$pack @($GRi,$GRj),$GRk */
+/* ld$pack $ldann($GRi,$GRj),$GRk */
{
FRV_INSN_LD, "ld", "ld", 32,
{ 0, { (1<<MACH_BASE), UNIT_LOAD, FR400_MAJOR_I_2, FR450_MAJOR_I_2, FR500_MAJOR_I_2, FR550_MAJOR_I_3 } }
@@ -2957,7 +2971,7 @@ static const CGEN_IBASE frv_cgen_insn_table[MAX_INSNS] =
FRV_INSN_NLDF, "nldf", "nldf", 32,
{ 0|A(FR_ACCESS)|A(NON_EXCEPTING), { (1<<MACH_SIMPLE)|(1<<MACH_TOMCAT)|(1<<MACH_FR500)|(1<<MACH_FR550)|(1<<MACH_FRV), UNIT_LOAD, FR400_MAJOR_NONE, FR450_MAJOR_NONE, FR500_MAJOR_I_2, FR550_MAJOR_I_3 } }
},
-/* ldd$pack @($GRi,$GRj),$GRdoublek */
+/* ldd$pack $lddann($GRi,$GRj),$GRdoublek */
{
FRV_INSN_LDD, "ldd", "ldd", 32,
{ 0, { (1<<MACH_BASE), UNIT_LOAD, FR400_MAJOR_I_2, FR450_MAJOR_I_2, FR500_MAJOR_I_2, FR550_MAJOR_I_3 } }
@@ -4197,7 +4211,7 @@ static const CGEN_IBASE frv_cgen_insn_table[MAX_INSNS] =
FRV_INSN_JMPL, "jmpl", "jmpl", 32,
{ 0|A(UNCOND_CTI), { (1<<MACH_BASE), UNIT_I0, FR400_MAJOR_I_5, FR450_MAJOR_I_5, FR500_MAJOR_I_5, FR550_MAJOR_I_6 } }
},
-/* calll$pack @($GRi,$GRj) */
+/* calll$pack $callann($GRi,$GRj) */
{
FRV_INSN_CALLL, "calll", "calll", 32,
{ 0|A(UNCOND_CTI), { (1<<MACH_BASE), UNIT_I0, FR400_MAJOR_I_5, FR450_MAJOR_I_5, FR500_MAJOR_I_5, FR550_MAJOR_I_6 } }
diff --git a/opcodes/frv-desc.h b/opcodes/frv-desc.h
index 4e9b446..7fe94f7 100644
--- a/opcodes/frv-desc.h
+++ b/opcodes/frv-desc.h
@@ -647,7 +647,7 @@ typedef enum ifield_type {
, FRV_F_MISC_NULL_4, FRV_F_MISC_NULL_5, FRV_F_MISC_NULL_6, FRV_F_MISC_NULL_7
, FRV_F_MISC_NULL_8, FRV_F_MISC_NULL_9, FRV_F_MISC_NULL_10, FRV_F_MISC_NULL_11
, FRV_F_LRA_NULL, FRV_F_TLBPR_NULL, FRV_F_LI_OFF, FRV_F_LI_ON
- , FRV_F_MAX
+ , FRV_F_RELOC_ANN, FRV_F_MAX
} IFIELD_TYPE;
#define MAX_IFLD ((int) FRV_F_MAX)
@@ -666,18 +666,18 @@ typedef enum cgen_hw_attr {
/* Enum declaration for frv hardware types. */
typedef enum cgen_hw_type {
HW_H_MEMORY, HW_H_SINT, HW_H_UINT, HW_H_ADDR
- , HW_H_IADDR, HW_H_PC, HW_H_PSR_IMPLE, HW_H_PSR_VER
- , HW_H_PSR_ICE, HW_H_PSR_NEM, HW_H_PSR_CM, HW_H_PSR_BE
- , HW_H_PSR_ESR, HW_H_PSR_EF, HW_H_PSR_EM, HW_H_PSR_PIL
- , HW_H_PSR_PS, HW_H_PSR_ET, HW_H_PSR_S, HW_H_TBR_TBA
- , HW_H_TBR_TT, HW_H_BPSR_BS, HW_H_BPSR_BET, HW_H_GR
- , HW_H_GR_DOUBLE, HW_H_GR_HI, HW_H_GR_LO, HW_H_FR
- , HW_H_FR_DOUBLE, HW_H_FR_INT, HW_H_FR_HI, HW_H_FR_LO
- , HW_H_FR_0, HW_H_FR_1, HW_H_FR_2, HW_H_FR_3
- , HW_H_CPR, HW_H_CPR_DOUBLE, HW_H_SPR, HW_H_ACCG
- , HW_H_ACC40S, HW_H_ACC40U, HW_H_IACC0, HW_H_ICCR
- , HW_H_FCCR, HW_H_CCCR, HW_H_PACK, HW_H_HINT_TAKEN
- , HW_H_HINT_NOT_TAKEN, HW_MAX
+ , HW_H_IADDR, HW_H_RELOC_ANN, HW_H_PC, HW_H_PSR_IMPLE
+ , HW_H_PSR_VER, HW_H_PSR_ICE, HW_H_PSR_NEM, HW_H_PSR_CM
+ , HW_H_PSR_BE, HW_H_PSR_ESR, HW_H_PSR_EF, HW_H_PSR_EM
+ , HW_H_PSR_PIL, HW_H_PSR_PS, HW_H_PSR_ET, HW_H_PSR_S
+ , HW_H_TBR_TBA, HW_H_TBR_TT, HW_H_BPSR_BS, HW_H_BPSR_BET
+ , HW_H_GR, HW_H_GR_DOUBLE, HW_H_GR_HI, HW_H_GR_LO
+ , HW_H_FR, HW_H_FR_DOUBLE, HW_H_FR_INT, HW_H_FR_HI
+ , HW_H_FR_LO, HW_H_FR_0, HW_H_FR_1, HW_H_FR_2
+ , HW_H_FR_3, HW_H_CPR, HW_H_CPR_DOUBLE, HW_H_SPR
+ , HW_H_ACCG, HW_H_ACC40S, HW_H_ACC40U, HW_H_IACC0
+ , HW_H_ICCR, HW_H_FCCR, HW_H_CCCR, HW_H_PACK
+ , HW_H_HINT_TAKEN, HW_H_HINT_NOT_TAKEN, HW_MAX
} CGEN_HW_TYPE;
#define MAX_HW ((int) HW_MAX)
@@ -712,17 +712,18 @@ typedef enum cgen_operand_type {
, FRV_OPERAND_U6, FRV_OPERAND_S5, FRV_OPERAND_COND, FRV_OPERAND_CCOND
, FRV_OPERAND_HINT, FRV_OPERAND_HINT_TAKEN, FRV_OPERAND_HINT_NOT_TAKEN, FRV_OPERAND_LI
, FRV_OPERAND_LOCK, FRV_OPERAND_DEBUG, FRV_OPERAND_AE, FRV_OPERAND_LABEL16
- , FRV_OPERAND_LABEL24, FRV_OPERAND_LRAE, FRV_OPERAND_LRAD, FRV_OPERAND_LRAS
- , FRV_OPERAND_TLBPROPX, FRV_OPERAND_TLBPRL, FRV_OPERAND_A0, FRV_OPERAND_A1
- , FRV_OPERAND_FRINTIEVEN, FRV_OPERAND_FRINTJEVEN, FRV_OPERAND_FRINTKEVEN, FRV_OPERAND_D12
- , FRV_OPERAND_S12, FRV_OPERAND_U12, FRV_OPERAND_SPR, FRV_OPERAND_ULO16
- , FRV_OPERAND_SLO16, FRV_OPERAND_UHI16, FRV_OPERAND_PSR_ESR, FRV_OPERAND_PSR_S
+ , FRV_OPERAND_LRAE, FRV_OPERAND_LRAD, FRV_OPERAND_LRAS, FRV_OPERAND_TLBPROPX
+ , FRV_OPERAND_TLBPRL, FRV_OPERAND_A0, FRV_OPERAND_A1, FRV_OPERAND_FRINTIEVEN
+ , FRV_OPERAND_FRINTJEVEN, FRV_OPERAND_FRINTKEVEN, FRV_OPERAND_D12, FRV_OPERAND_S12
+ , FRV_OPERAND_U12, FRV_OPERAND_SPR, FRV_OPERAND_ULO16, FRV_OPERAND_SLO16
+ , FRV_OPERAND_UHI16, FRV_OPERAND_LABEL24, FRV_OPERAND_PSR_ESR, FRV_OPERAND_PSR_S
, FRV_OPERAND_PSR_PS, FRV_OPERAND_PSR_ET, FRV_OPERAND_BPSR_BS, FRV_OPERAND_BPSR_BET
- , FRV_OPERAND_TBR_TBA, FRV_OPERAND_TBR_TT, FRV_OPERAND_MAX
+ , FRV_OPERAND_TBR_TBA, FRV_OPERAND_TBR_TT, FRV_OPERAND_LDANN, FRV_OPERAND_LDDANN
+ , FRV_OPERAND_CALLANN, FRV_OPERAND_MAX
} CGEN_OPERAND_TYPE;
/* Number of operands types. */
-#define MAX_OPERANDS 86
+#define MAX_OPERANDS 89
/* Maximum number of operands referenced by any insn. */
#define MAX_OPERAND_INSTANCES 8
diff --git a/opcodes/frv-dis.c b/opcodes/frv-dis.c
index 81af343..7e0ca3f 100644
--- a/opcodes/frv-dis.c
+++ b/opcodes/frv-dis.c
@@ -67,6 +67,19 @@ static void print_lo
PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
static void
+print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
+ PTR dis_info,
+ CGEN_KEYWORD *names ATTRIBUTE_UNUSED,
+ long value ATTRIBUTE_UNUSED,
+ bfd_vma pc ATTRIBUTE_UNUSED,
+ int length ATTRIBUTE_UNUSED
+ )
+{
+ disassemble_info *info = (disassemble_info *) dis_info;
+ (*info->fprintf_func) (info->stream, "@");
+}
+
+static void
print_spr (cd, dis_info, names, regno, attrs)
CGEN_CPU_DESC cd;
PTR dis_info;
@@ -307,6 +320,9 @@ frv_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
case FRV_OPERAND_AE :
print_normal (cd, info, fields->f_ae, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
break;
+ case FRV_OPERAND_CALLANN :
+ print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
+ break;
case FRV_OPERAND_CCOND :
print_normal (cd, info, fields->f_ccond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
break;
@@ -337,6 +353,12 @@ frv_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
case FRV_OPERAND_LABEL24 :
print_address (cd, info, fields->f_label24, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
break;
+ case FRV_OPERAND_LDANN :
+ print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
+ break;
+ case FRV_OPERAND_LDDANN :
+ print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
+ break;
case FRV_OPERAND_LOCK :
print_normal (cd, info, fields->f_lock, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
break;
diff --git a/opcodes/frv-ibld.c b/opcodes/frv-ibld.c
index 03686f8..81aef09 100644
--- a/opcodes/frv-ibld.c
+++ b/opcodes/frv-ibld.c
@@ -731,6 +731,9 @@ frv_cgen_insert_operand (cd, opindex, fields, buffer, pc)
case FRV_OPERAND_AE :
errmsg = insert_normal (cd, fields->f_ae, 0, 0, 25, 1, 32, total_length, buffer);
break;
+ case FRV_OPERAND_CALLANN :
+ errmsg = insert_normal (cd, fields->f_reloc_ann, 0, 0, 0, 0, 32, total_length, buffer);
+ break;
case FRV_OPERAND_CCOND :
errmsg = insert_normal (cd, fields->f_ccond, 0, 0, 12, 1, 32, total_length, buffer);
break;
@@ -776,6 +779,12 @@ frv_cgen_insert_operand (cd, opindex, fields, buffer, pc)
break;
}
break;
+ case FRV_OPERAND_LDANN :
+ errmsg = insert_normal (cd, fields->f_reloc_ann, 0, 0, 0, 0, 32, total_length, buffer);
+ break;
+ case FRV_OPERAND_LDDANN :
+ errmsg = insert_normal (cd, fields->f_reloc_ann, 0, 0, 0, 0, 32, total_length, buffer);
+ break;
case FRV_OPERAND_LOCK :
errmsg = insert_normal (cd, fields->f_lock, 0, 0, 25, 1, 32, total_length, buffer);
break;
@@ -1049,6 +1058,9 @@ frv_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
case FRV_OPERAND_AE :
length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 1, 32, total_length, pc, & fields->f_ae);
break;
+ case FRV_OPERAND_CALLANN :
+ length = extract_normal (cd, ex_info, insn_value, 0, 0, 0, 0, 32, total_length, pc, & fields->f_reloc_ann);
+ break;
case FRV_OPERAND_CCOND :
length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 1, 32, total_length, pc, & fields->f_ccond);
break;
@@ -1092,6 +1104,12 @@ frv_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
}
}
break;
+ case FRV_OPERAND_LDANN :
+ length = extract_normal (cd, ex_info, insn_value, 0, 0, 0, 0, 32, total_length, pc, & fields->f_reloc_ann);
+ break;
+ case FRV_OPERAND_LDDANN :
+ length = extract_normal (cd, ex_info, insn_value, 0, 0, 0, 0, 32, total_length, pc, & fields->f_reloc_ann);
+ break;
case FRV_OPERAND_LOCK :
length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 1, 32, total_length, pc, & fields->f_lock);
break;
@@ -1350,6 +1368,9 @@ frv_cgen_get_int_operand (cd, opindex, fields)
case FRV_OPERAND_AE :
value = fields->f_ae;
break;
+ case FRV_OPERAND_CALLANN :
+ value = fields->f_reloc_ann;
+ break;
case FRV_OPERAND_CCOND :
value = fields->f_ccond;
break;
@@ -1380,6 +1401,12 @@ frv_cgen_get_int_operand (cd, opindex, fields)
case FRV_OPERAND_LABEL24 :
value = fields->f_label24;
break;
+ case FRV_OPERAND_LDANN :
+ value = fields->f_reloc_ann;
+ break;
+ case FRV_OPERAND_LDDANN :
+ value = fields->f_reloc_ann;
+ break;
case FRV_OPERAND_LOCK :
value = fields->f_lock;
break;
@@ -1602,6 +1629,9 @@ frv_cgen_get_vma_operand (cd, opindex, fields)
case FRV_OPERAND_AE :
value = fields->f_ae;
break;
+ case FRV_OPERAND_CALLANN :
+ value = fields->f_reloc_ann;
+ break;
case FRV_OPERAND_CCOND :
value = fields->f_ccond;
break;
@@ -1632,6 +1662,12 @@ frv_cgen_get_vma_operand (cd, opindex, fields)
case FRV_OPERAND_LABEL24 :
value = fields->f_label24;
break;
+ case FRV_OPERAND_LDANN :
+ value = fields->f_reloc_ann;
+ break;
+ case FRV_OPERAND_LDDANN :
+ value = fields->f_reloc_ann;
+ break;
case FRV_OPERAND_LOCK :
value = fields->f_lock;
break;
@@ -1863,6 +1899,9 @@ frv_cgen_set_int_operand (cd, opindex, fields, value)
case FRV_OPERAND_AE :
fields->f_ae = value;
break;
+ case FRV_OPERAND_CALLANN :
+ fields->f_reloc_ann = value;
+ break;
case FRV_OPERAND_CCOND :
fields->f_ccond = value;
break;
@@ -1893,6 +1932,12 @@ frv_cgen_set_int_operand (cd, opindex, fields, value)
case FRV_OPERAND_LABEL24 :
fields->f_label24 = value;
break;
+ case FRV_OPERAND_LDANN :
+ fields->f_reloc_ann = value;
+ break;
+ case FRV_OPERAND_LDDANN :
+ fields->f_reloc_ann = value;
+ break;
case FRV_OPERAND_LOCK :
fields->f_lock = value;
break;
@@ -2112,6 +2157,9 @@ frv_cgen_set_vma_operand (cd, opindex, fields, value)
case FRV_OPERAND_AE :
fields->f_ae = value;
break;
+ case FRV_OPERAND_CALLANN :
+ fields->f_reloc_ann = value;
+ break;
case FRV_OPERAND_CCOND :
fields->f_ccond = value;
break;
@@ -2142,6 +2190,12 @@ frv_cgen_set_vma_operand (cd, opindex, fields, value)
case FRV_OPERAND_LABEL24 :
fields->f_label24 = value;
break;
+ case FRV_OPERAND_LDANN :
+ fields->f_reloc_ann = value;
+ break;
+ case FRV_OPERAND_LDDANN :
+ fields->f_reloc_ann = value;
+ break;
case FRV_OPERAND_LOCK :
fields->f_lock = value;
break;
diff --git a/opcodes/frv-opc.c b/opcodes/frv-opc.c
index f220799..f7d9358 100644
--- a/opcodes/frv-opc.c
+++ b/opcodes/frv-opc.c
@@ -2125,10 +2125,10 @@ static const CGEN_OPCODE frv_cgen_insn_opcode_table[MAX_INSNS] =
{ { MNEM, OP (PACK), ' ', '@', '(', OP (GRI), ',', OP (GRJ), ')', ',', OP (GRK), 0 } },
& ifmt_slass, { 0x800c0 }
},
-/* ld$pack @($GRi,$GRj),$GRk */
+/* ld$pack $ldann($GRi,$GRj),$GRk */
{
{ 0, 0, 0, 0 },
- { { MNEM, OP (PACK), ' ', '@', '(', OP (GRI), ',', OP (GRJ), ')', ',', OP (GRK), 0 } },
+ { { MNEM, OP (PACK), ' ', OP (LDANN), '(', OP (GRI), ',', OP (GRJ), ')', ',', OP (GRK), 0 } },
& ifmt_slass, { 0x80100 }
},
/* ldbf$pack @($GRi,$GRj),$FRintk */
@@ -2203,10 +2203,10 @@ static const CGEN_OPCODE frv_cgen_insn_opcode_table[MAX_INSNS] =
{ { MNEM, OP (PACK), ' ', '@', '(', OP (GRI), ',', OP (GRJ), ')', ',', OP (FRINTK), 0 } },
& ifmt_ldbf, { 0x80a80 }
},
-/* ldd$pack @($GRi,$GRj),$GRdoublek */
+/* ldd$pack $lddann($GRi,$GRj),$GRdoublek */
{
{ 0, 0, 0, 0 },
- { { MNEM, OP (PACK), ' ', '@', '(', OP (GRI), ',', OP (GRJ), ')', ',', OP (GRDOUBLEK), 0 } },
+ { { MNEM, OP (PACK), ' ', OP (LDDANN), '(', OP (GRI), ',', OP (GRJ), ')', ',', OP (GRDOUBLEK), 0 } },
& ifmt_ldd, { 0x80140 }
},
/* lddf$pack @($GRi,$GRj),$FRdoublek */
@@ -3691,10 +3691,10 @@ static const CGEN_OPCODE frv_cgen_insn_opcode_table[MAX_INSNS] =
{ { MNEM, OP (PACK), ' ', '@', '(', OP (GRI), ',', OP (GRJ), ')', 0 } },
& ifmt_jmpl, { 0x300000 }
},
-/* calll$pack @($GRi,$GRj) */
+/* calll$pack $callann($GRi,$GRj) */
{
{ 0, 0, 0, 0 },
- { { MNEM, OP (PACK), ' ', '@', '(', OP (GRI), ',', OP (GRJ), ')', 0 } },
+ { { MNEM, OP (PACK), ' ', OP (CALLANN), '(', OP (GRI), ',', OP (GRJ), ')', 0 } },
& ifmt_calll, { 0x2300000 }
},
/* jmpil$pack @($GRi,$s12) */
diff --git a/opcodes/frv-opc.h b/opcodes/frv-opc.h
index c0a52dc..8dc0954 100644
--- a/opcodes/frv-opc.h
+++ b/opcodes/frv-opc.h
@@ -366,6 +366,7 @@ struct cgen_fields
long f_TLBPR_null;
long f_LI_off;
long f_LI_on;
+ long f_reloc_ann;
};
#define CGEN_INIT_PARSE(od) \