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

Subversion Repositories or1k

[/] [or1k/] [tags/] [VER_5_3/] [gdb-5.3/] [bfd/] [cpu-ns32k.c] - Blame information for rev 1181

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

Line No. Rev Author Line
1 1181 sfurman
/* BFD support for the ns32k architecture.
2
   Copyright 1990, 1991, 1994, 1995, 1998, 2000, 2001, 2002
3
   Free Software Foundation, Inc.
4
   Almost totally rewritten by Ian Dall from initial work
5
   by Andrew Cagney.
6
 
7
   This file is part of BFD, the Binary File Descriptor library.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 2 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22
 
23
#include "bfd.h"
24
#include "sysdep.h"
25
#include "libbfd.h"
26
#include "ns32k.h"
27
 
28
#define N(machine, printable, d, next)  \
29
{  32, 32, 8, bfd_arch_ns32k, machine, "ns32k",printable,3,d,bfd_default_compatible,bfd_default_scan, next, }
30
 
31
static 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
 
36
const bfd_arch_info_type bfd_ns32k_arch =
37
  N(32032,"ns32k:32032",false, &arch_info_struct[0]);
38
 
39
static bfd_reloc_status_type do_ns32k_reloc
40
  PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
41
           bfd *, char **,
42
           bfd_vma (*) (bfd_byte *, int),
43
           void (*) (bfd_vma, bfd_byte *, int)));
44
 
45
bfd_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
 
78
void
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
 
109
bfd_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
 
132
void
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
 
156
static bfd_reloc_status_type
157
do_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 symbol_cache_entry *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 relocateable 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 > input_section->_cooked_size)
195
    return bfd_reloc_outofrange;
196
 
197
  /* Work out which section the relocation is targetted 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 relocateable 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 relocateable output it is not what the code
249
         actually does.  I don't want to change it, because it seems
250
         far too likely that something will break.  */
251
      relocation -=
252
        input_section->output_section->vma + input_section->output_offset;
253
 
254
      if (howto->pcrel_offset)
255
        relocation -= reloc_entry->address;
256
    }
257
 
258
  if (output_bfd != (bfd *) NULL)
259
    {
260
      if (! howto->partial_inplace)
261
        {
262
          /* This is a partial relocation, and we want to apply the relocation
263
             to the reloc entry rather than the raw data. Modify the reloc
264
             inplace to reflect what we now know.  */
265
          reloc_entry->addend = relocation;
266
          reloc_entry->address += input_section->output_offset;
267
          return flag;
268
        }
269
      else
270
        {
271
          /* This is a partial relocation, but inplace, so modify the
272
             reloc record a bit.
273
 
274
             If we've relocated with a symbol with a section, change
275
             into a ref to the section belonging to the symbol.  */
276
 
277
          reloc_entry->address += input_section->output_offset;
278
 
279
          /* WTF?? */
280
          if (abfd->xvec->flavour == bfd_target_coff_flavour)
281
            {
282
#if 1
283
              /* For m68k-coff, the addend was being subtracted twice during
284
                 relocation with -r.  Removing the line below this comment
285
                 fixes that problem; see PR 2953.
286
 
287
                 However, Ian wrote the following, regarding removing the line
288
                 below, which explains why it is still enabled:  --djm
289
 
290
                 If you put a patch like that into BFD you need to check all
291
                 the COFF linkers.  I am fairly certain that patch will break
292
                 coff-i386 (e.g., SCO); see coff_i386_reloc in coff-i386.c
293
                 where I worked around the problem in a different way.  There
294
                 may very well be a reason that the code works as it does.
295
 
296
                 Hmmm.  The first obvious point is that bfd_perform_relocation
297
                 should not have any tests that depend upon the flavour.  It's
298
                 seem like entirely the wrong place for such a thing.  The
299
                 second obvious point is that the current code ignores the
300
                 reloc addend when producing relocateable output for COFF.
301
                 That's peculiar.  In fact, I really have no idea what the
302
                 point of the line you want to remove is.
303
 
304
                 A typical COFF reloc subtracts the old value of the symbol
305
                 and adds in the new value to the location in the object file
306
                 (if it's a pc relative reloc it adds the difference between
307
                 the symbol value and the location).  When relocating we need
308
                 to preserve that property.
309
 
310
                 BFD handles this by setting the addend to the negative of the
311
                 old value of the symbol.  Unfortunately it handles common
312
                 symbols in a non-standard way (it doesn't subtract the old
313
                 value) but that's a different story (we can't change it
314
                 without losing backward compatibility with old object files)
315
                 (coff-i386 does subtract the old value, to be compatible with
316
                 existing coff-i386 targets, like SCO).
317
 
318
                 So everything works fine when not producing relocateable
319
                 output.  When we are producing relocateable output, logically
320
                 we should do exactly what we do when not producing
321
                 relocateable output.  Therefore, your patch is correct.  In
322
                 fact, it should probably always just set reloc_entry->addend
323
                 to 0 for all cases, since it is, in fact, going to add the
324
                 value into the object file.  This won't hurt the COFF code,
325
                 which doesn't use the addend; I'm not sure what it will do
326
                 to other formats (the thing to check for would be whether
327
                 any formats both use the addend and set partial_inplace).
328
 
329
                 When I wanted to make coff-i386 produce relocateable output,
330
                 I ran into the problem that you are running into: I wanted
331
                 to remove that line.  Rather than risk it, I made the
332
                 coff-i386 relocs use a special function; it's coff_i386_reloc
333
                 in coff-i386.c.  The function specifically adds the addend
334
                 field into the object file, knowing that bfd_perform_relocation
335
                 is not going to.  If you remove that line, then coff-i386.c
336
                 will wind up adding the addend field in twice.  It's trivial
337
                 to fix; it just needs to be done.
338
 
339
                 The problem with removing the line is just that it may break
340
                 some working code.  With BFD it's hard to be sure of anything.
341
                 The right way to deal with this is simply to build and test at
342
                 least all the supported COFF targets.  It should be
343
                 straightforward if time and disk space consuming.  For each
344
                 target:
345
                   1) build the linker
346
                   2) generate some executable, and link it using -r (I would
347
                      probably use paranoia.o and link against newlib/libc.a,
348
                      which for all the supported targets would be available in
349
                      /usr/cygnus/progressive/H-host/target/lib/libc.a).
350
                   3) make the change to reloc.c
351
                   4) rebuild the linker
352
                   5) repeat step 2
353
                   6) if the resulting object files are the same, you have at
354
                      least made it no worse
355
                   7) if they are different you have to figure out which
356
                      version is right.  */
357
              relocation -= reloc_entry->addend;
358
#endif
359
              reloc_entry->addend = 0;
360
            }
361
          else
362
            {
363
              reloc_entry->addend = relocation;
364
            }
365
        }
366
    }
