Fix bugs and remove compile time warnings for N"32K port.
[external/binutils.git] / bfd / cpu-ns32k.c
1 /* BFD support for the ns32k architecture.
2    Copyright 1990, 1991, 1994, 1995, 1998, 2000, 2001, 2002
3    Free Software Foundation, Inc.
4    Almost totally rewritten by Ian Dall from initial work
5    by Andrew Cagney.
6
7    This file is part of BFD, the Binary File Descriptor library.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
23 #include "bfd.h"
24 #include "sysdep.h"
25 #include "libbfd.h"
26 #include "ns32k.h"
27
28 #define N(machine, printable, d, next)  \
29 {  32, 32, 8, bfd_arch_ns32k, machine, "ns32k",printable,3,d,bfd_default_compatible,bfd_default_scan, next, }
30
31 static const bfd_arch_info_type arch_info_struct[] =
32 {
33   N(32532,"ns32k:32532",true, 0), /* The word ns32k will match this too.  */
34 };
35
36 const bfd_arch_info_type bfd_ns32k_arch =
37   N(32032,"ns32k:32032",false, &arch_info_struct[0]);
38
39 static bfd_reloc_status_type do_ns32k_reloc
40   PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
41            bfd *, char **,
42            bfd_vma (*) (bfd_byte *, int),
43            void (*) (bfd_vma, bfd_byte *, int)));
44
45 bfd_vma
46 _bfd_ns32k_get_displacement (buffer, size)
47      bfd_byte *buffer;
48      int size;
49 {
50   bfd_signed_vma value;
51
52   switch (size)
53     {
54     case 1:
55       value = ((*buffer & 0x7f) ^ 0x40) - 0x40;
56       break;
57
58     case 2:
59       value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
60       value = (value << 8) | (0xff & *buffer);
61       break;
62
63     case 4:
64       value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
65       value = (value << 8) | (0xff & *buffer++);
66       value = (value << 8) | (0xff & *buffer++);
67       value = (value << 8) | (0xff & *buffer);
68       break;
69
70     default:
71       abort ();
72       return 0;
73     }
74
75   return value;
76 }
77
78 void
79 _bfd_ns32k_put_displacement (value, buffer, size)
80      bfd_vma value;
81      bfd_byte *buffer;
82      int size;
83 {
84   switch (size)
85     {
86     case 1:
87       value &= 0x7f;
88       *buffer++ = value;
89       break;
90
91     case 2:
92       value &= 0x3fff;
93       value |= 0x8000;
94       *buffer++ = (value >> 8);
95       *buffer++ = value;
96       break;
97
98     case 4:
99       value |= (bfd_vma) 0xc0000000;
100       *buffer++ = (value >> 24);
101       *buffer++ = (value >> 16);
102       *buffer++ = (value >> 8);
103       *buffer++ = value;
104       break;
105   }
106   return;
107 }
108
109 bfd_vma
110 _bfd_ns32k_get_immediate (buffer, size)
111      bfd_byte *buffer;
112      int size;
113 {
114   bfd_vma value = 0;
115
116   switch (size)
117     {
118     case 4:
119       value = (value << 8) | (*buffer++ & 0xff);
120       value = (value << 8) | (*buffer++ & 0xff);
121     case 2:
122       value = (value << 8) | (*buffer++ & 0xff);
123     case 1:
124       value = (value << 8) | (*buffer++ & 0xff);
125       break;
126     default:
127       abort ();
128     }
129   return value;
130 }
131
132 void
133 _bfd_ns32k_put_immediate (value, buffer, size)
134      bfd_vma value;
135      bfd_byte *buffer;
136      int size;
137 {
138   buffer += size - 1;
139   switch (size)
140     {
141     case 4:
142       *buffer-- = (value & 0xff); value >>= 8;
143       *buffer-- = (value & 0xff); value >>= 8;
144     case 2:
145       *buffer-- = (value & 0xff); value >>= 8;
146     case 1:
147       *buffer-- = (value & 0xff); value >>= 8;
148     }
149 }
150
151 /* This is just like the standard perform_relocation except we
152    use get_data and put_data which know about the ns32k storage
153    methods.  This is probably a lot more complicated than it
154    needs to be!  */
155
156 static bfd_reloc_status_type
157 do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
158                 error_message, get_data, put_data)
159      bfd *abfd;
160      arelent *reloc_entry;
161      struct symbol_cache_entry *symbol;
162      PTR data;
163      asection *input_section;
164      bfd *output_bfd;
165      char **error_message ATTRIBUTE_UNUSED;
166      bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
167      void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
168 {
169   int overflow = 0;
170   bfd_vma relocation;
171   bfd_reloc_status_type flag = bfd_reloc_ok;
172   bfd_size_type addr = reloc_entry->address;
173   bfd_vma output_base = 0;
174   reloc_howto_type *howto = reloc_entry->howto;
175   asection *reloc_target_output_section;
176   bfd_byte *location;
177
178   if ((symbol->section == &bfd_abs_section)
179       && output_bfd != (bfd *) NULL)
180     {
181       reloc_entry->address += input_section->output_offset;
182       return bfd_reloc_ok;
183     }
184
185   /* If we are not producing relocateable output, return an error if
186      the symbol is not defined.  An undefined weak symbol is
187      considered to have a value of zero (SVR4 ABI, p. 4-27).  */
188   if (symbol->section == &bfd_und_section
189       && (symbol->flags & BSF_WEAK) == 0
190       && output_bfd == (bfd *) NULL)
191     flag = bfd_reloc_undefined;
192
193   /* Is the address of the relocation really within the section?  */
194   if (reloc_entry->address > input_section->_cooked_size)
195     return bfd_reloc_outofrange;
196
197   /* Work out which section the relocation is targetted at and the
198      initial relocation command value.  */
199
200   /* Get symbol value.  (Common symbols are special.)  */
201   if (bfd_is_com_section (symbol->section))
202     relocation = 0;
203   else
204     relocation = symbol->value;
205
206   reloc_target_output_section = symbol->section->output_section;
207
208   /* Convert input-section-relative symbol value to absolute.  */
209   if (output_bfd != NULL && ! howto->partial_inplace)
210     output_base = 0;
211   else
212     output_base = reloc_target_output_section->vma;
213
214   relocation += output_base + symbol->section->output_offset;
215
216   /* Add in supplied addend.  */
217   relocation += reloc_entry->addend;
218
219   /* Here the variable relocation holds the final address of the
220      symbol we are relocating against, plus any addend.  */
221
222   if (howto->pc_relative)
223     {
224       /* This is a PC relative relocation.  We want to set RELOCATION
225          to the distance between the address of the symbol and the
226          location.  RELOCATION is already the address of the symbol.
227
228          We start by subtracting the address of the section containing
229          the location.
230
231          If pcrel_offset is set, we must further subtract the position
232          of the location within the section.  Some targets arrange for
233          the addend to be the negative of the position of the location
234          within the section; for example, i386-aout does this.  For
235          i386-aout, pcrel_offset is false.  Some other targets do not
236          include the position of the location; for example, m88kbcs,
237          or ELF.  For those targets, pcrel_offset is true.
238
239          If we are producing relocateable output, then we must ensure
240          that this reloc will be correctly computed when the final
241          relocation is done.  If pcrel_offset is false we want to wind
242          up with the negative of the location within the section,
243          which means we must adjust the existing addend by the change
244          in the location within the section.  If pcrel_offset is true
245          we do not want to adjust the existing addend at all.
246
247          FIXME: This seems logical to me, but for the case of
248          producing relocateable output it is not what the code
249          actually does.  I don't want to change it, because it seems
250          far too likely that something will break.  */
251       relocation -=
252         input_section->output_section->vma + input_section->output_offset;
253
254       if (howto->pcrel_offset)
255         relocation -= reloc_entry->address;
256     }
257
258   if (output_bfd != (bfd *) NULL)
259     {
260       if (! howto->partial_inplace)
261         {
262           /* This is a partial relocation, and we want to apply the relocation
263              to the reloc entry rather than the raw data. Modify the reloc
264              inplace to reflect what we now know.  */
265           reloc_entry->addend = relocation;
266           reloc_entry->address += input_section->output_offset;
267           return flag;
268         }
269       else
270         {
271           /* This is a partial relocation, but inplace, so modify the
272              reloc record a bit.
273
274              If we've relocated with a symbol with a section, change
275              into a ref to the section belonging to the symbol.  */
276
277           reloc_entry->address += input_section->output_offset;
278
279           /* WTF?? */
280           if (abfd->xvec->flavour == bfd_target_coff_flavour)
281             {
282 #if 1
283               /* For m68k-coff, the addend was being subtracted twice during
284                  relocation with -r.  Removing the line below this comment
285                  fixes that problem; see PR 2953.
286
287                  However, Ian wrote the following, regarding removing the line
288                  below, which explains why it is still enabled:  --djm
289
290                  If you put a patch like that into BFD you need to check all
291                  the COFF linkers.  I am fairly certain that patch will break
292                  coff-i386 (e.g., SCO); see coff_i386_reloc in coff-i386.c
293                  where I worked around the problem in a different way.  There
294                  may very well be a reason that the code works as it does.
295
296                  Hmmm.  The first obvious point is that bfd_perform_relocation
297                  should not have any tests that depend upon the flavour.  It's
298                  seem like entirely the wrong place for such a thing.  The
299                  second obvious point is that the current code ignores the
300                  reloc addend when producing relocateable output for COFF.
301                  That's peculiar.  In fact, I really have no idea what the
302                  point of the line you want to remove is.
303
304                  A typical COFF reloc subtracts the old value of the symbol
305                  and adds in the new value to the location in the object file
306                  (if it's a pc relative reloc it adds the difference between
307                  the symbol value and the location).  When relocating we need
308                  to preserve that property.
309
310                  BFD handles this by setting the addend to the negative of the
311                  old value of the symbol.  Unfortunately it handles common
312                  symbols in a non-standard way (it doesn't subtract the old
313                  value) but that's a different story (we can't change it
314                  without losing backward compatibility with old object files)
315                  (coff-i386 does subtract the old value, to be compatible with
316                  existing coff-i386 targets, like SCO).
317
318                  So everything works fine when not producing relocateable
319                  output.  When we are producing relocateable output, logically
320                  we should do exactly what we do when not producing
321                  relocateable output.  Therefore, your patch is correct.  In
322                  fact, it should probably always just set reloc_entry->addend
323                  to 0 for all cases, since it is, in fact, going to add the
324                  value into the object file.  This won't hurt the COFF code,
325                  which doesn't use the addend; I'm not sure what it will do
326                  to other formats (the thing to check for would be whether
327                  any formats both use the addend and set partial_inplace).
328
329                  When I wanted to make coff-i386 produce relocateable output,
330                  I ran into the problem that you are running into: I wanted
331                  to remove that line.  Rather than risk it, I made the
332                  coff-i386 relocs use a special function; it's coff_i386_reloc
333                  in coff-i386.c.  The function specifically adds the addend
334                  field into the object file, knowing that bfd_perform_relocation
335                  is not going to.  If you remove that line, then coff-i386.c
336                  will wind up adding the addend field in twice.  It's trivial
337                  to fix; it just needs to be done.
338
339                  The problem with removing the line is just that it may break
340                  some working code.  With BFD it's hard to be sure of anything.
341                  The right way to deal with this is simply to build and test at
342                  least all the supported COFF targets.  It should be
343                  straightforward if time and disk space consuming.  For each
344                  target:
345                    1) build the linker
346                    2) generate some executable, and link it using -r (I would
347                       probably use paranoia.o and link against newlib/libc.a,
348                       which for all the supported targets would be available in
349                       /usr/cygnus/progressive/H-host/target/lib/libc.a).
350                    3) make the change to reloc.c
351                    4) rebuild the linker
352                    5) repeat step 2
353                    6) if the resulting object files are the same, you have at
354                       least made it no worse
355                    7) if they are different you have to figure out which
356                       version is right.  */
357               relocation -= reloc_entry->addend;
358 #endif
359               reloc_entry->addend = 0;
360             }
361           else
362             {
363               reloc_entry->addend = relocation;
364             }
365         }
366     }
367   else
368     {
369       reloc_entry->addend = 0;
370     }
371
372   /* FIXME: This overflow checking is incomplete, because the value
373      might have overflowed before we get here.  For a correct check we
374      need to compute the value in a size larger than bitsize, but we
375      can't reasonably do that for a reloc the same size as a host
376      machine word.
377      FIXME: We should also do overflow checking on the result after
378      adding in the value contained in the object file.  */
379   if (howto->complain_on_overflow != complain_overflow_dont)
380     {
381       bfd_vma check;
382
383       /* Get the value that will be used for the relocation, but
384          starting at bit position zero.  */
385       if (howto->rightshift > howto->bitpos)
386         check = relocation >> (howto->rightshift - howto->bitpos);
387       else
388         check = relocation << (howto->bitpos - howto->rightshift);
389       switch (howto->complain_on_overflow)
390         {
391         case complain_overflow_signed:
392           {
393             /* Assumes two's complement.  */
394             bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
395             bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
396
397             /* The above right shift is incorrect for a signed value.
398                Fix it up by forcing on the upper bits.  */
399             if (howto->rightshift > howto->bitpos
400                 && (bfd_signed_vma) relocation < 0)
401               check |= ((bfd_vma) - 1
402                         & ~((bfd_vma) - 1
403                             >> (howto->rightshift - howto->bitpos)));
404             if ((bfd_signed_vma) check > reloc_signed_max
405                 || (bfd_signed_vma) check < reloc_signed_min)
406               flag = bfd_reloc_overflow;
407           }
408           break;
409         case complain_overflow_unsigned:
410           {
411             /* Assumes two's complement.  This expression avoids
412                overflow if howto->bitsize is the number of bits in
413                bfd_vma.  */
414             bfd_vma reloc_unsigned_max =
415             (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
416
417             if ((bfd_vma) check > reloc_unsigned_max)
418               flag = bfd_reloc_overflow;
419           }
420           break;
421         case complain_overflow_bitfield:
422           {
423             /* Assumes two's complement.  This expression avoids
424                overflow if howto->bitsize is the number of bits in
425                bfd_vma.  */
426             bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
427
428             if (((bfd_vma) check & ~reloc_bits) != 0
429                 && (((bfd_vma) check & ~reloc_bits)
430                     != (-(bfd_vma) 1 & ~reloc_bits)))
431               {
432                 /* The above right shift is incorrect for a signed
433                    value.  See if turning on the upper bits fixes the
434                    overflow.  */
435                 if (howto->rightshift > howto->bitpos
436                     && (bfd_signed_vma) relocation < 0)
437                   {
438                     check |= ((bfd_vma) - 1
439                               & ~((bfd_vma) - 1
440                                   >> (howto->rightshift - howto->bitpos)));
441                     if (((bfd_vma) check & ~reloc_bits)
442                         != (-(bfd_vma) 1 & ~reloc_bits))
443                       flag = bfd_reloc_overflow;
444                   }
445                 else
446                   flag = bfd_reloc_overflow;
447               }
448           }
449           break;
450         default:
451           abort ();
452         }
453     }
454
455   /* Either we are relocating all the way, or we don't want to apply
456      the relocation to the reloc entry (probably because there isn't
457      any room in the output format to describe addends to relocs).  */
458
459   /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
460      (OSF version 1.3, compiler version 3.11).  It miscompiles the
461      following program:
462
463      struct str
464      {
465        unsigned int i0;
466      } s = { 0 };
467
468      int
469      main ()
470      {
471        unsigned long x;
472
473        x = 0x100000000;
474        x <<= (unsigned long) s.i0;
475        if (x == 0)
476          printf ("failed\n");
477        else
478          printf ("succeeded (%lx)\n", x);
479      }
480      */
481
482   relocation >>= (bfd_vma) howto->rightshift;
483
484   /* Shift everything up to where it's going to be used.  */
485   relocation <<= (bfd_vma) howto->bitpos;
486
487   /* Wait for the day when all have the mask in them.  */
488
489   /* What we do:
490      i instruction to be left alone
491      o offset within instruction
492      r relocation offset to apply
493      S src mask
494      D dst mask
495      N ~dst mask
496      A part 1
497      B part 2
498      R result
499
500      Do this:
501      i i i i i o o o o o        from bfd_get<size>
502      and           S S S S S    to get the size offset we want
503      +   r r r r r r r r r r  to get the final value to place
504      and           D D D D D  to chop to right size
505      -----------------------
506      A A A A A
507      And this:
508      ...   i i i i i o o o o o  from bfd_get<size>
509      and   N N N N N            get instruction
510      -----------------------
511      ...   B B B B B
512
513      And then:
514      B B B B B
515      or              A A A A A
516      -----------------------
517      R R R R R R R R R R        put into bfd_put<size>.  */
518
519 #define DOIT(x) \
520   x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) +  relocation) & howto->dst_mask))
521
522   location = (bfd_byte *) data + addr;
523   switch (howto->size)
524     {
525     case 0:
526       {
527         bfd_vma x = get_data (location, 1);
528         DOIT (x);
529         put_data ((bfd_vma) x, location, 1);
530       }
531       break;
532
533     case 1:
534       if (relocation)
535         {
536           bfd_vma x = get_data (location, 2);
537           DOIT (x);
538           put_data ((bfd_vma) x, location, 2);
539         }
540       break;
541     case 2:
542       if (relocation)
543         {
544           bfd_vma x = get_data (location, 4);
545           DOIT (x);
546           put_data ((bfd_vma) x, location, 4);
547         }
548       break;
549     case -2:
550       {
551         bfd_vma x = get_data (location, 4);
552         relocation = -relocation;
553         DOIT(x);
554         put_data ((bfd_vma) x, location, 4);
555       }
556       break;
557
558     case 3:
559       /* Do nothing.  */
560       break;
561
562     case 4:
563 #ifdef BFD64
564       if (relocation)
565         {
566           bfd_vma x = get_data (location, 8);
567           DOIT (x);
568           put_data (x, location, 8);
569         }
570 #else
571       abort ();
572 #endif
573       break;
574     default:
575       return bfd_reloc_other;
576     }
577   if ((howto->complain_on_overflow != complain_overflow_dont) && overflow)
578     return bfd_reloc_overflow;
579
580   return flag;
581 }
582
583 /* Relocate a given location using a given value and howto.  */
584
585 bfd_reloc_status_type
586 _bfd_do_ns32k_reloc_contents (howto, input_bfd, relocation, location,
587                               get_data, put_data)
588      reloc_howto_type *howto;
589      bfd *input_bfd ATTRIBUTE_UNUSED;
590      bfd_vma relocation;
591      bfd_byte *location;
592      bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
593      void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
594 {
595   int size;
596   bfd_vma x;
597   boolean overflow;
598
599   /* If the size is negative, negate RELOCATION.  This isn't very
600      general.  */
601   if (howto->size < 0)
602     relocation = -relocation;
603
604   /* Get the value we are going to relocate.  */
605   size = bfd_get_reloc_size (howto);
606   switch (size)
607     {
608     default:
609     case 0:
610       abort ();
611     case 1:
612     case 2:
613     case 4:
614 #ifdef BFD64
615     case 8:
616 #endif
617       x = get_data (location, size);
618       break;
619     }
620
621   /* Check for overflow.  FIXME: We may drop bits during the addition
622      which we don't check for.  We must either check at every single
623      operation, which would be tedious, or we must do the computations
624      in a type larger than bfd_vma, which would be inefficient.  */
625   overflow = false;
626   if (howto->complain_on_overflow != complain_overflow_dont)
627     {
628       bfd_vma check;
629       bfd_signed_vma signed_check;
630       bfd_vma add;
631       bfd_signed_vma signed_add;
632
633       if (howto->rightshift == 0)
634         {
635           check = relocation;
636           signed_check = (bfd_signed_vma) relocation;
637         }
638       else
639         {
640           /* Drop unwanted bits from the value we are relocating to.  */
641           check = relocation >> howto->rightshift;
642
643           /* If this is a signed value, the rightshift just dropped
644              leading 1 bits (assuming twos complement).  */
645           if ((bfd_signed_vma) relocation >= 0)
646             signed_check = check;
647           else
648             signed_check = (check
649                             | ((bfd_vma) - 1
650                                & ~((bfd_vma) - 1 >> howto->rightshift)));
651         }
652
653       /* Get the value from the object file.  */
654       add = x & howto->src_mask;
655
656       /* Get the value from the object file with an appropriate sign.
657          The expression involving howto->src_mask isolates the upper
658          bit of src_mask.  If that bit is set in the value we are
659          adding, it is negative, and we subtract out that number times
660          two.  If src_mask includes the highest possible bit, then we
661          can not get the upper bit, but that does not matter since
662          signed_add needs no adjustment to become negative in that
663          case.  */
664       signed_add = add;
665       if ((add & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0)
666         signed_add -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1;
667
668       /* Add the value from the object file, shifted so that it is a
669          straight number.  */
670       if (howto->bitpos == 0)
671         {
672           check += add;
673           signed_check += signed_add;
674         }
675       else
676         {
677           check += add >> howto->bitpos;
678
679           /* For the signed case we use ADD, rather than SIGNED_ADD,
680              to avoid warnings from SVR4 cc.  This is OK since we
681              explictly handle the sign bits.  */
682           if (signed_add >= 0)
683             signed_check += add >> howto->bitpos;
684           else
685             signed_check += ((add >> howto->bitpos)
686                              | ((bfd_vma) - 1
687                                 & ~((bfd_vma) - 1 >> howto->bitpos)));
688         }
689
690       switch (howto->complain_on_overflow)
691         {
692         case complain_overflow_signed:
693           {
694             /* Assumes two's complement.  */
695             bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
696             bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
697
698             if (signed_check > reloc_signed_max
699                 || signed_check < reloc_signed_min)
700               overflow = true;
701           }
702           break;
703         case complain_overflow_unsigned:
704           {
705             /* Assumes two's complement.  This expression avoids
706                overflow if howto->bitsize is the number of bits in
707                bfd_vma.  */
708             bfd_vma reloc_unsigned_max =
709             (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
710
711             if (check > reloc_unsigned_max)
712               overflow = true;
713           }
714           break;
715         case complain_overflow_bitfield:
716           {
717             /* Assumes two's complement.  This expression avoids
718                overflow if howto->bitsize is the number of bits in
719                bfd_vma.  */
720             bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
721
722             if ((check & ~reloc_bits) != 0
723                 && (((bfd_vma) signed_check & ~reloc_bits)
724                     != (-(bfd_vma) 1 & ~reloc_bits)))
725               overflow = true;
726           }
727           break;
728         default:
729           abort ();
730         }
731     }
732
733   /* Put RELOCATION in the right bits.  */
734   relocation >>= (bfd_vma) howto->rightshift;
735   relocation <<= (bfd_vma) howto->bitpos;
736
737   /* Add RELOCATION to the right bits of X.  */
738   x = ((x & ~howto->dst_mask)
739        | (((x & howto->src_mask) + relocation) & howto->dst_mask));
740
741   /* Put the relocated value back in the object file.  */
742   switch (size)
743     {
744     default:
745     case 0:
746       abort ();
747     case 1:
748     case 2:
749     case 4:
750 #ifdef BFD64
751     case 8:
752 #endif
753       put_data (x, location, size);
754       break;
755     }
756
757   return overflow ? bfd_reloc_overflow : bfd_reloc_ok;
758 }
759
760 bfd_reloc_status_type
761 _bfd_ns32k_reloc_disp (abfd, reloc_entry, symbol, data, input_section,
762                        output_bfd, error_message)
763      bfd *abfd;
764      arelent *reloc_entry;
765      struct symbol_cache_entry *symbol;
766      PTR data;
767      asection *input_section;
768      bfd *output_bfd;
769      char **error_message;
770 {
771   return do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section,
772                          output_bfd, error_message,
773                          _bfd_ns32k_get_displacement,
774                          _bfd_ns32k_put_displacement);
775 }
776
777 bfd_reloc_status_type
778 _bfd_ns32k_reloc_imm (abfd, reloc_entry, symbol, data, input_section,
779                       output_bfd, error_message)
780      bfd *abfd;
781      arelent *reloc_entry;
782      struct symbol_cache_entry *symbol;
783      PTR data;
784      asection *input_section;
785      bfd *output_bfd;
786      char **error_message;
787 {
788   return do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section,
789                          output_bfd, error_message, _bfd_ns32k_get_immediate,
790                          _bfd_ns32k_put_immediate);
791 }
792
793 bfd_reloc_status_type
794 _bfd_ns32k_final_link_relocate (howto, input_bfd, input_section, contents,
795                                 address, value, addend)
796      reloc_howto_type *howto;
797      bfd *input_bfd;
798      asection *input_section;
799      bfd_byte *contents;
800      bfd_vma address;
801      bfd_vma value;
802      bfd_vma addend;
803 {
804   bfd_vma relocation;
805
806   /* Sanity check the address.  */
807   if (address > input_section->_cooked_size)
808     return bfd_reloc_outofrange;
809
810   /* This function assumes that we are dealing with a basic relocation
811      against a symbol.  We want to compute the value of the symbol to
812      relocate to.  This is just VALUE, the value of the symbol, plus
813      ADDEND, any addend associated with the reloc.  */
814   relocation = value + addend;
815
816   /* If the relocation is PC relative, we want to set RELOCATION to
817      the distance between the symbol (currently in RELOCATION) and the
818      location we are relocating.  Some targets (e.g., i386-aout)
819      arrange for the contents of the section to be the negative of the
820      offset of the location within the section; for such targets
821      pcrel_offset is false.  Other targets (e.g., m88kbcs or ELF)
822      simply leave the contents of the section as zero; for such
823      targets pcrel_offset is true.  If pcrel_offset is false we do not
824      need to subtract out the offset of the location within the
825      section (which is just ADDRESS).  */
826   if (howto->pc_relative)
827     {
828       relocation -= (input_section->output_section->vma
829                      + input_section->output_offset);
830       if (howto->pcrel_offset)
831         relocation -= address;
832     }
833
834   return _bfd_ns32k_relocate_contents (howto, input_bfd, relocation,
835                                        contents + address);
836 }