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