367
  else
368
    {
369
      reloc_entry->addend = 0;
370
    }
371
 
372
  /* FIXME: This overflow checking is incomplete, because the value
373
     might have overflowed before we get here.  For a correct check we
374
     need to compute the value in a size larger than bitsize, but we
375
     can't reasonably do that for a reloc the same size as a host
376
     machine word.
377
     FIXME: We should also do overflow checking on the result after
378
     adding in the value contained in the object file.  */
379
  if (howto->complain_on_overflow != complain_overflow_dont)
380
    {
381
      bfd_vma check;
382
 
383
      /* Get the value that will be used for the relocation, but
384
         starting at bit position zero.  */
385
      if (howto->rightshift > howto->bitpos)
386
        check = relocation >> (howto->rightshift - howto->bitpos);
387
      else
388
        check = relocation << (howto->bitpos - howto->rightshift);
389
      switch (howto->complain_on_overflow)
390
        {
391
        case complain_overflow_signed:
392
          {
393
            /* Assumes two's complement.  */
394
            bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
395
            bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
396
 
397
            /* The above right shift is incorrect for a signed value.
398
               Fix it up by forcing on the upper bits.  */
399
            if (howto->rightshift > howto->bitpos
400
                && (bfd_signed_vma) relocation < 0)
401
              check |= ((bfd_vma) - 1
402
                        & ~((bfd_vma) - 1
403
                            >> (howto->rightshift - howto->bitpos)));
404
            if ((bfd_signed_vma) check > reloc_signed_max
405
                || (bfd_signed_vma) check < reloc_signed_min)
406
              flag = bfd_reloc_overflow;
407
          }
408
          break;
409
        case complain_overflow_unsigned:
410
          {
411
            /* Assumes two's complement.  This expression avoids
412
               overflow if howto->bitsize is the number of bits in
413
               bfd_vma.  */
414
            bfd_vma reloc_unsigned_max =
415
            (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
416
 
417
            if ((bfd_vma) check > reloc_unsigned_max)
418
              flag = bfd_reloc_overflow;
419
          }
420
          break;
421
        case complain_overflow_bitfield:
422
          {
423
            /* Assumes two's complement.  This expression avoids
424
               overflow if howto->bitsize is the number of bits in
425
               bfd_vma.  */
426
            bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
427
 
428
            if (((bfd_vma) check & ~reloc_bits) != 0
429
                && (((bfd_vma) check & ~reloc_bits)
430
                    != (-(bfd_vma) 1 & ~reloc_bits)))
431
              {
432
                /* The above right shift is incorrect for a signed
433
                   value.  See if turning on the upper bits fixes the
434
                   overflow.  */
435
                if (howto->rightshift > howto->bitpos
436
                    && (bfd_signed_vma) relocation < 0)
437
                  {
438
                    check |= ((bfd_vma) - 1
439
                              & ~((bfd_vma) - 1
440
                                  >> (howto->rightshift - howto->bitpos)));
441
                    if (((bfd_vma) check & ~reloc_bits)
442
                        != (-(bfd_vma) 1 & ~reloc_bits))
443
                      flag = bfd_reloc_overflow;
444
                  }
445
                else
446
                  flag = bfd_reloc_overflow;
447
              }
448
          }
449
          break;
450
        default:
451
          abort ();
452
        }
453
    }
454
 
455
  /* Either we are relocating all the way, or we don't want to apply
456
     the relocation to the reloc entry (probably because there isn't
457
     any room in the output format to describe addends to relocs).  */
458
 
459
  /* The cast to bfd_vma avoids a bug in the Alpha OSF/1 C compiler
460
     (OSF version 1.3, compiler version 3.11).  It miscompiles the
461
     following program:
462
 
463
     struct str
464
     {
465
       unsigned int i0;
466
     } s = { 0 };
467
 
468
     int
469
     main ()
470
     {
471
       unsigned long x;
472
 
473
       x = 0x100000000;
474
       x <<= (unsigned long) s.i0;
475
       if (x == 0)
476
         printf ("failed\n");
477
       else
478
         printf ("succeeded (%lx)\n", x);
479
     }
480
     */
481
 
482
  relocation >>= (bfd_vma) howto->rightshift;
483
 
484
  /* Shift everything up to where it's going to be used.  */
485
  relocation <<= (bfd_vma) howto->bitpos;
486
 
487
  /* Wait for the day when all have the mask in them.  */
488
 
489
  /* What we do:
490
     i instruction to be left alone
491
     o offset within instruction
492
     r relocation offset to apply
493
     S src mask
494
     D dst mask
495
     N ~dst mask
496
     A part 1
497
     B part 2
498
     R result
499
 
500
     Do this:
501
     i i i i i o o o o o        from bfd_get<size>
502
     and           S S S S S    to get the size offset we want
503
     +   r r r r r r r r r r  to get the final value to place
504
     and           D D D D D  to chop to right size
505
     -----------------------
506
     A A A A A
507
     And this:
508
     ...   i i i i i o o o o o  from bfd_get<size>
509
     and   N N N N N            get instruction
510
     -----------------------
511
     ...   B B B B B
512
 
513
     And then:
514
     B B B B B
515
     or              A A A A A
516
     -----------------------
517
     R R R R R R R R R R        put into bfd_put<size>.  */
518
 
519
#define DOIT(x) \
520
  x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) +  relocation) & howto->dst_mask))
