packaging: Enable testing infrastructure
[external/binutils.git] / bfd / coff-tic80.c
1 /* BFD back-end for Texas Instruments TMS320C80 Multimedia Video Processor (MVP).
2    Copyright (C) 1996-2019 Free Software Foundation, Inc.
3
4    Written by Fred Fish (fnf@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 #define COFF_ENCODE_ALIGNMENT(S,X) ((S).s_flags |= (((unsigned)(X) & 0xf) << 8))
46 #define COFF_DECODE_ALIGNMENT(X) (((X) >> 8) & 0xf)
47
48 #define GET_SCNHDR_FLAGS H_GET_16
49 #define PUT_SCNHDR_FLAGS H_PUT_16
50
51 static bfd_reloc_status_type ppbase_reloc
52   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
53 static bfd_reloc_status_type glob15_reloc
54   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
55 static bfd_reloc_status_type glob16_reloc
56   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
57 static bfd_reloc_status_type local16_reloc
58   (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
59
60
61 static reloc_howto_type tic80_howto_table[] =
62 {
63
64   HOWTO (R_RELLONG,                     /* type */
65          0,                             /* rightshift */
66          2,                             /* size (0 = byte, 1 = short, 2 = long) */
67          32,                            /* bitsize */
68          FALSE,                         /* pc_relative */
69          0,                             /* bitpos */
70          complain_overflow_bitfield,    /* complain_on_overflow */
71          NULL,                          /* special_function */
72          "RELLONG",                     /* name */
73          TRUE,                          /* partial_inplace */
74          0xffffffff,                    /* src_mask */
75          0xffffffff,                    /* dst_mask */
76          FALSE),                        /* pcrel_offset */
77
78   HOWTO (R_MPPCR,                       /* type */
79          2,                             /* rightshift */
80          2,                             /* size (0 = byte, 1 = short, 2 = long) */
81          32,                            /* bitsize */
82          TRUE,                          /* pc_relative */
83          0,                             /* bitpos */
84          complain_overflow_signed,      /* complain_on_overflow */
85          NULL,                          /* special_function */
86          "MPPCR",                       /* name */
87          TRUE,                          /* partial_inplace */
88          0xffffffff,                    /* src_mask */
89          0xffffffff,                    /* dst_mask */
90          TRUE),                         /* pcrel_offset */
91
92   HOWTO (R_ABS,                         /* type */
93          0,                             /* rightshift */
94          2,                             /* size (0 = byte, 1 = short, 2 = long) */
95          32,                            /* bitsize */
96          FALSE,                         /* pc_relative */
97          0,                             /* bitpos */
98          complain_overflow_bitfield,    /* complain_on_overflow */
99          NULL,                          /* special_function */
100          "ABS",                         /* name */
101          TRUE,                          /* partial_inplace */
102          0xffffffff,                    /* src_mask */
103          0xffffffff,                    /* dst_mask */
104          FALSE),                                /* pcrel_offset */
105
106   HOWTO (R_PPBASE,                      /* type */
107          0,                             /* rightshift */
108          2,                             /* size (0 = byte, 1 = short, 2 = long) */
109          32,                            /* bitsize */
110          FALSE,                         /* pc_relative */
111          0,                             /* bitpos */
112          complain_overflow_dont,        /* complain_on_overflow */
113          ppbase_reloc,                  /* special_function */
114          "PPBASE",                      /* name */
115          TRUE,                          /* partial_inplace */
116          0xffffffff,                    /* src_mask */
117          0xffffffff,                    /* dst_mask */
118          FALSE),                        /* pcrel_offset */
119
120   HOWTO (R_PPLBASE,                     /* type */
121          0,                             /* rightshift */
122          2,                             /* size (0 = byte, 1 = short, 2 = long) */
123          32,                            /* bitsize */
124          FALSE,                         /* pc_relative */
125          0,                             /* bitpos */
126          complain_overflow_dont,        /* complain_on_overflow */
127          ppbase_reloc,                  /* special_function */
128          "PPLBASE",                     /* name */
129          TRUE,                          /* partial_inplace */
130          0xffffffff,                    /* src_mask */
131          0xffffffff,                    /* dst_mask */
132          FALSE),                        /* pcrel_offset */
133
134   HOWTO (R_PP15,                        /* type */
135          0,                             /* rightshift */
136          2,                             /* size (0 = byte, 1 = short, 2 = long) */
137          15,                            /* bitsize */
138          FALSE,                         /* pc_relative */
139          6,                             /* bitpos */
140          complain_overflow_dont,        /* complain_on_overflow */
141          glob15_reloc,                  /* special_function */
142          "PP15",                        /* name */
143          TRUE,                          /* partial_inplace */
144          0x1ffc0,                       /* src_mask */
145          0x1ffc0,                       /* dst_mask */
146          FALSE),                        /* pcrel_offset */
147
148   HOWTO (R_PP15W,                       /* type */
149          2,                             /* rightshift */
150          2,                             /* size (0 = byte, 1 = short, 2 = long) */
151          15,                            /* bitsize */
152          FALSE,                         /* pc_relative */
153          6,                             /* bitpos */
154          complain_overflow_dont,        /* complain_on_overflow */
155          glob15_reloc,                  /* special_function */
156          "PP15W",                       /* name */
157          TRUE,                          /* partial_inplace */
158          0x1ffc0,                       /* src_mask */
159          0x1ffc0,                       /* dst_mask */
160          FALSE),                        /* pcrel_offset */
161
162   HOWTO (R_PP15H,                       /* type */
163          1,                             /* rightshift */
164          2,                             /* size (0 = byte, 1 = short, 2 = long) */
165          15,                            /* bitsize */
166          FALSE,                         /* pc_relative */
167          6,                             /* bitpos */
168          complain_overflow_dont,        /* complain_on_overflow */
169          glob15_reloc,                  /* special_function */
170          "PP15H",                       /* name */
171          TRUE,                          /* partial_inplace */
172          0x1ffc0,                       /* src_mask */
173          0x1ffc0,                       /* dst_mask */
174          FALSE),                        /* pcrel_offset */
175
176   HOWTO (R_PP16B,                       /* type */
177          0,                             /* rightshift */
178          2,                             /* size (0 = byte, 1 = short, 2 = long) */
179          16,                            /* bitsize */
180          FALSE,                         /* pc_relative */
181          6,                             /* bitpos */
182          complain_overflow_dont,        /* complain_on_overflow */
183          glob16_reloc,                  /* special_function */
184          "PP16B",                       /* name */
185          TRUE,                          /* partial_inplace */
186          0x3ffc0,                       /* src_mask */
187          0x3ffc0,                       /* dst_mask */
188          FALSE),                        /* pcrel_offset */
189
190   HOWTO (R_PPL15,                       /* type */
191          0,                             /* rightshift */
192          2,                             /* size (0 = byte, 1 = short, 2 = long) */
193          15,                            /* bitsize */
194          FALSE,                         /* pc_relative */
195          0,                             /* bitpos */
196          complain_overflow_dont,        /* complain_on_overflow */
197          NULL,                          /* special_function */
198          "PPL15",                       /* name */
199          TRUE,                          /* partial_inplace */
200          0x7fff,                        /* src_mask */
201          0x7fff,                        /* dst_mask */
202          FALSE),                        /* pcrel_offset */
203
204   HOWTO (R_PPL15W,                      /* type */
205          2,                             /* rightshift */
206          2,                             /* size (0 = byte, 1 = short, 2 = long) */
207          15,                            /* bitsize */
208          FALSE,                         /* pc_relative */
209          0,                             /* bitpos */
210          complain_overflow_dont,        /* complain_on_overflow */
211          NULL,                          /* special_function */
212          "PPL15W",                      /* name */
213          TRUE,                          /* partial_inplace */
214          0x7fff,                        /* src_mask */
215          0x7fff,                        /* dst_mask */
216          FALSE),                        /* pcrel_offset */
217
218   HOWTO (R_PPL15H,                      /* type */
219          1,                             /* rightshift */
220          2,                             /* size (0 = byte, 1 = short, 2 = long) */
221          15,                            /* bitsize */
222          FALSE,                         /* pc_relative */
223          0,                             /* bitpos */
224          complain_overflow_dont,        /* complain_on_overflow */
225          NULL,                          /* special_function */
226          "PPL15H",                      /* name */
227          TRUE,                          /* partial_inplace */
228          0x7fff,                        /* src_mask */
229          0x7fff,                        /* dst_mask */
230          FALSE),                        /* pcrel_offset */
231
232   HOWTO (R_PPL16B,                      /* type */
233          0,                             /* rightshift */
234          2,                             /* size (0 = byte, 1 = short, 2 = long) */
235          16,                            /* bitsize */
236          FALSE,                         /* pc_relative */
237          0,                             /* bitpos */
238          complain_overflow_dont,        /* complain_on_overflow */
239          local16_reloc,                 /* special_function */
240          "PPL16B",                      /* name */
241          TRUE,                          /* partial_inplace */
242          0xffff,                        /* src_mask */
243          0xffff,                        /* dst_mask */
244          FALSE),                        /* pcrel_offset */
245
246   HOWTO (R_PPN15,                       /* type */
247          0,                             /* rightshift */
248          -2,                            /* size (0 = byte, 1 = short, 2 = long) */
249          15,                            /* bitsize */
250          FALSE,                         /* pc_relative */
251          6,                             /* bitpos */
252          complain_overflow_dont,        /* complain_on_overflow */
253          glob15_reloc,                  /* special_function */
254          "PPN15",                       /* name */
255          TRUE,                          /* partial_inplace */
256          0x1ffc0,                       /* src_mask */
257          0x1ffc0,                       /* dst_mask */
258          FALSE),                        /* pcrel_offset */
259
260   HOWTO (R_PPN15W,                      /* type */
261          2,                             /* rightshift */
262          -2,                            /* size (0 = byte, 1 = short, 2 = long) */
263          15,                            /* bitsize */
264          FALSE,                         /* pc_relative */
265          6,                             /* bitpos */
266          complain_overflow_dont,        /* complain_on_overflow */
267          glob15_reloc,                  /* special_function */
268          "PPN15W",                      /* name */
269          TRUE,                          /* partial_inplace */
270          0x1ffc0,                       /* src_mask */
271          0x1ffc0,                       /* dst_mask */
272          FALSE),                        /* pcrel_offset */
273
274   HOWTO (R_PPN15H,                      /* type */
275          1,                             /* rightshift */
276          -2,                            /* size (0 = byte, 1 = short, 2 = long) */
277          15,                            /* bitsize */
278          FALSE,                         /* pc_relative */
279          6,                             /* bitpos */
280          complain_overflow_dont,        /* complain_on_overflow */
281          glob15_reloc,                  /* special_function */
282          "PPN15H",                      /* name */
283          TRUE,                          /* partial_inplace */
284          0x1ffc0,                       /* src_mask */
285          0x1ffc0,                       /* dst_mask */
286          FALSE),                        /* pcrel_offset */
287
288   HOWTO (R_PPN16B,                      /* type */
289          0,                             /* rightshift */
290          -2,                            /* size (0 = byte, 1 = short, 2 = long) */
291          16,                            /* bitsize */
292          FALSE,                         /* pc_relative */
293          6,                             /* bitpos */
294          complain_overflow_dont,        /* complain_on_overflow */
295          glob16_reloc,                  /* special_function */
296          "PPN16B",                      /* name */
297          TRUE,                          /* partial_inplace */
298          0x3ffc0,                       /* src_mask */
299          0x3ffc0,                       /* dst_mask */
300          FALSE),                        /* pcrel_offset */
301
302   HOWTO (R_PPLN15,                      /* type */
303          0,                             /* rightshift */
304          -2,                            /* size (0 = byte, 1 = short, 2 = long) */
305          15,                            /* bitsize */
306          FALSE,                         /* pc_relative */
307          0,                             /* bitpos */
308          complain_overflow_dont,        /* complain_on_overflow */
309          NULL,                          /* special_function */
310          "PPLN15",                      /* name */
311          TRUE,                          /* partial_inplace */
312          0x7fff,                        /* src_mask */
313          0x7fff,                        /* dst_mask */
314          FALSE),                        /* pcrel_offset */
315
316   HOWTO (R_PPLN15W,                     /* type */
317          2,                             /* rightshift */
318          -2,                            /* size (0 = byte, 1 = short, 2 = long) */
319          15,                            /* bitsize */
320          FALSE,                         /* pc_relative */
321          0,                             /* bitpos */
322          complain_overflow_dont,        /* complain_on_overflow */
323          NULL,                          /* special_function */
324          "PPLN15W",                     /* name */
325          TRUE,                          /* partial_inplace */
326          0x7fff,                        /* src_mask */
327          0x7fff,                        /* dst_mask */
328          FALSE),                        /* pcrel_offset */
329
330   HOWTO (R_PPLN15H,                     /* type */
331          1,                             /* rightshift */
332          -2,                            /* size (0 = byte, 1 = short, 2 = long) */
333          15,                            /* bitsize */
334          FALSE,                         /* pc_relative */
335          0,                             /* bitpos */
336          complain_overflow_dont,        /* complain_on_overflow */
337          NULL,                          /* special_function */
338          "PPLN15H",                     /* name */
339          TRUE,                          /* partial_inplace */
340          0x7fff,                        /* src_mask */
341          0x7fff,                        /* dst_mask */
342          FALSE),                        /* pcrel_offset */
343
344   HOWTO (R_PPLN16B,                     /* type */
345          0,                             /* rightshift */
346          -2,                            /* size (0 = byte, 1 = short, 2 = long) */
347          15,                            /* bitsize */
348          FALSE,                         /* pc_relative */
349          0,                             /* bitpos */
350          complain_overflow_dont,        /* complain_on_overflow */
351          local16_reloc,                 /* special_function */
352          "PPLN16B",                     /* name */
353          TRUE,                          /* partial_inplace */
354          0xffff,                        /* src_mask */
355          0xffff,                        /* dst_mask */
356          FALSE)                         /* pcrel_offset */
357 };
358 \f
359 /* Special relocation functions, used when the output file is not
360    itself a COFF TIc80 file.  */
361
362 /* This special function is used for the base address type
363    relocations.  */
364
365 static bfd_reloc_status_type
366 ppbase_reloc (bfd *abfd ATTRIBUTE_UNUSED,
367               arelent *reloc_entry ATTRIBUTE_UNUSED,
368               asymbol *symbol_in ATTRIBUTE_UNUSED,
369               void * data ATTRIBUTE_UNUSED,
370               asection *input_section ATTRIBUTE_UNUSED,
371               bfd *output_bfd ATTRIBUTE_UNUSED,
372               char **error_message ATTRIBUTE_UNUSED)
373 {
374   /* FIXME.  */
375   abort ();
376 }
377
378 /* This special function is used for the global 15 bit relocations.  */
379
380 static bfd_reloc_status_type
381 glob15_reloc (bfd *abfd ATTRIBUTE_UNUSED,
382               arelent *reloc_entry ATTRIBUTE_UNUSED,
383               asymbol *symbol_in ATTRIBUTE_UNUSED,
384               void * data ATTRIBUTE_UNUSED,
385               asection *input_section ATTRIBUTE_UNUSED,
386               bfd *output_bfd ATTRIBUTE_UNUSED,
387               char **error_message ATTRIBUTE_UNUSED)
388 {
389   /* FIXME.  */
390   abort ();
391 }
392
393 /* This special function is used for the global 16 bit relocations.  */
394
395 static bfd_reloc_status_type
396 glob16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
397               arelent *reloc_entry ATTRIBUTE_UNUSED,
398               asymbol *symbol_in ATTRIBUTE_UNUSED,
399               void * data ATTRIBUTE_UNUSED,
400               asection *input_section ATTRIBUTE_UNUSED,
401               bfd *output_bfd ATTRIBUTE_UNUSED,
402               char **error_message ATTRIBUTE_UNUSED)
403 {
404   /* FIXME.  */
405   abort ();
406 }
407
408 /* This special function is used for the local 16 bit relocations.  */
409
410 static bfd_reloc_status_type
411 local16_reloc (bfd *abfd ATTRIBUTE_UNUSED,
412                arelent *reloc_entry ATTRIBUTE_UNUSED,
413                asymbol *symbol_in ATTRIBUTE_UNUSED,
414                void * data ATTRIBUTE_UNUSED,
415                asection *input_section ATTRIBUTE_UNUSED,
416                bfd *output_bfd ATTRIBUTE_UNUSED,
417                char **error_message ATTRIBUTE_UNUSED)
418 {
419   /* FIXME.  */
420   abort ();
421 }
422 \f
423 /* 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 (_("unsupported relocation type %#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 \f
474 #define coff_relocate_section coff_tic80_relocate_section
475
476 /* We need a special relocation routine to handle the PP relocs.  Most
477    of this is a copy of _bfd_coff_generic_relocate_section.  */
478
479 static bfd_boolean
480 coff_tic80_relocate_section (bfd *output_bfd,
481                              struct bfd_link_info *info,
482                              bfd *input_bfd,
483                              asection *input_section,
484                              bfd_byte *contents,
485                              struct internal_reloc *relocs,
486                              struct internal_syment *syms,
487                              asection **sections)
488 {
489   struct internal_reloc *rel;
490   struct internal_reloc *relend;
491
492   rel = relocs;
493   relend = rel + input_section->reloc_count;
494   for (; rel < relend; rel++)
495     {
496       long symndx;
497       struct coff_link_hash_entry *h;
498       struct internal_syment *sym;
499       bfd_vma addend;
500       bfd_vma val;
501       reloc_howto_type *howto;
502       bfd_reloc_status_type rstat;
503       bfd_vma addr;
504
505       symndx = rel->r_symndx;
506
507       if (symndx == -1)
508         {
509           h = NULL;
510           sym = NULL;
511         }
512       else
513         {
514           h = obj_coff_sym_hashes (input_bfd)[symndx];
515           sym = syms + symndx;
516         }
517
518       /* COFF treats common symbols in one of two ways.  Either the
519          size of the symbol is included in the section contents, or it
520          is not.  We assume that the size is not included, and force
521          the rtype_to_howto function to adjust the addend as needed.  */
522
523       if (sym != NULL && sym->n_scnum != 0)
524         addend = - sym->n_value;
525       else
526         addend = 0;
527
528       howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
529                                        sym, &addend);
530       if (howto == NULL)
531         return FALSE;
532
533       val = 0;
534
535       if (h == NULL)
536         {
537           asection *sec;
538
539           if (symndx == -1)
540             {
541               sec = bfd_abs_section_ptr;
542               val = 0;
543             }
544           else
545             {
546               sec = sections[symndx];
547               val = (sec->output_section->vma
548                      + sec->output_offset
549                      + sym->n_value);
550               if (! obj_pe (output_bfd))
551                 val -= sec->vma;
552             }
553         }
554       else
555         {
556           if (h->root.type == bfd_link_hash_defined
557               || h->root.type == bfd_link_hash_defweak)
558             {
559               asection *sec;
560
561               sec = h->root.u.def.section;
562               val = (h->root.u.def.value
563                      + sec->output_section->vma
564                      + sec->output_offset);
565               }
566
567           else if (! bfd_link_relocatable (info))
568             (*info->callbacks->undefined_symbol)
569               (info, h->root.root.string, input_bfd, input_section,
570                rel->r_vaddr - input_section->vma, TRUE);
571         }
572
573       addr = rel->r_vaddr - input_section->vma;
574
575       /* FIXME: This code assumes little endian, but the PP can
576          apparently be bi-endian.  I don't know if the bi-endianness
577          applies to the instruction set or just to the data.  */
578       switch (howto->type)
579         {
580         default:
581         case R_ABS:
582         case R_RELLONGX:
583         case R_PPL15:
584         case R_PPL15W:
585         case R_PPL15H:
586         case R_PPLN15:
587         case R_PPLN15W:
588         case R_PPLN15H:
589           rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
590                                             contents, addr, val, addend);
591           break;
592
593         case R_PP15:
594         case R_PP15W:
595         case R_PP15H:
596         case R_PPN15:
597         case R_PPN15W:
598         case R_PPN15H:
599           /* Offset the address so that we can use 4 byte relocations.  */
600           rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
601                                             contents + 2, addr, val, addend);
602           break;
603
604         case R_PP16B:
605         case R_PPN16B:
606           {
607             /* The most significant bit is stored in bit 6.  */
608             bfd_byte hold;
609
610             hold = contents[addr + 4];
611             contents[addr + 4] &=~ 0x20;
612             contents[addr + 4] |= (contents[addr] >> 1) & 0x20;
613             rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
614                                               contents + 2, addr,
615                                               val, addend);
616             contents[addr] &=~ 0x40;
617             contents[addr] |= (contents[addr + 4] << 1) & 0x40;
618             contents[addr + 4] &=~ 0x20;
619             contents[addr + 4] |= hold & 0x20;
620             break;
621           }
622
623         case R_PPL16B:
624         case R_PPLN16B:
625           {
626             /* The most significant bit is stored in bit 28.  */
627             bfd_byte hold;
628
629             hold = contents[addr + 1];
630             contents[addr + 1] &=~ 0x80;
631             contents[addr + 1] |= (contents[addr + 3] << 3) & 0x80;
632             rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
633                                               contents, addr,
634                                               val, addend);
635             contents[addr + 3] &= ~0x10;
636             contents[addr + 3] |= (contents[addr + 1] >> 3) & 0x10;
637             contents[addr + 1] &=~ 0x80;
638             contents[addr + 1] |= hold & 0x80;
639             break;
640           }
641
642         case R_PPBASE:
643           /* Parameter RAM is from 0x1000000 to 0x1000800.  */
644           contents[addr] &=~ 0x3;
645           if (val >= 0x1000000 && val < 0x1000800)
646             contents[addr] |= 0x3;
647           else
648             contents[addr] |= 0x2;
649           rstat = bfd_reloc_ok;
650           break;
651
652         case R_PPLBASE:
653           /* Parameter RAM is from 0x1000000 to 0x1000800.  */
654           contents[addr + 2] &= ~0xc0;
655           if (val >= 0x1000000 && val < 0x1000800)
656             contents[addr + 2] |= 0xc0;
657           else
658             contents[addr + 2] |= 0x80;
659           rstat = bfd_reloc_ok;
660           break;
661         }
662
663       switch (rstat)
664         {
665         default:
666           abort ();
667         case bfd_reloc_ok:
668           break;
669         case bfd_reloc_outofrange:
670           _bfd_error_handler
671             /* xgettext: c-format */
672             (_("%pB: bad reloc address %#" PRIx64 " in section `%pA'"),
673              input_bfd, (uint64_t) rel->r_vaddr, input_section);
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 \f
701 #define TIC80COFF 1             /* Customize coffcode.h */
702 #undef C_AUTOARG                /* Clashes with TIc80's C_UEXT */
703 #undef C_LASTENT                /* Clashes with TIc80's C_STATLAB */
704
705 #ifndef bfd_pe_print_pdata
706 #define bfd_pe_print_pdata      NULL
707 #endif
708
709 #include "coffcode.h"
710
711 CREATE_LITTLE_COFF_TARGET_VEC (tic80_coff_vec, "coff-tic80", D_PAGED, 0, '_', NULL, COFF_SWAP_TABLE)