OSDN Git Service

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