1 /* BFD back-end for Texas Instruments TMS320C80 Multimedia Video Processor (MVP). 2 Copyright 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005 3 Free Software Foundation, Inc. 4 5 Written by Fred Fish (fnf@cygnus.com) 6 7 There is nothing new under the sun. This file draws a lot on other 8 coff files. 9 10 This file is part of BFD, the Binary File Descriptor library. 11 12 This program is free software; you can redistribute it and/or modify 13 it under the terms of the GNU General Public License as published by 14 the Free Software Foundation; either version 2 of the License, or 15 (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, 51 Franklin Street - Fifth Floor, 25 Boston, MA 02110-1301, USA. */ 26 27 #include "bfd.h" 28 #include "bfdlink.h" 29 #include "sysdep.h" 30 #include "libbfd.h" 31 #ifdef _CONST 32 /* Newlib-based hosts define _CONST as a STDC-safe alias for const, 33 but to the tic80 toolchain it means something altogether different. 34 Since sysdep.h will have pulled in stdio.h and hence _ansi.h which 35 contains this definition, we must undef it before including the 36 tic80-specific definition. */ 37 #undef _CONST 38 #endif /* _CONST */ 39 #include "coff/tic80.h" 40 #include "coff/internal.h" 41 #include "libcoff.h" 42 43 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2) 44 #define COFF_ALIGN_IN_SECTION_HEADER 1 45 #define COFF_ALIGN_IN_SFLAGS 1 46 47 #define GET_SCNHDR_FLAGS H_GET_16 48 #define PUT_SCNHDR_FLAGS H_PUT_16 49 50 static void rtype2howto 51 PARAMS ((arelent *cache_ptr, struct internal_reloc *dst)); 52 static bfd_reloc_status_type ppbase_reloc 53 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 54 static bfd_reloc_status_type glob15_reloc 55 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 56 static bfd_reloc_status_type glob16_reloc 57 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 58 static bfd_reloc_status_type local16_reloc 59 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **)); 60 static bfd_boolean coff_tic80_relocate_section 61 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, 62 struct internal_reloc *, struct internal_syment *, asection **)); 63 static reloc_howto_type * coff_tic80_rtype_to_howto 64 PARAMS ((bfd *, asection *, struct internal_reloc *, 65 struct coff_link_hash_entry *, struct internal_syment *, 66 bfd_vma *)); 67 68 static reloc_howto_type tic80_howto_table[] = 69 { 70 71 HOWTO (R_RELLONG, /* type */ 72 0, /* rightshift */ 73 2, /* size (0 = byte, 1 = short, 2 = long) */ 74 32, /* bitsize */ 75 FALSE, /* pc_relative */ 76 0, /* bitpos */ 77 complain_overflow_bitfield, /* complain_on_overflow */ 78 NULL, /* special_function */ 79 "RELLONG", /* name */ 80 TRUE, /* partial_inplace */ 81 0xffffffff, /* src_mask */ 82 0xffffffff, /* dst_mask */ 83 FALSE), /* pcrel_offset */ 84 85 HOWTO (R_MPPCR, /* type */ 86 2, /* rightshift */ 87 2, /* size (0 = byte, 1 = short, 2 = long) */ 88 32, /* bitsize */ 89 TRUE, /* pc_relative */ 90 0, /* bitpos */ 91 complain_overflow_signed, /* complain_on_overflow */ 92 NULL, /* special_function */ 93 "MPPCR", /* name */ 94 TRUE, /* partial_inplace */ 95 0xffffffff, /* src_mask */ 96 0xffffffff, /* dst_mask */ 97 TRUE), /* pcrel_offset */ 98 99 HOWTO (R_ABS, /* type */ 100 0, /* rightshift */ 101 2, /* size (0 = byte, 1 = short, 2 = long) */ 102 32, /* bitsize */ 103 FALSE, /* pc_relative */ 104 0, /* bitpos */ 105 complain_overflow_bitfield, /* complain_on_overflow */ 106 NULL, /* special_function */ 107 "ABS", /* name */ 108 TRUE, /* partial_inplace */ 109 0xffffffff, /* src_mask */ 110 0xffffffff, /* dst_mask */ 111 FALSE), /* pcrel_offset */ 112 113 HOWTO (R_PPBASE, /* type */ 114 0, /* rightshift */ 115 2, /* size (0 = byte, 1 = short, 2 = long) */ 116 32, /* bitsize */ 117 FALSE, /* pc_relative */ 118 0, /* bitpos */ 119 complain_overflow_dont, /* complain_on_overflow */ 120 ppbase_reloc, /* special_function */ 121 "PPBASE", /* name */ 122 TRUE, /* partial_inplace */ 123 0xffffffff, /* src_mask */ 124 0xffffffff, /* dst_mask */ 125 FALSE), /* pcrel_offset */ 126 127 HOWTO (R_PPLBASE, /* type */ 128 0, /* rightshift */ 129 2, /* size (0 = byte, 1 = short, 2 = long) */ 130 32, /* bitsize */ 131 FALSE, /* pc_relative */ 132 0, /* bitpos */ 133 complain_overflow_dont, /* complain_on_overflow */ 134 ppbase_reloc, /* special_function */ 135 "PPLBASE", /* name */ 136 TRUE, /* partial_inplace */ 137 0xffffffff, /* src_mask */ 138 0xffffffff, /* dst_mask */ 139 FALSE), /* pcrel_offset */ 140 141 HOWTO (R_PP15, /* type */ 142 0, /* rightshift */ 143 2, /* size (0 = byte, 1 = short, 2 = long) */ 144 15, /* bitsize */ 145 FALSE, /* pc_relative */ 146 6, /* bitpos */ 147 complain_overflow_dont, /* complain_on_overflow */ 148 glob15_reloc, /* special_function */ 149 "PP15", /* name */ 150 TRUE, /* partial_inplace */ 151 0x1ffc0, /* src_mask */ 152 0x1ffc0, /* dst_mask */ 153 FALSE), /* pcrel_offset */ 154 155 HOWTO (R_PP15W, /* type */ 156 2, /* rightshift */ 157 2, /* size (0 = byte, 1 = short, 2 = long) */ 158 15, /* bitsize */ 159 FALSE, /* pc_relative */ 160 6, /* bitpos */ 161 complain_overflow_dont, /* complain_on_overflow */ 162 glob15_reloc, /* special_function */ 163 "PP15W", /* name */ 164 TRUE, /* partial_inplace */ 165 0x1ffc0, /* src_mask */ 166 0x1ffc0, /* dst_mask */ 167 FALSE), /* pcrel_offset */ 168 169 HOWTO (R_PP15H, /* type */ 170 1, /* rightshift */ 171 2, /* size (0 = byte, 1 = short, 2 = long) */ 172 15, /* bitsize */ 173 FALSE, /* pc_relative */ 174 6, /* bitpos */ 175 complain_overflow_dont, /* complain_on_overflow */ 176 glob15_reloc, /* special_function */ 177 "PP15H", /* name */ 178 TRUE, /* partial_inplace */ 179 0x1ffc0, /* src_mask */ 180 0x1ffc0, /* dst_mask */ 181 FALSE), /* pcrel_offset */ 182 183 HOWTO (R_PP16B, /* type */ 184 0, /* rightshift */ 185 2, /* size (0 = byte, 1 = short, 2 = long) */ 186 16, /* bitsize */ 187 FALSE, /* pc_relative */ 188 6, /* bitpos */ 189 complain_overflow_dont, /* complain_on_overflow */ 190 glob16_reloc, /* special_function */ 191 "PP16B", /* name */ 192 TRUE, /* partial_inplace */ 193 0x3ffc0, /* src_mask */ 194 0x3ffc0, /* dst_mask */ 195 FALSE), /* pcrel_offset */ 196 197 HOWTO (R_PPL15, /* type */ 198 0, /* rightshift */ 199 2, /* size (0 = byte, 1 = short, 2 = long) */ 200 15, /* bitsize */ 201 FALSE, /* pc_relative */ 202 0, /* bitpos */ 203 complain_overflow_dont, /* complain_on_overflow */ 204 NULL, /* special_function */ 205 "PPL15", /* name */ 206 TRUE, /* partial_inplace */ 207 0x7fff, /* src_mask */ 208 0x7fff, /* dst_mask */ 209 FALSE), /* pcrel_offset */ 210 211 HOWTO (R_PPL15W, /* type */ 212 2, /* rightshift */ 213 2, /* size (0 = byte, 1 = short, 2 = long) */ 214 15, /* bitsize */ 215 FALSE, /* pc_relative */ 216 0, /* bitpos */ 217 complain_overflow_dont, /* complain_on_overflow */ 218 NULL, /* special_function */ 219 "PPL15W", /* name */ 220 TRUE, /* partial_inplace */ 221 0x7fff, /* src_mask */ 222 0x7fff, /* dst_mask */ 223 FALSE), /* pcrel_offset */ 224 225 HOWTO (R_PPL15H, /* type */ 226 1, /* rightshift */ 227 2, /* size (0 = byte, 1 = short, 2 = long) */ 228 15, /* bitsize */ 229 FALSE, /* pc_relative */ 230 0, /* bitpos */ 231 complain_overflow_dont, /* complain_on_overflow */ 232 NULL, /* special_function */ 233 "PPL15H", /* name */ 234 TRUE, /* partial_inplace */ 235 0x7fff, /* src_mask */ 236 0x7fff, /* dst_mask */ 237 FALSE), /* pcrel_offset */ 238 239 HOWTO (R_PPL16B, /* type */ 240 0, /* rightshift */ 241 2, /* size (0 = byte, 1 = short, 2 = long) */ 242 16, /* bitsize */ 243 FALSE, /* pc_relative */ 244 0, /* bitpos */ 245 complain_overflow_dont, /* complain_on_overflow */ 246 local16_reloc, /* special_function */ 247 "PPL16B", /* name */ 248 TRUE, /* partial_inplace */ 249 0xffff, /* src_mask */ 250 0xffff, /* dst_mask */ 251 FALSE), /* pcrel_offset */ 252 253 HOWTO (R_PPN15, /* type */ 254 0, /* rightshift */ 255 -2, /* size (0 = byte, 1 = short, 2 = long) */ 256 15, /* bitsize */ 257 FALSE, /* pc_relative */ 258 6, /* bitpos */ 259 complain_overflow_dont, /* complain_on_overflow */ 260 glob15_reloc, /* special_function */ 261 "PPN15", /* name */ 262 TRUE, /* partial_inplace */ 263 0x1ffc0, /* src_mask */ 264 0x1ffc0, /* dst_mask */ 265 FALSE), /* pcrel_offset */ 266 267 HOWTO (R_PPN15W, /* type */ 268 2, /* rightshift */ 269 -2, /* size (0 = byte, 1 = short, 2 = long) */ 270 15, /* bitsize */ 271 FALSE, /* pc_relative */ 272 6, /* bitpos */ 273 complain_overflow_dont, /* complain_on_overflow */ 274 glob15_reloc, /* special_function */ 275 "PPN15W", /* name */ 276 TRUE, /* partial_inplace */ 277 0x1ffc0, /* src_mask */ 278 0x1ffc0, /* dst_mask */ 279 FALSE), /* pcrel_offset */ 280 281 HOWTO (R_PPN15H, /* type */ 282 1, /* rightshift */ 283 -2, /* size (0 = byte, 1 = short, 2 = long) */ 284 15, /* bitsize */ 285 FALSE, /* pc_relative */ 286 6, /* bitpos */ 287 complain_overflow_dont, /* complain_on_overflow */ 288 glob15_reloc, /* special_function */ 289 "PPN15H", /* name */ 290 TRUE, /* partial_inplace */ 291 0x1ffc0, /* src_mask */ 292 0x1ffc0, /* dst_mask */ 293 FALSE), /* pcrel_offset */ 294 295 HOWTO (R_PPN16B, /* type */ 296 0, /* rightshift */ 297 -2, /* size (0 = byte, 1 = short, 2 = long) */ 298 16, /* bitsize */ 299 FALSE, /* pc_relative */ 300 6, /* bitpos */ 301 complain_overflow_dont, /* complain_on_overflow */ 302 glob16_reloc, /* special_function */ 303 "PPN16B", /* name */ 304 TRUE, /* partial_inplace */ 305 0x3ffc0, /* src_mask */ 306 0x3ffc0, /* dst_mask */ 307 FALSE), /* pcrel_offset */ 308 309 HOWTO (R_PPLN15, /* type */ 310 0, /* rightshift */ 311 -2, /* size (0 = byte, 1 = short, 2 = long) */ 312 15, /* bitsize */ 313 FALSE, /* pc_relative */ 314 0, /* bitpos */ 315 complain_overflow_dont, /* complain_on_overflow */ 316 NULL, /* special_function */ 317 "PPLN15", /* name */ 318 TRUE, /* partial_inplace */ 319 0x7fff, /* src_mask */ 320 0x7fff, /* dst_mask */ 321 FALSE), /* pcrel_offset */ 322 323 HOWTO (R_PPLN15W, /* type */ 324 2, /* rightshift */ 325 -2, /* size (0 = byte, 1 = short, 2 = long) */ 326 15, /* bitsize */ 327 FALSE, /* pc_relative */ 328 0, /* bitpos */ 329 complain_overflow_dont, /* complain_on_overflow */ 330 NULL, /* special_function */ 331 "PPLN15W", /* name */ 332 TRUE, /* partial_inplace */ 333 0x7fff, /* src_mask */ 334 0x7fff, /* dst_mask */ 335 FALSE), /* pcrel_offset */ 336 337 HOWTO (R_PPLN15H, /* type */ 338 1, /* rightshift */ 339 -2, /* size (0 = byte, 1 = short, 2 = long) */ 340 15, /* bitsize */ 341 FALSE, /* pc_relative */ 342 0, /* bitpos */ 343 complain_overflow_dont, /* complain_on_overflow */ 344 NULL, /* special_function */ 345 "PPLN15H", /* name */ 346 TRUE, /* partial_inplace */ 347 0x7fff, /* src_mask */ 348 0x7fff, /* dst_mask */ 349 FALSE), /* pcrel_offset */ 350 351 HOWTO (R_PPLN16B, /* type */ 352 0, /* rightshift */ 353 -2, /* size (0 = byte, 1 = short, 2 = long) */ 354 15, /* bitsize */ 355 FALSE, /* pc_relative */ 356 0, /* bitpos */ 357 complain_overflow_dont, /* complain_on_overflow */ 358 local16_reloc, /* special_function */ 359 "PPLN16B", /* name */ 360 TRUE, /* partial_inplace */ 361 0xffff, /* src_mask */ 362 0xffff, /* dst_mask */ 363 FALSE) /* pcrel_offset */ 364 }; 365 366 /* Special relocation functions, used when the output file is not 367 itself a COFF TIc80 file. */ 368 369 /* This special function is used for the base address type 370 relocations. */ 371 372 static bfd_reloc_status_type 373 ppbase_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, 374 error_message) 375 bfd *abfd ATTRIBUTE_UNUSED; 376 arelent *reloc_entry ATTRIBUTE_UNUSED; 377 asymbol *symbol_in ATTRIBUTE_UNUSED; 378 PTR data ATTRIBUTE_UNUSED; 379 asection *input_section ATTRIBUTE_UNUSED; 380 bfd *output_bfd ATTRIBUTE_UNUSED; 381 char **error_message ATTRIBUTE_UNUSED; 382 { 383 /* FIXME. */ 384 abort (); 385 } 386 387 /* This special function is used for the global 15 bit relocations. */ 388 389 static bfd_reloc_status_type 390 glob15_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, 391 error_message) 392 bfd *abfd ATTRIBUTE_UNUSED; 393 arelent *reloc_entry ATTRIBUTE_UNUSED; 394 asymbol *symbol_in ATTRIBUTE_UNUSED; 395 PTR data ATTRIBUTE_UNUSED; 396 asection *input_section ATTRIBUTE_UNUSED; 397 bfd *output_bfd ATTRIBUTE_UNUSED; 398 char **error_message ATTRIBUTE_UNUSED; 399 { 400 /* FIXME. */ 401 abort (); 402 } 403 404 /* This special function is used for the global 16 bit relocations. */ 405 406 static bfd_reloc_status_type 407 glob16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, 408 error_message) 409 bfd *abfd ATTRIBUTE_UNUSED; 410 arelent *reloc_entry ATTRIBUTE_UNUSED; 411 asymbol *symbol_in ATTRIBUTE_UNUSED; 412 PTR data ATTRIBUTE_UNUSED; 413 asection *input_section ATTRIBUTE_UNUSED; 414 bfd *output_bfd ATTRIBUTE_UNUSED; 415 char **error_message ATTRIBUTE_UNUSED; 416 { 417 /* FIXME. */ 418 abort (); 419 } 420 421 /* This special function is used for the local 16 bit relocations. */ 422 423 static bfd_reloc_status_type 424 local16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, 425 error_message) 426 bfd *abfd ATTRIBUTE_UNUSED; 427 arelent *reloc_entry ATTRIBUTE_UNUSED; 428 asymbol *symbol_in ATTRIBUTE_UNUSED; 429 PTR data ATTRIBUTE_UNUSED; 430 asection *input_section ATTRIBUTE_UNUSED; 431 bfd *output_bfd ATTRIBUTE_UNUSED; 432 char **error_message ATTRIBUTE_UNUSED; 433 { 434 /* FIXME. */ 435 abort (); 436 } 437 438 /* Code to turn an external r_type into a pointer to an entry in the howto_table. 439 If passed an r_type we don't recognize the abort rather than silently failing 440 to generate an output file. */ 441 442 static void 443 rtype2howto (cache_ptr, dst) 444 arelent *cache_ptr; 445 struct internal_reloc *dst; 446 { 447 unsigned int i; 448 449 for (i = 0; i < sizeof tic80_howto_table / sizeof tic80_howto_table[0]; i++) 450 { 451 if (tic80_howto_table[i].type == dst->r_type) 452 { 453 cache_ptr->howto = tic80_howto_table + i; 454 return; 455 } 456 } 457 458 (*_bfd_error_handler) (_("Unrecognized reloc type 0x%x"), 459 (unsigned int) dst->r_type); 460 cache_ptr->howto = tic80_howto_table + 0; 461 } 462 463 #define RTYPE2HOWTO(cache_ptr, dst) rtype2howto (cache_ptr, dst) 464 #define coff_rtype_to_howto coff_tic80_rtype_to_howto 465 466 static reloc_howto_type * 467 coff_tic80_rtype_to_howto (abfd, sec, rel, h, sym, addendp) 468 bfd *abfd ATTRIBUTE_UNUSED; 469 asection *sec; 470 struct internal_reloc *rel; 471 struct coff_link_hash_entry *h ATTRIBUTE_UNUSED; 472 struct internal_syment *sym ATTRIBUTE_UNUSED; 473 bfd_vma *addendp; 474 { 475 arelent genrel; 476 477 if (rel -> r_symndx == -1 && addendp != NULL) 478 { 479 /* This is a TI "internal relocation", which means that the relocation 480 amount is the amount by which the current section is being relocated 481 in the output section. */ 482 *addendp = (sec -> output_section -> vma + sec -> output_offset) - sec -> vma; 483 } 484 RTYPE2HOWTO (&genrel, rel); 485 return genrel.howto; 486 } 487 488 #ifndef BADMAG 489 #define BADMAG(x) TIC80BADMAG(x) 490 #endif 491 492 #define coff_relocate_section coff_tic80_relocate_section 493 494 /* We need a special relocation routine to handle the PP relocs. Most 495 of this is a copy of _bfd_coff_generic_relocate_section. */ 496 497 static bfd_boolean 498 coff_tic80_relocate_section (output_bfd, info, input_bfd, 499 input_section, contents, relocs, syms, 500 sections) 501 bfd *output_bfd; 502 struct bfd_link_info *info; 503 bfd *input_bfd; 504 asection *input_section; 505 bfd_byte *contents; 506 struct internal_reloc *relocs; 507 struct internal_syment *syms; 508 asection **sections; 509 { 510 struct internal_reloc *rel; 511 struct internal_reloc *relend; 512 513 rel = relocs; 514 relend = rel + input_section->reloc_count; 515 for (; rel < relend; rel++) 516 { 517 long symndx; 518 struct coff_link_hash_entry *h; 519 struct internal_syment *sym; 520 bfd_vma addend; 521 bfd_vma val; 522 reloc_howto_type *howto; 523 bfd_reloc_status_type rstat; 524 bfd_vma addr; 525 526 symndx = rel->r_symndx; 527 528 if (symndx == -1) 529 { 530 h = NULL; 531 sym = NULL; 532 } 533 else 534 { 535 h = obj_coff_sym_hashes (input_bfd)[symndx]; 536 sym = syms + symndx; 537 } 538 539 /* COFF treats common symbols in one of two ways. Either the 540 size of the symbol is included in the section contents, or it 541 is not. We assume that the size is not included, and force 542 the rtype_to_howto function to adjust the addend as needed. */ 543 544 if (sym != NULL && sym->n_scnum != 0) 545 addend = - sym->n_value; 546 else 547 addend = 0; 548 549 howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h, 550 sym, &addend); 551 if (howto == NULL) 552 return FALSE; 553 554 val = 0; 555 556 if (h == NULL) 557 { 558 asection *sec; 559 560 if (symndx == -1) 561 { 562 sec = bfd_abs_section_ptr; 563 val = 0; 564 } 565 else 566 { 567 sec = sections[symndx]; 568 val = (sec->output_section->vma 569 + sec->output_offset 570 + sym->n_value); 571 if (! obj_pe (output_bfd)) 572 val -= sec->vma; 573 } 574 } 575 else 576 { 577 if (h->root.type == bfd_link_hash_defined 578 || h->root.type == bfd_link_hash_defweak) 579 { 580 asection *sec; 581 582 sec = h->root.u.def.section; 583 val = (h->root.u.def.value 584 + sec->output_section->vma 585 + sec->output_offset); 586 } 587 588 else if (! info->relocatable) 589 { 590 if (! ((*info->callbacks->undefined_symbol) 591 (info, h->root.root.string, input_bfd, input_section, 592 rel->r_vaddr - input_section->vma, TRUE))) 593 return FALSE; 594 } 595 } 596 597 addr = rel->r_vaddr - input_section->vma; 598 599 /* FIXME: This code assumes little endian, but the PP can 600 apparently be bi-endian. I don't know if the bi-endianness 601 applies to the instruction set or just to the data. */ 602 switch (howto->type) 603 { 604 default: 605 case R_ABS: 606 case R_RELLONGX: 607 case R_PPL15: 608 case R_PPL15W: 609 case R_PPL15H: 610 case R_PPLN15: 611 case R_PPLN15W: 612 case R_PPLN15H: 613 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section, 614 contents, addr, val, addend); 615 break; 616 617 case R_PP15: 618 case R_PP15W: 619 case R_PP15H: 620 case R_PPN15: 621 case R_PPN15W: 622 case R_PPN15H: 623 /* Offset the address so that we can use 4 byte relocations. */ 624 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section, 625 contents + 2, addr, val, addend); 626 break; 627 628 case R_PP16B: 629 case R_PPN16B: 630 { 631 /* The most significant bit is stored in bit 6. */ 632 bfd_byte hold; 633 634 hold = contents[addr + 4]; 635 contents[addr + 4] &=~ 0x20; 636 contents[addr + 4] |= (contents[addr] >> 1) & 0x20; 637 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section, 638 contents + 2, addr, 639 val, addend); 640 contents[addr] &=~ 0x40; 641 contents[addr] |= (contents[addr + 4] << 1) & 0x40; 642 contents[addr + 4] &=~ 0x20; 643 contents[addr + 4] |= hold & 0x20; 644 break; 645 } 646 647 case R_PPL16B: 648 case R_PPLN16B: 649 { 650 /* The most significant bit is stored in bit 28. */ 651 bfd_byte hold; 652 653 hold = contents[addr + 1]; 654 contents[addr + 1] &=~ 0x80; 655 contents[addr + 1] |= (contents[addr + 3] << 3) & 0x80; 656 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section, 657 contents, addr, 658 val, addend); 659 contents[addr + 3] &= ~0x10; 660 contents[addr + 3] |= (contents[addr + 1] >> 3) & 0x10; 661 contents[addr + 1] &=~ 0x80; 662 contents[addr + 1] |= hold & 0x80; 663 break; 664 } 665 666 case R_PPBASE: 667 /* Parameter RAM is from 0x1000000 to 0x1000800. */ 668 contents[addr] &=~ 0x3; 669 if (val >= 0x1000000 && val < 0x1000800) 670 contents[addr] |= 0x3; 671 else 672 contents[addr] |= 0x2; 673 rstat = bfd_reloc_ok; 674 break; 675 676 case R_PPLBASE: 677 /* Parameter RAM is from 0x1000000 to 0x1000800. */ 678 contents[addr + 2] &= ~0xc0; 679 if (val >= 0x1000000 && val < 0x1000800) 680 contents[addr + 2] |= 0xc0; 681 else 682 contents[addr + 2] |= 0x80; 683 rstat = bfd_reloc_ok; 684 break; 685 } 686 687 switch (rstat) 688 { 689 default: 690 abort (); 691 case bfd_reloc_ok: 692 break; 693 case bfd_reloc_outofrange: 694 (*_bfd_error_handler) 695 (_("%B: bad reloc address 0x%lx in section `%A'"), 696 input_bfd, input_section, (unsigned long) rel->r_vaddr); 697 return FALSE; 698 case bfd_reloc_overflow: 699 { 700 const char *name; 701 char buf[SYMNMLEN + 1]; 702 703 if (symndx == -1) 704 name = "*ABS*"; 705 else if (h != NULL) 706 name = NULL; 707 else 708 { 709 name = _bfd_coff_internal_syment_name (input_bfd, sym, buf); 710 if (name == NULL) 711 return FALSE; 712 } 713 714 if (! ((*info->callbacks->reloc_overflow) 715 (info, (h ? &h->root : NULL), name, howto->name, 716 (bfd_vma) 0, input_bfd, input_section, 717 rel->r_vaddr - input_section->vma))) 718 return FALSE; 719 } 720 } 721 } 722 return TRUE; 723 } 724 725 /* Clear the r_reserved field in relocs. */ 726 #define SWAP_OUT_RELOC_EXTRA(abfd,src,dst) \ 727 do \ 728 { \ 729 dst->r_reserved[0] = 0; \ 730 dst->r_reserved[1] = 0; \ 731 } \ 732 while (0) 733 734 #define TIC80COFF 1 /* Customize coffcode.h */ 735 #undef C_AUTOARG /* Clashes with TIc80's C_UEXT */ 736 #undef C_LASTENT /* Clashes with TIc80's C_STATLAB */ 737 #include "coffcode.h" 738 739 CREATE_LITTLE_COFF_TARGET_VEC (tic80coff_vec, "coff-tic80", D_PAGED, 0, '_', NULL, COFF_SWAP_TABLE) 740