1/* BFD support for the ns32k architecture.
2   Copyright 1990, 1991, 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003,
3   2004, 2005 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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	      /* For m68k-coff, the addend was being subtracted twice during
283		 relocation with -r.  Removing the line below this comment
284		 fixes that problem; see PR 2953.
285
286		 However, Ian wrote the following, regarding removing the line
287		 below, which explains why it is still enabled:  --djm
288
289		 If you put a patch like that into BFD you need to check all
290		 the COFF linkers.  I am fairly certain that patch will break
291		 coff-i386 (e.g., SCO); see coff_i386_reloc in coff-i386.c
292		 where I worked around the problem in a different way.  There
293		 may very well be a reason that the code works as it does.
294
295		 Hmmm.  The first obvious point is that bfd_perform_relocation
296		 should not have any tests that depend upon the flavour.  It's
297		 seem like entirely the wrong place for such a thing.  The
298		 second obvious point is that the current code ignores the
299		 reloc addend when producing relocatable output for COFF.
300		 That's peculiar.  In fact, I really have no idea what the
301		 point of the line you want to remove is.
302
303		 A typical COFF reloc subtracts the old value of the symbol
304		 and adds in the new value to the location in the object file
305		 (if it's a pc relative reloc it adds the difference between
306		 the symbol value and the location).  When relocating we need
307		 to preserve that property.
308
309		 BFD handles this by setting the addend to the negative of the
310		 old value of the symbol.  Unfortunately it handles common
311		 symbols in a non-standard way (it doesn't subtract the old
312		 value) but that's a different story (we can't change it
313		 without losing backward compatibility with old object files)
314		 (coff-i386 does subtract the old value, to be compatible with
315		 existing coff-i386 targets, like SCO).
316
317		 So everything works fine when not producing relocatable
318		 output.  When we are producing relocatable output, logically
319		 we should do exactly what we do when not producing
320		 relocatable output.  Therefore, your patch is correct.  In
321		 fact, it should probably always just set reloc_entry->addend
322		 to 0 for all cases, since it is, in fact, going to add the
323		 value into the object file.  This won't hurt the COFF code,
324		 which doesn't use the addend; I'm not sure what it will do
325		 to other formats (the thing to check for would be whether
326		 any formats both use the addend and set partial_inplace).
327
328		 When I wanted to make coff-i386 produce relocatable output,
329		 I ran into the problem that you are running into: I wanted
330		 to remove that line.  Rather than risk it, I made the
331		 coff-i386 relocs use a special function; it's coff_i386_reloc
332		 in coff-i386.c.  The function specifically adds the addend
333		 field into the object file, knowing that bfd_perform_relocation
334		 is not going to.  If you remove that line, then coff-i386.c
335		 will wind up adding the addend field in twice.  It's trivial
336		 to fix; it just needs to be done.
337
338		 The problem with removing the line is just that it may break
339		 some working code.  With BFD it's hard to be sure of anything.
340		 The right way to deal with this is simply to build and test at
341		 least all the supported COFF targets.  It should be
342		 straightforward if time and disk space consuming.  For each
343		 target:
344		   1) build the linker
345		   2) generate some executable, and link it using -r (I would
346		      probably use paranoia.o and link against newlib/libc.a,
347		      which for all the supported targets would be available in
348		      /usr/cygnus/progressive/H-host/target/lib/libc.a).
349		   3) make the change to reloc.c
350		   4) rebuild the linker
351		   5) repeat step 2
352		   6) if the resulting object files are the same, you have at
353		      least made it no worse
354		   7) if they are different you have to figure out which
355		      version is right.  */
356	      relocation -= reloc_entry->addend;
357	      reloc_entry->addend = 0;
358	    }
359	  else
360	    {
361	      reloc_entry->addend = relocation;
362	    }
363	}
364    }
365  else
366    {
367      reloc_entry->addend = 0;
368    }
369
370  /* FIXME: This overflow checking is incomplete, because the value
371     might have overflowed before we get here.  For a correct check we
372     need to compute the value in a size larger than bitsize, but we
373     can't reasonably do that for a reloc the same size as a host
374     machine word.
375     FIXME: We should also do overflow checking on the result after
376     adding in the value contained in the object file.  */
377  if (howto->complain_on_overflow != complain_overflow_dont)
378    {
379      bfd_vma check;
380
381      /* Get the value that will be used for the relocation, but
382	 starting at bit position zero.  */
383      if (howto->rightshift > howto->bitpos)
384	check = relocation >> (howto->rightshift - howto->bitpos);
385      else
386	check = relocation << (howto->bitpos - howto->rightshift);
387      switch (howto->complain_on_overflow)
388	{
389	case complain_overflow_signed:
390	  {
391	    /* Assumes two's complement.  */
392	    bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
393	    bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
394
395	    /* The above right shift is incorrect for a signed value.
396	       Fix it up by forcing on the upper bits.  */
397	    if (howto->rightshift > howto->bitpos
398		&& (bfd_signed_vma) relocation < 0)
399	      check |= ((bfd_vma) - 1
400			& ~((bfd_vma) - 1
401			    >> (howto->rightshift - howto->bitpos)));
402	    if ((bfd_signed_vma) check > reloc_signed_max
403		|| (bfd_signed_vma) check < reloc_signed_min)
404	      flag = bfd_reloc_overflow;
405	  }
406	  break;
407	case complain_overflow_unsigned:
408	  {
409	    /* Assumes two's complement.  This expression avoids
410	       overflow if howto->bitsize is the number of bits in
411	       bfd_vma.  */
412	    bfd_vma reloc_unsigned_max =
413	    (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
414
415	    if ((bfd_vma) check > reloc_unsigned_max)
416	      flag = bfd_reloc_overflow;
417	  }
418	  break;
419	case complain_overflow_bitfield:
420	  {
421	    /* Assumes two's complement.  This expression avoids
422	       overflow if howto->bitsize is the number of bits in
423	       bfd_vma.  */
424	    bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
425
426	    if (((bfd_vma) check & ~reloc_bits) != 0
427		&& (((bfd_vma) check & ~reloc_bits)
428		    != (-(bfd_vma) 1 & ~reloc_bits)))
429	      {
430		/* The above right shift is incorrect for a signed
431		   value.  See if turning on the upper bits fixes the
432		   overflow.  */
433		if (howto->rightshift > howto->bitpos
434		    && (bfd_signed_vma) relocation < 0)
435		  {
436		    check |= ((bfd_vma) - 1
437			      & ~((bfd_vma) - 1
438				  >> (howto->rightshift - howto->bitpos)));
439		    if (((bfd_vma) check & ~reloc_bits)
440			!= (-(bfd_vma) 1 & ~reloc_bits))
441		      flag = bfd_reloc_overflow;
442		  }
443		else
444		  flag = bfd_reloc_overflow;
445	      }
446	  }
447	  break;
448	default:
449	  abort ();
450	}
451    }
452
453  /* Either we are relocating all the way, or we don't want to apply
454     the relocation to the reloc entry (probably because there isn't
455     any room in the output format to describe addends to relocs).  */
456
457  /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
458     (OSF version 1.3, compiler version 3.11).  It miscompiles the
459     following program:
460
461     struct str
462     {
463       unsigned int i0;
464     } s = { 0 };
465
466     int
467     main ()
468     {
469       unsigned long x;
470
471       x = 0x100000000;
472       x <<= (unsigned long) s.i0;
473       if (x == 0)
474	 printf ("failed\n");
475       else
476	 printf ("succeeded (%lx)\n", x);
477     }
478     */
479
480  relocation >>= (bfd_vma) howto->rightshift;
481
482  /* Shift everything up to where it's going to be used.  */
483  relocation <<= (bfd_vma) howto->bitpos;
484
485  /* Wait for the day when all have the mask in them.  */
486
487  /* What we do:
488     i instruction to be left alone
489     o offset within instruction
490     r relocation offset to apply
491     S src mask
492     D dst mask
493     N ~dst mask
494     A part 1
495     B part 2
496     R result
497
498     Do this:
499     i i i i i o o o o o        from bfd_get<size>
500     and           S S S S S    to get the size offset we want
501     +   r r r r r r r r r r  to get the final value to place
502     and           D D D D D  to chop to right size
503     -----------------------
504     A A A A A
505     And this:
506     ...   i i i i i o o o o o  from bfd_get<size>
507     and   N N N N N            get instruction
508     -----------------------
509     ...   B B B B B
510
511     And then:
512     B B B B B
513     or              A A A A A
514     -----------------------
515     R R R R R R R R R R        put into bfd_put<size>.  */
516
517#define DOIT(x) \
518  x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) +  relocation) & howto->dst_mask))
519
520  location = (bfd_byte *) data + addr;
521  switch (howto->size)
522    {
523    case 0:
524      {
525	bfd_vma x = get_data (location, 1);
526	DOIT (x);
527	put_data ((bfd_vma) x, location, 1);
528      }
529      break;
530
531    case 1:
532      if (relocation)
533	{
534	  bfd_vma x = get_data (location, 2);
535	  DOIT (x);
536	  put_data ((bfd_vma) x, location, 2);
537	}
538      break;
539    case 2:
540      if (relocation)
541	{
542	  bfd_vma x = get_data (location, 4);
543	  DOIT (x);
544	  put_data ((bfd_vma) x, location, 4);
545	}
546      break;
547    case -2:
548      {
549	bfd_vma x = get_data (location, 4);
550	relocation = -relocation;
551	DOIT(x);
552	put_data ((bfd_vma) x, location, 4);
553      }
554      break;
555
556    case 3:
557      /* Do nothing.  */
558      break;
559
560    case 4:
561#ifdef BFD64
562      if (relocation)
563	{
564	  bfd_vma x = get_data (location, 8);
565	  DOIT (x);
566	  put_data (x, location, 8);
567	}
568#else
569      abort ();
570#endif
571      break;
572    default:
573      return bfd_reloc_other;
574    }
575  if ((howto->complain_on_overflow != complain_overflow_dont) && overflow)
576    return bfd_reloc_overflow;
577
578  return flag;
579}
580
581/* Relocate a given location using a given value and howto.  */
582
583bfd_reloc_status_type
584_bfd_do_ns32k_reloc_contents (howto, input_bfd, relocation, location,
585			      get_data, put_data)
586     reloc_howto_type *howto;
587     bfd *input_bfd ATTRIBUTE_UNUSED;
588     bfd_vma relocation;
589     bfd_byte *location;
590     bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
591     void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
592{
593  int size;
594  bfd_vma x;
595  bfd_boolean overflow;
596
597  /* If the size is negative, negate RELOCATION.  This isn't very
598     general.  */
599  if (howto->size < 0)
600    relocation = -relocation;
601
602  /* Get the value we are going to relocate.  */
603  size = bfd_get_reloc_size (howto);
604  switch (size)
605    {
606    default:
607    case 0:
608      abort ();
609    case 1:
610    case 2:
611    case 4:
612#ifdef BFD64
613    case 8:
614#endif
615      x = get_data (location, size);
616      break;
617    }
618
619  /* Check for overflow.  FIXME: We may drop bits during the addition
620     which we don't check for.  We must either check at every single
621     operation, which would be tedious, or we must do the computations
622     in a type larger than bfd_vma, which would be inefficient.  */
623  overflow = FALSE;
624  if (howto->complain_on_overflow != complain_overflow_dont)
625    {
626      bfd_vma check;
627      bfd_signed_vma signed_check;
628      bfd_vma add;
629      bfd_signed_vma signed_add;
630
631      if (howto->rightshift == 0)
632	{
633	  check = relocation;
634	  signed_check = (bfd_signed_vma) relocation;
635	}
636      else
637	{
638	  /* Drop unwanted bits from the value we are relocating to.  */
639	  check = relocation >> howto->rightshift;
640
641	  /* If this is a signed value, the rightshift just dropped
642	     leading 1 bits (assuming twos complement).  */
643	  if ((bfd_signed_vma) relocation >= 0)
644	    signed_check = check;
645	  else
646	    signed_check = (check
647			    | ((bfd_vma) - 1
648			       & ~((bfd_vma) - 1 >> howto->rightshift)));
649	}
650
651      /* Get the value from the object file.  */
652      add = x & howto->src_mask;
653
654      /* Get the value from the object file with an appropriate sign.
655	 The expression involving howto->src_mask isolates the upper
656	 bit of src_mask.  If that bit is set in the value we are
657	 adding, it is negative, and we subtract out that number times
658	 two.  If src_mask includes the highest possible bit, then we
659	 can not get the upper bit, but that does not matter since
660	 signed_add needs no adjustment to become negative in that
661	 case.  */
662      signed_add = add;
663      if ((add & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0)
664	signed_add -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1;
665
666      /* Add the value from the object file, shifted so that it is a
667	 straight number.  */
668      if (howto->bitpos == 0)
669	{
670	  check += add;
671	  signed_check += signed_add;
672	}
673      else
674	{
675	  check += add >> howto->bitpos;
676
677	  /* For the signed case we use ADD, rather than SIGNED_ADD,
678	     to avoid warnings from SVR4 cc.  This is OK since we
679	     explicitly handle the sign bits.  */
680	  if (signed_add >= 0)
681	    signed_check += add >> howto->bitpos;
682	  else
683	    signed_check += ((add >> howto->bitpos)
684			     | ((bfd_vma) - 1
685				& ~((bfd_vma) - 1 >> howto->bitpos)));
686	}
687
688      switch (howto->complain_on_overflow)
689	{
690	case complain_overflow_signed:
691	  {
692	    /* Assumes two's complement.  */
693	    bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
694	    bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
695
696	    if (signed_check > reloc_signed_max
697		|| signed_check < reloc_signed_min)
698	      overflow = TRUE;
699	  }
700	  break;
701	case complain_overflow_unsigned:
702	  {
703	    /* Assumes two's complement.  This expression avoids
704	       overflow if howto->bitsize is the number of bits in
705	       bfd_vma.  */
706	    bfd_vma reloc_unsigned_max =
707	    (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
708
709	    if (check > reloc_unsigned_max)
710	      overflow = TRUE;
711	  }
712	  break;
713	case complain_overflow_bitfield:
714	  {
715	    /* Assumes two's complement.  This expression avoids
716	       overflow if howto->bitsize is the number of bits in
717	       bfd_vma.  */
718	    bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
719
720	    if ((check & ~reloc_bits) != 0
721		&& (((bfd_vma) signed_check & ~reloc_bits)
722		    != (-(bfd_vma) 1 & ~reloc_bits)))
723	      overflow = TRUE;
724	  }
725	  break;
726	default:
727	  abort ();
728	}
729    }
730
731  /* Put RELOCATION in the right bits.  */
732  relocation >>= (bfd_vma) howto->rightshift;
733  relocation <<= (bfd_vma) howto->bitpos;
734
735  /* Add RELOCATION to the right bits of X.  */
736  x = ((x & ~howto->dst_mask)
737       | (((x & howto->src_mask) + relocation) & howto->dst_mask));
738
739  /* Put the relocated value back in the object file.  */
740  switch (size)
741    {
742    default:
743    case 0:
744      abort ();
745    case 1:
746    case 2:
747    case 4:
748#ifdef BFD64
749    case 8:
750#endif
751      put_data (x, location, size);
752      break;
753    }
754
755  return overflow ? bfd_reloc_overflow : bfd_reloc_ok;
756}
757
758bfd_reloc_status_type
759_bfd_ns32k_reloc_disp (abfd, reloc_entry, symbol, data, input_section,
760		       output_bfd, error_message)
761     bfd *abfd;
762     arelent *reloc_entry;
763     struct bfd_symbol *symbol;
764     PTR data;
765     asection *input_section;
766     bfd *output_bfd;
767     char **error_message;
768{
769  return do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section,
770			 output_bfd, error_message,
771			 _bfd_ns32k_get_displacement,
772			 _bfd_ns32k_put_displacement);
773}
774
775bfd_reloc_status_type
776_bfd_ns32k_reloc_imm (abfd, reloc_entry, symbol, data, input_section,
777		      output_bfd, error_message)
778     bfd *abfd;
779     arelent *reloc_entry;
780     struct bfd_symbol *symbol;
781     PTR data;
782     asection *input_section;
783     bfd *output_bfd;
784     char **error_message;
785{
786  return do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section,
787			 output_bfd, error_message, _bfd_ns32k_get_immediate,
788			 _bfd_ns32k_put_immediate);
789}
790
791bfd_reloc_status_type
792_bfd_ns32k_final_link_relocate (howto, input_bfd, input_section, contents,
793				address, value, addend)
794     reloc_howto_type *howto;
795     bfd *input_bfd;
796     asection *input_section;
797     bfd_byte *contents;
798     bfd_vma address;
799     bfd_vma value;
800     bfd_vma addend;
801{
802  bfd_vma relocation;
803
804  /* Sanity check the address.  */
805  if (address > bfd_get_section_limit (input_bfd, input_section))
806    return bfd_reloc_outofrange;
807
808  /* This function assumes that we are dealing with a basic relocation
809     against a symbol.  We want to compute the value of the symbol to
810     relocate to.  This is just VALUE, the value of the symbol, plus
811     ADDEND, any addend associated with the reloc.  */
812  relocation = value + addend;
813
814  /* If the relocation is PC relative, we want to set RELOCATION to
815     the distance between the symbol (currently in RELOCATION) and the
816     location we are relocating.  Some targets (e.g., i386-aout)
817     arrange for the contents of the section to be the negative of the
818     offset of the location within the section; for such targets
819     pcrel_offset is FALSE.  Other targets (e.g., m88kbcs or ELF)
820     simply leave the contents of the section as zero; for such
821     targets pcrel_offset is TRUE.  If pcrel_offset is FALSE we do not
822     need to subtract out the offset of the location within the
823     section (which is just ADDRESS).  */
824  if (howto->pc_relative)
825    {
826      relocation -= (input_section->output_section->vma
827		     + input_section->output_offset);
828      if (howto->pcrel_offset)
829	relocation -= address;
830    }
831
832  return _bfd_ns32k_relocate_contents (howto, input_bfd, relocation,
833				       contents + address);
834}
835