- /* Mark as relocation completed. */
- r = bfd_reloc_ok;
- r_type = R_M68HC11_NONE;
- break;
-
- /* The HI8 and LO8 relocs are generated by %hi(expr) %lo(expr)
- assembler directives. %hi does not support carry. */
- case R_M68HC11_HI8:
- case R_M68HC11_LO8:
- relocation = phys_addr;
- break;
-
- case R_M68HC11_24:
- /* Reloc used by 68HC12 call instruction. */
- bfd_put_16 (input_bfd, phys_addr,
- (bfd_byte*) contents + rel->r_offset);
- bfd_put_8 (input_bfd, phys_page,
- (bfd_byte*) contents + rel->r_offset + 2);
- r = bfd_reloc_ok;
- r_type = R_M68HC11_NONE;
- break;
-
- case R_M68HC11_NONE:
- r = bfd_reloc_ok;
- break;
-
- case R_M68HC11_LO16:
- /* Reloc generated by %addr(expr) gas to obtain the
- address as mapped in the memory bank window. */
- relocation = phys_addr;
- break;
-
- case R_M68HC11_PAGE:
- /* Reloc generated by %page(expr) gas to obtain the
- page number associated with the address. */
- relocation = phys_page;
- break;
-
- case R_M68HC11_16:
- /* Get virtual address of instruction having the relocation. */
- if (is_far)
- {
- const char* msg;
- char* buf;
- msg = _("Reference to the far symbol `%s' using a wrong "
- "relocation may result in incorrect execution");
- buf = alloca (strlen (msg) + strlen (name) + 10);
- sprintf (buf, msg, name);
-
- (* info->callbacks->warning)
- (info, buf, name, input_bfd, NULL, rel->r_offset);
- }
-
- /* Get virtual address of instruction having the relocation. */
- insn_addr = input_section->output_section->vma
- + input_section->output_offset
- + rel->r_offset;
-
- insn_page = m68hc11_phys_page (pinfo, insn_addr);
-
- if (m68hc11_addr_is_banked (pinfo, relocation + rel->r_addend)
- && m68hc11_addr_is_banked (pinfo, insn_addr)
- && phys_page != insn_page)
- {
- const char* msg;
- char* buf;
-
- msg = _("banked address [%lx:%04lx] (%lx) is not in the same bank "
- "as current banked address [%lx:%04lx] (%lx)");
-
- buf = alloca (strlen (msg) + 128);
- sprintf (buf, msg, phys_page, phys_addr,
- (long) (relocation + rel->r_addend),
- insn_page, m68hc11_phys_addr (pinfo, insn_addr),
- (long) (insn_addr));
- if (!((*info->callbacks->warning)
- (info, buf, name, input_bfd, input_section,
- rel->r_offset)))
- return FALSE;
- break;
- }
- if (phys_page != 0 && insn_page == 0)
- {
- const char* msg;
- char* buf;
-
- msg = _("reference to a banked address [%lx:%04lx] in the "
- "normal address space at %04lx");
-
- buf = alloca (strlen (msg) + 128);
- sprintf (buf, msg, phys_page, phys_addr, insn_addr);
- if (!((*info->callbacks->warning)
- (info, buf, name, input_bfd, input_section,
- insn_addr)))
- return FALSE;
-
- relocation = phys_addr;
- break;
- }
-
- /* If this is a banked address use the phys_addr so that
- we stay in the banked window. */
- if (m68hc11_addr_is_banked (pinfo, relocation + rel->r_addend))
- relocation = phys_addr;
- break;
- }
+ /* Mark as relocation completed. */
+ r = bfd_reloc_ok;
+ r_type = R_M68HC11_NONE;
+ break;
+
+ /* The HI8 and LO8 relocs are generated by %hi(expr) %lo(expr)
+ assembler directives. %hi does not support carry. */
+ case R_M68HC11_HI8:
+ case R_M68HC11_LO8:
+ relocation = phys_addr;
+ break;
+
+ case R_M68HC11_24:
+ /* Reloc used by 68HC12 call instruction. */
+ bfd_put_16 (input_bfd, phys_addr,
+ (bfd_byte*) contents + rel->r_offset);
+ bfd_put_8 (input_bfd, phys_page,
+ (bfd_byte*) contents + rel->r_offset + 2);
+ r = bfd_reloc_ok;
+ r_type = R_M68HC11_NONE;
+ break;
+
+ case R_M68HC11_NONE:
+ r = bfd_reloc_ok;
+ break;
+
+ case R_M68HC11_LO16:
+ /* Reloc generated by %addr(expr) gas to obtain the
+ address as mapped in the memory bank window. */
+ relocation = phys_addr;
+ break;
+
+ case R_M68HC11_PAGE:
+ /* Reloc generated by %page(expr) gas to obtain the
+ page number associated with the address. */
+ relocation = phys_page;
+ break;
+
+ case R_M68HC11_16:
+ if (is_far)
+ {
+ if (!reloc_warning (info, name, input_bfd, input_section, rel,
+ _("reference to the far symbol `%s' using a "
+ "wrong relocation may result in incorrect "
+ "execution"), name))
+ return FALSE;
+ }
+
+ /* Get virtual address of instruction having the relocation. */
+ insn_addr = input_section->output_section->vma
+ + input_section->output_offset
+ + rel->r_offset;
+
+ 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
+ {
+ if (!reloc_warning (info, name, input_bfd, input_section, rel,
+ _("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."), (long) phys_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
+ && !(e_flags & E_M68HC11_NO_BANK_WARNING))
+ {
+ if (!reloc_warning (info, name, input_bfd, input_section, rel,
+ _("banked address [%lx:%04lx] (%lx) is not "
+ "in the same bank as current banked "
+ "address [%lx:%04lx] (%lx)"),
+ (long) phys_page, (long) phys_addr,
+ (long) (relocation + rel->r_addend),
+ (long) insn_page,
+ (long) m68hc11_phys_addr (pinfo, insn_addr),
+ (long) insn_addr))
+ return FALSE;
+ break;
+ }
+
+ if (phys_page != 0 && insn_page == 0)
+ {
+ if (!reloc_warning (info, name, input_bfd, input_section, rel,
+ _("reference to a banked address [%lx:%04lx] "
+ "in the normal address space at %04lx"),
+ (long) phys_page, (long) phys_addr,
+ (long) insn_addr))
+ return FALSE;
+ relocation = phys_addr;
+ break;
+ }
+
+ /* If this is a banked address use the phys_addr so that
+ we stay in the banked window. */
+ if (m68hc11_addr_is_banked (pinfo, relocation + rel->r_addend))
+ relocation = phys_addr;
+ 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
+ {
+ if (!reloc_warning (info, name, input_bfd, input_section, rel,
+ _("S12 address (%lx) is not within "
+ "shared RAM(0x2000-0x4000), therefore "
+ "you must manually offset the address "
+ "in your code"), (long) phys_addr))
+ return FALSE;
+ break;
+ }
+ }
+ }