+\f
+/* Far trampoline generation. */
+
+/* Build a 68HC12 trampoline stub. */
+static bfd_boolean
+m68hc12_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
+{
+ struct elf32_m68hc11_stub_hash_entry *stub_entry;
+ struct bfd_link_info *info;
+ struct m68hc11_elf_link_hash_table *htab;
+ asection *stub_sec;
+ bfd *stub_bfd;
+ bfd_byte *loc;
+ bfd_vma sym_value, phys_page, phys_addr;
+
+ /* Massage our args to the form they really have. */
+ stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
+ info = (struct bfd_link_info *) in_arg;
+
+ htab = m68hc11_elf_hash_table (info);
+
+ stub_sec = stub_entry->stub_sec;
+
+ /* Make a note of the offset within the stubs for this entry. */
+ stub_entry->stub_offset = stub_sec->size;
+ stub_sec->size += 7;
+ loc = stub_sec->contents + stub_entry->stub_offset;
+
+ stub_bfd = stub_sec->owner;
+
+ /* Create the trampoline call stub:
+
+ ldy #%addr(symbol)
+ call %page(symbol), __trampoline
+
+ */
+ sym_value = (stub_entry->target_value
+ + stub_entry->target_section->output_offset
+ + stub_entry->target_section->output_section->vma);
+ phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
+ phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
+
+ /* ldy #%page(sym) */
+ bfd_put_8 (stub_bfd, 0xCD, loc);
+ bfd_put_16 (stub_bfd, phys_addr, loc + 1);
+ loc += 3;
+
+ /* call %page(sym), __trampoline */
+ bfd_put_8 (stub_bfd, 0x4a, loc);
+ bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
+ bfd_put_8 (stub_bfd, phys_page, loc + 3);
+
+ return TRUE;
+}
+
+/* As above, but don't actually build the stub. Just bump offset so
+ we know stub section sizes. */
+
+static bfd_boolean
+m68hc12_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
+ void *in_arg ATTRIBUTE_UNUSED)
+{
+ struct elf32_m68hc11_stub_hash_entry *stub_entry;
+
+ /* Massage our args to the form they really have. */
+ stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
+
+ stub_entry->stub_sec->size += 7;
+ return TRUE;
+}
+
+/* Create a 68HC12 ELF linker hash table. */
+
+static struct bfd_link_hash_table *
+m68hc12_elf_bfd_link_hash_table_create (bfd *abfd)
+{
+ struct m68hc11_elf_link_hash_table *ret;
+
+ ret = m68hc11_elf_hash_table_create (abfd);
+ if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
+ return NULL;
+
+ ret->size_one_stub = m68hc12_elf_size_one_stub;
+ ret->build_one_stub = m68hc12_elf_build_one_stub;
+
+ return &ret->root.root;
+}
+\f
+static bfd_boolean
+m68hc12_elf_set_mach_from_flags (bfd *abfd)
+{
+ flagword flags = elf_elfheader (abfd)->e_flags;
+
+ switch (flags & EF_M68HC11_MACH_MASK)
+ {
+ case EF_M68HC12_MACH:
+ bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12, bfd_mach_m6812);
+ break;
+ case EF_M68HCS12_MACH:
+ bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12, bfd_mach_m6812s);
+ break;
+ case EF_M68HC11_GENERIC:
+ bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12,
+ bfd_mach_m6812_default);
+ break;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Specific sections:
+ - The .page0 is a data section that is mapped in [0x0000..0x00FF].
+ Page0 accesses are faster on the M68HC12.
+ - The .vectors is the section that represents the interrupt
+ vectors. */
+static const struct bfd_elf_special_section elf32_m68hc12_special_sections[] =
+{
+ { STRING_COMMA_LEN (".eeprom"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".page0"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".vectors"), 0, SHT_PROGBITS, SHF_ALLOC },
+ { NULL, 0, 0, 0, 0 }
+};
+\f