Touches most files in bfd/, so likely will be blamed for everything..
[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 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 2 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, 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA.  */
25
26 #include "bfd.h"
27 #include "bfdlink.h"
28 #include "sysdep.h"
29 #include "libbfd.h"
30 #include "coff/tic80.h"
31 #include "coff/internal.h"
32 #include "libcoff.h"
33
34 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
35 #define COFF_ALIGN_IN_SECTION_HEADER 1
36 #define COFF_ALIGN_IN_SFLAGS 1
37
38 #define GET_SCNHDR_FLAGS H_GET_16
39 #define PUT_SCNHDR_FLAGS H_PUT_16
40
41 static void rtype2howto
42   PARAMS ((arelent *cache_ptr, struct internal_reloc *dst));
43 static bfd_reloc_status_type ppbase_reloc
44   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
45 static bfd_reloc_status_type glob15_reloc
46   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
47 static bfd_reloc_status_type glob16_reloc
48   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
49 static bfd_reloc_status_type local16_reloc
50   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
51 static boolean coff_tic80_relocate_section
52   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
53            struct internal_reloc *, struct internal_syment *, asection **));
54 static reloc_howto_type * coff_tic80_rtype_to_howto
55   PARAMS ((bfd *, asection *, struct internal_reloc *,
56            struct coff_link_hash_entry *, struct internal_syment *,
57            bfd_vma *));
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 \f
357 /* Special relocation functions, used when the output file is not
358    itself a COFF TIc80 file.  */
359
360 /* This special function is used for the base address type
361    relocations.  */
362
363 static bfd_reloc_status_type
364 ppbase_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
365               error_message)
366      bfd *abfd ATTRIBUTE_UNUSED;
367      arelent *reloc_entry ATTRIBUTE_UNUSED;
368      asymbol *symbol_in ATTRIBUTE_UNUSED;
369      PTR 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 (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
382               error_message)
383      bfd *abfd ATTRIBUTE_UNUSED;
384      arelent *reloc_entry ATTRIBUTE_UNUSED;
385      asymbol *symbol_in ATTRIBUTE_UNUSED;
386      PTR data ATTRIBUTE_UNUSED;
387      asection *input_section ATTRIBUTE_UNUSED;
388      bfd *output_bfd ATTRIBUTE_UNUSED;
389      char **error_message ATTRIBUTE_UNUSED;
390 {
391   /* FIXME.  */
392   abort ();
393 }
394
395 /* This special function is used for the global 16 bit relocations.  */
396
397 static bfd_reloc_status_type
398 glob16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
399               error_message)
400      bfd *abfd ATTRIBUTE_UNUSED;
401      arelent *reloc_entry ATTRIBUTE_UNUSED;
402      asymbol *symbol_in ATTRIBUTE_UNUSED;
403      PTR data ATTRIBUTE_UNUSED;
404      asection *input_section ATTRIBUTE_UNUSED;
405      bfd *output_bfd ATTRIBUTE_UNUSED;
406      char **error_message ATTRIBUTE_UNUSED;
407 {
408   /* FIXME.  */
409   abort ();
410 }
411
412 /* This special function is used for the local 16 bit relocations.  */
413
414 static bfd_reloc_status_type
415 local16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
416               error_message)
417      bfd *abfd ATTRIBUTE_UNUSED;
418      arelent *reloc_entry ATTRIBUTE_UNUSED;
419      asymbol *symbol_in ATTRIBUTE_UNUSED;
420      PTR data ATTRIBUTE_UNUSED;
421      asection *input_section ATTRIBUTE_UNUSED;
422      bfd *output_bfd ATTRIBUTE_UNUSED;
423      char **error_message ATTRIBUTE_UNUSED;
424 {
425   /* FIXME.  */
426   abort ();
427 }
428 \f
429 /* Code to turn an external r_type into a pointer to an entry in the howto_table.
430    If passed an r_type we don't recognize the abort rather than silently failing
431    to generate an output file.  */
432
433 static void
434 rtype2howto (cache_ptr, dst)
435      arelent *cache_ptr;
436      struct internal_reloc *dst;
437 {
438   unsigned int i;
439
440   for (i = 0; i < sizeof tic80_howto_table / sizeof tic80_howto_table[0]; i++)
441     {
442       if (tic80_howto_table[i].type == dst->r_type)
443         {
444           cache_ptr->howto = tic80_howto_table + i;
445           return;
446         }
447     }
448
449   (*_bfd_error_handler) (_("Unrecognized reloc type 0x%x"),
450                          (unsigned int) dst->r_type);
451   cache_ptr->howto = tic80_howto_table + 0;
452 }
453
454 #define RTYPE2HOWTO(cache_ptr, dst) rtype2howto (cache_ptr, dst)
455 #define coff_rtype_to_howto coff_tic80_rtype_to_howto
456
457 static reloc_howto_type *
458 coff_tic80_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
459      bfd *abfd ATTRIBUTE_UNUSED;
460      asection *sec;
461      struct internal_reloc *rel;
462      struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
463      struct internal_syment *sym ATTRIBUTE_UNUSED;
464      bfd_vma *addendp;
465 {
466   arelent genrel;
467
468   if (rel -> r_symndx == -1 && addendp != NULL)
469     {
470       /* This is a TI "internal relocation", which means that the relocation
471          amount is the amount by which the current section is being relocated
472          in the output section.  */
473       *addendp = (sec -> output_section -> vma + sec -> output_offset) - sec -> vma;
474     }
475   RTYPE2HOWTO (&genrel, rel);
476   return genrel.howto;
477 }
478
479 #ifndef BADMAG
480 #define BADMAG(x) TIC80BADMAG(x)
481 #endif
482 \f
483 #define coff_relocate_section coff_tic80_relocate_section
484
485 /* We need a special relocation routine to handle the PP relocs.  Most
486    of this is a copy of _bfd_coff_generic_relocate_section.  */
487
488 static boolean
489 coff_tic80_relocate_section (output_bfd, info, input_bfd,
490                              input_section, contents, relocs, syms,
491                              sections)
492      bfd *output_bfd;
493      struct bfd_link_info *info;
494      bfd *input_bfd;
495      asection *input_section;
496      bfd_byte *contents;
497      struct internal_reloc *relocs;
498      struct internal_syment *syms;
499      asection **sections;
500 {
501   struct internal_reloc *rel;
502   struct internal_reloc *relend;
503
504   rel = relocs;
505   relend = rel + input_section->reloc_count;
506   for (; rel < relend; rel++)
507     {
508       long symndx;
509       struct coff_link_hash_entry *h;
510       struct internal_syment *sym;
511       bfd_vma addend;
512       bfd_vma val;
513       reloc_howto_type *howto;
514       bfd_reloc_status_type rstat;
515       bfd_vma addr;
516
517       symndx = rel->r_symndx;
518
519       if (symndx == -1)
520         {
521           h = NULL;
522           sym = NULL;
523         }
524       else
525         {
526           h = obj_coff_sym_hashes (input_bfd)[symndx];
527           sym = syms + symndx;
528         }
529
530       /* COFF treats common symbols in one of two ways.  Either the
531          size of the symbol is included in the section contents, or it
532          is not.  We assume that the size is not included, and force
533          the rtype_to_howto function to adjust the addend as needed.  */
534
535       if (sym != NULL && sym->n_scnum != 0)
536         addend = - sym->n_value;
537       else
538         addend = 0;
539
540       howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
541                                        sym, &addend);
542       if (howto == NULL)
543         return false;
544
545       val = 0;
546
547       if (h == NULL)
548         {
549           asection *sec;
550
551           if (symndx == -1)
552             {
553               sec = bfd_abs_section_ptr;
554               val = 0;
555             }
556           else
557             {
558               sec = sections[symndx];
559               val = (sec->output_section->vma
560                      + sec->output_offset
561                      + sym->n_value);
562               if (! obj_pe (output_bfd))
563                 val -= sec->vma;
564             }
565         }
566       else
567         {
568           if (h->root.type == bfd_link_hash_defined
569               || h->root.type == bfd_link_hash_defweak)
570             {
571               asection *sec;
572
573               sec = h->root.u.def.section;
574               val = (h->root.u.def.value
575                      + sec->output_section->vma
576                      + sec->output_offset);
577               }
578
579           else if (! info->relocateable)
580             {
581               if (! ((*info->callbacks->undefined_symbol)
582                      (info, h->root.root.string, input_bfd, input_section,
583                       rel->r_vaddr - input_section->vma, true)))
584                 return false;
585             }
586         }
587
588       addr = rel->r_vaddr - input_section->vma;
589
590       /* FIXME: This code assumes little endian, but the PP can
591          apparently be bi-endian.  I don't know if the bi-endianness
592          applies to the instruction set or just to the data.  */
593       switch (howto->type)
594         {
595         default:
596         case R_ABS:
597         case R_RELLONGX:
598         case R_PPL15:
599         case R_PPL15W:
600         case R_PPL15H:
601         case R_PPLN15:
602         case R_PPLN15W:
603         case R_PPLN15H:
604           rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
605                                             contents, addr, val, addend);
606           break;
607
608         case R_PP15:
609         case R_PP15W:
610         case R_PP15H:
611         case R_PPN15:
612         case R_PPN15W:
613         case R_PPN15H:
614           /* Offset the address so that we can use 4 byte relocations.  */
615           rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
616                                             contents + 2, addr, val, addend);
617           break;
618
619         case R_PP16B:
620         case R_PPN16B:
621           {
622             /* The most significant bit is stored in bit 6.  */
623             bfd_byte hold;
624
625             hold = contents[addr + 4];
626             contents[addr + 4] &=~ 0x20;
627             contents[addr + 4] |= (contents[addr] >> 1) & 0x20;
628             rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
629                                               contents + 2, addr,
630                                               val, addend);
631             contents[addr] &=~ 0x40;
632             contents[addr] |= (contents[addr + 4] << 1) & 0x40;
633             contents[addr + 4] &=~ 0x20;
634             contents[addr + 4] |= hold & 0x20;
635             break;
636           }
637
638         case R_PPL16B:
639         case R_PPLN16B:
640           {
641             /* The most significant bit is stored in bit 28.  */
642             bfd_byte hold;
643
644             hold = contents[addr + 1];
645             contents[addr + 1] &=~ 0x80;
646             contents[addr + 1] |= (contents[addr + 3] << 3) & 0x80;
647             rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
648                                               contents, addr,
649                                               val, addend);
650             contents[addr + 3] &= ~0x10;
651             contents[addr + 3] |= (contents[addr + 1] >> 3) & 0x10;
652             contents[addr + 1] &=~ 0x80;
653             contents[addr + 1] |= hold & 0x80;
654             break;
655           }
656
657         case R_PPBASE:
658           /* Parameter RAM is from 0x1000000 to 0x1000800.  */
659           contents[addr] &=~ 0x3;
660           if (val >= 0x1000000 && val < 0x1000800)
661             contents[addr] |= 0x3;
662           else
663             contents[addr] |= 0x2;
664           rstat = bfd_reloc_ok;
665           break;
666
667         case R_PPLBASE:
668           /* Parameter RAM is from 0x1000000 to 0x1000800.  */
669           contents[addr + 2] &= ~0xc0;
670           if (val >= 0x1000000 && val < 0x1000800)
671             contents[addr + 2] |= 0xc0;
672           else
673             contents[addr + 2] |= 0x80;
674           rstat = bfd_reloc_ok;
675           break;
676         }
677
678       switch (rstat)
679         {
680         default:
681           abort ();
682         case bfd_reloc_ok:
683           break;
684         case bfd_reloc_outofrange:
685           (*_bfd_error_handler)
686             (_("%s: bad reloc address 0x%lx in section `%s'"),
687              bfd_get_filename (input_bfd),
688              (unsigned long) rel->r_vaddr,
689              bfd_get_section_name (input_bfd, input_section));
690           return false;
691         case bfd_reloc_overflow:
692           {
693             const char *name;
694             char buf[SYMNMLEN + 1];
695
696             if (symndx == -1)
697               name = "*ABS*";
698             else if (h != NULL)
699               name = h->root.root.string;
700             else
701               {
702                 name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
703                 if (name == NULL)
704                   return false;
705               }
706
707             if (! ((*info->callbacks->reloc_overflow)
708                    (info, name, howto->name, (bfd_vma) 0, input_bfd,
709                     input_section, rel->r_vaddr - input_section->vma)))
710               return false;
711           }
712         }
713     }
714   return true;
715 }
716 \f
717 #define TIC80COFF 1             /* Customize coffcode.h */
718 #undef C_AUTOARG                /* Clashes with TIc80's C_UEXT */
719 #undef C_LASTENT                /* Clashes with TIc80's C_STATLAB */
720 #include "coffcode.h"
721
722 CREATE_LITTLE_COFF_TARGET_VEC (tic80coff_vec, "coff-tic80", D_PAGED, 0, '_', NULL)