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