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

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [cpu-ns32k.c] - Blame information for rev 167

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

Line No. Rev Author Line
1 14 khays
/* BFD support for the ns32k architecture.
2
   Copyright 1990, 1991, 1994, 1995, 1998, 1999, 2000, 2001, 2002, 2003,
3
   2004, 2005, 2007 Free Software Foundation, Inc.
4
   Almost totally rewritten by Ian Dall from initial work
5
   by Andrew Cagney.
6
 
7
   This file is part of BFD, the Binary File Descriptor library.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22
   MA 02110-1301, USA.  */
23
 
24
#include "sysdep.h"
25
#include "bfd.h"
26
#include "libbfd.h"
27
#include "ns32k.h"
28
 
29
#define N(machine, printable, d, next)  \
30 166 khays
{  32, 32, 8, bfd_arch_ns32k, machine, "ns32k",printable,3,d, \
31
   bfd_default_compatible,bfd_default_scan,bfd_arch_default_fill,next, }
32 14 khays
 
33
static const bfd_arch_info_type arch_info_struct[] =
34
{
35
  N(32532,"ns32k:32532",TRUE, 0), /* The word ns32k will match this too.  */
36
};
37
 
38
const bfd_arch_info_type bfd_ns32k_arch =
39
  N(32032,"ns32k:32032",FALSE, &arch_info_struct[0]);
40
 
41
static bfd_reloc_status_type do_ns32k_reloc
42
  PARAMS ((bfd *, arelent *, struct bfd_symbol *, PTR, asection *,
43
           bfd *, char **,
44
           bfd_vma (*) (bfd_byte *, int),
45
           void (*) (bfd_vma, bfd_byte *, int)));
46
 
47
bfd_vma
48
_bfd_ns32k_get_displacement (buffer, size)
49
     bfd_byte *buffer;
50
     int size;
51
{
52
  bfd_signed_vma value;
53
 
54
  switch (size)
55
    {
56
    case 1:
57
      value = ((*buffer & 0x7f) ^ 0x40) - 0x40;
58
      break;
59
 
60
    case 2:
61
      value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
62
      value = (value << 8) | (0xff & *buffer);
63
      break;
64
 
65
    case 4:
66
      value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
67
      value = (value << 8) | (0xff & *buffer++);
68
      value = (value << 8) | (0xff & *buffer++);
69
      value = (value << 8) | (0xff & *buffer);
70
      break;
71
 
72
    default:
73
      abort ();
74
      return 0;
75
    }
76
 
77
  return value;
78
}
79
 
80
void
81
_bfd_ns32k_put_displacement (value, buffer, size)
82
     bfd_vma value;
83
     bfd_byte *buffer;
84
     int size;
85
{
86
  switch (size)
87
    {
88
    case 1:
89
      value &= 0x7f;
90
      *buffer++ = value;
91
      break;
92
 
93
    case 2:
94
      value &= 0x3fff;
95
      value |= 0x8000;
96
      *buffer++ = (value >> 8);
97
      *buffer++ = value;
98
      break;
99
 
100
    case 4:
101
      value |= (bfd_vma) 0xc0000000;
102
      *buffer++ = (value >> 24);
103
      *buffer++ = (value >> 16);
104
      *buffer++ = (value >> 8);
105
      *buffer++ = value;
106
      break;
107
  }
108
  return;
109
}
110
 
111
bfd_vma
112
_bfd_ns32k_get_immediate (buffer, size)
113
     bfd_byte *buffer;
114
     int size;
115
{
116
  bfd_vma value = 0;
117
 
118
  switch (size)
119
    {
120
    case 4:
121
      value = (value << 8) | (*buffer++ & 0xff);
122
      value = (value << 8) | (*buffer++ & 0xff);
123
    case 2:
124
      value = (value << 8) | (*buffer++ & 0xff);
125
    case 1:
126
      value = (value << 8) | (*buffer++ & 0xff);
127
      break;
128
    default:
129
      abort ();
130
    }
131
  return value;
132
}
133
 
134
void
135
_bfd_ns32k_put_immediate (value, buffer, size)
136
     bfd_vma value;
137
     bfd_byte *buffer;
138
     int size;
139
{
140
  buffer += size - 1;
141
  switch (size)
142
    {
143
    case 4:
144
      *buffer-- = (value & 0xff); value >>= 8;
145
      *buffer-- = (value & 0xff); value >>= 8;
146
    case 2:
147
      *buffer-- = (value & 0xff); value >>= 8;
148
    case 1:
149
      *buffer-- = (value & 0xff); value >>= 8;
150
    }
151
}
152
 
