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