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