521
 
522
  location = (bfd_byte *) data + addr;
523
  switch (howto->size)
524
    {
525
    case 0:
526
      {
527
        bfd_vma x = get_data (location, 1);
528
        DOIT (x);
529
        put_data ((bfd_vma) x, location, 1);
530
      }
531
      break;
532
 
533
    case 1:
534
      if (relocation)
535
        {
536
          bfd_vma x = get_data (location, 2);
537
          DOIT (x);
538
          put_data ((bfd_vma) x, location, 2);
539
        }
540
      break;
541
    case 2:
542
      if (relocation)
543
        {
544
          bfd_vma x = get_data (location, 4);
545
          DOIT (x);
546
          put_data ((bfd_vma) x, location, 4);
547
        }
548
      break;
549
    case -2:
550
      {
551
        bfd_vma x = get_data (location, 4);
552
        relocation = -relocation;
553
        DOIT(x);
554
        put_data ((bfd_vma) x, location, 4);
555
      }
556
      break;
557
 
558
    case 3:
559
      /* Do nothing.  */
560
      break;
561
 
562
    case 4:
563
#ifdef BFD64
564
      if (relocation)
565
        {
566
          bfd_vma x = get_data (location, 8);
567
          DOIT (x);
568
          put_data (x, location, 8);
569
        }
570
#else
571
      abort ();
572
#endif
573
      break;
574
    default:
575
      return bfd_reloc_other;
576
    }
577
  if ((howto->complain_on_overflow != complain_overflow_dont) && overflow)
578
    return bfd_reloc_overflow;
579
 
580
  return flag;
581
}
582
 
583
/* Relocate a given location using a given value and howto.  */
584
 
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
  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
             explictly 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 symbol_cache_entry *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 symbol_cache_entry *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 > input_section->_cooked_size)
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.