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