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