(root)/
binutils-2.41/
bfd/
elf32-m68hc12.c
       1  /* Motorola 68HC12-specific support for 32-bit ELF
       2     Copyright (C) 1999-2023 Free Software Foundation, Inc.
       3     Contributed by Stephane Carrez (stcarrez@nerim.fr)
       4     (Heavily copied from the D10V port by Martin Hunt (hunt@cygnus.com))
       5  
       6     This file is part of BFD, the Binary File Descriptor library.
       7  
       8     This program is free software; you can redistribute it and/or modify
       9     it under the terms of the GNU General Public License as published by
      10     the Free Software Foundation; either version 3 of the License, or
      11     (at your option) any later version.
      12  
      13     This program is distributed in the hope that it will be useful,
      14     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16     GNU General Public License for more details.
      17  
      18     You should have received a copy of the GNU General Public License
      19     along with this program; if not, write to the Free Software
      20     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      21     MA 02110-1301, USA.  */
      22  
      23  #include "sysdep.h"
      24  #include "bfd.h"
      25  #include "bfdlink.h"
      26  #include "libbfd.h"
      27  #include "elf-bfd.h"
      28  #include "elf32-m68hc1x.h"
      29  #include "elf/m68hc11.h"
      30  #include "opcode/m68hc11.h"
      31  
      32  /* Relocation functions.  */
      33  static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
      34    (bfd *, bfd_reloc_code_real_type);
      35  static bool m68hc11_info_to_howto_rel
      36    (bfd *, arelent *, Elf_Internal_Rela *);
      37  
      38  /* Trampoline generation.  */
      39  
      40  
      41  /* Use REL instead of RELA to save space */
      42  #define USE_REL	1
      43  
      44  /* The 68HC12 microcontroler has a memory bank switching system
      45     with a 16Kb window in the 64Kb address space.  The extended memory
      46     is mapped in the 16Kb window (at 0x8000).  The page register controls
      47     which 16Kb bank is mapped.  The call/rtc instructions take care of
      48     bank switching in function calls/returns.
      49  
      50     For GNU Binutils to work, we consider there is a physical memory
      51     at 0..0x0ffff and a kind of virtual memory above that.  Symbols
      52     in virtual memory have their addresses treated in a special way
      53     when disassembling and when linking.
      54  
      55     For the linker to work properly, we must always relocate the virtual
      56     memory as if it is mapped at 0x8000.  When a 16-bit relocation is
      57     made in the virtual memory, we check that it does not cross the
      58     memory bank where it is used.  This would involve a page change
      59     which would be wrong.  The 24-bit relocation is for that and it
      60     treats the address as a physical address + page number.
      61  
      62  
      63  					Banked
      64  					Address Space
      65  					|		|	Page n
      66  					+---------------+ 0x1010000
      67  					|		|
      68  					| jsr _foo	|
      69  					| ..		|	Page 3
      70  					| _foo:		|
      71  					+---------------+ 0x100C000
      72  					|		|
      73  					| call _bar	|
      74  					| ..		|	Page 2
      75  					| _bar:		|
      76  					+---------------+ 0x1008000
      77  				/------>|		|
      78  				|	| call _foo	|	Page 1
      79  				|	|		|
      80  				|	+---------------+ 0x1004000
      81        Physical			|	|		|
      82        Address Space		|	|		|	Page 0
      83  				|	|		|
      84      +-----------+ 0x00FFFF	|	+---------------+ 0x1000000
      85      |		|		|
      86      | call _foo	|		|
      87      |		|		|
      88      +-----------+ 0x00BFFF -+---/
      89      |		|	    |
      90      |		|	    |
      91      |		| 16K	    |
      92      |		|	    |
      93      +-----------+ 0x008000 -+
      94      |		|
      95      |		|
      96      =		=
      97      |		|
      98      |		|
      99      +-----------+ 0000
     100  
     101  
     102     The 'call _foo' must be relocated with page 3 and 16-bit address
     103     mapped at 0x8000.
     104  
     105     The 3-bit and 16-bit PC rel relocation is only used by 68HC12.  */
     106  static reloc_howto_type elf_m68hc11_howto_table[] = {
     107    /* This reloc does nothing.  */
     108    HOWTO (R_M68HC11_NONE,	/* type */
     109  	 0,			/* rightshift */
     110  	 0,			/* size */
     111  	 0,			/* bitsize */
     112  	 false,			/* pc_relative */
     113  	 0,			/* bitpos */
     114  	 complain_overflow_dont,/* complain_on_overflow */
     115  	 bfd_elf_generic_reloc,	/* special_function */
     116  	 "R_M68HC12_NONE",	/* name */
     117  	 false,			/* partial_inplace */
     118  	 0,			/* src_mask */
     119  	 0,			/* dst_mask */
     120  	 false),		/* pcrel_offset */
     121  
     122    /* A 8 bit absolute relocation */
     123    HOWTO (R_M68HC11_8,		/* type */
     124  	 0,			/* rightshift */
     125  	 1,			/* size */
     126  	 8,			/* bitsize */
     127  	 false,			/* pc_relative */
     128  	 0,			/* bitpos */
     129  	 complain_overflow_bitfield,	/* complain_on_overflow */
     130  	 bfd_elf_generic_reloc,	/* special_function */
     131  	 "R_M68HC12_8",		/* name */
     132  	 false,			/* partial_inplace */
     133  	 0x00ff,		/* src_mask */
     134  	 0x00ff,		/* dst_mask */
     135  	 false),		/* pcrel_offset */
     136  
     137    /* A 8 bit absolute relocation (upper address) */
     138    HOWTO (R_M68HC11_HI8,		/* type */
     139  	 8,			/* rightshift */
     140  	 1,			/* size */
     141  	 8,			/* bitsize */
     142  	 false,			/* pc_relative */
     143  	 0,			/* bitpos */
     144  	 complain_overflow_bitfield,	/* complain_on_overflow */
     145  	 bfd_elf_generic_reloc,	/* special_function */
     146  	 "R_M68HC12_HI8",	/* name */
     147  	 false,			/* partial_inplace */
     148  	 0x00ff,		/* src_mask */
     149  	 0x00ff,		/* dst_mask */
     150  	 false),		/* pcrel_offset */
     151  
     152    /* A 8 bit absolute relocation (upper address) */
     153    HOWTO (R_M68HC11_LO8,		/* type */
     154  	 0,			/* rightshift */
     155  	 1,			/* size */
     156  	 8,			/* bitsize */
     157  	 false,			/* pc_relative */
     158  	 0,			/* bitpos */
     159  	 complain_overflow_dont,	/* complain_on_overflow */
     160  	 bfd_elf_generic_reloc,	/* special_function */
     161  	 "R_M68HC12_LO8",	/* name */
     162  	 false,			/* partial_inplace */
     163  	 0x00ff,		/* src_mask */
     164  	 0x00ff,		/* dst_mask */
     165  	 false),		/* pcrel_offset */
     166  
     167    /* A 8 bit PC-rel relocation */
     168    HOWTO (R_M68HC11_PCREL_8,	/* type */
     169  	 0,			/* rightshift */
     170  	 1,			/* size */
     171  	 8,			/* bitsize */
     172  	 true,			/* pc_relative */
     173  	 0,			/* bitpos */
     174  	 complain_overflow_bitfield,	/* complain_on_overflow */
     175  	 bfd_elf_generic_reloc,	/* special_function */
     176  	 "R_M68HC12_PCREL_8",	/* name */
     177  	 false,			/* partial_inplace */
     178  	 0x00ff,		/* src_mask */
     179  	 0x00ff,		/* dst_mask */
     180  	 true),			/* pcrel_offset */
     181  
     182    /* A 16 bit absolute relocation */
     183    HOWTO (R_M68HC11_16,		/* type */
     184  	 0,			/* rightshift */
     185  	 2,			/* size */
     186  	 16,			/* bitsize */
     187  	 false,			/* pc_relative */
     188  	 0,			/* bitpos */
     189  	 complain_overflow_dont /*bitfield */ ,	/* complain_on_overflow */
     190  	 bfd_elf_generic_reloc,	/* special_function */
     191  	 "R_M68HC12_16",	/* name */
     192  	 false,			/* partial_inplace */
     193  	 0xffff,		/* src_mask */
     194  	 0xffff,		/* dst_mask */
     195  	 false),		/* pcrel_offset */
     196  
     197    /* A 32 bit absolute relocation.  This one is never used for the
     198       code relocation.  It's used by gas for -gstabs generation.  */
     199    HOWTO (R_M68HC11_32,		/* type */
     200  	 0,			/* rightshift */
     201  	 4,			/* size */
     202  	 32,			/* bitsize */
     203  	 false,			/* pc_relative */
     204  	 0,			/* bitpos */
     205  	 complain_overflow_bitfield,	/* complain_on_overflow */
     206  	 bfd_elf_generic_reloc,	/* special_function */
     207  	 "R_M68HC12_32",	/* name */
     208  	 false,			/* partial_inplace */
     209  	 0xffffffff,		/* src_mask */
     210  	 0xffffffff,		/* dst_mask */
     211  	 false),		/* pcrel_offset */
     212  
     213    /* A 3 bit absolute relocation */
     214    HOWTO (R_M68HC11_3B,		/* type */
     215  	 0,			/* rightshift */
     216  	 1,			/* size */
     217  	 3,			/* bitsize */
     218  	 false,			/* pc_relative */
     219  	 0,			/* bitpos */
     220  	 complain_overflow_bitfield,	/* complain_on_overflow */
     221  	 bfd_elf_generic_reloc,	/* special_function */
     222  	 "R_M68HC12_4B",	/* name */
     223  	 false,			/* partial_inplace */
     224  	 0x003,			/* src_mask */
     225  	 0x003,			/* dst_mask */
     226  	 false),		/* pcrel_offset */
     227  
     228    /* A 16 bit PC-rel relocation */
     229    HOWTO (R_M68HC11_PCREL_16,	/* type */
     230  	 0,			/* rightshift */
     231  	 2,			/* size */
     232  	 16,			/* bitsize */
     233  	 true,			/* pc_relative */
     234  	 0,			/* bitpos */
     235  	 complain_overflow_dont,	/* complain_on_overflow */
     236  	 bfd_elf_generic_reloc,	/* special_function */
     237  	 "R_M68HC12_PCREL_16",	/* name */
     238  	 false,			/* partial_inplace */
     239  	 0xffff,		/* src_mask */
     240  	 0xffff,		/* dst_mask */
     241  	 true),			/* pcrel_offset */
     242  
     243    /* GNU extension to record C++ vtable hierarchy */
     244    HOWTO (R_M68HC11_GNU_VTINHERIT,	/* type */
     245  	 0,			/* rightshift */
     246  	 2,			/* size */
     247  	 0,			/* bitsize */
     248  	 false,			/* pc_relative */
     249  	 0,			/* bitpos */
     250  	 complain_overflow_dont,	/* complain_on_overflow */
     251  	 NULL,			/* special_function */
     252  	 "R_M68HC11_GNU_VTINHERIT",	/* name */
     253  	 false,			/* partial_inplace */
     254  	 0,			/* src_mask */
     255  	 0,			/* dst_mask */
     256  	 false),		/* pcrel_offset */
     257  
     258    /* GNU extension to record C++ vtable member usage */
     259    HOWTO (R_M68HC11_GNU_VTENTRY,	/* type */
     260  	 0,			/* rightshift */
     261  	 2,			/* size */
     262  	 0,			/* bitsize */
     263  	 false,			/* pc_relative */
     264  	 0,			/* bitpos */
     265  	 complain_overflow_dont,	/* complain_on_overflow */
     266  	 _bfd_elf_rel_vtable_reloc_fn,	/* special_function */
     267  	 "R_M68HC11_GNU_VTENTRY",	/* name */
     268  	 false,			/* partial_inplace */
     269  	 0,			/* src_mask */
     270  	 0,			/* dst_mask */
     271  	 false),		/* pcrel_offset */
     272  
     273    /* A 24 bit relocation */
     274    HOWTO (R_M68HC11_24,		/* type */
     275  	 0,			/* rightshift */
     276  	 4,			/* size */
     277  	 24,			/* bitsize */
     278  	 false,			/* pc_relative */
     279  	 0,			/* bitpos */
     280  	 complain_overflow_dont,	/* complain_on_overflow */
     281  	 m68hc11_elf_special_reloc,	/* special_function */
     282  	 "R_M68HC12_24",	/* name */
     283  	 false,			/* partial_inplace */
     284  	 0xffffff,		/* src_mask */
     285  	 0xffffff,		/* dst_mask */
     286  	 false),		/* pcrel_offset */
     287  
     288    /* A 16-bit low relocation */
     289    HOWTO (R_M68HC11_LO16,	/* type */
     290  	 0,			/* rightshift */
     291  	 2,			/* size */
     292  	 16,			/* bitsize */
     293  	 false,			/* pc_relative */
     294  	 0,			/* bitpos */
     295  	 complain_overflow_dont,	/* complain_on_overflow */
     296  	 m68hc11_elf_special_reloc,/* special_function */
     297  	 "R_M68HC12_LO16",	/* name */
     298  	 false,			/* partial_inplace */
     299  	 0xffff,		/* src_mask */
     300  	 0xffff,		/* dst_mask */
     301  	 false),		/* pcrel_offset */
     302  
     303    /* A page relocation */
     304    HOWTO (R_M68HC11_PAGE,	/* type */
     305  	 0,			/* rightshift */
     306  	 1,			/* size */
     307  	 8,			/* bitsize */
     308  	 false,			/* pc_relative */
     309  	 0,			/* bitpos */
     310  	 complain_overflow_dont,	/* complain_on_overflow */
     311  	 m68hc11_elf_special_reloc,/* special_function */
     312  	 "R_M68HC12_PAGE",	/* name */
     313  	 false,			/* partial_inplace */
     314  	 0x00ff,		/* src_mask */
     315  	 0x00ff,		/* dst_mask */
     316  	 false),		/* pcrel_offset */
     317  
     318    EMPTY_HOWTO (14),
     319  
     320    /* A 16 bit absolute relocation.  */
     321    HOWTO (R_M68HC12_16B,		/* type */
     322  	 0,			/* rightshift */
     323  	 2,			/* size */
     324  	 16,			/* bitsize */
     325  	 false,			/* pc_relative */
     326  	 0,			/* bitpos */
     327  	 complain_overflow_bitfield,	/* complain_on_overflow */
     328  	 bfd_elf_generic_reloc,	/* special_function */
     329  	 "R_M68HC12_16B",	/* name */
     330  	 false,			/* partial_inplace */
     331  	 0xffff,		/* src_mask */
     332  	 0xffff,		/* dst_mask */
     333  	 false),		/* pcrel_offset */
     334  
     335    /* A 9 bit PC-rel relocation.  */
     336    HOWTO (R_M68HC12_PCREL_9,	/* type */
     337  	 1,			/* rightshift */
     338  	 2,			/* size */
     339  	 10,			/* bitsize (result is >>1) */
     340  	 true,			/* pc_relative */
     341  	 0,			/* bitpos */
     342  	 complain_overflow_dont,	/* complain_on_overflow */
     343  	 bfd_elf_generic_reloc,	/* special_function */
     344  	 "R_M68HC12_PCREL_9",	/* name */
     345  	 true,			/* partial_inplace */
     346  	 0xfe00,		/* src_mask */
     347  	 0x01ff,		/* dst_mask */
     348  	 true),			/* pcrel_offset */
     349  
     350    /* A 10 bit PC-rel relocation.  */
     351    HOWTO (R_M68HC12_PCREL_10,	/* type */
     352  	 1,			/* rightshift */
     353  	 2,			/* size */
     354  	 11,			/* bitsize (result is >>1) */
     355  	 true,			/* pc_relative */
     356  	 0,			/* bitpos */
     357  	 complain_overflow_dont,	/* complain_on_overflow */
     358  	 bfd_elf_generic_reloc,	/* special_function */
     359  	 "R_M68HC12_PCREL_10",	/* name */
     360  	 true,			/* partial_inplace */
     361  	 0xfc00,		/* src_mask */
     362  	 0x03ff,		/* dst_mask */
     363  	 true),			/* pcrel_offset */
     364  
     365    /* A 8 bit absolute relocation (upper address).  */
     366    HOWTO (R_M68HC12_HI8XG,		/* type */
     367  	 8,			/* rightshift */
     368  	 1,			/* size */
     369  	 8,			/* bitsize */
     370  	 false,			/* pc_relative */
     371  	 0,			/* bitpos */
     372  	 complain_overflow_bitfield,	/* complain_on_overflow */
     373  	 bfd_elf_generic_reloc,	/* special_function */
     374  	 "R_M68HC12_HI8XG",	/* name */
     375  	 false,			/* partial_inplace */
     376  	 0x00ff,		/* src_mask */
     377  	 0x00ff,		/* dst_mask */
     378  	 false),		/* pcrel_offset */
     379  
     380    /* A 8 bit absolute relocation (lower address).  */
     381    HOWTO (R_M68HC12_LO8XG,		/* type */
     382  	 8,			/* rightshift */
     383  	 1,			/* size */
     384  	 8,			/* bitsize */
     385  	 false,			/* pc_relative */
     386  	 0,			/* bitpos */
     387  	 complain_overflow_bitfield,	/* complain_on_overflow */
     388  	 bfd_elf_generic_reloc,	/* special_function */
     389  	 "R_M68HC12_LO8XG",	/* name */
     390  	 false,			/* partial_inplace */
     391  	 0x00ff,		/* src_mask */
     392  	 0x00ff,		/* dst_mask */
     393  	 false),		/* pcrel_offset */
     394  
     395    /* Mark beginning of a jump instruction (any form).  */
     396    HOWTO (R_M68HC11_RL_JUMP,	/* type */
     397  	 0,			/* rightshift */
     398  	 2,			/* size */
     399  	 0,			/* bitsize */
     400  	 false,			/* pc_relative */
     401  	 0,			/* bitpos */
     402  	 complain_overflow_dont,	/* complain_on_overflow */
     403  	 m68hc11_elf_ignore_reloc,	/* special_function */
     404  	 "R_M68HC12_RL_JUMP",	/* name */
     405  	 true,			/* partial_inplace */
     406  	 0,			/* src_mask */
     407  	 0,			/* dst_mask */
     408  	 true),			/* pcrel_offset */
     409  
     410    /* Mark beginning of Gcc relaxation group instruction.  */
     411    HOWTO (R_M68HC11_RL_GROUP,	/* type */
     412  	 0,			/* rightshift */
     413  	 2,			/* size */
     414  	 0,			/* bitsize */
     415  	 false,			/* pc_relative */
     416  	 0,			/* bitpos */
     417  	 complain_overflow_dont,	/* complain_on_overflow */
     418  	 m68hc11_elf_ignore_reloc,	/* special_function */
     419  	 "R_M68HC12_RL_GROUP",	/* name */
     420  	 true,			/* partial_inplace */
     421  	 0,			/* src_mask */
     422  	 0,			/* dst_mask */
     423  	 true),			/* pcrel_offset */
     424  };
     425  
     426  /* Map BFD reloc types to M68HC11 ELF reloc types.  */
     427  
     428  struct m68hc11_reloc_map
     429  {
     430    bfd_reloc_code_real_type bfd_reloc_val;
     431    unsigned char elf_reloc_val;
     432  };
     433  
     434  static const struct m68hc11_reloc_map m68hc11_reloc_map[] =
     435  {
     436    {BFD_RELOC_NONE, R_M68HC11_NONE,},
     437    {BFD_RELOC_8, R_M68HC11_8},
     438    {BFD_RELOC_M68HC11_HI8, R_M68HC11_HI8},
     439    {BFD_RELOC_M68HC11_LO8, R_M68HC11_LO8},
     440    {BFD_RELOC_8_PCREL, R_M68HC11_PCREL_8},
     441    {BFD_RELOC_16_PCREL, R_M68HC11_PCREL_16},
     442    {BFD_RELOC_16, R_M68HC11_16},
     443    {BFD_RELOC_32, R_M68HC11_32},
     444    {BFD_RELOC_M68HC11_3B, R_M68HC11_3B},
     445  
     446    {BFD_RELOC_VTABLE_INHERIT, R_M68HC11_GNU_VTINHERIT},
     447    {BFD_RELOC_VTABLE_ENTRY, R_M68HC11_GNU_VTENTRY},
     448  
     449    {BFD_RELOC_M68HC11_LO16, R_M68HC11_LO16},
     450    {BFD_RELOC_M68HC11_PAGE, R_M68HC11_PAGE},
     451    {BFD_RELOC_M68HC11_24, R_M68HC11_24},
     452  
     453    {BFD_RELOC_M68HC11_RL_JUMP, R_M68HC11_RL_JUMP},
     454    {BFD_RELOC_M68HC11_RL_GROUP, R_M68HC11_RL_GROUP},
     455  
     456    {BFD_RELOC_M68HC12_16B, R_M68HC12_16B},
     457  
     458    {BFD_RELOC_M68HC12_9_PCREL, R_M68HC12_PCREL_9},
     459    {BFD_RELOC_M68HC12_10_PCREL, R_M68HC12_PCREL_10},
     460    {BFD_RELOC_M68HC12_HI8XG, R_M68HC12_HI8XG},
     461    {BFD_RELOC_M68HC12_LO8XG, R_M68HC12_LO8XG},
     462  };
     463  
     464  static reloc_howto_type *
     465  bfd_elf32_bfd_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     466  				 bfd_reloc_code_real_type code)
     467  {
     468    unsigned int i;
     469  
     470    for (i = 0;
     471         i < sizeof (m68hc11_reloc_map) / sizeof (struct m68hc11_reloc_map);
     472         i++)
     473      {
     474        if (m68hc11_reloc_map[i].bfd_reloc_val == code)
     475  	return &elf_m68hc11_howto_table[m68hc11_reloc_map[i].elf_reloc_val];
     476      }
     477  
     478    return NULL;
     479  }
     480  
     481  static reloc_howto_type *
     482  bfd_elf32_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
     483  				 const char *r_name)
     484  {
     485    unsigned int i;
     486  
     487    for (i = 0;
     488         i < (sizeof (elf_m68hc11_howto_table)
     489  	    / sizeof (elf_m68hc11_howto_table[0]));
     490         i++)
     491      if (elf_m68hc11_howto_table[i].name != NULL
     492  	&& strcasecmp (elf_m68hc11_howto_table[i].name, r_name) == 0)
     493        return &elf_m68hc11_howto_table[i];
     494  
     495    return NULL;
     496  }
     497  
     498  /* Set the howto pointer for an M68HC11 ELF reloc.  */
     499  
     500  static bool
     501  m68hc11_info_to_howto_rel (bfd *abfd,
     502  			   arelent *cache_ptr, Elf_Internal_Rela *dst)
     503  {
     504    unsigned int r_type;
     505  
     506    r_type = ELF32_R_TYPE (dst->r_info);
     507    if (r_type >= (unsigned int) R_M68HC11_max)
     508      {
     509        /* xgettext:c-format */
     510        _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
     511  			  abfd, r_type);
     512        bfd_set_error (bfd_error_bad_value);
     513        return false;
     514      }
     515    cache_ptr->howto = &elf_m68hc11_howto_table[r_type];
     516    return true;
     517  }
     518  
     519  
     520  /* Far trampoline generation.  */
     521  
     522  /* Build a 68HC12 trampoline stub.  */
     523  static bool
     524  m68hc12_elf_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
     525  {
     526    struct elf32_m68hc11_stub_hash_entry *stub_entry;
     527    struct bfd_link_info *info;
     528    struct m68hc11_elf_link_hash_table *htab;
     529    asection *stub_sec;
     530    bfd *stub_bfd;
     531    bfd_byte *loc;
     532    bfd_vma sym_value, phys_page, phys_addr;
     533  
     534    /* Massage our args to the form they really have.  */
     535    stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
     536    info = (struct bfd_link_info *) in_arg;
     537  
     538    /* Fail if the target section could not be assigned to an output
     539       section.  The user should fix his linker script.  */
     540    if (stub_entry->target_section->output_section == NULL
     541        && info->non_contiguous_regions)
     542      info->callbacks->einfo (_("%F%P: Could not assign `%pA' to an output section. "
     543  			      "Retry without --enable-non-contiguous-regions.\n"),
     544  			    stub_entry->target_section);
     545  
     546    htab = m68hc11_elf_hash_table (info);
     547  
     548    stub_sec = stub_entry->stub_sec;
     549  
     550    /* Make a note of the offset within the stubs for this entry.  */
     551    stub_entry->stub_offset = stub_sec->size;
     552    stub_sec->size += 7;
     553    loc = stub_sec->contents + stub_entry->stub_offset;
     554  
     555    stub_bfd = stub_sec->owner;
     556  
     557    /* Create the trampoline call stub:
     558  
     559       ldy #%addr(symbol)
     560       call %page(symbol), __trampoline
     561  
     562    */
     563    sym_value = (stub_entry->target_value
     564  	       + stub_entry->target_section->output_offset
     565  	       + stub_entry->target_section->output_section->vma);
     566    phys_addr = m68hc11_phys_addr (&htab->pinfo, sym_value);
     567    phys_page = m68hc11_phys_page (&htab->pinfo, sym_value);
     568  
     569    /* ldy #%page(sym) */
     570    bfd_put_8 (stub_bfd, 0xCD, loc);
     571    bfd_put_16 (stub_bfd, phys_addr, loc + 1);
     572    loc += 3;
     573  
     574    /* call %page(sym), __trampoline  */
     575    bfd_put_8 (stub_bfd, 0x4a, loc);
     576    bfd_put_16 (stub_bfd, htab->pinfo.trampoline_addr, loc + 1);
     577    bfd_put_8 (stub_bfd, phys_page, loc + 3);
     578  
     579    return true;
     580  }
     581  
     582  /* As above, but don't actually build the stub.  Just bump offset so
     583     we know stub section sizes.  */
     584  
     585  static bool
     586  m68hc12_elf_size_one_stub (struct bfd_hash_entry *gen_entry,
     587  			   void *in_arg ATTRIBUTE_UNUSED)
     588  {
     589    struct elf32_m68hc11_stub_hash_entry *stub_entry;
     590  
     591    /* Massage our args to the form they really have.  */
     592    stub_entry = (struct elf32_m68hc11_stub_hash_entry *) gen_entry;
     593  
     594    stub_entry->stub_sec->size += 7;
     595    return true;
     596  }
     597  
     598  /* Create a 68HC12 ELF linker hash table.  */
     599  
     600  static struct bfd_link_hash_table *
     601  m68hc12_elf_bfd_link_hash_table_create (bfd *abfd)
     602  {
     603    struct m68hc11_elf_link_hash_table *ret;
     604  
     605    ret = m68hc11_elf_hash_table_create (abfd);
     606    if (ret == (struct m68hc11_elf_link_hash_table *) NULL)
     607      return NULL;
     608  
     609    ret->size_one_stub = m68hc12_elf_size_one_stub;
     610    ret->build_one_stub = m68hc12_elf_build_one_stub;
     611  
     612    return &ret->root.root;
     613  }
     614  
     615  static bool
     616  m68hc12_elf_set_mach_from_flags (bfd *abfd)
     617  {
     618    flagword flags = elf_elfheader (abfd)->e_flags;
     619  
     620    switch (flags & EF_M68HC11_MACH_MASK)
     621      {
     622      case EF_M68HC12_MACH:
     623        bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12, bfd_mach_m6812);
     624        break;
     625      case EF_M68HCS12_MACH:
     626        bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12, bfd_mach_m6812s);
     627        break;
     628      case EF_M68HC11_GENERIC:
     629        bfd_default_set_arch_mach (abfd, bfd_arch_m68hc12,
     630  				 bfd_mach_m6812_default);
     631        break;
     632      default:
     633        return false;
     634      }
     635    return true;
     636  }
     637  
     638  /* Specific sections:
     639     - The .page0 is a data section that is mapped in [0x0000..0x00FF].
     640       Page0 accesses are faster on the M68HC12.
     641     - The .vectors is the section that represents the interrupt
     642       vectors.  */
     643  static const struct bfd_elf_special_section elf32_m68hc12_special_sections[] =
     644  {
     645    { STRING_COMMA_LEN (".eeprom"),   0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
     646    { STRING_COMMA_LEN (".page0"),    0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
     647    { STRING_COMMA_LEN (".softregs"), 0, SHT_NOBITS,   SHF_ALLOC + SHF_WRITE },
     648    { STRING_COMMA_LEN (".vectors"),  0, SHT_PROGBITS, SHF_ALLOC },
     649    { NULL,			0,  0, 0,	     0 }
     650  };
     651  
     652  #define ELF_ARCH		bfd_arch_m68hc12
     653  #define ELF_TARGET_ID		M68HC11_ELF_DATA
     654  #define ELF_MACHINE_CODE	EM_68HC12
     655  #define ELF_MAXPAGESIZE		0x1000
     656  
     657  #define TARGET_BIG_SYM		m68hc12_elf32_vec
     658  #define TARGET_BIG_NAME		"elf32-m68hc12"
     659  
     660  #define elf_info_to_howto	NULL
     661  #define elf_info_to_howto_rel	m68hc11_info_to_howto_rel
     662  #define elf_backend_check_relocs     elf32_m68hc11_check_relocs
     663  #define elf_backend_relocate_section elf32_m68hc11_relocate_section
     664  #define elf_backend_object_p		m68hc12_elf_set_mach_from_flags
     665  #define elf_backend_can_gc_sections		1
     666  #define elf_backend_special_sections elf32_m68hc12_special_sections
     667  #define elf_backend_init_file_header     elf32_m68hc11_init_file_header
     668  #define elf_backend_add_symbol_hook  elf32_m68hc11_add_symbol_hook
     669  #define elf_backend_merge_symbol_attribute elf32_m68hc11_merge_symbol_attribute
     670  
     671  #define bfd_elf32_bfd_link_hash_table_create \
     672  				m68hc12_elf_bfd_link_hash_table_create
     673  #define bfd_elf32_bfd_merge_private_bfd_data \
     674  					_bfd_m68hc11_elf_merge_private_bfd_data
     675  #define bfd_elf32_bfd_set_private_flags	_bfd_m68hc11_elf_set_private_flags
     676  #define bfd_elf32_bfd_print_private_bfd_data \
     677  					_bfd_m68hc11_elf_print_private_bfd_data
     678  
     679  #include "elf32-target.h"