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