Back to index

cell-binutils  2.17cvs20070401
cpu-ns32k.c
Go to the documentation of this file.
00001 /* BFD support for the ns32k architecture.
00002    Copyright 1990, 1991, 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003,
00003    2004, 2005 Free Software Foundation, Inc.
00004    Almost totally rewritten by Ian Dall from initial work
00005    by Andrew Cagney.
00006 
00007    This file is part of BFD, the Binary File Descriptor library.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00022 
00023 #include "bfd.h"
00024 #include "sysdep.h"
00025 #include "libbfd.h"
00026 #include "ns32k.h"
00027 
00028 #define N(machine, printable, d, next)  \
00029 {  32, 32, 8, bfd_arch_ns32k, machine, "ns32k",printable,3,d,bfd_default_compatible,bfd_default_scan, next, }
00030 
00031 static const bfd_arch_info_type arch_info_struct[] =
00032 {
00033   N(32532,"ns32k:32532",TRUE, 0), /* The word ns32k will match this too.  */
00034 };
00035 
00036 const bfd_arch_info_type bfd_ns32k_arch =
00037   N(32032,"ns32k:32032",FALSE, &arch_info_struct[0]);
00038 
00039 static bfd_reloc_status_type do_ns32k_reloc
00040   PARAMS ((bfd *, arelent *, struct bfd_symbol *, PTR, asection *,
00041           bfd *, char **,
00042           bfd_vma (*) (bfd_byte *, int),
00043           void (*) (bfd_vma, bfd_byte *, int)));
00044 
00045 bfd_vma
00046 _bfd_ns32k_get_displacement (buffer, size)
00047      bfd_byte *buffer;
00048      int size;
00049 {
00050   bfd_signed_vma value;
00051 
00052   switch (size)
00053     {
00054     case 1:
00055       value = ((*buffer & 0x7f) ^ 0x40) - 0x40;
00056       break;
00057 
00058     case 2:
00059       value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
00060       value = (value << 8) | (0xff & *buffer);
00061       break;
00062 
00063     case 4:
00064       value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
00065       value = (value << 8) | (0xff & *buffer++);
00066       value = (value << 8) | (0xff & *buffer++);
00067       value = (value << 8) | (0xff & *buffer);
00068       break;
00069 
00070     default:
00071       abort ();
00072       return 0;
00073     }
00074 
00075   return value;
00076 }
00077 
00078 void
00079 _bfd_ns32k_put_displacement (value, buffer, size)
00080      bfd_vma value;
00081      bfd_byte *buffer;
00082      int size;
00083 {
00084   switch (size)
00085     {
00086     case 1:
00087       value &= 0x7f;
00088       *buffer++ = value;
00089       break;
00090 
00091     case 2:
00092       value &= 0x3fff;
00093       value |= 0x8000;
00094       *buffer++ = (value >> 8);
00095       *buffer++ = value;
00096       break;
00097 
00098     case 4:
00099       value |= (bfd_vma) 0xc0000000;
00100       *buffer++ = (value >> 24);
00101       *buffer++ = (value >> 16);
00102       *buffer++ = (value >> 8);
00103       *buffer++ = value;
00104       break;
00105   }
00106   return;
00107 }
00108 
00109 bfd_vma
00110 _bfd_ns32k_get_immediate (buffer, size)
00111      bfd_byte *buffer;
00112      int size;
00113 {
00114   bfd_vma value = 0;
00115 
00116   switch (size)
00117     {
00118     case 4:
00119       value = (value << 8) | (*buffer++ & 0xff);
00120       value = (value << 8) | (*buffer++ & 0xff);
00121     case 2:
00122       value = (value << 8) | (*buffer++ & 0xff);
00123     case 1:
00124       value = (value << 8) | (*buffer++ & 0xff);
00125       break;
00126     default:
00127       abort ();
00128     }
00129   return value;
00130 }
00131 
00132 void
00133 _bfd_ns32k_put_immediate (value, buffer, size)
00134      bfd_vma value;
00135      bfd_byte *buffer;
00136      int size;
00137 {
00138   buffer += size - 1;
00139   switch (size)
00140     {
00141     case 4:
00142       *buffer-- = (value & 0xff); value >>= 8;
00143       *buffer-- = (value & 0xff); value >>= 8;
00144     case 2:
00145       *buffer-- = (value & 0xff); value >>= 8;
00146     case 1:
00147       *buffer-- = (value & 0xff); value >>= 8;
00148     }
00149 }
00150 
00151 /* This is just like the standard perform_relocation except we
00152    use get_data and put_data which know about the ns32k storage
00153    methods.  This is probably a lot more complicated than it
00154    needs to be!  */
00155 
00156 static bfd_reloc_status_type
00157 do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
00158               error_message, get_data, put_data)
00159      bfd *abfd;
00160      arelent *reloc_entry;
00161      struct bfd_symbol *symbol;
00162      PTR data;
00163      asection *input_section;
00164      bfd *output_bfd;
00165      char **error_message ATTRIBUTE_UNUSED;
00166      bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
00167      void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
00168 {
00169   int overflow = 0;
00170   bfd_vma relocation;
00171   bfd_reloc_status_type flag = bfd_reloc_ok;
00172   bfd_size_type addr = reloc_entry->address;
00173   bfd_vma output_base = 0;
00174   reloc_howto_type *howto = reloc_entry->howto;
00175   asection *reloc_target_output_section;
00176   bfd_byte *location;
00177 
00178   if ((symbol->section == &bfd_abs_section)
00179       && output_bfd != (bfd *) NULL)
00180     {
00181       reloc_entry->address += input_section->output_offset;
00182       return bfd_reloc_ok;
00183     }
00184 
00185   /* If we are not producing relocatable output, return an error if
00186      the symbol is not defined.  An undefined weak symbol is
00187      considered to have a value of zero (SVR4 ABI, p. 4-27).  */
00188   if (symbol->section == &bfd_und_section
00189       && (symbol->flags & BSF_WEAK) == 0
00190       && output_bfd == (bfd *) NULL)
00191     flag = bfd_reloc_undefined;
00192 
00193   /* Is the address of the relocation really within the section?  */
00194   if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
00195     return bfd_reloc_outofrange;
00196 
00197   /* Work out which section the relocation is targeted at and the
00198      initial relocation command value.  */
00199 
00200   /* Get symbol value.  (Common symbols are special.)  */
00201   if (bfd_is_com_section (symbol->section))
00202     relocation = 0;
00203   else
00204     relocation = symbol->value;
00205 
00206   reloc_target_output_section = symbol->section->output_section;
00207 
00208   /* Convert input-section-relative symbol value to absolute.  */
00209   if (output_bfd != NULL && ! howto->partial_inplace)
00210     output_base = 0;
00211   else
00212     output_base = reloc_target_output_section->vma;
00213 
00214   relocation += output_base + symbol->section->output_offset;
00215 
00216   /* Add in supplied addend.  */
00217   relocation += reloc_entry->addend;
00218 
00219   /* Here the variable relocation holds the final address of the
00220      symbol we are relocating against, plus any addend.  */
00221 
00222   if (howto->pc_relative)
00223     {
00224       /* This is a PC relative relocation.  We want to set RELOCATION
00225         to the distance between the address of the symbol and the
00226         location.  RELOCATION is already the address of the symbol.
00227 
00228         We start by subtracting the address of the section containing
00229         the location.
00230 
00231         If pcrel_offset is set, we must further subtract the position
00232         of the location within the section.  Some targets arrange for
00233         the addend to be the negative of the position of the location
00234         within the section; for example, i386-aout does this.  For
00235         i386-aout, pcrel_offset is FALSE.  Some other targets do not
00236         include the position of the location; for example, m88kbcs,
00237         or ELF.  For those targets, pcrel_offset is TRUE.
00238 
00239         If we are producing relocatable output, then we must ensure
00240         that this reloc will be correctly computed when the final
00241         relocation is done.  If pcrel_offset is FALSE we want to wind
00242         up with the negative of the location within the section,
00243         which means we must adjust the existing addend by the change
00244         in the location within the section.  If pcrel_offset is TRUE
00245         we do not want to adjust the existing addend at all.
00246 
00247         FIXME: This seems logical to me, but for the case of
00248         producing relocatable output it is not what the code
00249         actually does.  I don't want to change it, because it seems
00250         far too likely that something will break.  */
00251       relocation -=
00252        input_section->output_section->vma + input_section->output_offset;
00253 
00254       if (howto->pcrel_offset)
00255        relocation -= reloc_entry->address;
00256     }
00257 
00258   if (output_bfd != (bfd *) NULL)
00259     {
00260       if (! howto->partial_inplace)
00261        {
00262          /* This is a partial relocation, and we want to apply the relocation
00263             to the reloc entry rather than the raw data. Modify the reloc
00264             inplace to reflect what we now know.  */
00265          reloc_entry->addend = relocation;
00266          reloc_entry->address += input_section->output_offset;
00267          return flag;
00268        }
00269       else
00270        {
00271          /* This is a partial relocation, but inplace, so modify the
00272             reloc record a bit.
00273 
00274             If we've relocated with a symbol with a section, change
00275             into a ref to the section belonging to the symbol.  */
00276 
00277          reloc_entry->address += input_section->output_offset;
00278 
00279          /* WTF?? */
00280          if (abfd->xvec->flavour == bfd_target_coff_flavour)
00281            {
00282              /* For m68k-coff, the addend was being subtracted twice during
00283                relocation with -r.  Removing the line below this comment
00284                fixes that problem; see PR 2953.
00285 
00286                However, Ian wrote the following, regarding removing the line
00287                below, which explains why it is still enabled:  --djm
00288 
00289                If you put a patch like that into BFD you need to check all
00290                the COFF linkers.  I am fairly certain that patch will break
00291                coff-i386 (e.g., SCO); see coff_i386_reloc in coff-i386.c
00292                where I worked around the problem in a different way.  There
00293                may very well be a reason that the code works as it does.
00294 
00295                Hmmm.  The first obvious point is that bfd_perform_relocation
00296                should not have any tests that depend upon the flavour.  It's
00297                seem like entirely the wrong place for such a thing.  The
00298                second obvious point is that the current code ignores the
00299                reloc addend when producing relocatable output for COFF.
00300                That's peculiar.  In fact, I really have no idea what the
00301                point of the line you want to remove is.
00302 
00303                A typical COFF reloc subtracts the old value of the symbol
00304                and adds in the new value to the location in the object file
00305                (if it's a pc relative reloc it adds the difference between
00306                the symbol value and the location).  When relocating we need
00307                to preserve that property.
00308 
00309                BFD handles this by setting the addend to the negative of the
00310                old value of the symbol.  Unfortunately it handles common
00311                symbols in a non-standard way (it doesn't subtract the old
00312                value) but that's a different story (we can't change it
00313                without losing backward compatibility with old object files)
00314                (coff-i386 does subtract the old value, to be compatible with
00315                existing coff-i386 targets, like SCO).
00316 
00317                So everything works fine when not producing relocatable
00318                output.  When we are producing relocatable output, logically
00319                we should do exactly what we do when not producing
00320                relocatable output.  Therefore, your patch is correct.  In
00321                fact, it should probably always just set reloc_entry->addend
00322                to 0 for all cases, since it is, in fact, going to add the
00323                value into the object file.  This won't hurt the COFF code,
00324                which doesn't use the addend; I'm not sure what it will do
00325                to other formats (the thing to check for would be whether
00326                any formats both use the addend and set partial_inplace).
00327 
00328                When I wanted to make coff-i386 produce relocatable output,
00329                I ran into the problem that you are running into: I wanted
00330                to remove that line.  Rather than risk it, I made the
00331                coff-i386 relocs use a special function; it's coff_i386_reloc
00332                in coff-i386.c.  The function specifically adds the addend
00333                field into the object file, knowing that bfd_perform_relocation
00334                is not going to.  If you remove that line, then coff-i386.c
00335                will wind up adding the addend field in twice.  It's trivial
00336                to fix; it just needs to be done.
00337 
00338                The problem with removing the line is just that it may break
00339                some working code.  With BFD it's hard to be sure of anything.
00340                The right way to deal with this is simply to build and test at
00341                least all the supported COFF targets.  It should be
00342                straightforward if time and disk space consuming.  For each
00343                target:
00344                  1) build the linker
00345                  2) generate some executable, and link it using -r (I would
00346                     probably use paranoia.o and link against newlib/libc.a,
00347                     which for all the supported targets would be available in
00348                     /usr/cygnus/progressive/H-host/target/lib/libc.a).
00349                  3) make the change to reloc.c
00350                  4) rebuild the linker
00351                  5) repeat step 2
00352                  6) if the resulting object files are the same, you have at
00353                     least made it no worse
00354                  7) if they are different you have to figure out which
00355                     version is right.  */
00356              relocation -= reloc_entry->addend;
00357              reloc_entry->addend = 0;
00358            }
00359          else
00360            {
00361              reloc_entry->addend = relocation;
00362            }
00363        }
00364     }
00365   else
00366     {
00367       reloc_entry->addend = 0;
00368     }
00369 
00370   /* FIXME: This overflow checking is incomplete, because the value
00371      might have overflowed before we get here.  For a correct check we
00372      need to compute the value in a size larger than bitsize, but we
00373      can't reasonably do that for a reloc the same size as a host
00374      machine word.
00375      FIXME: We should also do overflow checking on the result after
00376      adding in the value contained in the object file.  */
00377   if (howto->complain_on_overflow != complain_overflow_dont)
00378     {
00379       bfd_vma check;
00380 
00381       /* Get the value that will be used for the relocation, but
00382         starting at bit position zero.  */
00383       if (howto->rightshift > howto->bitpos)
00384        check = relocation >> (howto->rightshift - howto->bitpos);
00385       else
00386        check = relocation << (howto->bitpos - howto->rightshift);
00387       switch (howto->complain_on_overflow)
00388        {
00389        case complain_overflow_signed:
00390          {
00391            /* Assumes two's complement.  */
00392            bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
00393            bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
00394 
00395            /* The above right shift is incorrect for a signed value.
00396               Fix it up by forcing on the upper bits.  */
00397            if (howto->rightshift > howto->bitpos
00398               && (bfd_signed_vma) relocation < 0)
00399              check |= ((bfd_vma) - 1
00400                      & ~((bfd_vma) - 1
00401                          >> (howto->rightshift - howto->bitpos)));
00402            if ((bfd_signed_vma) check > reloc_signed_max
00403               || (bfd_signed_vma) check < reloc_signed_min)
00404              flag = bfd_reloc_overflow;
00405          }
00406          break;
00407        case complain_overflow_unsigned:
00408          {
00409            /* Assumes two's complement.  This expression avoids
00410               overflow if howto->bitsize is the number of bits in
00411               bfd_vma.  */
00412            bfd_vma reloc_unsigned_max =
00413            (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
00414 
00415            if ((bfd_vma) check > reloc_unsigned_max)
00416              flag = bfd_reloc_overflow;
00417          }
00418          break;
00419        case complain_overflow_bitfield:
00420          {
00421            /* Assumes two's complement.  This expression avoids
00422               overflow if howto->bitsize is the number of bits in
00423               bfd_vma.  */
00424            bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
00425 
00426            if (((bfd_vma) check & ~reloc_bits) != 0
00427               && (((bfd_vma) check & ~reloc_bits)
00428                   != (-(bfd_vma) 1 & ~reloc_bits)))
00429              {
00430               /* The above right shift is incorrect for a signed
00431                  value.  See if turning on the upper bits fixes the
00432                  overflow.  */
00433               if (howto->rightshift > howto->bitpos
00434                   && (bfd_signed_vma) relocation < 0)
00435                 {
00436                   check |= ((bfd_vma) - 1
00437                            & ~((bfd_vma) - 1
00438                               >> (howto->rightshift - howto->bitpos)));
00439                   if (((bfd_vma) check & ~reloc_bits)
00440                      != (-(bfd_vma) 1 & ~reloc_bits))
00441                     flag = bfd_reloc_overflow;
00442                 }
00443               else
00444                 flag = bfd_reloc_overflow;
00445              }
00446          }
00447          break;
00448        default:
00449          abort ();
00450        }
00451     }
00452 
00453   /* Either we are relocating all the way, or we don't want to apply
00454      the relocation to the reloc entry (probably because there isn't
00455      any room in the output format to describe addends to relocs).  */
00456 
00457   /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
00458      (OSF version 1.3, compiler version 3.11).  It miscompiles the
00459      following program:
00460 
00461      struct str
00462      {
00463        unsigned int i0;
00464      } s = { 0 };
00465 
00466      int
00467      main ()
00468      {
00469        unsigned long x;
00470 
00471        x = 0x100000000;
00472        x <<= (unsigned long) s.i0;
00473        if (x == 0)
00474         printf ("failed\n");
00475        else
00476         printf ("succeeded (%lx)\n", x);
00477      }
00478      */
00479 
00480   relocation >>= (bfd_vma) howto->rightshift;
00481 
00482   /* Shift everything up to where it's going to be used.  */
00483   relocation <<= (bfd_vma) howto->bitpos;
00484 
00485   /* Wait for the day when all have the mask in them.  */
00486 
00487   /* What we do:
00488      i instruction to be left alone
00489      o offset within instruction
00490      r relocation offset to apply
00491      S src mask
00492      D dst mask
00493      N ~dst mask
00494      A part 1
00495      B part 2
00496      R result
00497 
00498      Do this:
00499      i i i i i o o o o o        from bfd_get<size>
00500      and           S S S S S    to get the size offset we want
00501      +   r r r r r r r r r r  to get the final value to place
00502      and           D D D D D  to chop to right size
00503      -----------------------
00504      A A A A A
00505      And this:
00506      ...   i i i i i o o o o o  from bfd_get<size>
00507      and   N N N N N            get instruction
00508      -----------------------
00509      ...   B B B B B
00510 
00511      And then:
00512      B B B B B
00513      or              A A A A A
00514      -----------------------
00515      R R R R R R R R R R        put into bfd_put<size>.  */
00516 
00517 #define DOIT(x) \
00518   x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) +  relocation) & howto->dst_mask))
00519 
00520   location = (bfd_byte *) data + addr;
00521   switch (howto->size)
00522     {
00523     case 0:
00524       {
00525        bfd_vma x = get_data (location, 1);
00526        DOIT (x);
00527        put_data ((bfd_vma) x, location, 1);
00528       }
00529       break;
00530 
00531     case 1:
00532       if (relocation)
00533        {
00534          bfd_vma x = get_data (location, 2);
00535          DOIT (x);
00536          put_data ((bfd_vma) x, location, 2);
00537        }
00538       break;
00539     case 2:
00540       if (relocation)
00541        {
00542          bfd_vma x = get_data (location, 4);
00543          DOIT (x);
00544          put_data ((bfd_vma) x, location, 4);
00545        }
00546       break;
00547     case -2:
00548       {
00549        bfd_vma x = get_data (location, 4);
00550        relocation = -relocation;
00551        DOIT(x);
00552        put_data ((bfd_vma) x, location, 4);
00553       }
00554       break;
00555 
00556     case 3:
00557       /* Do nothing.  */
00558       break;
00559 
00560     case 4:
00561 #ifdef BFD64
00562       if (relocation)
00563        {
00564          bfd_vma x = get_data (location, 8);
00565          DOIT (x);
00566          put_data (x, location, 8);
00567        }
00568 #else
00569       abort ();
00570 #endif
00571       break;
00572     default:
00573       return bfd_reloc_other;
00574     }
00575   if ((howto->complain_on_overflow != complain_overflow_dont) && overflow)
00576     return bfd_reloc_overflow;
00577 
00578   return flag;
00579 }
00580 
00581 /* Relocate a given location using a given value and howto.  */
00582 
00583 bfd_reloc_status_type
00584 _bfd_do_ns32k_reloc_contents (howto, input_bfd, relocation, location,
00585                            get_data, put_data)
00586      reloc_howto_type *howto;
00587      bfd *input_bfd ATTRIBUTE_UNUSED;
00588      bfd_vma relocation;
00589      bfd_byte *location;
00590      bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
00591      void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
00592 {
00593   int size;
00594   bfd_vma x;
00595   bfd_boolean overflow;
00596 
00597   /* If the size is negative, negate RELOCATION.  This isn't very
00598      general.  */
00599   if (howto->size < 0)
00600     relocation = -relocation;
00601 
00602   /* Get the value we are going to relocate.  */
00603   size = bfd_get_reloc_size (howto);
00604   switch (size)
00605     {
00606     default:
00607     case 0:
00608       abort ();
00609     case 1:
00610     case 2:
00611     case 4:
00612 #ifdef BFD64
00613     case 8:
00614 #endif
00615       x = get_data (location, size);
00616       break;
00617     }
00618 
00619   /* Check for overflow.  FIXME: We may drop bits during the addition
00620      which we don't check for.  We must either check at every single
00621      operation, which would be tedious, or we must do the computations
00622      in a type larger than bfd_vma, which would be inefficient.  */
00623   overflow = FALSE;
00624   if (howto->complain_on_overflow != complain_overflow_dont)
00625     {
00626       bfd_vma check;
00627       bfd_signed_vma signed_check;
00628       bfd_vma add;
00629       bfd_signed_vma signed_add;
00630 
00631       if (howto->rightshift == 0)
00632        {
00633          check = relocation;
00634          signed_check = (bfd_signed_vma) relocation;
00635        }
00636       else
00637        {
00638          /* Drop unwanted bits from the value we are relocating to.  */
00639          check = relocation >> howto->rightshift;
00640 
00641          /* If this is a signed value, the rightshift just dropped
00642             leading 1 bits (assuming twos complement).  */
00643          if ((bfd_signed_vma) relocation >= 0)
00644            signed_check = check;
00645          else
00646            signed_check = (check
00647                          | ((bfd_vma) - 1
00648                             & ~((bfd_vma) - 1 >> howto->rightshift)));
00649        }
00650 
00651       /* Get the value from the object file.  */
00652       add = x & howto->src_mask;
00653 
00654       /* Get the value from the object file with an appropriate sign.
00655         The expression involving howto->src_mask isolates the upper
00656         bit of src_mask.  If that bit is set in the value we are
00657         adding, it is negative, and we subtract out that number times
00658         two.  If src_mask includes the highest possible bit, then we
00659         can not get the upper bit, but that does not matter since
00660         signed_add needs no adjustment to become negative in that
00661         case.  */
00662       signed_add = add;
00663       if ((add & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0)
00664        signed_add -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1;
00665 
00666       /* Add the value from the object file, shifted so that it is a
00667         straight number.  */
00668       if (howto->bitpos == 0)
00669        {
00670          check += add;
00671          signed_check += signed_add;
00672        }
00673       else
00674        {
00675          check += add >> howto->bitpos;
00676 
00677          /* For the signed case we use ADD, rather than SIGNED_ADD,
00678             to avoid warnings from SVR4 cc.  This is OK since we
00679             explicitly handle the sign bits.  */
00680          if (signed_add >= 0)
00681            signed_check += add >> howto->bitpos;
00682          else
00683            signed_check += ((add >> howto->bitpos)
00684                           | ((bfd_vma) - 1
00685                             & ~((bfd_vma) - 1 >> howto->bitpos)));
00686        }
00687 
00688       switch (howto->complain_on_overflow)
00689        {
00690        case complain_overflow_signed:
00691          {
00692            /* Assumes two's complement.  */
00693            bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
00694            bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
00695 
00696            if (signed_check > reloc_signed_max
00697               || signed_check < reloc_signed_min)
00698              overflow = TRUE;
00699          }
00700          break;
00701        case complain_overflow_unsigned:
00702          {
00703            /* Assumes two's complement.  This expression avoids
00704               overflow if howto->bitsize is the number of bits in
00705               bfd_vma.  */
00706            bfd_vma reloc_unsigned_max =
00707            (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
00708 
00709            if (check > reloc_unsigned_max)
00710              overflow = TRUE;
00711          }
00712          break;
00713        case complain_overflow_bitfield:
00714          {
00715            /* Assumes two's complement.  This expression avoids
00716               overflow if howto->bitsize is the number of bits in
00717               bfd_vma.  */
00718            bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
00719 
00720            if ((check & ~reloc_bits) != 0
00721               && (((bfd_vma) signed_check & ~reloc_bits)
00722                   != (-(bfd_vma) 1 & ~reloc_bits)))
00723              overflow = TRUE;
00724          }
00725          break;
00726        default:
00727          abort ();
00728        }
00729     }
00730 
00731   /* Put RELOCATION in the right bits.  */
00732   relocation >>= (bfd_vma) howto->rightshift;
00733   relocation <<= (bfd_vma) howto->bitpos;
00734 
00735   /* Add RELOCATION to the right bits of X.  */
00736   x = ((x & ~howto->dst_mask)
00737        | (((x & howto->src_mask) + relocation) & howto->dst_mask));
00738 
00739   /* Put the relocated value back in the object file.  */
00740   switch (size)
00741     {
00742     default:
00743     case 0:
00744       abort ();
00745     case 1:
00746     case 2:
00747     case 4:
00748 #ifdef BFD64
00749     case 8:
00750 #endif
00751       put_data (x, location, size);
00752       break;
00753     }
00754 
00755   return overflow ? bfd_reloc_overflow : bfd_reloc_ok;
00756 }
00757 
00758 bfd_reloc_status_type
00759 _bfd_ns32k_reloc_disp (abfd, reloc_entry, symbol, data, input_section,
00760                      output_bfd, error_message)
00761      bfd *abfd;
00762      arelent *reloc_entry;
00763      struct bfd_symbol *symbol;
00764      PTR data;
00765      asection *input_section;
00766      bfd *output_bfd;
00767      char **error_message;
00768 {
00769   return do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section,
00770                       output_bfd, error_message,
00771                       _bfd_ns32k_get_displacement,
00772                       _bfd_ns32k_put_displacement);
00773 }
00774 
00775 bfd_reloc_status_type
00776 _bfd_ns32k_reloc_imm (abfd, reloc_entry, symbol, data, input_section,
00777                     output_bfd, error_message)
00778      bfd *abfd;
00779      arelent *reloc_entry;
00780      struct bfd_symbol *symbol;
00781      PTR data;
00782      asection *input_section;
00783      bfd *output_bfd;
00784      char **error_message;
00785 {
00786   return do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section,
00787                       output_bfd, error_message, _bfd_ns32k_get_immediate,
00788                       _bfd_ns32k_put_immediate);
00789 }
00790 
00791 bfd_reloc_status_type
00792 _bfd_ns32k_final_link_relocate (howto, input_bfd, input_section, contents,
00793                             address, value, addend)
00794      reloc_howto_type *howto;
00795      bfd *input_bfd;
00796      asection *input_section;
00797      bfd_byte *contents;
00798      bfd_vma address;
00799      bfd_vma value;
00800      bfd_vma addend;
00801 {
00802   bfd_vma relocation;
00803 
00804   /* Sanity check the address.  */
00805   if (address > bfd_get_section_limit (input_bfd, input_section))
00806     return bfd_reloc_outofrange;
00807 
00808   /* This function assumes that we are dealing with a basic relocation
00809      against a symbol.  We want to compute the value of the symbol to
00810      relocate to.  This is just VALUE, the value of the symbol, plus
00811      ADDEND, any addend associated with the reloc.  */
00812   relocation = value + addend;
00813 
00814   /* If the relocation is PC relative, we want to set RELOCATION to
00815      the distance between the symbol (currently in RELOCATION) and the
00816      location we are relocating.  Some targets (e.g., i386-aout)
00817      arrange for the contents of the section to be the negative of the
00818      offset of the location within the section; for such targets
00819      pcrel_offset is FALSE.  Other targets (e.g., m88kbcs or ELF)
00820      simply leave the contents of the section as zero; for such
00821      targets pcrel_offset is TRUE.  If pcrel_offset is FALSE we do not
00822      need to subtract out the offset of the location within the
00823      section (which is just ADDRESS).  */
00824   if (howto->pc_relative)
00825     {
00826       relocation -= (input_section->output_section->vma
00827                    + input_section->output_offset);
00828       if (howto->pcrel_offset)
00829        relocation -= address;
00830     }
00831 
00832   return _bfd_ns32k_relocate_contents (howto, input_bfd, relocation,
00833                                    contents + address);
00834 }