00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "bfd.h"
00028 #include "sysdep.h"
00029 #include "libbfd.h"
00030 #include "ns32k.h"
00031
00032 #define N(machine, printable, d, next) \
00033 { 32, 32, 8, bfd_arch_ns32k, machine, "ns32k",printable,3,d,bfd_default_compatible,bfd_default_scan, next, }
00034
00035 static const bfd_arch_info_type arch_info_struct[] =
00036 {
00037 N(32532,"ns32k:32532",TRUE, 0),
00038 };
00039
00040 const bfd_arch_info_type bfd_ns32k_arch =
00041 N(32032,"ns32k:32032",FALSE, &arch_info_struct[0]);
00042
00043 static bfd_reloc_status_type do_ns32k_reloc
00044 PARAMS ((bfd *, arelent *, struct bfd_symbol *, PTR, asection *,
00045 bfd *, char **,
00046 bfd_vma (*) (bfd_byte *, int),
00047 void (*) (bfd_vma, bfd_byte *, int)));
00048
00049 bfd_vma
00050 _bfd_ns32k_get_displacement (buffer, size)
00051 bfd_byte *buffer;
00052 int size;
00053 {
00054 bfd_signed_vma value;
00055
00056 switch (size)
00057 {
00058 case 1:
00059 value = ((*buffer & 0x7f) ^ 0x40) - 0x40;
00060 break;
00061
00062 case 2:
00063 value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
00064 value = (value << 8) | (0xff & *buffer);
00065 break;
00066
00067 case 4:
00068 value = ((*buffer++ & 0x3f) ^ 0x20) - 0x20;
00069 value = (value << 8) | (0xff & *buffer++);
00070 value = (value << 8) | (0xff & *buffer++);
00071 value = (value << 8) | (0xff & *buffer);
00072 break;
00073
00074 default:
00075 abort ();
00076 return 0;
00077 }
00078
00079 return value;
00080 }
00081
00082 void
00083 _bfd_ns32k_put_displacement (value, buffer, size)
00084 bfd_vma value;
00085 bfd_byte *buffer;
00086 int size;
00087 {
00088 switch (size)
00089 {
00090 case 1:
00091 value &= 0x7f;
00092 *buffer++ = value;
00093 break;
00094
00095 case 2:
00096 value &= 0x3fff;
00097 value |= 0x8000;
00098 *buffer++ = (value >> 8);
00099 *buffer++ = value;
00100 break;
00101
00102 case 4:
00103 value |= (bfd_vma) 0xc0000000;
00104 *buffer++ = (value >> 24);
00105 *buffer++ = (value >> 16);
00106 *buffer++ = (value >> 8);
00107 *buffer++ = value;
00108 break;
00109 }
00110 return;
00111 }
00112
00113 bfd_vma
00114 _bfd_ns32k_get_immediate (buffer, size)
00115 bfd_byte *buffer;
00116 int size;
00117 {
00118 bfd_vma value = 0;
00119
00120 switch (size)
00121 {
00122 case 4:
00123 value = (value << 8) | (*buffer++ & 0xff);
00124 value = (value << 8) | (*buffer++ & 0xff);
00125 case 2:
00126 value = (value << 8) | (*buffer++ & 0xff);
00127 case 1:
00128 value = (value << 8) | (*buffer++ & 0xff);
00129 break;
00130 default:
00131 abort ();
00132 }
00133 return value;
00134 }
00135
00136 void
00137 _bfd_ns32k_put_immediate (value, buffer, size)
00138 bfd_vma value;
00139 bfd_byte *buffer;
00140 int size;
00141 {
00142 buffer += size - 1;
00143 switch (size)
00144 {
00145 case 4:
00146 *buffer-- = (value & 0xff); value >>= 8;
00147 *buffer-- = (value & 0xff); value >>= 8;
00148 case 2:
00149 *buffer-- = (value & 0xff); value >>= 8;
00150 case 1:
00151 *buffer-- = (value & 0xff); value >>= 8;
00152 }
00153 }
00154
00155
00156
00157
00158
00159
00160 static bfd_reloc_status_type
00161 do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
00162 error_message, get_data, put_data)
00163 bfd *abfd;
00164 arelent *reloc_entry;
00165 struct bfd_symbol *symbol;
00166 PTR data;
00167 asection *input_section;
00168 bfd *output_bfd;
00169 char **error_message ATTRIBUTE_UNUSED;
00170 bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
00171 void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
00172 {
00173 int overflow = 0;
00174 bfd_vma relocation;
00175 bfd_reloc_status_type flag = bfd_reloc_ok;
00176 bfd_size_type addr = reloc_entry->address;
00177 bfd_vma output_base = 0;
00178 reloc_howto_type *howto = reloc_entry->howto;
00179 asection *reloc_target_output_section;
00180 bfd_byte *location;
00181
00182 if ((symbol->section == &bfd_abs_section)
00183 && output_bfd != (bfd *) NULL)
00184 {
00185 reloc_entry->address += input_section->output_offset;
00186 return bfd_reloc_ok;
00187 }
00188
00189
00190
00191
00192 if (symbol->section == &bfd_und_section
00193 && (symbol->flags & BSF_WEAK) == 0
00194 && output_bfd == (bfd *) NULL)
00195 flag = bfd_reloc_undefined;
00196
00197
00198 if (reloc_entry->address > bfd_get_section_limit (abfd, input_section))
00199 return bfd_reloc_outofrange;
00200
00201
00202
00203
00204
00205 if (bfd_is_com_section (symbol->section))
00206 relocation = 0;
00207 else
00208 relocation = symbol->value;
00209
00210 reloc_target_output_section = symbol->section->output_section;
00211
00212
00213 if (output_bfd != NULL && ! howto->partial_inplace)
00214 output_base = 0;
00215 else
00216 output_base = reloc_target_output_section->vma;
00217
00218 relocation += output_base + symbol->section->output_offset;
00219
00220
00221 relocation += reloc_entry->addend;
00222
00223
00224
00225
00226 if (howto->pc_relative)
00227 {
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 relocation -=
00256 input_section->output_section->vma + input_section->output_offset;
00257
00258 if (howto->pcrel_offset)
00259 relocation -= reloc_entry->address;
00260 }
00261
00262 if (output_bfd != (bfd *) NULL)
00263 {
00264 if (! howto->partial_inplace)
00265 {
00266
00267
00268
00269 reloc_entry->addend = relocation;
00270 reloc_entry->address += input_section->output_offset;
00271 return flag;
00272 }
00273 else
00274 {
00275
00276
00277
00278
00279
00280
00281 reloc_entry->address += input_section->output_offset;
00282
00283
00284 if (abfd->xvec->flavour == bfd_target_coff_flavour)
00285 {
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 relocation -= reloc_entry->addend;
00361 reloc_entry->addend = 0;
00362 }
00363 else
00364 {
00365 reloc_entry->addend = relocation;
00366 }
00367 }
00368 }
00369 else
00370 {
00371 reloc_entry->addend = 0;
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381 if (howto->complain_on_overflow != complain_overflow_dont)
00382 {
00383 bfd_vma check;
00384
00385
00386
00387 if (howto->rightshift > howto->bitpos)
00388 check = relocation >> (howto->rightshift - howto->bitpos);
00389 else
00390 check = relocation << (howto->bitpos - howto->rightshift);
00391 switch (howto->complain_on_overflow)
00392 {
00393 case complain_overflow_signed:
00394 {
00395
00396 bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
00397 bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
00398
00399
00400
00401 if (howto->rightshift > howto->bitpos
00402 && (bfd_signed_vma) relocation < 0)
00403 check |= ((bfd_vma) - 1
00404 & ~((bfd_vma) - 1
00405 >> (howto->rightshift - howto->bitpos)));
00406 if ((bfd_signed_vma) check > reloc_signed_max
00407 || (bfd_signed_vma) check < reloc_signed_min)
00408 flag = bfd_reloc_overflow;
00409 }
00410 break;
00411 case complain_overflow_unsigned:
00412 {
00413
00414
00415
00416 bfd_vma reloc_unsigned_max =
00417 (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
00418
00419 if ((bfd_vma) check > reloc_unsigned_max)
00420 flag = bfd_reloc_overflow;
00421 }
00422 break;
00423 case complain_overflow_bitfield:
00424 {
00425
00426
00427
00428 bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
00429
00430 if (((bfd_vma) check & ~reloc_bits) != 0
00431 && (((bfd_vma) check & ~reloc_bits)
00432 != (-(bfd_vma) 1 & ~reloc_bits)))
00433 {
00434
00435
00436
00437 if (howto->rightshift > howto->bitpos
00438 && (bfd_signed_vma) relocation < 0)
00439 {
00440 check |= ((bfd_vma) - 1
00441 & ~((bfd_vma) - 1
00442 >> (howto->rightshift - howto->bitpos)));
00443 if (((bfd_vma) check & ~reloc_bits)
00444 != (-(bfd_vma) 1 & ~reloc_bits))
00445 flag = bfd_reloc_overflow;
00446 }
00447 else
00448 flag = bfd_reloc_overflow;
00449 }
00450 }
00451 break;
00452 default:
00453 abort ();
00454 }
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 relocation >>= (bfd_vma) howto->rightshift;
00485
00486
00487 relocation <<= (bfd_vma) howto->bitpos;
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521 #define DOIT(x) \
00522 x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask))
00523
00524 location = (bfd_byte *) data + addr;
00525 switch (howto->size)
00526 {
00527 case 0:
00528 {
00529 bfd_vma x = get_data (location, 1);
00530 DOIT (x);
00531 put_data ((bfd_vma) x, location, 1);
00532 }
00533 break;
00534
00535 case 1:
00536 if (relocation)
00537 {
00538 bfd_vma x = get_data (location, 2);
00539 DOIT (x);
00540 put_data ((bfd_vma) x, location, 2);
00541 }
00542 break;
00543 case 2:
00544 if (relocation)
00545 {
00546 bfd_vma x = get_data (location, 4);
00547 DOIT (x);
00548 put_data ((bfd_vma) x, location, 4);
00549 }
00550 break;
00551 case -2:
00552 {
00553 bfd_vma x = get_data (location, 4);
00554 relocation = -relocation;
00555 DOIT(x);
00556 put_data ((bfd_vma) x, location, 4);
00557 }
00558 break;
00559
00560 case 3:
00561
00562 break;
00563
00564 case 4:
00565 #ifdef BFD64
00566 if (relocation)
00567 {
00568 bfd_vma x = get_data (location, 8);
00569 DOIT (x);
00570 put_data (x, location, 8);
00571 }
00572 #else
00573 abort ();
00574 #endif
00575 break;
00576 default:
00577 return bfd_reloc_other;
00578 }
00579 if ((howto->complain_on_overflow != complain_overflow_dont) && overflow)
00580 return bfd_reloc_overflow;
00581
00582 return flag;
00583 }
00584
00585
00586
00587 bfd_reloc_status_type
00588 _bfd_do_ns32k_reloc_contents (howto, input_bfd, relocation, location,
00589 get_data, put_data)
00590 reloc_howto_type *howto;
00591 bfd *input_bfd ATTRIBUTE_UNUSED;
00592 bfd_vma relocation;
00593 bfd_byte *location;
00594 bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
00595 void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
00596 {
00597 int size;
00598 bfd_vma x;
00599 bfd_boolean overflow;
00600
00601
00602
00603 if (howto->size < 0)
00604 relocation = -relocation;
00605
00606
00607 size = bfd_get_reloc_size (howto);
00608 switch (size)
00609 {
00610 default:
00611 case 0:
00612 abort ();
00613 case 1:
00614 case 2:
00615 case 4:
00616 #ifdef BFD64
00617 case 8:
00618 #endif
00619 x = get_data (location, size);
00620 break;
00621 }
00622
00623
00624
00625
00626
00627 overflow = FALSE;
00628 if (howto->complain_on_overflow != complain_overflow_dont)
00629 {
00630 bfd_vma check;
00631 bfd_signed_vma signed_check;
00632 bfd_vma add;
00633 bfd_signed_vma signed_add;
00634
00635 if (howto->rightshift == 0)
00636 {
00637 check = relocation;
00638 signed_check = (bfd_signed_vma) relocation;
00639 }
00640 else
00641 {
00642
00643 check = relocation >> howto->rightshift;
00644
00645
00646
00647 if ((bfd_signed_vma) relocation >= 0)
00648 signed_check = check;
00649 else
00650 signed_check = (check
00651 | ((bfd_vma) - 1
00652 & ~((bfd_vma) - 1 >> howto->rightshift)));
00653 }
00654
00655
00656 add = x & howto->src_mask;
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666 signed_add = add;
00667 if ((add & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0)
00668 signed_add -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1;
00669
00670
00671
00672 if (howto->bitpos == 0)
00673 {
00674 check += add;
00675 signed_check += signed_add;
00676 }
00677 else
00678 {
00679 check += add >> howto->bitpos;
00680
00681
00682
00683
00684 if (signed_add >= 0)
00685 signed_check += add >> howto->bitpos;
00686 else
00687 signed_check += ((add >> howto->bitpos)
00688 | ((bfd_vma) - 1
00689 & ~((bfd_vma) - 1 >> howto->bitpos)));
00690 }
00691
00692 switch (howto->complain_on_overflow)
00693 {
00694 case complain_overflow_signed:
00695 {
00696
00697 bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1;
00698 bfd_signed_vma reloc_signed_min = ~reloc_signed_max;
00699
00700 if (signed_check > reloc_signed_max
00701 || signed_check < reloc_signed_min)
00702 overflow = TRUE;
00703 }
00704 break;
00705 case complain_overflow_unsigned:
00706 {
00707
00708
00709
00710 bfd_vma reloc_unsigned_max =
00711 (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
00712
00713 if (check > reloc_unsigned_max)
00714 overflow = TRUE;
00715 }
00716 break;
00717 case complain_overflow_bitfield:
00718 {
00719
00720
00721
00722 bfd_vma reloc_bits = (((1 << (howto->bitsize - 1)) - 1) << 1) | 1;
00723
00724 if ((check & ~reloc_bits) != 0
00725 && (((bfd_vma) signed_check & ~reloc_bits)
00726 != (-(bfd_vma) 1 & ~reloc_bits)))
00727 overflow = TRUE;
00728 }
00729 break;
00730 default:
00731 abort ();
00732 }
00733 }
00734
00735
00736 relocation >>= (bfd_vma) howto->rightshift;
00737 relocation <<= (bfd_vma) howto->bitpos;
00738
00739
00740 x = ((x & ~howto->dst_mask)
00741 | (((x & howto->src_mask) + relocation) & howto->dst_mask));
00742
00743
00744 switch (size)
00745 {
00746 default:
00747 case 0:
00748 abort ();
00749 case 1:
00750 case 2:
00751 case 4:
00752 #ifdef BFD64
00753 case 8:
00754 #endif
00755 put_data (x, location, size);
00756 break;
00757 }
00758
00759 return overflow ? bfd_reloc_overflow : bfd_reloc_ok;
00760 }
00761
00762 bfd_reloc_status_type
00763 _bfd_ns32k_reloc_disp (abfd, reloc_entry, symbol, data, input_section,
00764 output_bfd, error_message)
00765 bfd *abfd;
00766 arelent *reloc_entry;
00767 struct bfd_symbol *symbol;
00768 PTR data;
00769 asection *input_section;
00770 bfd *output_bfd;
00771 char **error_message;
00772 {
00773 return do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section,
00774 output_bfd, error_message,
00775 _bfd_ns32k_get_displacement,
00776 _bfd_ns32k_put_displacement);
00777 }
00778
00779 bfd_reloc_status_type
00780 _bfd_ns32k_reloc_imm (abfd, reloc_entry, symbol, data, input_section,
00781 output_bfd, error_message)
00782 bfd *abfd;
00783 arelent *reloc_entry;
00784 struct bfd_symbol *symbol;
00785 PTR data;
00786 asection *input_section;
00787 bfd *output_bfd;
00788 char **error_message;
00789 {
00790 return do_ns32k_reloc (abfd, reloc_entry, symbol, data, input_section,
00791 output_bfd, error_message, _bfd_ns32k_get_immediate,
00792 _bfd_ns32k_put_immediate);
00793 }
00794
00795 bfd_reloc_status_type
00796 _bfd_ns32k_final_link_relocate (howto, input_bfd, input_section, contents,
00797 address, value, addend)
00798 reloc_howto_type *howto;
00799 bfd *input_bfd;
00800 asection *input_section;
00801 bfd_byte *contents;
00802 bfd_vma address;
00803 bfd_vma value;
00804 bfd_vma addend;
00805 {
00806 bfd_vma relocation;
00807
00808
00809 if (address > bfd_get_section_limit (input_bfd, input_section))
00810 return bfd_reloc_outofrange;
00811
00812
00813
00814
00815
00816 relocation = value + addend;
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 if (howto->pc_relative)
00829 {
00830 relocation -= (input_section->output_section->vma
00831 + input_section->output_offset);
00832 if (howto->pcrel_offset)
00833 relocation -= address;
00834 }
00835
00836 return _bfd_ns32k_relocate_contents (howto, input_bfd, relocation,
00837 contents + address);
00838 }