struct m68hc11_page_info *pinfo;
const struct elf_backend_data * const ebd = get_elf_backend_data (input_bfd);
struct m68hc11_elf_link_hash_table *htab;
+ unsigned long e_flags;
symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
+ e_flags = elf_elfheader (input_bfd)->e_flags;
htab = m68hc11_elf_hash_table (info);
if (htab == NULL)
bfd_vma insn_addr;
bfd_vma insn_page;
bfd_boolean is_far = FALSE;
+ bfd_boolean is_xgate_symbol = FALSE;
+ bfd_boolean is_section_symbol = FALSE;
struct elf_link_hash_entry *h;
bfd_vma val;
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == R_M68HC11_GNU_VTENTRY
- || r_type == R_M68HC11_GNU_VTINHERIT )
+ || r_type == R_M68HC11_GNU_VTINHERIT)
continue;
(*ebd->elf_info_to_howto_rel) (input_bfd, &arel, rel);
+ sec->output_offset
+ sym->st_value);
is_far = (sym && (sym->st_other & STO_M68HC12_FAR));
+ is_xgate_symbol = (sym && (sym->st_target_internal));
+ is_section_symbol = ELF_ST_TYPE (sym->st_info) & STT_SECTION;
}
else
{
warned);
is_far = (h && (h->other & STO_M68HC12_FAR));
+ is_xgate_symbol = (h && (h->target_internal));
}
if (sec != NULL && discarded_section (sec))
a LO8XG. Does not actually check that it was a LO8XG.
Adjusts high and low bytes. */
relocation = phys_addr;
- if ((elf_elfheader (input_bfd)->e_flags & E_M68HC11_XGATE_RAMOFFSET)
+ if ((e_flags & E_M68HC11_XGATE_RAMOFFSET)
&& (relocation >= 0x2000))
relocation += 0xc000; /* HARDCODED RAM offset for XGATE. */
insn_page = m68hc11_phys_page (pinfo, insn_addr);
+ /* If we are linking an S12 instruction against an XGATE symbol, we
+ need to change the offset of the symbol value so that it's correct
+ from the S12's perspective. */
+ if (is_xgate_symbol)
+ {
+ /* The ram in the global space is mapped to 0x2000 in the 16-bit
+ address space for S12 and 0xE000 in the 16-bit address space
+ for XGATE. */
+ if (relocation >= 0xE000)
+ {
+ /* We offset the address by the difference
+ between these two mappings. */
+ relocation -= 0xC000;
+ break;
+ }
+ else
+ {
+ const char * msg;
+ char * buf;
+
+ msg = _("XGATE address (%lx) is not within shared RAM"
+ "(0xE000-0xFFFF), therefore you must manually offset "
+ "the address, and possibly manage the page, in your "
+ "code.");
+ buf = alloca (strlen (msg) + 128);
+ sprintf (buf, msg, phys_addr);
+ if (!((*info->callbacks->warning) (info, buf, name, input_bfd,
+ input_section, insn_addr)))
+ return FALSE;
+ break;
+ }
+ }
+
if (m68hc11_addr_is_banked (pinfo, relocation + rel->r_addend)
&& m68hc11_addr_is_banked (pinfo, insn_addr)
- && phys_page != insn_page)
+ && phys_page != insn_page && !(e_flags & E_M68HC11_NO_BANK_WARNING))
{
- const char* msg;
- char* buf;
+ const char * msg;
+ char * buf;
msg = _("banked address [%lx:%04lx] (%lx) is not in the same bank "
"as current banked address [%lx:%04lx] (%lx)");
return FALSE;
break;
}
+
if (phys_page != 0 && insn_page == 0)
{
- const char* msg;
- char* buf;
+ const char * msg;
+ char * buf;
msg = _("reference to a banked address [%lx:%04lx] in the "
"normal address space at %04lx");
break;
}
+ /* If we are linking an XGATE instruction against an S12 symbol, we
+ need to change the offset of the symbol value so that it's correct
+ from the XGATE's perspective. */
+ if (!strcmp (howto->name, "R_XGATE_IMM8_LO")
+ || !strcmp (howto->name, "R_XGATE_IMM8_HI"))
+ {
+ /* We can only offset S12 addresses that lie within the non-paged
+ area of RAM. */
+ if (!is_xgate_symbol && !is_section_symbol)
+ {
+ /* The ram in the global space is mapped to 0x2000 and stops at
+ 0x4000 in the 16-bit address space for S12 and 0xE000 in the
+ 16-bit address space for XGATE. */
+ if (relocation >= 0x2000 && relocation < 0x4000)
+ /* We offset the address by the difference
+ between these two mappings. */
+ relocation += 0xC000;
+ else
+ {
+ const char * msg;
+ char * buf;
+
+ /* Get virtual address of instruction having the relocation. */
+ insn_addr = input_section->output_section->vma
+ + input_section->output_offset + rel->r_offset;
+
+ msg = _("S12 address (%lx) is not within shared RAM"
+ "(0x2000-0x4000), therefore you must manually "
+ "offset the address in your code");
+ buf = alloca (strlen (msg) + 128);
+ sprintf (buf, msg, phys_addr);
+ if (!((*info->callbacks->warning) (info, buf, name, input_bfd,
+ input_section, insn_addr)))
+ return FALSE;
+ break;
+ }
+ }
+ }
+
if (r_type != R_M68HC11_NONE)
{
if ((r_type == R_M68HC12_PCREL_9) || (r_type == R_M68HC12_PCREL_10))