OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [bfd/] [cpu-ns32k.c] - Blame information for rev 1778

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.