1/* BFD support for the ns32k architecture.
2   Copyright 1990, 1991, 1994, 1995, 1998, 2000, 2001, 2002, 2003, 2004
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
31static 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
36const bfd_arch_info_type bfd_ns32k_arch =
37  N(32032,"ns32k:32032",FALSE, &arch_info_struct[0]);
38
39static bfd_reloc_status_type do_ns32k_reloc
40  PARAMS ((bfd *, arelent *, struct bfd_symbol *, PTR, asection *,
41	   bfd *, char **,
42	   bfd_vma (*) (bfd_byte *, int),
43	   void (*) (bfd_vma, bfd_byte *, int)));
44
45bfd_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
78void
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
109bfd_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
132void
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
156static bfd_reloc_status_type
157do_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 bfd_symbol *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 relocatable 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 > bfd_get_section_limit (abfd, input_section))
195    return bfd_reloc_outofrange;
196
197  /* Work out which section the relocation is targeted 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 relocatable 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 relocatable 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 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#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
585bfd_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  bfd_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	     explicitly 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
760bfd_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 bfd_symbol *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
777bfd_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 bfd_symbol *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
793bfd_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 > bfd_get_section_limit (input_bfd, input_section))
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}
837