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