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