153
/* This is just like the standard perform_relocation except we
154
   use get_data and put_data which know about the ns32k storage
155
   methods.  This is probably a lot more complicated than it
156
   needs to be!  */
157
 
158
static bfd_reloc_status_type
159
do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
160
                error_message, get_data, put_data)
161
     bfd *abfd;
162
     arelent *reloc_entry;
163
     struct bfd_symbol *symbol;
164
     PTR data;
165
     asection *input_section;
166
     bfd *output_bfd;
167
     char **error_message ATTRIBUTE_UNUSED;
168
     bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
169
     void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
170
{
171
  int overflow = 0;
172
  bfd_vma relocation;
173
  bfd_reloc_status_type flag = bfd_reloc_ok;
174
  bfd_size_type addr = reloc_entry->address;
175
  bfd_vma output_base = 0;
176
  reloc_howto_type *howto = reloc_entry->howto;
177
  asection *reloc_target_output_section;
178
  bfd_byte *location;
179
 
180
  if ((symbol->section == &bfd_abs_section)
181
      && output_bfd != (bfd *) NULL)
182
    {
183
      reloc_entry->address += input_section->output_offset;
184
      return bfd_reloc_ok;
185
    }
186
 
187
  /* If we are not producing relocatable output, return an error if
188
     the symbol is not defined.  An undefined weak symbol is
189
     considered to have a value of zero (SVR4 ABI, p. 4-27).  */
190
  if (symbol->section == &bfd_und_section
191
      && (symbol->flags & BSF_WEAK) == 0
192
      && output_bfd == (bfd *) NULL)
193
    flag = bfd_reloc_undefined;
194
 
195
  /* Is the address of the relocation really within the section?  */
196
  if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
197
    return bfd_reloc_outofrange;
198
 
199
  /* Work out which section the relocation is targeted at and the
200
     initial relocation command value.  */
201
 
202
  /* Get symbol value.  (Common symbols are special.)  */
203
  if (bfd_is_com_section (symbol->section))
204
    relocation = 0;
205
  else
206
    relocation = symbol->value;
207
 
208
  reloc_target_output_section = symbol->section->output_section;
209
 
210
  /* Convert input-section-relative symbol value to absolute.  */
211
  if (output_bfd != NULL && ! howto->partial_inplace)
212
    output_base = 0;
213
  else
214
    output_base = reloc_target_output_section->vma;
215
 
216
  relocation += output_base + symbol->section->output_offset;
217
 
218
  /* Add in supplied addend.  */
219
  relocation += reloc_entry->addend;
220
 
221
  /* Here the variable relocation holds the final address of the
222
     symbol we are relocating against, plus any addend.  */
223
 
224
  if (howto->pc_relative)
225
    {
226
      /* This is a PC relative relocation.  We want to set RELOCATION
227
         to the distance between the address of the symbol and the
228
         location.  RELOCATION is already the address of the symbol.
229
 
230
         We start by subtracting the address of the section containing
231
         the location.
232
 
233
         If pcrel_offset is set, we must further subtract the position
234
         of the location within the section.  Some targets arrange for
235
         the addend to be the negative of the position of the location
236
         within the section; for example, i386-aout does this.  For
237
         i386-aout, pcrel_offset is FALSE.  Some other targets do not
238
         include the position of the location; for example, m88kbcs,
239
         or ELF.  For those targets, pcrel_offset is TRUE.
240
 
241
         If we are producing relocatable output, then we must ensure
242
         that this reloc will be correctly computed when the final
243
         relocation is done.  If pcrel_offset is FALSE we want to wind
244
         up with the negative of the location within the section,
245
         which means we must adjust the existing addend by the change
246
         in the location within the section.  If pcrel_offset is TRUE
247
         we do not want to adjust the existing addend at all.
248
 
249
         FIXME: This seems logical to me, but for the case of
250
         producing relocatable output it is not what the code
251
         actually does.  I don't want to change it, because it seems
252
         far too likely that something will break.  */
253
      relocation -=
254
        input_section->output_section->vma + input_section->output_offset;
255
 
256
      if (howto->pcrel_offset)
257
        relocation -= reloc_entry->address;
258
    }
259
 
260
  if (output_bfd != (bfd *) NULL)
261
    {
262
      if (! howto->partial_inplace)
263
        {
264
          /* This is a partial relocation, and we want to apply the relocation
265
             to the reloc entry rather than the raw data. Modify the reloc
266
             inplace to reflect what we now know.  */
267
          reloc_entry->addend = relocation;
268
          reloc_entry->address += input_section->output_offset;
269
          return flag;
270
        }
271
      else
272
        {
273
          /* This is a partial relocation, but inplace, so modify the
274
             reloc record a bit.
275
 
276
             If we've relocated with a symbol with a section, change
277
             into a ref to the section belonging to the symbol.  */
278
 
279
          reloc_entry->address += input_section->output_offset;
280
 
281
          /* WTF?? */
282
          if (abfd->xvec->flavour == bfd_target_coff_flavour)
283
            {
284
              /* For m68k-coff, the addend was being subtracted twice during
285
                 relocation with -r.  Removing the line below this comment
286
                 fixes that problem; see PR 2953.
287
 
288
                 However, Ian wrote the following, regarding removing the line
289
                 below, which explains why it is still enabled:  --djm
290
 
291
                 If you put a patch like that into BFD you need to check all
292
                 the COFF linkers.  I am fairly certain that patch will break
293
                 coff-i386 (e.g., SCO); see coff_i386_reloc in coff-i386.c
294
                 where I worked around the problem in a different way.  There
295
                 may very well be a reason that the code works as it does.
296
 
297
                 Hmmm.  The first obvious point is that bfd_perform_relocation
298
                 should not have any tests that depend upon the flavour.  It's
299
                 seem like entirely the wrong place for such a thing.  The
300
                 second obvious point is that the current code ignores the
301
                 reloc addend when producing relocatable output for COFF.
302
                 That's peculiar.  In fact, I really have no idea what the
303
                 point of the line you want to remove is.
304
 
305
                 A typical COFF reloc subtracts the old value of the symbol
306
                 and adds in the new value to the location in the object file
307
                 (if it's a pc relative reloc it adds the difference between
308
                 the symbol value and the location).  When relocating we need
309
                 to preserve that property.
310
 
311
                 BFD handles this by setting the addend to the negative of the
312
                 old value of the symbol.  Unfortunately it handles common
313
                 symbols in a non-standard way (it doesn't subtract the old
314
                 value) but that's a different story (we can't change it
315
                 without losing backward compatibility with old object files)
316
                 (coff-i386 does subtract the old value, to be compatible with
317
                 existing coff-i386 targets, like SCO).
318
 
319
                 So everything works fine when not producing relocatable
320
                 output.  When we are producing relocatable output, logically
321
                 we should do exactly what we do when not producing
322
                 relocatable output.  Therefore, your patch is correct.  In
323
                 fact, it should probably always just set reloc_entry->addend
324
                 to 0 for all cases, since it is, in fact, going to add the
325
                 value into the object file.  This won't hurt the COFF code,
326
                 which doesn't use the addend; I'm not sure what it will do
327
                 to other formats (the thing to check for would be whether
328
                 any formats both use the addend and set partial_inplace).
329
 
330
                 When I wanted to make coff-i386 produce relocatable output,
331
                 I ran into the problem that you are running into: I wanted
332
                 to remove that line.  Rather than risk it, I made the
333
                 coff-i386 relocs use a special function; it's coff_i386_reloc
334
                 in coff-i386.c.  The function specifically adds the addend
335
                 field into the object file, knowing that bfd_perform_relocation
336
                 is not going to.  If you remove that line, then coff-i386.c
337
                 will wind up adding the addend field in twice.  It's trivial
338
                 to fix; it just needs to be done.
339
 
340
                 The problem with removing the line is just that it may break
341
                 some working code.  With BFD it's hard to be sure of anything.
342
                 The right way to deal with this is simply to build and test at
343
                 least all the supported COFF targets.  It should be
344
                 straightforward if time and disk space consuming.  For each
345
                 target:
346
                   1) build the linker
347
                   2) generate some executable, and link it using -r (I would
348
                      probably use paranoia.o and link against newlib/libc.a,
349
                      which for all the supported targets would be available in
350
                      /usr/cygnus/progressive/H-host/target/lib/libc.a).
351
                   3) make the change to reloc.c
352
                   4) rebuild the linker
353
                   5) repeat step 2
354
                   6) if the resulting object files are the same, you have at
355
                      least made it no worse
356
                   7) if they are different you have to figure out which
357
                      version is right.  */
358
              relocation -= reloc_entry->addend;
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
 
585
bfd_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
 
760
bfd_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
 
777
bfd_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
 
793
bfd_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
}

powered by: WebSVN 2.1.0

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