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