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