Back to index

cell-binutils  2.17cvs20070401
coff-tic80.c
Go to the documentation of this file.
00001 /* BFD back-end for Texas Instruments TMS320C80 Multimedia Video Processor (MVP).
00002    Copyright 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005
00003    Free Software Foundation, Inc.
00004 
00005    Written by Fred Fish (fnf@cygnus.com)
00006 
00007    There is nothing new under the sun. This file draws a lot on other
00008    coff files.
00009 
00010 This file is part of BFD, the Binary File Descriptor library.
00011 
00012 This program is free software; you can redistribute it and/or modify
00013 it under the terms of the GNU General Public License as published by
00014 the Free Software Foundation; either version 2 of the License, or
00015 (at your option) any later version.
00016 
00017 This program is distributed in the hope that it will be useful,
00018 but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 GNU General Public License for more details.
00021 
00022 You should have received a copy of the GNU General Public License
00023 along with this program; if not, write to the Free Software
00024 Foundation, 51 Franklin Street - Fifth Floor,
00025 Boston, MA 02110-1301, USA.  */
00026 
00027 #include "bfd.h"
00028 #include "bfdlink.h"
00029 #include "sysdep.h"
00030 #include "libbfd.h"
00031 #ifdef _CONST
00032 /* Newlib-based hosts define _CONST as a STDC-safe alias for const,
00033   but to the tic80 toolchain it means something altogether different.
00034   Since sysdep.h will have pulled in stdio.h and hence _ansi.h which
00035   contains this definition, we must undef it before including the 
00036   tic80-specific definition. */
00037 #undef _CONST
00038 #endif /* _CONST */
00039 #include "coff/tic80.h"
00040 #include "coff/internal.h"
00041 #include "libcoff.h"
00042 
00043 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
00044 #define COFF_ALIGN_IN_SECTION_HEADER 1
00045 #define COFF_ALIGN_IN_SFLAGS 1
00046 
00047 #define GET_SCNHDR_FLAGS H_GET_16
00048 #define PUT_SCNHDR_FLAGS H_PUT_16
00049 
00050 static void rtype2howto
00051   PARAMS ((arelent *cache_ptr, struct internal_reloc *dst));
00052 static bfd_reloc_status_type ppbase_reloc
00053   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00054 static bfd_reloc_status_type glob15_reloc
00055   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00056 static bfd_reloc_status_type glob16_reloc
00057   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00058 static bfd_reloc_status_type local16_reloc
00059   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00060 static bfd_boolean coff_tic80_relocate_section
00061   PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00062           struct internal_reloc *, struct internal_syment *, asection **));
00063 static reloc_howto_type * coff_tic80_rtype_to_howto
00064   PARAMS ((bfd *, asection *, struct internal_reloc *,
00065           struct coff_link_hash_entry *, struct internal_syment *,
00066           bfd_vma *));
00067 
00068 static reloc_howto_type tic80_howto_table[] =
00069 {
00070 
00071   HOWTO (R_RELLONG,                /* type */
00072         0,                         /* rightshift */
00073         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00074         32,                        /* bitsize */
00075         FALSE,                            /* pc_relative */
00076         0,                         /* bitpos */
00077         complain_overflow_bitfield,       /* complain_on_overflow */
00078         NULL,                      /* special_function */
00079         "RELLONG",                 /* name */
00080         TRUE,                      /* partial_inplace */
00081         0xffffffff,                /* src_mask */
00082         0xffffffff,                /* dst_mask */
00083         FALSE),                    /* pcrel_offset */
00084 
00085   HOWTO (R_MPPCR,                  /* type */
00086         2,                         /* rightshift */
00087         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00088         32,                        /* bitsize */
00089         TRUE,                      /* pc_relative */
00090         0,                         /* bitpos */
00091         complain_overflow_signed,  /* complain_on_overflow */
00092         NULL,                      /* special_function */
00093         "MPPCR",                   /* name */
00094         TRUE,                      /* partial_inplace */
00095         0xffffffff,                /* src_mask */
00096         0xffffffff,                /* dst_mask */
00097         TRUE),                            /* pcrel_offset */
00098 
00099   HOWTO (R_ABS,                           /* type */
00100         0,                         /* rightshift */
00101         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00102         32,                        /* bitsize */
00103         FALSE,                            /* pc_relative */
00104         0,                         /* bitpos */
00105         complain_overflow_bitfield,       /* complain_on_overflow */
00106         NULL,                      /* special_function */
00107         "ABS",                            /* name */
00108         TRUE,                      /* partial_inplace */
00109         0xffffffff,                /* src_mask */
00110         0xffffffff,                /* dst_mask */
00111         FALSE),                           /* pcrel_offset */
00112 
00113   HOWTO (R_PPBASE,                 /* type */
00114         0,                         /* rightshift */
00115         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00116         32,                        /* bitsize */
00117         FALSE,                            /* pc_relative */
00118         0,                         /* bitpos */
00119         complain_overflow_dont,    /* complain_on_overflow */
00120         ppbase_reloc,                     /* special_function */
00121         "PPBASE",                  /* name */
00122         TRUE,                      /* partial_inplace */
00123         0xffffffff,                /* src_mask */
00124         0xffffffff,                /* dst_mask */
00125         FALSE),                    /* pcrel_offset */
00126 
00127   HOWTO (R_PPLBASE,                /* type */
00128         0,                         /* rightshift */
00129         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00130         32,                        /* bitsize */
00131         FALSE,                            /* pc_relative */
00132         0,                         /* bitpos */
00133         complain_overflow_dont,    /* complain_on_overflow */
00134         ppbase_reloc,                     /* special_function */
00135         "PPLBASE",                 /* name */
00136         TRUE,                      /* partial_inplace */
00137         0xffffffff,                /* src_mask */
00138         0xffffffff,                /* dst_mask */
00139         FALSE),                    /* pcrel_offset */
00140 
00141   HOWTO (R_PP15,                   /* type */
00142         0,                         /* rightshift */
00143         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00144         15,                        /* bitsize */
00145         FALSE,                            /* pc_relative */
00146         6,                         /* bitpos */
00147         complain_overflow_dont,    /* complain_on_overflow */
00148         glob15_reloc,                     /* special_function */
00149         "PP15",                    /* name */
00150         TRUE,                      /* partial_inplace */
00151         0x1ffc0,                   /* src_mask */
00152         0x1ffc0,                   /* dst_mask */
00153         FALSE),                    /* pcrel_offset */
00154 
00155   HOWTO (R_PP15W,                  /* type */
00156         2,                         /* rightshift */
00157         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00158         15,                        /* bitsize */
00159         FALSE,                            /* pc_relative */
00160         6,                         /* bitpos */
00161         complain_overflow_dont,    /* complain_on_overflow */
00162         glob15_reloc,                     /* special_function */
00163         "PP15W",                   /* name */
00164         TRUE,                      /* partial_inplace */
00165         0x1ffc0,                   /* src_mask */
00166         0x1ffc0,                   /* dst_mask */
00167         FALSE),                    /* pcrel_offset */
00168 
00169   HOWTO (R_PP15H,                  /* type */
00170         1,                         /* rightshift */
00171         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00172         15,                        /* bitsize */
00173         FALSE,                            /* pc_relative */
00174         6,                         /* bitpos */
00175         complain_overflow_dont,    /* complain_on_overflow */
00176         glob15_reloc,                     /* special_function */
00177         "PP15H",                   /* name */
00178         TRUE,                      /* partial_inplace */
00179         0x1ffc0,                   /* src_mask */
00180         0x1ffc0,                   /* dst_mask */
00181         FALSE),                    /* pcrel_offset */
00182 
00183   HOWTO (R_PP16B,                  /* type */
00184         0,                         /* rightshift */
00185         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00186         16,                        /* bitsize */
00187         FALSE,                            /* pc_relative */
00188         6,                         /* bitpos */
00189         complain_overflow_dont,    /* complain_on_overflow */
00190         glob16_reloc,                     /* special_function */
00191         "PP16B",                   /* name */
00192         TRUE,                      /* partial_inplace */
00193         0x3ffc0,                   /* src_mask */
00194         0x3ffc0,                   /* dst_mask */
00195         FALSE),                    /* pcrel_offset */
00196 
00197   HOWTO (R_PPL15,                  /* type */
00198         0,                         /* rightshift */
00199         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00200         15,                        /* bitsize */
00201         FALSE,                            /* pc_relative */
00202         0,                         /* bitpos */
00203         complain_overflow_dont,    /* complain_on_overflow */
00204         NULL,                      /* special_function */
00205         "PPL15",                   /* name */
00206         TRUE,                      /* partial_inplace */
00207         0x7fff,                    /* src_mask */
00208         0x7fff,                    /* dst_mask */
00209         FALSE),                    /* pcrel_offset */
00210 
00211   HOWTO (R_PPL15W,                 /* type */
00212         2,                         /* rightshift */
00213         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00214         15,                        /* bitsize */
00215         FALSE,                            /* pc_relative */
00216         0,                         /* bitpos */
00217         complain_overflow_dont,    /* complain_on_overflow */
00218         NULL,                      /* special_function */
00219         "PPL15W",                  /* name */
00220         TRUE,                      /* partial_inplace */
00221         0x7fff,                    /* src_mask */
00222         0x7fff,                    /* dst_mask */
00223         FALSE),                    /* pcrel_offset */
00224 
00225   HOWTO (R_PPL15H,                 /* type */
00226         1,                         /* rightshift */
00227         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00228         15,                        /* bitsize */
00229         FALSE,                            /* pc_relative */
00230         0,                         /* bitpos */
00231         complain_overflow_dont,    /* complain_on_overflow */
00232         NULL,                      /* special_function */
00233         "PPL15H",                  /* name */
00234         TRUE,                      /* partial_inplace */
00235         0x7fff,                    /* src_mask */
00236         0x7fff,                    /* dst_mask */
00237         FALSE),                    /* pcrel_offset */
00238 
00239   HOWTO (R_PPL16B,                 /* type */
00240         0,                         /* rightshift */
00241         2,                         /* size (0 = byte, 1 = short, 2 = long) */
00242         16,                        /* bitsize */
00243         FALSE,                            /* pc_relative */
00244         0,                         /* bitpos */
00245         complain_overflow_dont,    /* complain_on_overflow */
00246         local16_reloc,                    /* special_function */
00247         "PPL16B",                  /* name */
00248         TRUE,                      /* partial_inplace */
00249         0xffff,                    /* src_mask */
00250         0xffff,                    /* dst_mask */
00251         FALSE),                    /* pcrel_offset */
00252 
00253   HOWTO (R_PPN15,                  /* type */
00254         0,                         /* rightshift */
00255         -2,                        /* size (0 = byte, 1 = short, 2 = long) */
00256         15,                        /* bitsize */
00257         FALSE,                            /* pc_relative */
00258         6,                         /* bitpos */
00259         complain_overflow_dont,    /* complain_on_overflow */
00260         glob15_reloc,                     /* special_function */
00261         "PPN15",                   /* name */
00262         TRUE,                      /* partial_inplace */
00263         0x1ffc0,                   /* src_mask */
00264         0x1ffc0,                   /* dst_mask */
00265         FALSE),                    /* pcrel_offset */
00266 
00267   HOWTO (R_PPN15W,                 /* type */
00268         2,                         /* rightshift */
00269         -2,                        /* size (0 = byte, 1 = short, 2 = long) */
00270         15,                        /* bitsize */
00271         FALSE,                            /* pc_relative */
00272         6,                         /* bitpos */
00273         complain_overflow_dont,    /* complain_on_overflow */
00274         glob15_reloc,                     /* special_function */
00275         "PPN15W",                  /* name */
00276         TRUE,                      /* partial_inplace */
00277         0x1ffc0,                   /* src_mask */
00278         0x1ffc0,                   /* dst_mask */
00279         FALSE),                    /* pcrel_offset */
00280 
00281   HOWTO (R_PPN15H,                 /* type */
00282         1,                         /* rightshift */
00283         -2,                        /* size (0 = byte, 1 = short, 2 = long) */
00284         15,                        /* bitsize */
00285         FALSE,                            /* pc_relative */
00286         6,                         /* bitpos */
00287         complain_overflow_dont,    /* complain_on_overflow */
00288         glob15_reloc,                     /* special_function */
00289         "PPN15H",                  /* name */
00290         TRUE,                      /* partial_inplace */
00291         0x1ffc0,                   /* src_mask */
00292         0x1ffc0,                   /* dst_mask */
00293         FALSE),                    /* pcrel_offset */
00294 
00295   HOWTO (R_PPN16B,                 /* type */
00296         0,                         /* rightshift */
00297         -2,                        /* size (0 = byte, 1 = short, 2 = long) */
00298         16,                        /* bitsize */
00299         FALSE,                            /* pc_relative */
00300         6,                         /* bitpos */
00301         complain_overflow_dont,    /* complain_on_overflow */
00302         glob16_reloc,                     /* special_function */
00303         "PPN16B",                  /* name */
00304         TRUE,                      /* partial_inplace */
00305         0x3ffc0,                   /* src_mask */
00306         0x3ffc0,                   /* dst_mask */
00307         FALSE),                    /* pcrel_offset */
00308 
00309   HOWTO (R_PPLN15,                 /* type */
00310         0,                         /* rightshift */
00311         -2,                        /* size (0 = byte, 1 = short, 2 = long) */
00312         15,                        /* bitsize */
00313         FALSE,                            /* pc_relative */
00314         0,                         /* bitpos */
00315         complain_overflow_dont,    /* complain_on_overflow */
00316         NULL,                      /* special_function */
00317         "PPLN15",                  /* name */
00318         TRUE,                      /* partial_inplace */
00319         0x7fff,                    /* src_mask */
00320         0x7fff,                    /* dst_mask */
00321         FALSE),                    /* pcrel_offset */
00322 
00323   HOWTO (R_PPLN15W,                /* type */
00324         2,                         /* rightshift */
00325         -2,                        /* size (0 = byte, 1 = short, 2 = long) */
00326         15,                        /* bitsize */
00327         FALSE,                            /* pc_relative */
00328         0,                         /* bitpos */
00329         complain_overflow_dont,    /* complain_on_overflow */
00330         NULL,                      /* special_function */
00331         "PPLN15W",                 /* name */
00332         TRUE,                      /* partial_inplace */
00333         0x7fff,                    /* src_mask */
00334         0x7fff,                    /* dst_mask */
00335         FALSE),                    /* pcrel_offset */
00336 
00337   HOWTO (R_PPLN15H,                /* type */
00338         1,                         /* rightshift */
00339         -2,                        /* size (0 = byte, 1 = short, 2 = long) */
00340         15,                        /* bitsize */
00341         FALSE,                            /* pc_relative */
00342         0,                         /* bitpos */
00343         complain_overflow_dont,    /* complain_on_overflow */
00344         NULL,                      /* special_function */
00345         "PPLN15H",                 /* name */
00346         TRUE,                      /* partial_inplace */
00347         0x7fff,                    /* src_mask */
00348         0x7fff,                    /* dst_mask */
00349         FALSE),                    /* pcrel_offset */
00350 
00351   HOWTO (R_PPLN16B,                /* type */
00352         0,                         /* rightshift */
00353         -2,                        /* size (0 = byte, 1 = short, 2 = long) */
00354         15,                        /* bitsize */
00355         FALSE,                            /* pc_relative */
00356         0,                         /* bitpos */
00357         complain_overflow_dont,    /* complain_on_overflow */
00358         local16_reloc,                    /* special_function */
00359         "PPLN16B",                 /* name */
00360         TRUE,                      /* partial_inplace */
00361         0xffff,                    /* src_mask */
00362         0xffff,                    /* dst_mask */
00363         FALSE)                            /* pcrel_offset */
00364 };
00365 
00366 /* Special relocation functions, used when the output file is not
00367    itself a COFF TIc80 file.  */
00368 
00369 /* This special function is used for the base address type
00370    relocations.  */
00371 
00372 static bfd_reloc_status_type
00373 ppbase_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
00374              error_message)
00375      bfd *abfd ATTRIBUTE_UNUSED;
00376      arelent *reloc_entry ATTRIBUTE_UNUSED;
00377      asymbol *symbol_in ATTRIBUTE_UNUSED;
00378      PTR data ATTRIBUTE_UNUSED;
00379      asection *input_section ATTRIBUTE_UNUSED;
00380      bfd *output_bfd ATTRIBUTE_UNUSED;
00381      char **error_message ATTRIBUTE_UNUSED;
00382 {
00383   /* FIXME.  */
00384   abort ();
00385 }
00386 
00387 /* This special function is used for the global 15 bit relocations.  */
00388 
00389 static bfd_reloc_status_type
00390 glob15_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
00391              error_message)
00392      bfd *abfd ATTRIBUTE_UNUSED;
00393      arelent *reloc_entry ATTRIBUTE_UNUSED;
00394      asymbol *symbol_in ATTRIBUTE_UNUSED;
00395      PTR data ATTRIBUTE_UNUSED;
00396      asection *input_section ATTRIBUTE_UNUSED;
00397      bfd *output_bfd ATTRIBUTE_UNUSED;
00398      char **error_message ATTRIBUTE_UNUSED;
00399 {
00400   /* FIXME.  */
00401   abort ();
00402 }
00403 
00404 /* This special function is used for the global 16 bit relocations.  */
00405 
00406 static bfd_reloc_status_type
00407 glob16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
00408              error_message)
00409      bfd *abfd ATTRIBUTE_UNUSED;
00410      arelent *reloc_entry ATTRIBUTE_UNUSED;
00411      asymbol *symbol_in ATTRIBUTE_UNUSED;
00412      PTR data ATTRIBUTE_UNUSED;
00413      asection *input_section ATTRIBUTE_UNUSED;
00414      bfd *output_bfd ATTRIBUTE_UNUSED;
00415      char **error_message ATTRIBUTE_UNUSED;
00416 {
00417   /* FIXME.  */
00418   abort ();
00419 }
00420 
00421 /* This special function is used for the local 16 bit relocations.  */
00422 
00423 static bfd_reloc_status_type
00424 local16_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
00425              error_message)
00426      bfd *abfd ATTRIBUTE_UNUSED;
00427      arelent *reloc_entry ATTRIBUTE_UNUSED;
00428      asymbol *symbol_in ATTRIBUTE_UNUSED;
00429      PTR data ATTRIBUTE_UNUSED;
00430      asection *input_section ATTRIBUTE_UNUSED;
00431      bfd *output_bfd ATTRIBUTE_UNUSED;
00432      char **error_message ATTRIBUTE_UNUSED;
00433 {
00434   /* FIXME.  */
00435   abort ();
00436 }
00437 
00438 /* Code to turn an external r_type into a pointer to an entry in the howto_table.
00439    If passed an r_type we don't recognize the abort rather than silently failing
00440    to generate an output file.  */
00441 
00442 static void
00443 rtype2howto (cache_ptr, dst)
00444      arelent *cache_ptr;
00445      struct internal_reloc *dst;
00446 {
00447   unsigned int i;
00448 
00449   for (i = 0; i < sizeof tic80_howto_table / sizeof tic80_howto_table[0]; i++)
00450     {
00451       if (tic80_howto_table[i].type == dst->r_type)
00452        {
00453          cache_ptr->howto = tic80_howto_table + i;
00454          return;
00455        }
00456     }
00457 
00458   (*_bfd_error_handler) (_("Unrecognized reloc type 0x%x"),
00459                       (unsigned int) dst->r_type);
00460   cache_ptr->howto = tic80_howto_table + 0;
00461 }
00462 
00463 #define RTYPE2HOWTO(cache_ptr, dst) rtype2howto (cache_ptr, dst)
00464 #define coff_rtype_to_howto coff_tic80_rtype_to_howto
00465 
00466 static reloc_howto_type *
00467 coff_tic80_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00468      bfd *abfd ATTRIBUTE_UNUSED;
00469      asection *sec;
00470      struct internal_reloc *rel;
00471      struct coff_link_hash_entry *h ATTRIBUTE_UNUSED;
00472      struct internal_syment *sym ATTRIBUTE_UNUSED;
00473      bfd_vma *addendp;
00474 {
00475   arelent genrel;
00476 
00477   if (rel -> r_symndx == -1 && addendp != NULL)
00478     {
00479       /* This is a TI "internal relocation", which means that the relocation
00480         amount is the amount by which the current section is being relocated
00481         in the output section.  */
00482       *addendp = (sec -> output_section -> vma + sec -> output_offset) - sec -> vma;
00483     }
00484   RTYPE2HOWTO (&genrel, rel);
00485   return genrel.howto;
00486 }
00487 
00488 #ifndef BADMAG
00489 #define BADMAG(x) TIC80BADMAG(x)
00490 #endif
00491 
00492 #define coff_relocate_section coff_tic80_relocate_section
00493 
00494 /* We need a special relocation routine to handle the PP relocs.  Most
00495    of this is a copy of _bfd_coff_generic_relocate_section.  */
00496 
00497 static bfd_boolean
00498 coff_tic80_relocate_section (output_bfd, info, input_bfd,
00499                           input_section, contents, relocs, syms,
00500                           sections)
00501      bfd *output_bfd;
00502      struct bfd_link_info *info;
00503      bfd *input_bfd;
00504      asection *input_section;
00505      bfd_byte *contents;
00506      struct internal_reloc *relocs;
00507      struct internal_syment *syms;
00508      asection **sections;
00509 {
00510   struct internal_reloc *rel;
00511   struct internal_reloc *relend;
00512 
00513   rel = relocs;
00514   relend = rel + input_section->reloc_count;
00515   for (; rel < relend; rel++)
00516     {
00517       long symndx;
00518       struct coff_link_hash_entry *h;
00519       struct internal_syment *sym;
00520       bfd_vma addend;
00521       bfd_vma val;
00522       reloc_howto_type *howto;
00523       bfd_reloc_status_type rstat;
00524       bfd_vma addr;
00525 
00526       symndx = rel->r_symndx;
00527 
00528       if (symndx == -1)
00529        {
00530          h = NULL;
00531          sym = NULL;
00532        }
00533       else
00534        {
00535          h = obj_coff_sym_hashes (input_bfd)[symndx];
00536          sym = syms + symndx;
00537        }
00538 
00539       /* COFF treats common symbols in one of two ways.  Either the
00540          size of the symbol is included in the section contents, or it
00541          is not.  We assume that the size is not included, and force
00542          the rtype_to_howto function to adjust the addend as needed.  */
00543 
00544       if (sym != NULL && sym->n_scnum != 0)
00545        addend = - sym->n_value;
00546       else
00547        addend = 0;
00548 
00549       howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
00550                                    sym, &addend);
00551       if (howto == NULL)
00552        return FALSE;
00553 
00554       val = 0;
00555 
00556       if (h == NULL)
00557        {
00558          asection *sec;
00559 
00560          if (symndx == -1)
00561            {
00562              sec = bfd_abs_section_ptr;
00563              val = 0;
00564            }
00565          else
00566            {
00567              sec = sections[symndx];
00568               val = (sec->output_section->vma
00569                    + sec->output_offset
00570                    + sym->n_value);
00571              if (! obj_pe (output_bfd))
00572               val -= sec->vma;
00573            }
00574        }
00575       else
00576        {
00577          if (h->root.type == bfd_link_hash_defined
00578              || h->root.type == bfd_link_hash_defweak)
00579            {
00580              asection *sec;
00581 
00582              sec = h->root.u.def.section;
00583              val = (h->root.u.def.value
00584                    + sec->output_section->vma
00585                    + sec->output_offset);
00586              }
00587 
00588          else if (! info->relocatable)
00589            {
00590              if (! ((*info->callbacks->undefined_symbol)
00591                    (info, h->root.root.string, input_bfd, input_section,
00592                     rel->r_vaddr - input_section->vma, TRUE)))
00593               return FALSE;
00594            }
00595        }
00596 
00597       addr = rel->r_vaddr - input_section->vma;
00598 
00599       /* FIXME: This code assumes little endian, but the PP can
00600          apparently be bi-endian.  I don't know if the bi-endianness
00601          applies to the instruction set or just to the data.  */
00602       switch (howto->type)
00603        {
00604        default:
00605        case R_ABS:
00606        case R_RELLONGX:
00607        case R_PPL15:
00608        case R_PPL15W:
00609        case R_PPL15H:
00610        case R_PPLN15:
00611        case R_PPLN15W:
00612        case R_PPLN15H:
00613          rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
00614                                        contents, addr, val, addend);
00615          break;
00616 
00617        case R_PP15:
00618        case R_PP15W:
00619        case R_PP15H:
00620        case R_PPN15:
00621        case R_PPN15W:
00622        case R_PPN15H:
00623          /* Offset the address so that we can use 4 byte relocations.  */
00624          rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
00625                                        contents + 2, addr, val, addend);
00626          break;
00627 
00628        case R_PP16B:
00629        case R_PPN16B:
00630          {
00631            /* The most significant bit is stored in bit 6.  */
00632            bfd_byte hold;
00633 
00634            hold = contents[addr + 4];
00635            contents[addr + 4] &=~ 0x20;
00636            contents[addr + 4] |= (contents[addr] >> 1) & 0x20;
00637            rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
00638                                          contents + 2, addr,
00639                                          val, addend);
00640            contents[addr] &=~ 0x40;
00641            contents[addr] |= (contents[addr + 4] << 1) & 0x40;
00642            contents[addr + 4] &=~ 0x20;
00643            contents[addr + 4] |= hold & 0x20;
00644            break;
00645          }
00646 
00647        case R_PPL16B:
00648        case R_PPLN16B:
00649          {
00650            /* The most significant bit is stored in bit 28.  */
00651            bfd_byte hold;
00652 
00653            hold = contents[addr + 1];
00654            contents[addr + 1] &=~ 0x80;
00655            contents[addr + 1] |= (contents[addr + 3] << 3) & 0x80;
00656            rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
00657                                          contents, addr,
00658                                          val, addend);
00659            contents[addr + 3] &= ~0x10;
00660            contents[addr + 3] |= (contents[addr + 1] >> 3) & 0x10;
00661            contents[addr + 1] &=~ 0x80;
00662            contents[addr + 1] |= hold & 0x80;
00663            break;
00664          }
00665 
00666        case R_PPBASE:
00667          /* Parameter RAM is from 0x1000000 to 0x1000800.  */
00668          contents[addr] &=~ 0x3;
00669          if (val >= 0x1000000 && val < 0x1000800)
00670            contents[addr] |= 0x3;
00671          else
00672            contents[addr] |= 0x2;
00673          rstat = bfd_reloc_ok;
00674          break;
00675 
00676        case R_PPLBASE:
00677          /* Parameter RAM is from 0x1000000 to 0x1000800.  */
00678          contents[addr + 2] &= ~0xc0;
00679          if (val >= 0x1000000 && val < 0x1000800)
00680            contents[addr + 2] |= 0xc0;
00681          else
00682            contents[addr + 2] |= 0x80;
00683          rstat = bfd_reloc_ok;
00684          break;
00685        }
00686 
00687       switch (rstat)
00688        {
00689        default:
00690          abort ();
00691        case bfd_reloc_ok:
00692          break;
00693        case bfd_reloc_outofrange:
00694          (*_bfd_error_handler)
00695            (_("%B: bad reloc address 0x%lx in section `%A'"),
00696             input_bfd, input_section, (unsigned long) rel->r_vaddr);
00697          return FALSE;
00698        case bfd_reloc_overflow:
00699          {
00700            const char *name;
00701            char buf[SYMNMLEN + 1];
00702 
00703            if (symndx == -1)
00704              name = "*ABS*";
00705            else if (h != NULL)
00706              name = NULL;
00707            else
00708              {
00709               name = _bfd_coff_internal_syment_name (input_bfd, sym, buf);
00710               if (name == NULL)
00711                 return FALSE;
00712              }
00713 
00714            if (! ((*info->callbacks->reloc_overflow)
00715                  (info, (h ? &h->root : NULL), name, howto->name,
00716                   (bfd_vma) 0, input_bfd, input_section,
00717                   rel->r_vaddr - input_section->vma)))
00718              return FALSE;
00719          }
00720        }
00721     }
00722   return TRUE;
00723 }
00724 
00725 /* Clear the r_reserved field in relocs.  */
00726 #define SWAP_OUT_RELOC_EXTRA(abfd,src,dst) \
00727   do \
00728     { \
00729       dst->r_reserved[0] = 0; \
00730       dst->r_reserved[1] = 0; \
00731     } \
00732   while (0)
00733 
00734 #define TIC80COFF 1         /* Customize coffcode.h */
00735 #undef C_AUTOARG            /* Clashes with TIc80's C_UEXT */
00736 #undef C_LASTENT            /* Clashes with TIc80's C_STATLAB */
00737 #include "coffcode.h"
00738 
00739 CREATE_LITTLE_COFF_TARGET_VEC (tic80coff_vec, "coff-tic80", D_PAGED, 0, '_', NULL, COFF_SWAP_TABLE)