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
00028 #include "bfd.h"
00029 #include "sysdep.h"
00030 #include "libiberty.h"
00031 #include "libbfd.h"
00032 #include "bfdlink.h"
00033 #include "coff/sh.h"
00034 #include "coff/internal.h"
00035
00036 #ifdef COFF_WITH_PE
00037 #include "coff/pe.h"
00038
00039 #ifndef COFF_IMAGE_WITH_PE
00040 static bfd_boolean sh_align_load_span
00041 PARAMS ((bfd *, asection *, bfd_byte *,
00042 bfd_boolean (*) (bfd *, asection *, PTR, bfd_byte *, bfd_vma),
00043 PTR, bfd_vma **, bfd_vma *, bfd_vma, bfd_vma, bfd_boolean *));
00044
00045 #define _bfd_sh_align_load_span sh_align_load_span
00046 #endif
00047 #endif
00048
00049 #include "libcoff.h"
00050
00051
00052 static bfd_reloc_status_type sh_reloc
00053 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
00054 static long get_symbol_value PARAMS ((asymbol *));
00055 static bfd_boolean sh_relax_section
00056 PARAMS ((bfd *, asection *, struct bfd_link_info *, bfd_boolean *));
00057 static bfd_boolean sh_relax_delete_bytes
00058 PARAMS ((bfd *, asection *, bfd_vma, int));
00059 #ifndef COFF_IMAGE_WITH_PE
00060 static const struct sh_opcode *sh_insn_info PARAMS ((unsigned int));
00061 #endif
00062 static bfd_boolean sh_align_loads
00063 PARAMS ((bfd *, asection *, struct internal_reloc *, bfd_byte *,
00064 bfd_boolean *));
00065 static bfd_boolean sh_swap_insns
00066 PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
00067 static bfd_boolean sh_relocate_section
00068 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
00069 struct internal_reloc *, struct internal_syment *, asection **));
00070 static bfd_byte *sh_coff_get_relocated_section_contents
00071 PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *,
00072 bfd_byte *, bfd_boolean, asymbol **));
00073 static reloc_howto_type * sh_coff_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
00074
00075 #ifdef COFF_WITH_PE
00076
00077 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
00078 #else
00079
00080 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 4
00081 #endif
00082
00083 #ifdef COFF_IMAGE_WITH_PE
00084
00085 #define COFF_PAGE_SIZE 0x1000
00086 #endif
00087
00088
00089 #define COFF_LONG_FILENAMES
00090
00091 #ifdef COFF_WITH_PE
00092 static bfd_boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
00093
00094
00095 static bfd_boolean in_reloc_p (abfd, howto)
00096 bfd * abfd ATTRIBUTE_UNUSED;
00097 reloc_howto_type * howto;
00098 {
00099 return ! howto->pc_relative && howto->type != R_SH_IMAGEBASE;
00100 }
00101 #endif
00102
00103
00104
00105 static reloc_howto_type sh_coff_howtos[] =
00106 {
00107 EMPTY_HOWTO (0),
00108 EMPTY_HOWTO (1),
00109 #ifdef COFF_WITH_PE
00110
00111 HOWTO (R_SH_IMM32CE,
00112 0,
00113 2,
00114 32,
00115 FALSE,
00116 0,
00117 complain_overflow_bitfield,
00118 sh_reloc,
00119 "r_imm32ce",
00120 TRUE,
00121 0xffffffff,
00122 0xffffffff,
00123 FALSE),
00124 #else
00125 EMPTY_HOWTO (2),
00126 #endif
00127 EMPTY_HOWTO (3),
00128 EMPTY_HOWTO (4),
00129 EMPTY_HOWTO (5),
00130 EMPTY_HOWTO (6),
00131 EMPTY_HOWTO (7),
00132 EMPTY_HOWTO (8),
00133 EMPTY_HOWTO (9),
00134
00135 HOWTO (R_SH_PCDISP8BY2,
00136 1,
00137 1,
00138 8,
00139 TRUE,
00140 0,
00141 complain_overflow_signed,
00142 sh_reloc,
00143 "r_pcdisp8by2",
00144 TRUE,
00145 0xff,
00146 0xff,
00147 TRUE),
00148
00149 EMPTY_HOWTO (11),
00150
00151 HOWTO (R_SH_PCDISP,
00152 1,
00153 1,
00154 12,
00155 TRUE,
00156 0,
00157 complain_overflow_signed,
00158 sh_reloc,
00159 "r_pcdisp12by2",
00160 TRUE,
00161 0xfff,
00162 0xfff,
00163 TRUE),
00164
00165 EMPTY_HOWTO (13),
00166
00167 HOWTO (R_SH_IMM32,
00168 0,
00169 2,
00170 32,
00171 FALSE,
00172 0,
00173 complain_overflow_bitfield,
00174 sh_reloc,
00175 "r_imm32",
00176 TRUE,
00177 0xffffffff,
00178 0xffffffff,
00179 FALSE),
00180
00181 EMPTY_HOWTO (15),
00182 #ifdef COFF_WITH_PE
00183 HOWTO (R_SH_IMAGEBASE,
00184 0,
00185 2,
00186 32,
00187 FALSE,
00188 0,
00189 complain_overflow_bitfield,
00190 sh_reloc,
00191 "rva32",
00192 TRUE,
00193 0xffffffff,
00194 0xffffffff,
00195 FALSE),
00196 #else
00197 EMPTY_HOWTO (16),
00198 #endif
00199 EMPTY_HOWTO (17),
00200 EMPTY_HOWTO (18),
00201 EMPTY_HOWTO (19),
00202 EMPTY_HOWTO (20),
00203 EMPTY_HOWTO (21),
00204
00205 HOWTO (R_SH_PCRELIMM8BY2,
00206 1,
00207 1,
00208 8,
00209 TRUE,
00210 0,
00211 complain_overflow_unsigned,
00212 sh_reloc,
00213 "r_pcrelimm8by2",
00214 TRUE,
00215 0xff,
00216 0xff,
00217 TRUE),
00218
00219 HOWTO (R_SH_PCRELIMM8BY4,
00220 2,
00221 1,
00222 8,
00223 TRUE,
00224 0,
00225 complain_overflow_unsigned,
00226 sh_reloc,
00227 "r_pcrelimm8by4",
00228 TRUE,
00229 0xff,
00230 0xff,
00231 TRUE),
00232
00233 HOWTO (R_SH_IMM16,
00234 0,
00235 1,
00236 16,
00237 FALSE,
00238 0,
00239 complain_overflow_bitfield,
00240 sh_reloc,
00241 "r_imm16",
00242 TRUE,
00243 0xffff,
00244 0xffff,
00245 FALSE),
00246
00247 HOWTO (R_SH_SWITCH16,
00248 0,
00249 1,
00250 16,
00251 FALSE,
00252 0,
00253 complain_overflow_bitfield,
00254 sh_reloc,
00255 "r_switch16",
00256 TRUE,
00257 0xffff,
00258 0xffff,
00259 FALSE),
00260
00261 HOWTO (R_SH_SWITCH32,
00262 0,
00263 2,
00264 32,
00265 FALSE,
00266 0,
00267 complain_overflow_bitfield,
00268 sh_reloc,
00269 "r_switch32",
00270 TRUE,
00271 0xffffffff,
00272 0xffffffff,
00273 FALSE),
00274
00275 HOWTO (R_SH_USES,
00276 0,
00277 1,
00278 16,
00279 FALSE,
00280 0,
00281 complain_overflow_bitfield,
00282 sh_reloc,
00283 "r_uses",
00284 TRUE,
00285 0xffff,
00286 0xffff,
00287 FALSE),
00288
00289 HOWTO (R_SH_COUNT,
00290 0,
00291 2,
00292 32,
00293 FALSE,
00294 0,
00295 complain_overflow_bitfield,
00296 sh_reloc,
00297 "r_count",
00298 TRUE,
00299 0xffffffff,
00300 0xffffffff,
00301 FALSE),
00302
00303 HOWTO (R_SH_ALIGN,
00304 0,
00305 2,
00306 32,
00307 FALSE,
00308 0,
00309 complain_overflow_bitfield,
00310 sh_reloc,
00311 "r_align",
00312 TRUE,
00313 0xffffffff,
00314 0xffffffff,
00315 FALSE),
00316
00317 HOWTO (R_SH_CODE,
00318 0,
00319 2,
00320 32,
00321 FALSE,
00322 0,
00323 complain_overflow_bitfield,
00324 sh_reloc,
00325 "r_code",
00326 TRUE,
00327 0xffffffff,
00328 0xffffffff,
00329 FALSE),
00330
00331 HOWTO (R_SH_DATA,
00332 0,
00333 2,
00334 32,
00335 FALSE,
00336 0,
00337 complain_overflow_bitfield,
00338 sh_reloc,
00339 "r_data",
00340 TRUE,
00341 0xffffffff,
00342 0xffffffff,
00343 FALSE),
00344
00345 HOWTO (R_SH_LABEL,
00346 0,
00347 2,
00348 32,
00349 FALSE,
00350 0,
00351 complain_overflow_bitfield,
00352 sh_reloc,
00353 "r_label",
00354 TRUE,
00355 0xffffffff,
00356 0xffffffff,
00357 FALSE),
00358
00359 HOWTO (R_SH_SWITCH8,
00360 0,
00361 0,
00362 8,
00363 FALSE,
00364 0,
00365 complain_overflow_bitfield,
00366 sh_reloc,
00367 "r_switch8",
00368 TRUE,
00369 0xff,
00370 0xff,
00371 FALSE)
00372 };
00373
00374 #define SH_COFF_HOWTO_COUNT (sizeof sh_coff_howtos / sizeof sh_coff_howtos[0])
00375
00376
00377 #define BADMAG(x) SHBADMAG(x)
00378
00379
00380 #define SH 1
00381
00382
00383 #define __A_MAGIC_SET__
00384
00385 #ifndef COFF_WITH_PE
00386
00387 #define SWAP_IN_RELOC_OFFSET H_GET_32
00388 #define SWAP_OUT_RELOC_OFFSET H_PUT_32
00389
00390
00391 #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
00392 do \
00393 { \
00394 dst->r_stuff[0] = 'S'; \
00395 dst->r_stuff[1] = 'C'; \
00396 } \
00397 while (0)
00398 #endif
00399
00400
00401
00402 static long
00403 get_symbol_value (symbol)
00404 asymbol *symbol;
00405 {
00406 bfd_vma relocation;
00407
00408 if (bfd_is_com_section (symbol->section))
00409 relocation = 0;
00410 else
00411 relocation = (symbol->value +
00412 symbol->section->output_section->vma +
00413 symbol->section->output_offset);
00414
00415 return relocation;
00416 }
00417
00418 #ifdef COFF_WITH_PE
00419
00420
00421 #define coff_rtype_to_howto coff_sh_rtype_to_howto
00422 static reloc_howto_type * coff_sh_rtype_to_howto PARAMS ((bfd *, asection *, struct internal_reloc *, struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *));
00423
00424 static reloc_howto_type *
00425 coff_sh_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
00426 bfd * abfd ATTRIBUTE_UNUSED;
00427 asection * sec;
00428 struct internal_reloc * rel;
00429 struct coff_link_hash_entry * h;
00430 struct internal_syment * sym;
00431 bfd_vma * addendp;
00432 {
00433 reloc_howto_type * howto;
00434
00435 howto = sh_coff_howtos + rel->r_type;
00436
00437 *addendp = 0;
00438
00439 if (howto->pc_relative)
00440 *addendp += sec->vma;
00441
00442 if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
00443 {
00444
00445
00446
00447
00448
00449 BFD_ASSERT (h != NULL);
00450 }
00451
00452 if (howto->pc_relative)
00453 {
00454 *addendp -= 4;
00455
00456
00457
00458
00459
00460
00461
00462 if (sym != NULL && sym->n_scnum != 0)
00463 *addendp -= sym->n_value;
00464 }
00465
00466 if (rel->r_type == R_SH_IMAGEBASE)
00467 *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
00468
00469 return howto;
00470 }
00471
00472 #endif
00473
00474
00475 struct shcoff_reloc_map
00476 {
00477 bfd_reloc_code_real_type bfd_reloc_val;
00478 unsigned char shcoff_reloc_val;
00479 };
00480
00481 #ifdef COFF_WITH_PE
00482
00483 static const struct shcoff_reloc_map sh_reloc_map[] =
00484 {
00485 { BFD_RELOC_32, R_SH_IMM32CE },
00486 { BFD_RELOC_RVA, R_SH_IMAGEBASE },
00487 { BFD_RELOC_CTOR, R_SH_IMM32CE },
00488 };
00489 #else
00490
00491 static const struct shcoff_reloc_map sh_reloc_map[] =
00492 {
00493 { BFD_RELOC_32, R_SH_IMM32 },
00494 { BFD_RELOC_CTOR, R_SH_IMM32 },
00495 };
00496 #endif
00497
00498
00499
00500 #define coff_bfd_reloc_type_lookup sh_coff_reloc_type_lookup
00501
00502 static reloc_howto_type *
00503 sh_coff_reloc_type_lookup (abfd, code)
00504 bfd * abfd ATTRIBUTE_UNUSED;
00505 bfd_reloc_code_real_type code;
00506 {
00507 unsigned int i;
00508
00509 for (i = ARRAY_SIZE (sh_reloc_map); i--;)
00510 if (sh_reloc_map[i].bfd_reloc_val == code)
00511 return &sh_coff_howtos[(int) sh_reloc_map[i].shcoff_reloc_val];
00512
00513 fprintf (stderr, "SH Error: unknown reloc type %d\n", code);
00514 return NULL;
00515 }
00516
00517
00518
00519
00520 #define RTYPE2HOWTO(relent, internal) \
00521 ((relent)->howto = \
00522 ((internal)->r_type < SH_COFF_HOWTO_COUNT \
00523 ? &sh_coff_howtos[(internal)->r_type] \
00524 : (reloc_howto_type *) NULL))
00525
00526
00527
00528 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
00529 { \
00530 coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
00531 if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
00532 coffsym = (obj_symbols (abfd) \
00533 + (cache_ptr->sym_ptr_ptr - symbols)); \
00534 else if (ptr) \
00535 coffsym = coff_symbol_from (abfd, ptr); \
00536 if (coffsym != (coff_symbol_type *) NULL \
00537 && coffsym->native->u.syment.n_scnum == 0) \
00538 cache_ptr->addend = 0; \
00539 else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
00540 && ptr->section != (asection *) NULL) \
00541 cache_ptr->addend = - (ptr->section->vma + ptr->value); \
00542 else \
00543 cache_ptr->addend = 0; \
00544 if ((reloc).r_type == R_SH_SWITCH8 \
00545 || (reloc).r_type == R_SH_SWITCH16 \
00546 || (reloc).r_type == R_SH_SWITCH32 \
00547 || (reloc).r_type == R_SH_USES \
00548 || (reloc).r_type == R_SH_COUNT \
00549 || (reloc).r_type == R_SH_ALIGN) \
00550 cache_ptr->addend = (reloc).r_offset; \
00551 }
00552
00553
00554
00555 static bfd_reloc_status_type
00556 sh_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd,
00557 error_message)
00558 bfd *abfd;
00559 arelent *reloc_entry;
00560 asymbol *symbol_in;
00561 PTR data;
00562 asection *input_section;
00563 bfd *output_bfd;
00564 char **error_message ATTRIBUTE_UNUSED;
00565 {
00566 unsigned long insn;
00567 bfd_vma sym_value;
00568 unsigned short r_type;
00569 bfd_vma addr = reloc_entry->address;
00570 bfd_byte *hit_data = addr + (bfd_byte *) data;
00571
00572 r_type = reloc_entry->howto->type;
00573
00574 if (output_bfd != NULL)
00575 {
00576
00577 reloc_entry->address += input_section->output_offset;
00578 return bfd_reloc_ok;
00579 }
00580
00581
00582
00583 if (r_type != R_SH_IMM32
00584 #ifdef COFF_WITH_PE
00585 && r_type != R_SH_IMM32CE
00586 && r_type != R_SH_IMAGEBASE
00587 #endif
00588 && (r_type != R_SH_PCDISP
00589 || (symbol_in->flags & BSF_LOCAL) != 0))
00590 return bfd_reloc_ok;
00591
00592 if (symbol_in != NULL
00593 && bfd_is_und_section (symbol_in->section))
00594 return bfd_reloc_undefined;
00595
00596 sym_value = get_symbol_value (symbol_in);
00597
00598 switch (r_type)
00599 {
00600 case R_SH_IMM32:
00601 #ifdef COFF_WITH_PE
00602 case R_SH_IMM32CE:
00603 #endif
00604 insn = bfd_get_32 (abfd, hit_data);
00605 insn += sym_value + reloc_entry->addend;
00606 bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
00607 break;
00608 #ifdef COFF_WITH_PE
00609 case R_SH_IMAGEBASE:
00610 insn = bfd_get_32 (abfd, hit_data);
00611 insn += sym_value + reloc_entry->addend;
00612 insn -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
00613 bfd_put_32 (abfd, (bfd_vma) insn, hit_data);
00614 break;
00615 #endif
00616 case R_SH_PCDISP:
00617 insn = bfd_get_16 (abfd, hit_data);
00618 sym_value += reloc_entry->addend;
00619 sym_value -= (input_section->output_section->vma
00620 + input_section->output_offset
00621 + addr
00622 + 4);
00623 sym_value += (insn & 0xfff) << 1;
00624 if (insn & 0x800)
00625 sym_value -= 0x1000;
00626 insn = (insn & 0xf000) | (sym_value & 0xfff);
00627 bfd_put_16 (abfd, (bfd_vma) insn, hit_data);
00628 if (sym_value < (bfd_vma) -0x1000 || sym_value >= 0x1000)
00629 return bfd_reloc_overflow;
00630 break;
00631 default:
00632 abort ();
00633 break;
00634 }
00635
00636 return bfd_reloc_ok;
00637 }
00638
00639 #define coff_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
00640
00641
00642 #define coff_bfd_relax_section sh_relax_section
00643
00644
00645 #define coff_relocate_section sh_relocate_section
00646
00647
00648
00649 #define coff_bfd_get_relocated_section_contents \
00650 sh_coff_get_relocated_section_contents
00651
00652 #include "coffcode.h"
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697 static bfd_boolean
00698 sh_relax_section (abfd, sec, link_info, again)
00699 bfd *abfd;
00700 asection *sec;
00701 struct bfd_link_info *link_info;
00702 bfd_boolean *again;
00703 {
00704 struct internal_reloc *internal_relocs;
00705 bfd_boolean have_code;
00706 struct internal_reloc *irel, *irelend;
00707 bfd_byte *contents = NULL;
00708
00709 *again = FALSE;
00710
00711 if (link_info->relocatable
00712 || (sec->flags & SEC_RELOC) == 0
00713 || sec->reloc_count == 0)
00714 return TRUE;
00715
00716 if (coff_section_data (abfd, sec) == NULL)
00717 {
00718 bfd_size_type amt = sizeof (struct coff_section_tdata);
00719 sec->used_by_bfd = (PTR) bfd_zalloc (abfd, amt);
00720 if (sec->used_by_bfd == NULL)
00721 return FALSE;
00722 }
00723
00724 internal_relocs = (_bfd_coff_read_internal_relocs
00725 (abfd, sec, link_info->keep_memory,
00726 (bfd_byte *) NULL, FALSE,
00727 (struct internal_reloc *) NULL));
00728 if (internal_relocs == NULL)
00729 goto error_return;
00730
00731 have_code = FALSE;
00732
00733 irelend = internal_relocs + sec->reloc_count;
00734 for (irel = internal_relocs; irel < irelend; irel++)
00735 {
00736 bfd_vma laddr, paddr, symval;
00737 unsigned short insn;
00738 struct internal_reloc *irelfn, *irelscan, *irelcount;
00739 struct internal_syment sym;
00740 bfd_signed_vma foff;
00741
00742 if (irel->r_type == R_SH_CODE)
00743 have_code = TRUE;
00744
00745 if (irel->r_type != R_SH_USES)
00746 continue;
00747
00748
00749 if (contents == NULL)
00750 {
00751 if (coff_section_data (abfd, sec)->contents != NULL)
00752 contents = coff_section_data (abfd, sec)->contents;
00753 else
00754 {
00755 if (!bfd_malloc_and_get_section (abfd, sec, &contents))
00756 goto error_return;
00757 }
00758 }
00759
00760
00761
00762
00763
00764 laddr = irel->r_vaddr - sec->vma + 4;
00765
00766 laddr += ((irel->r_offset & 0xffffffff) ^ 0x80000000) - 0x80000000;
00767 if (laddr >= sec->size)
00768 {
00769 (*_bfd_error_handler) ("%B: 0x%lx: warning: bad R_SH_USES offset",
00770 abfd, (unsigned long) irel->r_vaddr);
00771 continue;
00772 }
00773 insn = bfd_get_16 (abfd, contents + laddr);
00774
00775
00776 if ((insn & 0xf000) != 0xd000)
00777 {
00778 ((*_bfd_error_handler)
00779 ("%B: 0x%lx: warning: R_SH_USES points to unrecognized insn 0x%x",
00780 abfd, (unsigned long) irel->r_vaddr, insn));
00781 continue;
00782 }
00783
00784
00785
00786
00787
00788
00789
00790 paddr = insn & 0xff;
00791 paddr *= 4;
00792 paddr += (laddr + 4) &~ (bfd_vma) 3;
00793 if (paddr >= sec->size)
00794 {
00795 ((*_bfd_error_handler)
00796 ("%B: 0x%lx: warning: bad R_SH_USES load offset",
00797 abfd, (unsigned long) irel->r_vaddr));
00798 continue;
00799 }
00800
00801
00802
00803
00804 paddr += sec->vma;
00805 for (irelfn = internal_relocs; irelfn < irelend; irelfn++)
00806 if (irelfn->r_vaddr == paddr
00807 #ifdef COFF_WITH_PE
00808 && (irelfn->r_type == R_SH_IMM32
00809 || irelfn->r_type == R_SH_IMM32CE
00810 || irelfn->r_type == R_SH_IMAGEBASE)
00811
00812 #else
00813 && irelfn->r_type == R_SH_IMM32
00814 #endif
00815 )
00816 break;
00817 if (irelfn >= irelend)
00818 {
00819 ((*_bfd_error_handler)
00820 ("%B: 0x%lx: warning: could not find expected reloc",
00821 abfd, (unsigned long) paddr));
00822 continue;
00823 }
00824
00825
00826 if (! _bfd_coff_get_external_symbols (abfd))
00827 goto error_return;
00828 bfd_coff_swap_sym_in (abfd,
00829 ((bfd_byte *) obj_coff_external_syms (abfd)
00830 + (irelfn->r_symndx
00831 * bfd_coff_symesz (abfd))),
00832 &sym);
00833 if (sym.n_scnum != 0 && sym.n_scnum != sec->target_index)
00834 {
00835 ((*_bfd_error_handler)
00836 ("%B: 0x%lx: warning: symbol in unexpected section",
00837 abfd, (unsigned long) paddr));
00838 continue;
00839 }
00840
00841 if (sym.n_sclass != C_EXT)
00842 {
00843 symval = (sym.n_value
00844 - sec->vma
00845 + sec->output_section->vma
00846 + sec->output_offset);
00847 }
00848 else
00849 {
00850 struct coff_link_hash_entry *h;
00851
00852 h = obj_coff_sym_hashes (abfd)[irelfn->r_symndx];
00853 BFD_ASSERT (h != NULL);
00854 if (h->root.type != bfd_link_hash_defined
00855 && h->root.type != bfd_link_hash_defweak)
00856 {
00857
00858
00859
00860 continue;
00861 }
00862
00863 symval = (h->root.u.def.value
00864 + h->root.u.def.section->output_section->vma
00865 + h->root.u.def.section->output_offset);
00866 }
00867
00868 symval += bfd_get_32 (abfd, contents + paddr - sec->vma);
00869
00870
00871 foff = (symval
00872 - (irel->r_vaddr
00873 - sec->vma
00874 + sec->output_section->vma
00875 + sec->output_offset
00876 + 4));
00877 if (foff < -0x1000 || foff >= 0x1000)
00878 {
00879
00880 continue;
00881 }
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893 coff_section_data (abfd, sec)->relocs = internal_relocs;
00894 coff_section_data (abfd, sec)->keep_relocs = TRUE;
00895
00896 coff_section_data (abfd, sec)->contents = contents;
00897 coff_section_data (abfd, sec)->keep_contents = TRUE;
00898
00899 obj_coff_keep_syms (abfd) = TRUE;
00900
00901
00902
00903
00904
00905 irel->r_type = R_SH_PCDISP;
00906 irel->r_symndx = irelfn->r_symndx;
00907 if (sym.n_sclass != C_EXT)
00908 {
00909
00910
00911
00912 bfd_put_16 (abfd,
00913 (bfd_vma) 0xb000 | ((foff >> 1) & 0xfff),
00914 contents + irel->r_vaddr - sec->vma);
00915 }
00916 else
00917 {
00918
00919
00920
00921 bfd_put_16 (abfd, (bfd_vma) 0xb000,
00922 contents + irel->r_vaddr - sec->vma);
00923 }
00924
00925
00926
00927 for (irelscan = internal_relocs; irelscan < irelend; irelscan++)
00928 if (irelscan->r_type == R_SH_USES
00929 && laddr == irelscan->r_vaddr - sec->vma + 4 + irelscan->r_offset)
00930 break;
00931 if (irelscan < irelend)
00932 {
00933
00934
00935
00936
00937 continue;
00938 }
00939
00940
00941
00942
00943 for (irelcount = internal_relocs; irelcount < irelend; irelcount++)
00944 if (irelcount->r_vaddr == paddr
00945 && irelcount->r_type == R_SH_COUNT)
00946 break;
00947
00948
00949 if (! sh_relax_delete_bytes (abfd, sec, laddr, 2))
00950 goto error_return;
00951
00952
00953
00954
00955 *again = TRUE;
00956
00957
00958 if (irelcount >= irelend)
00959 {
00960 ((*_bfd_error_handler)
00961 ("%B: 0x%lx: warning: could not find expected COUNT reloc",
00962 abfd, (unsigned long) paddr));
00963 continue;
00964 }
00965
00966
00967
00968 if (irelcount->r_offset == 0)
00969 {
00970 ((*_bfd_error_handler) ("%B: 0x%lx: warning: bad count",
00971 abfd, (unsigned long) paddr));
00972 continue;
00973 }
00974
00975 --irelcount->r_offset;
00976
00977
00978
00979
00980 if (irelcount->r_offset == 0)
00981 {
00982 if (! sh_relax_delete_bytes (abfd, sec,
00983 irelfn->r_vaddr - sec->vma, 4))
00984 goto error_return;
00985 }
00986
00987
00988 }
00989
00990
00991
00992 if (have_code)
00993 {
00994 bfd_boolean swapped;
00995
00996
00997 if (contents == NULL)
00998 {
00999 if (coff_section_data (abfd, sec)->contents != NULL)
01000 contents = coff_section_data (abfd, sec)->contents;
01001 else
01002 {
01003 if (!bfd_malloc_and_get_section (abfd, sec, &contents))
01004 goto error_return;
01005 }
01006 }
01007
01008 if (! sh_align_loads (abfd, sec, internal_relocs, contents, &swapped))
01009 goto error_return;
01010
01011 if (swapped)
01012 {
01013 coff_section_data (abfd, sec)->relocs = internal_relocs;
01014 coff_section_data (abfd, sec)->keep_relocs = TRUE;
01015
01016 coff_section_data (abfd, sec)->contents = contents;
01017 coff_section_data (abfd, sec)->keep_contents = TRUE;
01018
01019 obj_coff_keep_syms (abfd) = TRUE;
01020 }
01021 }
01022
01023 if (internal_relocs != NULL
01024 && internal_relocs != coff_section_data (abfd, sec)->relocs)
01025 {
01026 if (! link_info->keep_memory)
01027 free (internal_relocs);
01028 else
01029 coff_section_data (abfd, sec)->relocs = internal_relocs;
01030 }
01031
01032 if (contents != NULL && contents != coff_section_data (abfd, sec)->contents)
01033 {
01034 if (! link_info->keep_memory)
01035 free (contents);
01036 else
01037
01038 coff_section_data (abfd, sec)->contents = contents;
01039 }
01040
01041 return TRUE;
01042
01043 error_return:
01044 if (internal_relocs != NULL
01045 && internal_relocs != coff_section_data (abfd, sec)->relocs)
01046 free (internal_relocs);
01047 if (contents != NULL && contents != coff_section_data (abfd, sec)->contents)
01048 free (contents);
01049 return FALSE;
01050 }
01051
01052
01053
01054 static bfd_boolean
01055 sh_relax_delete_bytes (abfd, sec, addr, count)
01056 bfd *abfd;
01057 asection *sec;
01058 bfd_vma addr;
01059 int count;
01060 {
01061 bfd_byte *contents;
01062 struct internal_reloc *irel, *irelend;
01063 struct internal_reloc *irelalign;
01064 bfd_vma toaddr;
01065 bfd_byte *esym, *esymend;
01066 bfd_size_type symesz;
01067 struct coff_link_hash_entry **sym_hash;
01068 asection *o;
01069
01070 contents = coff_section_data (abfd, sec)->contents;
01071
01072
01073
01074
01075 irelalign = NULL;
01076 toaddr = sec->size;
01077
01078 irel = coff_section_data (abfd, sec)->relocs;
01079 irelend = irel + sec->reloc_count;
01080 for (; irel < irelend; irel++)
01081 {
01082 if (irel->r_type == R_SH_ALIGN
01083 && irel->r_vaddr - sec->vma > addr
01084 && count < (1 << irel->r_offset))
01085 {
01086 irelalign = irel;
01087 toaddr = irel->r_vaddr - sec->vma;
01088 break;
01089 }
01090 }
01091
01092
01093 memmove (contents + addr, contents + addr + count,
01094 (size_t) (toaddr - addr - count));
01095 if (irelalign == NULL)
01096 sec->size -= count;
01097 else
01098 {
01099 int i;
01100
01101 #define NOP_OPCODE (0x0009)
01102
01103 BFD_ASSERT ((count & 1) == 0);
01104 for (i = 0; i < count; i += 2)
01105 bfd_put_16 (abfd, (bfd_vma) NOP_OPCODE, contents + toaddr - count + i);
01106 }
01107
01108
01109 for (irel = coff_section_data (abfd, sec)->relocs; irel < irelend; irel++)
01110 {
01111 bfd_vma nraddr, stop;
01112 bfd_vma start = 0;
01113 int insn = 0;
01114 struct internal_syment sym;
01115 int off, adjust, oinsn;
01116 bfd_signed_vma voff = 0;
01117 bfd_boolean overflow;
01118
01119
01120 nraddr = irel->r_vaddr - sec->vma;
01121 if ((irel->r_vaddr - sec->vma > addr
01122 && irel->r_vaddr - sec->vma < toaddr)
01123 || (irel->r_type == R_SH_ALIGN
01124 && irel->r_vaddr - sec->vma == toaddr))
01125 nraddr -= count;
01126
01127
01128
01129
01130 if (irel->r_vaddr - sec->vma >= addr
01131 && irel->r_vaddr - sec->vma < addr + count
01132 && irel->r_type != R_SH_ALIGN
01133 && irel->r_type != R_SH_CODE
01134 && irel->r_type != R_SH_DATA
01135 && irel->r_type != R_SH_LABEL)
01136 irel->r_type = R_SH_UNUSED;
01137
01138
01139
01140 switch (irel->r_type)
01141 {
01142 default:
01143 break;
01144
01145 case R_SH_PCDISP8BY2:
01146 case R_SH_PCDISP:
01147 case R_SH_PCRELIMM8BY2:
01148 case R_SH_PCRELIMM8BY4:
01149 start = irel->r_vaddr - sec->vma;
01150 insn = bfd_get_16 (abfd, contents + nraddr);
01151 break;
01152 }
01153
01154 switch (irel->r_type)
01155 {
01156 default:
01157 start = stop = addr;
01158 break;
01159
01160 case R_SH_IMM32:
01161 #ifdef COFF_WITH_PE
01162 case R_SH_IMM32CE:
01163 case R_SH_IMAGEBASE:
01164 #endif
01165
01166
01167
01168
01169 bfd_coff_swap_sym_in (abfd,
01170 ((bfd_byte *) obj_coff_external_syms (abfd)
01171 + (irel->r_symndx
01172 * bfd_coff_symesz (abfd))),
01173 &sym);
01174 if (sym.n_sclass != C_EXT
01175 && sym.n_scnum == sec->target_index
01176 && ((bfd_vma) sym.n_value <= addr
01177 || (bfd_vma) sym.n_value >= toaddr))
01178 {
01179 bfd_vma val;
01180
01181 val = bfd_get_32 (abfd, contents + nraddr);
01182 val += sym.n_value;
01183 if (val > addr && val < toaddr)
01184 bfd_put_32 (abfd, val - count, contents + nraddr);
01185 }
01186 start = stop = addr;
01187 break;
01188
01189 case R_SH_PCDISP8BY2:
01190 off = insn & 0xff;
01191 if (off & 0x80)
01192 off -= 0x100;
01193 stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
01194 break;
01195
01196 case R_SH_PCDISP:
01197 bfd_coff_swap_sym_in (abfd,
01198 ((bfd_byte *) obj_coff_external_syms (abfd)
01199 + (irel->r_symndx
01200 * bfd_coff_symesz (abfd))),
01201 &sym);
01202 if (sym.n_sclass == C_EXT)
01203 start = stop = addr;
01204 else
01205 {
01206 off = insn & 0xfff;
01207 if (off & 0x800)
01208 off -= 0x1000;
01209 stop = (bfd_vma) ((bfd_signed_vma) start + 4 + off * 2);
01210 }
01211 break;
01212
01213 case R_SH_PCRELIMM8BY2:
01214 off = insn & 0xff;
01215 stop = start + 4 + off * 2;
01216 break;
01217
01218 case R_SH_PCRELIMM8BY4:
01219 off = insn & 0xff;
01220 stop = (start &~ (bfd_vma) 3) + 4 + off * 4;
01221 break;
01222
01223 case R_SH_SWITCH8:
01224 case R_SH_SWITCH16:
01225 case R_SH_SWITCH32:
01226
01227
01228
01229
01230
01231
01232
01233 start = irel->r_vaddr - sec->vma;
01234 stop = (bfd_vma) ((bfd_signed_vma) start - (long) irel->r_offset);
01235
01236 if (start > addr
01237 && start < toaddr
01238 && (stop <= addr || stop >= toaddr))
01239 irel->r_offset += count;
01240 else if (stop > addr
01241 && stop < toaddr
01242 && (start <= addr || start >= toaddr))
01243 irel->r_offset -= count;
01244
01245 start = stop;
01246
01247 if (irel->r_type == R_SH_SWITCH16)
01248 voff = bfd_get_signed_16 (abfd, contents + nraddr);
01249 else if (irel->r_type == R_SH_SWITCH8)
01250 voff = bfd_get_8 (abfd, contents + nraddr);
01251 else
01252 voff = bfd_get_signed_32 (abfd, contents + nraddr);
01253 stop = (bfd_vma) ((bfd_signed_vma) start + voff);
01254
01255 break;
01256
01257 case R_SH_USES:
01258 start = irel->r_vaddr - sec->vma;
01259 stop = (bfd_vma) ((bfd_signed_vma) start
01260 + (long) irel->r_offset
01261 + 4);
01262 break;
01263 }
01264
01265 if (start > addr
01266 && start < toaddr
01267 && (stop <= addr || stop >= toaddr))
01268 adjust = count;
01269 else if (stop > addr
01270 && stop < toaddr
01271 && (start <= addr || start >= toaddr))
01272 adjust = - count;
01273 else
01274 adjust = 0;
01275
01276 if (adjust != 0)
01277 {
01278 oinsn = insn;
01279 overflow = FALSE;
01280 switch (irel->r_type)
01281 {
01282 default:
01283 abort ();
01284 break;
01285
01286 case R_SH_PCDISP8BY2:
01287 case R_SH_PCRELIMM8BY2:
01288 insn += adjust / 2;
01289 if ((oinsn & 0xff00) != (insn & 0xff00))
01290 overflow = TRUE;
01291 bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
01292 break;
01293
01294 case R_SH_PCDISP:
01295 insn += adjust / 2;
01296 if ((oinsn & 0xf000) != (insn & 0xf000))
01297 overflow = TRUE;
01298 bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
01299 break;
01300
01301 case R_SH_PCRELIMM8BY4:
01302 BFD_ASSERT (adjust == count || count >= 4);
01303 if (count >= 4)
01304 insn += adjust / 4;
01305 else
01306 {
01307 if ((irel->r_vaddr & 3) == 0)
01308 ++insn;
01309 }
01310 if ((oinsn & 0xff00) != (insn & 0xff00))
01311 overflow = TRUE;
01312 bfd_put_16 (abfd, (bfd_vma) insn, contents + nraddr);
01313 break;
01314
01315 case R_SH_SWITCH8:
01316 voff += adjust;
01317 if (voff < 0 || voff >= 0xff)
01318 overflow = TRUE;
01319 bfd_put_8 (abfd, (bfd_vma) voff, contents + nraddr);
01320 break;
01321
01322 case R_SH_SWITCH16:
01323 voff += adjust;
01324 if (voff < - 0x8000 || voff >= 0x8000)
01325 overflow = TRUE;
01326 bfd_put_signed_16 (abfd, (bfd_vma) voff, contents + nraddr);
01327 break;
01328
01329 case R_SH_SWITCH32:
01330 voff += adjust;
01331 bfd_put_signed_32 (abfd, (bfd_vma) voff, contents + nraddr);
01332 break;
01333
01334 case R_SH_USES:
01335 irel->r_offset += adjust;
01336 break;
01337 }
01338
01339 if (overflow)
01340 {
01341 ((*_bfd_error_handler)
01342 ("%B: 0x%lx: fatal: reloc overflow while relaxing",
01343 abfd, (unsigned long) irel->r_vaddr));
01344 bfd_set_error (bfd_error_bad_value);
01345 return FALSE;
01346 }
01347 }
01348
01349 irel->r_vaddr = nraddr + sec->vma;
01350 }
01351
01352
01353
01354
01355 for (o = abfd->sections; o != NULL; o = o->next)
01356 {
01357 struct internal_reloc *internal_relocs;
01358 struct internal_reloc *irelscan, *irelscanend;
01359 bfd_byte *ocontents;
01360
01361 if (o == sec
01362 || (o->flags & SEC_RELOC) == 0
01363 || o->reloc_count == 0)
01364 continue;
01365
01366
01367
01368
01369 internal_relocs = (_bfd_coff_read_internal_relocs
01370 (abfd, o, TRUE, (bfd_byte *) NULL, FALSE,
01371 (struct internal_reloc *) NULL));
01372 if (internal_relocs == NULL)
01373 return FALSE;
01374
01375 ocontents = NULL;
01376 irelscanend = internal_relocs + o->reloc_count;
01377 for (irelscan = internal_relocs; irelscan < irelscanend; irelscan++)
01378 {
01379 struct internal_syment sym;
01380
01381 #ifdef COFF_WITH_PE
01382 if (irelscan->r_type != R_SH_IMM32
01383 && irelscan->r_type != R_SH_IMAGEBASE
01384 && irelscan->r_type != R_SH_IMM32CE)
01385 #else
01386 if (irelscan->r_type != R_SH_IMM32)
01387 #endif
01388 continue;
01389
01390 bfd_coff_swap_sym_in (abfd,
01391 ((bfd_byte *) obj_coff_external_syms (abfd)
01392 + (irelscan->r_symndx
01393 * bfd_coff_symesz (abfd))),
01394 &sym);
01395 if (sym.n_sclass != C_EXT
01396 && sym.n_scnum == sec->target_index
01397 && ((bfd_vma) sym.n_value <= addr
01398 || (bfd_vma) sym.n_value >= toaddr))
01399 {
01400 bfd_vma val;
01401
01402 if (ocontents == NULL)
01403 {
01404 if (coff_section_data (abfd, o)->contents != NULL)
01405 ocontents = coff_section_data (abfd, o)->contents;
01406 else
01407 {
01408 if (!bfd_malloc_and_get_section (abfd, o, &ocontents))
01409 return FALSE;
01410
01411
01412
01413
01414 coff_section_data (abfd, o)->contents = ocontents;
01415 }
01416 }
01417
01418 val = bfd_get_32 (abfd, ocontents + irelscan->r_vaddr - o->vma);
01419 val += sym.n_value;
01420 if (val > addr && val < toaddr)
01421 bfd_put_32 (abfd, val - count,
01422 ocontents + irelscan->r_vaddr - o->vma);
01423
01424 coff_section_data (abfd, o)->keep_contents = TRUE;
01425 }
01426 }
01427 }
01428
01429
01430
01431
01432
01433 if (obj_symbols (abfd) != NULL
01434 || obj_raw_syments (abfd) != NULL)
01435 {
01436 ((*_bfd_error_handler)
01437 ("%B: fatal: generic symbols retrieved before relaxing", abfd));
01438 bfd_set_error (bfd_error_invalid_operation);
01439 return FALSE;
01440 }
01441
01442
01443 sym_hash = obj_coff_sym_hashes (abfd);
01444 symesz = bfd_coff_symesz (abfd);
01445 esym = (bfd_byte *) obj_coff_external_syms (abfd);
01446 esymend = esym + obj_raw_syment_count (abfd) * symesz;
01447 while (esym < esymend)
01448 {
01449 struct internal_syment isym;
01450
01451 bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &isym);
01452
01453 if (isym.n_scnum == sec->target_index
01454 && (bfd_vma) isym.n_value > addr
01455 && (bfd_vma) isym.n_value < toaddr)
01456 {
01457 isym.n_value -= count;
01458
01459 bfd_coff_swap_sym_out (abfd, (PTR) &isym, (PTR) esym);
01460
01461 if (*sym_hash != NULL)
01462 {
01463 BFD_ASSERT ((*sym_hash)->root.type == bfd_link_hash_defined
01464 || (*sym_hash)->root.type == bfd_link_hash_defweak);
01465 BFD_ASSERT ((*sym_hash)->root.u.def.value >= addr
01466 && (*sym_hash)->root.u.def.value < toaddr);
01467 (*sym_hash)->root.u.def.value -= count;
01468 }
01469 }
01470
01471 esym += (isym.n_numaux + 1) * symesz;
01472 sym_hash += isym.n_numaux + 1;
01473 }
01474
01475
01476
01477 if (irelalign != NULL)
01478 {
01479 bfd_vma alignto, alignaddr;
01480
01481 alignto = BFD_ALIGN (toaddr, 1 << irelalign->r_offset);
01482 alignaddr = BFD_ALIGN (irelalign->r_vaddr - sec->vma,
01483 1 << irelalign->r_offset);
01484 if (alignto != alignaddr)
01485 {
01486
01487 return sh_relax_delete_bytes (abfd, sec, alignaddr,
01488 (int) (alignto - alignaddr));
01489 }
01490 }
01491
01492 return TRUE;
01493 }
01494
01495
01496
01497
01498
01499
01500
01501 struct sh_major_opcode
01502 {
01503
01504
01505 const struct sh_minor_opcode *minor_opcodes;
01506
01507 unsigned short count;
01508 };
01509
01510
01511
01512
01513
01514 struct sh_minor_opcode
01515 {
01516
01517 const struct sh_opcode *opcodes;
01518
01519 unsigned short count;
01520
01521 unsigned short mask;
01522 };
01523
01524
01525
01526
01527 struct sh_opcode
01528 {
01529
01530
01531 unsigned short opcode;
01532
01533 unsigned long flags;
01534 };
01535
01536
01537
01538
01539 #define LOAD (0x1)
01540
01541
01542 #define STORE (0x2)
01543
01544
01545 #define BRANCH (0x4)
01546
01547
01548 #define DELAY (0x8)
01549
01550
01551
01552 #define USES1 (0x10)
01553 #define USES1_REG(x) ((x & 0x0f00) >> 8)
01554
01555
01556
01557 #define USES2 (0x20)
01558 #define USES2_REG(x) ((x & 0x00f0) >> 4)
01559
01560
01561 #define USESR0 (0x40)
01562
01563
01564
01565 #define SETS1 (0x80)
01566 #define SETS1_REG(x) ((x & 0x0f00) >> 8)
01567
01568
01569
01570 #define SETS2 (0x100)
01571 #define SETS2_REG(x) ((x & 0x00f0) >> 4)
01572
01573
01574 #define SETSR0 (0x200)
01575
01576
01577 #define SETSSP (0x400)
01578
01579
01580 #define USESSP (0x800)
01581
01582
01583
01584 #define USESF1 (0x1000)
01585 #define USESF1_REG(x) ((x & 0x0f00) >> 8)
01586
01587
01588
01589 #define USESF2 (0x2000)
01590 #define USESF2_REG(x) ((x & 0x00f0) >> 4)
01591
01592
01593 #define USESF0 (0x4000)
01594
01595
01596
01597 #define SETSF1 (0x8000)
01598 #define SETSF1_REG(x) ((x & 0x0f00) >> 8)
01599
01600 #define USESAS (0x10000)
01601 #define USESAS_REG(x) (((((x) >> 8) - 2) & 3) + 2)
01602 #define USESR8 (0x20000)
01603 #define SETSAS (0x40000)
01604 #define SETSAS_REG(x) USESAS_REG (x)
01605
01606 #define MAP(a) a, sizeof a / sizeof a[0]
01607
01608 #ifndef COFF_IMAGE_WITH_PE
01609 static bfd_boolean sh_insn_uses_reg
01610 PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
01611 static bfd_boolean sh_insn_sets_reg
01612 PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
01613 static bfd_boolean sh_insn_uses_or_sets_reg
01614 PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
01615 static bfd_boolean sh_insn_uses_freg
01616 PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
01617 static bfd_boolean sh_insn_sets_freg
01618 PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
01619 static bfd_boolean sh_insn_uses_or_sets_freg
01620 PARAMS ((unsigned int, const struct sh_opcode *, unsigned int));
01621 static bfd_boolean sh_insns_conflict
01622 PARAMS ((unsigned int, const struct sh_opcode *, unsigned int,
01623 const struct sh_opcode *));
01624 static bfd_boolean sh_load_use
01625 PARAMS ((unsigned int, const struct sh_opcode *, unsigned int,
01626 const struct sh_opcode *));
01627
01628
01629
01630 static const struct sh_opcode sh_opcode00[] =
01631 {
01632 { 0x0008, SETSSP },
01633 { 0x0009, 0 },
01634 { 0x000b, BRANCH | DELAY | USESSP },
01635 { 0x0018, SETSSP },
01636 { 0x0019, SETSSP },
01637 { 0x001b, 0 },
01638 { 0x0028, SETSSP },
01639 { 0x002b, BRANCH | DELAY | SETSSP },
01640 { 0x0038, USESSP | SETSSP },
01641 { 0x0048, SETSSP },
01642 { 0x0058, SETSSP }
01643 };
01644
01645 static const struct sh_opcode sh_opcode01[] =
01646 {
01647 { 0x0003, BRANCH | DELAY | USES1 | SETSSP },
01648 { 0x000a, SETS1 | USESSP },
01649 { 0x001a, SETS1 | USESSP },
01650 { 0x0023, BRANCH | DELAY | USES1 },
01651 { 0x0029, SETS1 | USESSP },
01652 { 0x002a, SETS1 | USESSP },
01653 { 0x005a, SETS1 | USESSP },
01654 { 0x006a, SETS1 | USESSP },
01655 { 0x0083, LOAD | USES1 },
01656 { 0x007a, SETS1 | USESSP },
01657 { 0x008a, SETS1 | USESSP },
01658 { 0x009a, SETS1 | USESSP },
01659 { 0x00aa, SETS1 | USESSP },
01660 { 0x00ba, SETS1 | USESSP }
01661 };
01662
01663 static const struct sh_opcode sh_opcode02[] =
01664 {
01665 { 0x0002, SETS1 | USESSP },
01666 { 0x0004, STORE | USES1 | USES2 | USESR0 },
01667 { 0x0005, STORE | USES1 | USES2 | USESR0 },
01668 { 0x0006, STORE | USES1 | USES2 | USESR0 },
01669 { 0x0007, SETSSP | USES1 | USES2 },
01670 { 0x000c, LOAD | SETS1 | USES2 | USESR0 },
01671 { 0x000d, LOAD | SETS1 | USES2 | USESR0 },
01672 { 0x000e, LOAD | SETS1 | USES2 | USESR0 },
01673 { 0x000f, LOAD|SETS1|SETS2|SETSSP|USES1|USES2|USESSP },
01674 };
01675
01676 static const struct sh_minor_opcode sh_opcode0[] =
01677 {
01678 { MAP (sh_opcode00), 0xffff },
01679 { MAP (sh_opcode01), 0xf0ff },
01680 { MAP (sh_opcode02), 0xf00f }
01681 };
01682
01683 static const struct sh_opcode sh_opcode10[] =
01684 {
01685 { 0x1000, STORE | USES1 | USES2 }
01686 };
01687
01688 static const struct sh_minor_opcode sh_opcode1[] =
01689 {
01690 { MAP (sh_opcode10), 0xf000 }
01691 };
01692
01693 static const struct sh_opcode sh_opcode20[] =
01694 {
01695 { 0x2000, STORE | USES1 | USES2 },
01696 { 0x2001, STORE | USES1 | USES2 },
01697 { 0x2002, STORE | USES1 | USES2 },
01698 { 0x2004, STORE | SETS1 | USES1 | USES2 },
01699 { 0x2005, STORE | SETS1 | USES1 | USES2 },
01700 { 0x2006, STORE | SETS1 | USES1 | USES2 },
01701 { 0x2007, SETSSP | USES1 | USES2 | USESSP },
01702 { 0x2008, SETSSP | USES1 | USES2 },
01703 { 0x2009, SETS1 | USES1 | USES2 },
01704 { 0x200a, SETS1 | USES1 | USES2 },
01705 { 0x200b, SETS1 | USES1 | USES2 },
01706 { 0x200c, SETSSP | USES1 | USES2 },
01707 { 0x200d, SETS1 | USES1 | USES2 },
01708 { 0x200e, SETSSP | USES1 | USES2 },
01709 { 0x200f, SETSSP | USES1 | USES2 }
01710 };
01711
01712 static const struct sh_minor_opcode sh_opcode2[] =
01713 {
01714 { MAP (sh_opcode20), 0xf00f }
01715 };
01716
01717 static const struct sh_opcode sh_opcode30[] =
01718 {
01719 { 0x3000, SETSSP | USES1 | USES2 },
01720 { 0x3002, SETSSP | USES1 | USES2 },
01721 { 0x3003, SETSSP | USES1 | USES2 },
01722 { 0x3004, SETSSP | USESSP | USES1 | USES2 },
01723 { 0x3005, SETSSP | USES1 | USES2 },
01724 { 0x3006, SETSSP | USES1 | USES2 },
01725 { 0x3007, SETSSP | USES1 | USES2 },
01726 { 0x3008, SETS1 | USES1 | USES2 },
01727 { 0x300a, SETS1 | SETSSP | USES1 | USES2 | USESSP },
01728 { 0x300b, SETS1 | SETSSP | USES1 | USES2 },
01729 { 0x300c, SETS1 | USES1 | USES2 },
01730 { 0x300d, SETSSP | USES1 | USES2 },
01731 { 0x300e, SETS1 | SETSSP | USES1 | USES2 | USESSP },
01732 { 0x300f, SETS1 | SETSSP | USES1 | USES2 }
01733 };
01734
01735 static const struct sh_minor_opcode sh_opcode3[] =
01736 {
01737 { MAP (sh_opcode30), 0xf00f }
01738 };
01739
01740 static const struct sh_opcode sh_opcode40[] =
01741 {
01742 { 0x4000, SETS1 | SETSSP | USES1 },
01743 { 0x4001, SETS1 | SETSSP | USES1 },
01744 { 0x4002, STORE | SETS1 | USES1 | USESSP },
01745 { 0x4004, SETS1 | SETSSP | USES1 },
01746 { 0x4005, SETS1 | SETSSP | USES1 },
01747 { 0x4006, LOAD | SETS1 | SETSSP | USES1 },
01748 { 0x4008, SETS1 | USES1 },
01749 { 0x4009, SETS1 | USES1 },
01750 { 0x400a, SETSSP | USES1 },
01751 { 0x400b, BRANCH | DELAY | USES1 },
01752 { 0x4010, SETS1 | SETSSP | USES1 },
01753 { 0x4011, SETSSP | USES1 },
01754 { 0x4012, STORE | SETS1 | USES1 | USESSP },
01755 { 0x4014, SETSSP | USES1 },
01756 { 0x4015, SETSSP | USES1 },
01757 { 0x4016, LOAD | SETS1 | SETSSP | USES1 },
01758 { 0x4018, SETS1 | USES1 },
01759 { 0x4019, SETS1 | USES1 },
01760 { 0x401a, SETSSP | USES1 },
01761 { 0x401b, LOAD | SETSSP | USES1 },
01762 { 0x4020, SETS1 | SETSSP | USES1 },
01763 { 0x4021, SETS1 | SETSSP | USES1 },
01764 { 0x4022, STORE | SETS1 | USES1 | USESSP },
01765 { 0x4024, SETS1 | SETSSP | USES1 | USESSP },
01766 { 0x4025, SETS1 | SETSSP | USES1 | USESSP },
01767 { 0x4026, LOAD | SETS1 | SETSSP | USES1 },
01768 { 0x4028, SETS1 | USES1 },
01769 { 0x4029, SETS1 | USES1 },
01770 { 0x402a, SETSSP | USES1 },
01771 { 0x402b, BRANCH | DELAY | USES1 },
01772 { 0x4052, STORE | SETS1 | USES1 | USESSP },
01773 { 0x4056, LOAD | SETS1 | SETSSP | USES1 },
01774 { 0x405a, SETSSP | USES1 },
01775 { 0x4062, STORE | SETS1 | USES1 | USESSP },
01776 { 0x4066, LOAD | SETS1 | SETSSP | USES1 },
01777 { 0x406a, SETSSP | USES1 },
01778 { 0x4072, STORE | SETS1 | USES1 | USESSP },
01779 { 0x4076, LOAD | SETS1 | SETSSP | USES1 },
01780 { 0x407a, SETSSP | USES1 },
01781 { 0x4082, STORE | SETS1 | USES1 | USESSP },
01782 { 0x4086, LOAD | SETS1 | SETSSP | USES1 },
01783 { 0x408a, SETSSP | USES1 },
01784 { 0x4092, STORE | SETS1 | USES1 | USESSP },
01785 { 0x4096, LOAD | SETS1 | SETSSP | USES1 },
01786 { 0x409a, SETSSP | USES1 },
01787 { 0x40a2, STORE | SETS1 | USES1 | USESSP },
01788 { 0x40a6, LOAD | SETS1 | SETSSP | USES1 },
01789 { 0x40aa, SETSSP | USES1 },
01790 { 0x40b2, STORE | SETS1 | USES1 | USESSP },
01791 { 0x40b6, LOAD | SETS1 | SETSSP | USES1 },
01792 { 0x40ba, SETSSP | USES1 }
01793 };
01794
01795 static const struct sh_opcode sh_opcode41[] =
01796 {
01797 { 0x4003, STORE | SETS1 | USES1 | USESSP },
01798 { 0x4007, LOAD | SETS1 | SETSSP | USES1 },
01799 { 0x400c, SETS1 | USES1 | USES2 },
01800 { 0x400d, SETS1 | USES1 | USES2 },
01801 { 0x400e, SETSSP | USES1 },
01802 { 0x400f, LOAD|SETS1|SETS2|SETSSP|USES1|USES2|USESSP },
01803 };
01804
01805 static const struct sh_minor_opcode sh_opcode4[] =
01806 {
01807 { MAP (sh_opcode40), 0xf0ff },
01808 { MAP (sh_opcode41), 0xf00f }
01809 };
01810
01811 static const struct sh_opcode sh_opcode50[] =
01812 {
01813 { 0x5000, LOAD | SETS1 | USES2 }
01814 };
01815
01816 static const struct sh_minor_opcode sh_opcode5[] =
01817 {
01818 { MAP (sh_opcode50), 0xf000 }
01819 };
01820
01821 static const struct sh_opcode sh_opcode60[] =
01822 {
01823 { 0x6000, LOAD | SETS1 | USES2 },
01824 { 0x6001, LOAD | SETS1 | USES2 },
01825 { 0x6002, LOAD | SETS1 | USES2 },
01826 { 0x6003, SETS1 | USES2 },
01827 { 0x6004, LOAD | SETS1 | SETS2 | USES2 },
01828 { 0x6005, LOAD | SETS1 | SETS2 | USES2 },
01829 { 0x6006, LOAD | SETS1 | SETS2 | USES2 },
01830 { 0x6007, SETS1 | USES2 },
01831 { 0x6008, SETS1 | USES2 },
01832 { 0x6009, SETS1 | USES2 },
01833 { 0x600a, SETS1 | SETSSP | USES2 | USESSP },
01834 { 0x600b, SETS1 | USES2 },
01835 { 0x600c, SETS1 | USES2 },
01836 { 0x600d, SETS1 | USES2 },
01837 { 0x600e, SETS1 | USES2 },
01838 { 0x600f, SETS1 | USES2 }
01839 };
01840
01841 static const struct sh_minor_opcode sh_opcode6[] =
01842 {
01843 { MAP (sh_opcode60), 0xf00f }
01844 };
01845
01846 static const struct sh_opcode sh_opcode70[] =
01847 {
01848 { 0x7000, SETS1 | USES1 }
01849 };
01850
01851 static const struct sh_minor_opcode sh_opcode7[] =
01852 {
01853 { MAP (sh_opcode70), 0xf000 }
01854 };
01855
01856 static const struct sh_opcode sh_opcode80[] =
01857 {
01858 { 0x8000, STORE | USES2 | USESR0 },
01859 { 0x8100, STORE | USES2 | USESR0 },
01860 { 0x8200, SETSSP },
01861 { 0x8400, LOAD | SETSR0 | USES2 },
01862 { 0x8500, LOAD | SETSR0 | USES2 },
01863 { 0x8800, SETSSP | USESR0 },
01864 { 0x8900, BRANCH | USESSP },
01865 { 0x8b00, BRANCH | USESSP },
01866 { 0x8c00, SETSSP },
01867 { 0x8d00, BRANCH | DELAY | USESSP },
01868 { 0x8e00, SETSSP },
01869 { 0x8f00, BRANCH | DELAY | USESSP }
01870 };
01871
01872 static const struct sh_minor_opcode sh_opcode8[] =
01873 {
01874 { MAP (sh_opcode80), 0xff00 }
01875 };
01876
01877 static const struct sh_opcode sh_opcode90[] =
01878 {
01879 { 0x9000, LOAD | SETS1 }
01880 };
01881
01882 static const struct sh_minor_opcode sh_opcode9[] =
01883 {
01884 { MAP (sh_opcode90), 0xf000 }
01885 };
01886
01887 static const struct sh_opcode sh_opcodea0[] =
01888 {
01889 { 0xa000, BRANCH | DELAY }
01890 };
01891
01892 static const struct sh_minor_opcode sh_opcodea[] =
01893 {
01894 { MAP (sh_opcodea0), 0xf000 }
01895 };
01896
01897 static const struct sh_opcode sh_opcodeb0[] =
01898 {
01899 { 0xb000, BRANCH | DELAY }
01900 };
01901
01902 static const struct sh_minor_opcode sh_opcodeb[] =
01903 {
01904 { MAP (sh_opcodeb0), 0xf000 }
01905 };
01906
01907 static const struct sh_opcode sh_opcodec0[] =
01908 {
01909 { 0xc000, STORE | USESR0 | USESSP },
01910 { 0xc100, STORE | USESR0 | USESSP },
01911 { 0xc200, STORE | USESR0 | USESSP },
01912 { 0xc300, BRANCH | USESSP },
01913 { 0xc400, LOAD | SETSR0 | USESSP },
01914 { 0xc500, LOAD | SETSR0 | USESSP },
01915 { 0xc600, LOAD | SETSR0 | USESSP },
01916 { 0xc700, SETSR0 },
01917 { 0xc800, SETSSP | USESR0 },
01918 { 0xc900, SETSR0 | USESR0 },
01919 { 0xca00, SETSR0 | USESR0 },
01920 { 0xcb00, SETSR0 | USESR0 },
01921 { 0xcc00, LOAD | SETSSP | USESR0 | USESSP },
01922 { 0xcd00, LOAD | STORE | USESR0 | USESSP },
01923 { 0xce00, LOAD | STORE | USESR0 | USESSP },
01924 { 0xcf00, LOAD | STORE | USESR0 | USESSP }
01925 };
01926
01927 static const struct sh_minor_opcode sh_opcodec[] =
01928 {
01929 { MAP (sh_opcodec0), 0xff00 }
01930 };
01931
01932 static const struct sh_opcode sh_opcoded0[] =
01933 {
01934 { 0xd000, LOAD | SETS1 }
01935 };
01936
01937 static const struct sh_minor_opcode sh_opcoded[] =
01938 {
01939 { MAP (sh_opcoded0), 0xf000 }
01940 };
01941
01942 static const struct sh_opcode sh_opcodee0[] =
01943 {
01944 { 0xe000, SETS1 }
01945 };
01946
01947 static const struct sh_minor_opcode sh_opcodee[] =
01948 {
01949 { MAP (sh_opcodee0), 0xf000 }
01950 };
01951
01952 static const struct sh_opcode sh_opcodef0[] =
01953 {
01954 { 0xf000, SETSF1 | USESF1 | USESF2 },
01955 { 0xf001, SETSF1 | USESF1 | USESF2 },
01956 { 0xf002, SETSF1 | USESF1 | USESF2 },
01957 { 0xf003, SETSF1 | USESF1 | USESF2 },
01958 { 0xf004, SETSSP | USESF1 | USESF2 },
01959 { 0xf005, SETSSP | USESF1 | USESF2 },
01960 { 0xf006, LOAD | SETSF1 | USES2 | USESR0 },
01961 { 0xf007, STORE | USES1 | USESF2 | USESR0 },
01962 { 0xf008, LOAD | SETSF1 | USES2 },
01963 { 0xf009, LOAD | SETS2 | SETSF1 | USES2 },
01964 { 0xf00a, STORE | USES1 | USESF2 },
01965 { 0xf00b, STORE | SETS1 | USES1 | USESF2 },
01966 { 0xf00c, SETSF1 | USESF2 },
01967 { 0xf00e, SETSF1 | USESF1 | USESF2 | USESF0 }
01968 };
01969
01970 static const struct sh_opcode sh_opcodef1[] =
01971 {
01972 { 0xf00d, SETSF1 | USESSP },
01973 { 0xf01d, SETSSP | USESF1 },
01974 { 0xf02d, SETSF1 | USESSP },
01975 { 0xf03d, SETSSP | USESF1 },
01976 { 0xf04d, SETSF1 | USESF1 },
01977 { 0xf05d, SETSF1 | USESF1 },
01978 { 0xf06d, SETSF1 | USESF1 },
01979 { 0xf07d, SETSSP | USESF1 },
01980 { 0xf08d, SETSF1 },
01981 { 0xf09d, SETSF1 }
01982 };
01983
01984 static const struct sh_minor_opcode sh_opcodef[] =
01985 {
01986 { MAP (sh_opcodef0), 0xf00f },
01987 { MAP (sh_opcodef1), 0xf0ff }
01988 };
01989
01990 static struct sh_major_opcode sh_opcodes[] =
01991 {
01992 { MAP (sh_opcode0) },
01993 { MAP (sh_opcode1) },
01994 { MAP (sh_opcode2) },
01995 { MAP (sh_opcode3) },
01996 { MAP (sh_opcode4) },
01997 { MAP (sh_opcode5) },
01998 { MAP (sh_opcode6) },
01999 { MAP (sh_opcode7) },
02000 { MAP (sh_opcode8) },
02001 { MAP (sh_opcode9) },
02002 { MAP (sh_opcodea) },
02003 { MAP (sh_opcodeb) },
02004 { MAP (sh_opcodec) },
02005 { MAP (sh_opcoded) },
02006 { MAP (sh_opcodee) },
02007 { MAP (sh_opcodef) }
02008 };
02009
02010
02011
02012
02013 static const struct sh_opcode sh_dsp_opcodef0[] =
02014 {
02015 { 0xf400, USESAS | SETSAS | LOAD | SETSSP },
02016 { 0xf401, USESAS | SETSAS | STORE | USESSP },
02017 { 0xf404, USESAS | LOAD | SETSSP },
02018 { 0xf405, USESAS | STORE | USESSP },
02019 { 0xf408, USESAS | SETSAS | LOAD | SETSSP },
02020 { 0xf409, USESAS | SETSAS | STORE | USESSP },
02021 { 0xf40c, USESAS | SETSAS | LOAD | SETSSP | USESR8 },
02022 { 0xf40d, USESAS | SETSAS | STORE | USESSP | USESR8 }
02023 };
02024
02025 static const struct sh_minor_opcode sh_dsp_opcodef[] =
02026 {
02027 { MAP (sh_dsp_opcodef0), 0xfc0d }
02028 };
02029
02030
02031
02032
02033
02034 static const struct sh_opcode *
02035 sh_insn_info (insn)
02036 unsigned int insn;
02037 {
02038 const struct sh_major_opcode *maj;
02039 const struct sh_minor_opcode *min, *minend;
02040
02041 maj = &sh_opcodes[(insn & 0xf000) >> 12];
02042 min = maj->minor_opcodes;
02043 minend = min + maj->count;
02044 for (; min < minend; min++)
02045 {
02046 unsigned int l;
02047 const struct sh_opcode *op, *opend;
02048
02049 l = insn & min->mask;
02050 op = min->opcodes;
02051 opend = op + min->count;
02052
02053
02054
02055 for (; op < opend; op++)
02056 if (op->opcode == l)
02057 return op;
02058 }
02059
02060 return NULL;
02061 }
02062
02063
02064
02065 static bfd_boolean
02066 sh_insn_uses_or_sets_reg (insn, op, reg)
02067 unsigned int insn;
02068 const struct sh_opcode *op;
02069 unsigned int reg;
02070 {
02071 if (sh_insn_uses_reg (insn, op, reg))
02072 return TRUE;
02073
02074 return sh_insn_sets_reg (insn, op, reg);
02075 }
02076
02077
02078
02079 static bfd_boolean
02080 sh_insn_uses_reg (insn, op, reg)
02081 unsigned int insn;
02082 const struct sh_opcode *op;
02083 unsigned int reg;
02084 {
02085 unsigned int f;
02086
02087 f = op->flags;
02088
02089 if ((f & USES1) != 0
02090 && USES1_REG (insn) == reg)
02091 return TRUE;
02092 if ((f & USES2) != 0
02093 && USES2_REG (insn) == reg)
02094 return TRUE;
02095 if ((f & USESR0) != 0
02096 && reg == 0)
02097 return TRUE;
02098 if ((f & USESAS) && reg == USESAS_REG (insn))
02099 return TRUE;
02100 if ((f & USESR8) && reg == 8)
02101 return TRUE;
02102
02103 return FALSE;
02104 }
02105
02106
02107
02108 static bfd_boolean
02109 sh_insn_sets_reg (insn, op, reg)
02110 unsigned int insn;
02111 const struct sh_opcode *op;
02112 unsigned int reg;
02113 {
02114 unsigned int f;
02115
02116 f = op->flags;
02117
02118 if ((f & SETS1) != 0
02119 && SETS1_REG (insn) == reg)
02120 return TRUE;
02121 if ((f & SETS2) != 0
02122 && SETS2_REG (insn) == reg)
02123 return TRUE;
02124 if ((f & SETSR0) != 0
02125 && reg == 0)
02126 return TRUE;
02127 if ((f & SETSAS) && reg == SETSAS_REG (insn))
02128 return TRUE;
02129
02130 return FALSE;
02131 }
02132
02133
02134
02135 static bfd_boolean
02136 sh_insn_uses_or_sets_freg (insn, op, reg)
02137 unsigned int insn;
02138 const struct sh_opcode *op;
02139 unsigned int reg;
02140 {
02141 if (sh_insn_uses_freg (insn, op, reg))
02142 return TRUE;
02143
02144 return sh_insn_sets_freg (insn, op, reg);
02145 }
02146
02147
02148
02149 static bfd_boolean
02150 sh_insn_uses_freg (insn, op, freg)
02151 unsigned int insn;
02152 const struct sh_opcode *op;
02153 unsigned int freg;
02154 {
02155 unsigned int f;
02156
02157 f = op->flags;
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168 if ((f & USESF1) != 0
02169 && (USESF1_REG (insn) & 0xe) == (freg & 0xe))
02170 return TRUE;
02171 if ((f & USESF2) != 0
02172 && (USESF2_REG (insn) & 0xe) == (freg & 0xe))
02173 return TRUE;
02174 if ((f & USESF0) != 0
02175 && freg == 0)
02176 return TRUE;
02177
02178 return FALSE;
02179 }
02180
02181
02182
02183 static bfd_boolean
02184 sh_insn_sets_freg (insn, op, freg)
02185 unsigned int insn;
02186 const struct sh_opcode *op;
02187 unsigned int freg;
02188 {
02189 unsigned int f;
02190
02191 f = op->flags;
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202 if ((f & SETSF1) != 0
02203 && (SETSF1_REG (insn) & 0xe) == (freg & 0xe))
02204 return TRUE;
02205
02206 return FALSE;
02207 }
02208
02209
02210
02211
02212
02213
02214 static bfd_boolean
02215 sh_insns_conflict (i1, op1, i2, op2)
02216 unsigned int i1;
02217 const struct sh_opcode *op1;
02218 unsigned int i2;
02219 const struct sh_opcode *op2;
02220 {
02221 unsigned int f1, f2;
02222
02223 f1 = op1->flags;
02224 f2 = op2->flags;
02225
02226
02227
02228 if (((i1 & 0xf0ff) == 0x4066 && (i2 & 0xf000) == 0xf000)
02229 || ((i2 & 0xf0ff) == 0x4066 && (i1 & 0xf000) == 0xf000))
02230 return TRUE;
02231
02232 if ((f1 & (BRANCH | DELAY)) != 0
02233 || (f2 & (BRANCH | DELAY)) != 0)
02234 return TRUE;
02235
02236 if (((f1 | f2) & SETSSP)
02237 && (f1 & (SETSSP | USESSP))
02238 && (f2 & (SETSSP | USESSP)))
02239 return TRUE;
02240
02241 if ((f1 & SETS1) != 0
02242 && sh_insn_uses_or_sets_reg (i2, op2, SETS1_REG (i1)))
02243 return TRUE;
02244 if ((f1 & SETS2) != 0
02245 && sh_insn_uses_or_sets_reg (i2, op2, SETS2_REG (i1)))
02246 return TRUE;
02247 if ((f1 & SETSR0) != 0
02248 && sh_insn_uses_or_sets_reg (i2, op2, 0))
02249 return TRUE;
02250 if ((f1 & SETSAS)
02251 && sh_insn_uses_or_sets_reg (i2, op2, SETSAS_REG (i1)))
02252 return TRUE;
02253 if ((f1 & SETSF1) != 0
02254 && sh_insn_uses_or_sets_freg (i2, op2, SETSF1_REG (i1)))
02255 return TRUE;
02256
02257 if ((f2 & SETS1) != 0
02258 && sh_insn_uses_or_sets_reg (i1, op1, SETS1_REG (i2)))
02259 return TRUE;
02260 if ((f2 & SETS2) != 0
02261 && sh_insn_uses_or_sets_reg (i1, op1, SETS2_REG (i2)))
02262 return TRUE;
02263 if ((f2 & SETSR0) != 0
02264 && sh_insn_uses_or_sets_reg (i1, op1, 0))
02265 return TRUE;
02266 if ((f2 & SETSAS)
02267 && sh_insn_uses_or_sets_reg (i1, op1, SETSAS_REG (i2)))
02268 return TRUE;
02269 if ((f2 & SETSF1) != 0
02270 && sh_insn_uses_or_sets_freg (i1, op1, SETSF1_REG (i2)))
02271 return TRUE;
02272
02273
02274 return FALSE;
02275 }
02276
02277
02278
02279
02280 static bfd_boolean
02281 sh_load_use (i1, op1, i2, op2)
02282 unsigned int i1;
02283 const struct sh_opcode *op1;
02284 unsigned int i2;
02285 const struct sh_opcode *op2;
02286 {
02287 unsigned int f1;
02288
02289 f1 = op1->flags;
02290
02291 if ((f1 & LOAD) == 0)
02292 return FALSE;
02293
02294
02295
02296
02297 if ((f1 & SETS1) != 0
02298 && (f1 & SETSSP) == 0
02299 && sh_insn_uses_reg (i2, op2, (i1 & 0x0f00) >> 8))
02300 return TRUE;
02301
02302 if ((f1 & SETSR0) != 0
02303 && sh_insn_uses_reg (i2, op2, 0))
02304 return TRUE;
02305
02306 if ((f1 & SETSF1) != 0
02307 && sh_insn_uses_freg (i2, op2, (i1 & 0x0f00) >> 8))
02308 return TRUE;
02309
02310 return FALSE;
02311 }
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323 #ifdef COFF_WITH_PE
02324 static
02325 #endif
02326 bfd_boolean
02327 _bfd_sh_align_load_span (abfd, sec, contents, swap, relocs,
02328 plabel, label_end, start, stop, pswapped)
02329 bfd *abfd;
02330 asection *sec;
02331 bfd_byte *contents;
02332 bfd_boolean (*swap) PARAMS ((bfd *, asection *, PTR, bfd_byte *, bfd_vma));
02333 PTR relocs;
02334 bfd_vma **plabel;
02335 bfd_vma *label_end;
02336 bfd_vma start;
02337 bfd_vma stop;
02338 bfd_boolean *pswapped;
02339 {
02340 int dsp = (abfd->arch_info->mach == bfd_mach_sh_dsp
02341 || abfd->arch_info->mach == bfd_mach_sh3_dsp);
02342 bfd_vma i;
02343
02344
02345
02346
02347 if (abfd->arch_info->mach == bfd_mach_sh4)
02348 return TRUE;
02349
02350
02351
02352 if (dsp)
02353 {
02354 sh_opcodes[0xf].minor_opcodes = sh_dsp_opcodef;
02355 sh_opcodes[0xf].count = sizeof sh_dsp_opcodef / sizeof sh_dsp_opcodef;
02356 }
02357
02358
02359 if ((start & 1) == 1)
02360 ++start;
02361
02362
02363 i = start;
02364 if ((i & 2) == 0)
02365 i += 2;
02366 for (; i < stop; i += 4)
02367 {
02368 unsigned int insn;
02369 const struct sh_opcode *op;
02370 unsigned int prev_insn = 0;
02371 const struct sh_opcode *prev_op = NULL;
02372
02373 insn = bfd_get_16 (abfd, contents + i);
02374 op = sh_insn_info (insn);
02375 if (op == NULL
02376 || (op->flags & (LOAD | STORE)) == 0)
02377 continue;
02378
02379
02380
02381 while (*plabel < label_end && **plabel < i)
02382 ++*plabel;
02383
02384 if (i > start)
02385 {
02386 prev_insn = bfd_get_16 (abfd, contents + i - 2);
02387
02388
02389
02390
02391
02392 if (dsp && (prev_insn & 0xfc00) == 0xf800)
02393 continue;
02394
02395
02396
02397
02398 if (dsp && i - 2 > start)
02399 {
02400 unsigned pprev_insn = bfd_get_16 (abfd, contents + i - 4);
02401
02402 if ((pprev_insn & 0xfc00) == 0xf800)
02403 prev_op = NULL;
02404 else
02405 prev_op = sh_insn_info (prev_insn);
02406 }
02407 else
02408 prev_op = sh_insn_info (prev_insn);
02409
02410
02411
02412 if (prev_op == NULL
02413 || (prev_op->flags & DELAY) != 0)
02414 continue;
02415 }
02416 if (i > start
02417 && (*plabel >= label_end || **plabel != i)
02418 && prev_op != NULL
02419 && (prev_op->flags & (LOAD | STORE)) == 0
02420 && ! sh_insns_conflict (prev_insn, prev_op, insn, op))
02421 {
02422 bfd_boolean ok;
02423
02424
02425
02426
02427
02428
02429 ok = TRUE;
02430
02431 if (i >= start + 4)
02432 {
02433 unsigned int prev2_insn;
02434 const struct sh_opcode *prev2_op;
02435
02436 prev2_insn = bfd_get_16 (abfd, contents + i - 4);
02437 prev2_op = sh_insn_info (prev2_insn);
02438
02439
02440
02441
02442 if (prev2_op == NULL
02443 || (prev2_op->flags & DELAY) != 0)
02444 ok = FALSE;
02445
02446
02447
02448
02449
02450
02451 if (ok
02452 && (prev2_op->flags & LOAD) != 0
02453 && sh_load_use (prev2_insn, prev2_op, insn, op))
02454 ok = FALSE;
02455 }
02456
02457 if (ok)
02458 {
02459 if (! (*swap) (abfd, sec, relocs, contents, i - 2))
02460 return FALSE;
02461 *pswapped = TRUE;
02462 continue;
02463 }
02464 }
02465
02466 while (*plabel < label_end && **plabel < i + 2)
02467 ++*plabel;
02468
02469 if (i + 2 < stop
02470 && (*plabel >= label_end || **plabel != i + 2))
02471 {
02472 unsigned int next_insn;
02473 const struct sh_opcode *next_op;
02474
02475
02476
02477 next_insn = bfd_get_16 (abfd, contents + i + 2);
02478 next_op = sh_insn_info (next_insn);
02479 if (next_op != NULL
02480 && (next_op->flags & (LOAD | STORE)) == 0
02481 && ! sh_insns_conflict (insn, op, next_insn, next_op))
02482 {
02483 bfd_boolean ok;
02484
02485
02486
02487
02488 ok = TRUE;
02489
02490
02491
02492
02493
02494 if (prev_op != NULL
02495 && (prev_op->flags & LOAD) != 0
02496 && sh_load_use (prev_insn, prev_op, next_insn, next_op))
02497 ok = FALSE;
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508 if (ok
02509 && i + 4 < stop
02510 && (op->flags & LOAD) != 0)
02511 {
02512 unsigned int next2_insn;
02513 const struct sh_opcode *next2_op;
02514
02515 next2_insn = bfd_get_16 (abfd, contents + i + 4);
02516 next2_op = sh_insn_info (next2_insn);
02517 if ((next2_op->flags & (LOAD | STORE)) == 0
02518 && sh_load_use (insn, op, next2_insn, next2_op))
02519 ok = FALSE;
02520 }
02521
02522 if (ok)
02523 {
02524 if (! (*swap) (abfd, sec, relocs, contents, i))
02525 return FALSE;
02526 *pswapped = TRUE;
02527 continue;
02528 }
02529 }
02530 }
02531 }
02532
02533 return TRUE;
02534 }
02535 #endif
02536
02537
02538
02539
02540
02541
02542 static bfd_boolean
02543 sh_align_loads (abfd, sec, internal_relocs, contents, pswapped)
02544 bfd *abfd;
02545 asection *sec;
02546 struct internal_reloc *internal_relocs;
02547 bfd_byte *contents;
02548 bfd_boolean *pswapped;
02549 {
02550 struct internal_reloc *irel, *irelend;
02551 bfd_vma *labels = NULL;
02552 bfd_vma *label, *label_end;
02553 bfd_size_type amt;
02554
02555 *pswapped = FALSE;
02556
02557 irelend = internal_relocs + sec->reloc_count;
02558
02559
02560 amt = (bfd_size_type) sec->reloc_count * sizeof (bfd_vma);
02561 labels = (bfd_vma *) bfd_malloc (amt);
02562 if (labels == NULL)
02563 goto error_return;
02564 label_end = labels;
02565 for (irel = internal_relocs; irel < irelend; irel++)
02566 {
02567 if (irel->r_type == R_SH_LABEL)
02568 {
02569 *label_end = irel->r_vaddr - sec->vma;
02570 ++label_end;
02571 }
02572 }
02573
02574
02575
02576
02577
02578 label = labels;
02579
02580 for (irel = internal_relocs; irel < irelend; irel++)
02581 {
02582 bfd_vma start, stop;
02583
02584 if (irel->r_type != R_SH_CODE)
02585 continue;
02586
02587 start = irel->r_vaddr - sec->vma;
02588
02589 for (irel++; irel < irelend; irel++)
02590 if (irel->r_type == R_SH_DATA)
02591 break;
02592 if (irel < irelend)
02593 stop = irel->r_vaddr - sec->vma;
02594 else
02595 stop = sec->size;
02596
02597 if (! _bfd_sh_align_load_span (abfd, sec, contents, sh_swap_insns,
02598 (PTR) internal_relocs, &label,
02599 label_end, start, stop, pswapped))
02600 goto error_return;
02601 }
02602
02603 free (labels);
02604
02605 return TRUE;
02606
02607 error_return:
02608 if (labels != NULL)
02609 free (labels);
02610 return FALSE;
02611 }
02612
02613
02614
02615 static bfd_boolean
02616 sh_swap_insns (abfd, sec, relocs, contents, addr)
02617 bfd *abfd;
02618 asection *sec;
02619 PTR relocs;
02620 bfd_byte *contents;
02621 bfd_vma addr;
02622 {
02623 struct internal_reloc *internal_relocs = (struct internal_reloc *) relocs;
02624 unsigned short i1, i2;
02625 struct internal_reloc *irel, *irelend;
02626
02627
02628 i1 = bfd_get_16 (abfd, contents + addr);
02629 i2 = bfd_get_16 (abfd, contents + addr + 2);
02630 bfd_put_16 (abfd, (bfd_vma) i2, contents + addr);
02631 bfd_put_16 (abfd, (bfd_vma) i1, contents + addr + 2);
02632
02633
02634 irelend = internal_relocs + sec->reloc_count;
02635 for (irel = internal_relocs; irel < irelend; irel++)
02636 {
02637 int type, add;
02638
02639
02640
02641
02642 type = irel->r_type;
02643 if (type == R_SH_ALIGN
02644 || type == R_SH_CODE
02645 || type == R_SH_DATA
02646 || type == R_SH_LABEL)
02647 continue;
02648
02649
02650
02651
02652
02653
02654
02655 if (type == R_SH_USES)
02656 {
02657 bfd_vma off;
02658
02659 off = irel->r_vaddr - sec->vma + 4 + irel->r_offset;
02660 if (off == addr)
02661 irel->r_offset += 2;
02662 else if (off == addr + 2)
02663 irel->r_offset -= 2;
02664 }
02665
02666 if (irel->r_vaddr - sec->vma == addr)
02667 {
02668 irel->r_vaddr += 2;
02669 add = -2;
02670 }
02671 else if (irel->r_vaddr - sec->vma == addr + 2)
02672 {
02673 irel->r_vaddr -= 2;
02674 add = 2;
02675 }
02676 else
02677 add = 0;
02678
02679 if (add != 0)
02680 {
02681 bfd_byte *loc;
02682 unsigned short insn, oinsn;
02683 bfd_boolean overflow;
02684
02685 loc = contents + irel->r_vaddr - sec->vma;
02686 overflow = FALSE;
02687 switch (type)
02688 {
02689 default:
02690 break;
02691
02692 case R_SH_PCDISP8BY2:
02693 case R_SH_PCRELIMM8BY2:
02694 insn = bfd_get_16 (abfd, loc);
02695 oinsn = insn;
02696 insn += add / 2;
02697 if ((oinsn & 0xff00) != (insn & 0xff00))
02698 overflow = TRUE;
02699 bfd_put_16 (abfd, (bfd_vma) insn, loc);
02700 break;
02701
02702 case R_SH_PCDISP:
02703 insn = bfd_get_16 (abfd, loc);
02704 oinsn = insn;
02705 insn += add / 2;
02706 if ((oinsn & 0xf000) != (insn & 0xf000))
02707 overflow = TRUE;
02708 bfd_put_16 (abfd, (bfd_vma) insn, loc);
02709 break;
02710
02711 case R_SH_PCRELIMM8BY4:
02712
02713
02714
02715
02716
02717
02718 if ((addr & 3) != 0)
02719 {
02720 insn = bfd_get_16 (abfd, loc);
02721 oinsn = insn;
02722 insn += add / 2;
02723 if ((oinsn & 0xff00) != (insn & 0xff00))
02724 overflow = TRUE;
02725 bfd_put_16 (abfd, (bfd_vma) insn, loc);
02726 }
02727
02728 break;
02729 }
02730
02731 if (overflow)
02732 {
02733 ((*_bfd_error_handler)
02734 ("%B: 0x%lx: fatal: reloc overflow while relaxing",
02735 abfd, (unsigned long) irel->r_vaddr));
02736 bfd_set_error (bfd_error_bad_value);
02737 return FALSE;
02738 }
02739 }
02740 }
02741
02742 return TRUE;
02743 }
02744
02745
02746
02747
02748 static bfd_boolean
02749 sh_relocate_section (output_bfd, info, input_bfd, input_section, contents,
02750 relocs, syms, sections)
02751 bfd *output_bfd ATTRIBUTE_UNUSED;
02752 struct bfd_link_info *info;
02753 bfd *input_bfd;
02754 asection *input_section;
02755 bfd_byte *contents;
02756 struct internal_reloc *relocs;
02757 struct internal_syment *syms;
02758 asection **sections;
02759 {
02760 struct internal_reloc *rel;
02761 struct internal_reloc *relend;
02762
02763 rel = relocs;
02764 relend = rel + input_section->reloc_count;
02765 for (; rel < relend; rel++)
02766 {
02767 long symndx;
02768 struct coff_link_hash_entry *h;
02769 struct internal_syment *sym;
02770 bfd_vma addend;
02771 bfd_vma val;
02772 reloc_howto_type *howto;
02773 bfd_reloc_status_type rstat;
02774
02775
02776
02777 if (rel->r_type != R_SH_IMM32
02778 #ifdef COFF_WITH_PE
02779 && rel->r_type != R_SH_IMM32CE
02780 && rel->r_type != R_SH_IMAGEBASE
02781 #endif
02782 && rel->r_type != R_SH_PCDISP)
02783 continue;
02784
02785 symndx = rel->r_symndx;
02786
02787 if (symndx == -1)
02788 {
02789 h = NULL;
02790 sym = NULL;
02791 }
02792 else
02793 {
02794 if (symndx < 0
02795 || (unsigned long) symndx >= obj_raw_syment_count (input_bfd))
02796 {
02797 (*_bfd_error_handler)
02798 ("%B: illegal symbol index %ld in relocs",
02799 input_bfd, symndx);
02800 bfd_set_error (bfd_error_bad_value);
02801 return FALSE;
02802 }
02803 h = obj_coff_sym_hashes (input_bfd)[symndx];
02804 sym = syms + symndx;
02805 }
02806
02807 if (sym != NULL && sym->n_scnum != 0)
02808 addend = - sym->n_value;
02809 else
02810 addend = 0;
02811
02812 if (rel->r_type == R_SH_PCDISP)
02813 addend -= 4;
02814
02815 if (rel->r_type >= SH_COFF_HOWTO_COUNT)
02816 howto = NULL;
02817 else
02818 howto = &sh_coff_howtos[rel->r_type];
02819
02820 if (howto == NULL)
02821 {
02822 bfd_set_error (bfd_error_bad_value);
02823 return FALSE;
02824 }
02825
02826 #ifdef COFF_WITH_PE
02827 if (rel->r_type == R_SH_IMAGEBASE)
02828 addend -= pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
02829 #endif
02830
02831 val = 0;
02832
02833 if (h == NULL)
02834 {
02835 asection *sec;
02836
02837
02838 if (rel->r_type == R_SH_PCDISP)
02839 continue;
02840
02841 if (symndx == -1)
02842 {
02843 sec = bfd_abs_section_ptr;
02844 val = 0;
02845 }
02846 else
02847 {
02848 sec = sections[symndx];
02849 val = (sec->output_section->vma
02850 + sec->output_offset
02851 + sym->n_value
02852 - sec->vma);
02853 }
02854 }
02855 else
02856 {
02857 if (h->root.type == bfd_link_hash_defined
02858 || h->root.type == bfd_link_hash_defweak)
02859 {
02860 asection *sec;
02861
02862 sec = h->root.u.def.section;
02863 val = (h->root.u.def.value
02864 + sec->output_section->vma
02865 + sec->output_offset);
02866 }
02867 else if (! info->relocatable)
02868 {
02869 if (! ((*info->callbacks->undefined_symbol)
02870 (info, h->root.root.string, input_bfd, input_section,
02871 rel->r_vaddr - input_section->vma, TRUE)))
02872 return FALSE;
02873 }
02874 }
02875
02876 rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
02877 contents,
02878 rel->r_vaddr - input_section->vma,
02879 val, addend);
02880
02881 switch (rstat)
02882 {
02883 default:
02884 abort ();
02885 case bfd_reloc_ok:
02886 break;
02887 case bfd_reloc_overflow:
02888 {
02889 const char *name;
02890 char buf[SYMNMLEN + 1];
02891
02892 if (symndx == -1)
02893 name = "*ABS*";
02894 else if (h != NULL)
02895 name = NULL;
02896 else if (sym->_n._n_n._n_zeroes == 0
02897 && sym->_n._n_n._n_offset != 0)
02898 name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
02899 else
02900 {
02901 strncpy (buf, sym->_n._n_name, SYMNMLEN);
02902 buf[SYMNMLEN] = '\0';
02903 name = buf;
02904 }
02905
02906 if (! ((*info->callbacks->reloc_overflow)
02907 (info, (h ? &h->root : NULL), name, howto->name,
02908 (bfd_vma) 0, input_bfd, input_section,
02909 rel->r_vaddr - input_section->vma)))
02910 return FALSE;
02911 }
02912 }
02913 }
02914
02915 return TRUE;
02916 }
02917
02918
02919
02920
02921 static bfd_byte *
02922 sh_coff_get_relocated_section_contents (output_bfd, link_info, link_order,
02923 data, relocatable, symbols)
02924 bfd *output_bfd;
02925 struct bfd_link_info *link_info;
02926 struct bfd_link_order *link_order;
02927 bfd_byte *data;
02928 bfd_boolean relocatable;
02929 asymbol **symbols;
02930 {
02931 asection *input_section = link_order->u.indirect.section;
02932 bfd *input_bfd = input_section->owner;
02933 asection **sections = NULL;
02934 struct internal_reloc *internal_relocs = NULL;
02935 struct internal_syment *internal_syms = NULL;
02936
02937
02938
02939 if (relocatable
02940 || coff_section_data (input_bfd, input_section) == NULL
02941 || coff_section_data (input_bfd, input_section)->contents == NULL)
02942 return bfd_generic_get_relocated_section_contents (output_bfd, link_info,
02943 link_order, data,
02944 relocatable,
02945 symbols);
02946
02947 memcpy (data, coff_section_data (input_bfd, input_section)->contents,
02948 (size_t) input_section->size);
02949
02950 if ((input_section->flags & SEC_RELOC) != 0
02951 && input_section->reloc_count > 0)
02952 {
02953 bfd_size_type symesz = bfd_coff_symesz (input_bfd);
02954 bfd_byte *esym, *esymend;
02955 struct internal_syment *isymp;
02956 asection **secpp;
02957 bfd_size_type amt;
02958
02959 if (! _bfd_coff_get_external_symbols (input_bfd))
02960 goto error_return;
02961
02962 internal_relocs = (_bfd_coff_read_internal_relocs
02963 (input_bfd, input_section, FALSE, (bfd_byte *) NULL,
02964 FALSE, (struct internal_reloc *) NULL));
02965 if (internal_relocs == NULL)
02966 goto error_return;
02967
02968 amt = obj_raw_syment_count (input_bfd);
02969 amt *= sizeof (struct internal_syment);
02970 internal_syms = (struct internal_syment *) bfd_malloc (amt);
02971 if (internal_syms == NULL)
02972 goto error_return;
02973
02974 amt = obj_raw_syment_count (input_bfd);
02975 amt *= sizeof (asection *);
02976 sections = (asection **) bfd_malloc (amt);
02977 if (sections == NULL)
02978 goto error_return;
02979
02980 isymp = internal_syms;
02981 secpp = sections;
02982 esym = (bfd_byte *) obj_coff_external_syms (input_bfd);
02983 esymend = esym + obj_raw_syment_count (input_bfd) * symesz;
02984 while (esym < esymend)
02985 {
02986 bfd_coff_swap_sym_in (input_bfd, (PTR) esym, (PTR) isymp);
02987
02988 if (isymp->n_scnum != 0)
02989 *secpp = coff_section_from_bfd_index (input_bfd, isymp->n_scnum);
02990 else
02991 {
02992 if (isymp->n_value == 0)
02993 *secpp = bfd_und_section_ptr;
02994 else
02995 *secpp = bfd_com_section_ptr;
02996 }
02997
02998 esym += (isymp->n_numaux + 1) * symesz;
02999 secpp += isymp->n_numaux + 1;
03000 isymp += isymp->n_numaux + 1;
03001 }
03002
03003 if (! sh_relocate_section (output_bfd, link_info, input_bfd,
03004 input_section, data, internal_relocs,
03005 internal_syms, sections))
03006 goto error_return;
03007
03008 free (sections);
03009 sections = NULL;
03010 free (internal_syms);
03011 internal_syms = NULL;
03012 free (internal_relocs);
03013 internal_relocs = NULL;
03014 }
03015
03016 return data;
03017
03018 error_return:
03019 if (internal_relocs != NULL)
03020 free (internal_relocs);
03021 if (internal_syms != NULL)
03022 free (internal_syms);
03023 if (sections != NULL)
03024 free (sections);
03025 return NULL;
03026 }
03027
03028
03029
03030 #ifndef TARGET_SHL_SYM
03031 CREATE_BIG_COFF_TARGET_VEC (shcoff_vec, "coff-sh", BFD_IS_RELAXABLE, 0, '_', NULL, COFF_SWAP_TABLE)
03032 #endif
03033
03034 #ifdef TARGET_SHL_SYM
03035 #define TARGET_SYM TARGET_SHL_SYM
03036 #else
03037 #define TARGET_SYM shlcoff_vec
03038 #endif
03039
03040 #ifndef TARGET_SHL_NAME
03041 #define TARGET_SHL_NAME "coff-shl"
03042 #endif
03043
03044 #ifdef COFF_WITH_PE
03045 CREATE_LITTLE_COFF_TARGET_VEC (TARGET_SYM, TARGET_SHL_NAME, BFD_IS_RELAXABLE,
03046 SEC_CODE | SEC_DATA, '_', NULL, COFF_SWAP_TABLE);
03047 #else
03048 CREATE_LITTLE_COFF_TARGET_VEC (TARGET_SYM, TARGET_SHL_NAME, BFD_IS_RELAXABLE,
03049 0, '_', NULL, COFF_SWAP_TABLE)
03050 #endif
03051
03052 #ifndef TARGET_SHL_SYM
03053 static const bfd_target * coff_small_object_p PARAMS ((bfd *));
03054 static bfd_boolean coff_small_new_section_hook PARAMS ((bfd *, asection *));
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066
03067
03068
03069 static const bfd_target *
03070 coff_small_object_p (abfd)
03071 bfd *abfd;
03072 {
03073 if (abfd->target_defaulted)
03074 {
03075 bfd_set_error (bfd_error_wrong_format);
03076 return NULL;
03077 }
03078 return coff_object_p (abfd);
03079 }
03080
03081
03082
03083 static bfd_boolean
03084 coff_small_new_section_hook (abfd, section)
03085 bfd *abfd;
03086 asection *section;
03087 {
03088 if (! coff_new_section_hook (abfd, section))
03089 return FALSE;
03090
03091
03092
03093 if (section->alignment_power == COFF_DEFAULT_SECTION_ALIGNMENT_POWER)
03094 section->alignment_power = 2;
03095
03096 return TRUE;
03097 }
03098
03099
03100
03101
03102 static const bfd_coff_backend_data bfd_coff_small_swap_table =
03103 {
03104 coff_swap_aux_in, coff_swap_sym_in, coff_swap_lineno_in,
03105 coff_swap_aux_out, coff_swap_sym_out,
03106 coff_swap_lineno_out, coff_swap_reloc_out,
03107 coff_swap_filehdr_out, coff_swap_aouthdr_out,
03108 coff_swap_scnhdr_out,
03109 FILHSZ, AOUTSZ, SCNHSZ, SYMESZ, AUXESZ, RELSZ, LINESZ, FILNMLEN,
03110 #ifdef COFF_LONG_FILENAMES
03111 TRUE,
03112 #else
03113 FALSE,
03114 #endif
03115 #ifdef COFF_LONG_SECTION_NAMES
03116 TRUE,
03117 #else
03118 FALSE,
03119 #endif
03120 2,
03121 #ifdef COFF_FORCE_SYMBOLS_IN_STRINGS
03122 TRUE,
03123 #else
03124 FALSE,
03125 #endif
03126 #ifdef COFF_DEBUG_STRING_WIDE_PREFIX
03127 4,
03128 #else
03129 2,
03130 #endif
03131 coff_swap_filehdr_in, coff_swap_aouthdr_in, coff_swap_scnhdr_in,
03132 coff_swap_reloc_in, coff_bad_format_hook, coff_set_arch_mach_hook,
03133 coff_mkobject_hook, styp_to_sec_flags, coff_set_alignment_hook,
03134 coff_slurp_symbol_table, symname_in_debug_hook, coff_pointerize_aux_hook,
03135 coff_print_aux, coff_reloc16_extra_cases, coff_reloc16_estimate,
03136 coff_classify_symbol, coff_compute_section_file_positions,
03137 coff_start_final_link, coff_relocate_section, coff_rtype_to_howto,
03138 coff_adjust_symndx, coff_link_add_one_symbol,
03139 coff_link_output_has_begun, coff_final_link_postscript
03140 };
03141
03142 #define coff_small_close_and_cleanup \
03143 coff_close_and_cleanup
03144 #define coff_small_bfd_free_cached_info \
03145 coff_bfd_free_cached_info
03146 #define coff_small_get_section_contents \
03147 coff_get_section_contents
03148 #define coff_small_get_section_contents_in_window \
03149 coff_get_section_contents_in_window
03150
03151 extern const bfd_target shlcoff_small_vec;
03152
03153 const bfd_target shcoff_small_vec =
03154 {
03155 "coff-sh-small",
03156 bfd_target_coff_flavour,
03157 BFD_ENDIAN_BIG,
03158 BFD_ENDIAN_BIG,
03159
03160 (HAS_RELOC | EXEC_P |
03161 HAS_LINENO | HAS_DEBUG |
03162 HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
03163
03164 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
03165 '_',
03166 '/',
03167 15,
03168 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
03169 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
03170 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
03171 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
03172 bfd_getb32, bfd_getb_signed_32, bfd_putb32,
03173 bfd_getb16, bfd_getb_signed_16, bfd_putb16,
03174
03175 {_bfd_dummy_target, coff_small_object_p,
03176 bfd_generic_archive_p, _bfd_dummy_target},
03177 {bfd_false, coff_mkobject, _bfd_generic_mkarchive,
03178 bfd_false},
03179 {bfd_false, coff_write_object_contents,
03180 _bfd_write_archive_contents, bfd_false},
03181
03182 BFD_JUMP_TABLE_GENERIC (coff_small),
03183 BFD_JUMP_TABLE_COPY (coff),
03184 BFD_JUMP_TABLE_CORE (_bfd_nocore),
03185 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
03186 BFD_JUMP_TABLE_SYMBOLS (coff),
03187 BFD_JUMP_TABLE_RELOCS (coff),
03188 BFD_JUMP_TABLE_WRITE (coff),
03189 BFD_JUMP_TABLE_LINK (coff),
03190 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
03191
03192 & shlcoff_small_vec,
03193
03194 (PTR) &bfd_coff_small_swap_table
03195 };
03196
03197 const bfd_target shlcoff_small_vec =
03198 {
03199 "coff-shl-small",
03200 bfd_target_coff_flavour,
03201 BFD_ENDIAN_LITTLE,
03202 BFD_ENDIAN_LITTLE,
03203
03204 (HAS_RELOC | EXEC_P |
03205 HAS_LINENO | HAS_DEBUG |
03206 HAS_SYMS | HAS_LOCALS | WP_TEXT | BFD_IS_RELAXABLE),
03207
03208 (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC),
03209 '_',
03210 '/',
03211 15,
03212 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
03213 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
03214 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
03215 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
03216 bfd_getl32, bfd_getl_signed_32, bfd_putl32,
03217 bfd_getl16, bfd_getl_signed_16, bfd_putl16,
03218
03219 {_bfd_dummy_target, coff_small_object_p,
03220 bfd_generic_archive_p, _bfd_dummy_target},
03221 {bfd_false, coff_mkobject, _bfd_generic_mkarchive,
03222 bfd_false},
03223 {bfd_false, coff_write_object_contents,
03224 _bfd_write_archive_contents, bfd_false},
03225
03226 BFD_JUMP_TABLE_GENERIC (coff_small),
03227 BFD_JUMP_TABLE_COPY (coff),
03228 BFD_JUMP_TABLE_CORE (_bfd_nocore),
03229 BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
03230 BFD_JUMP_TABLE_SYMBOLS (coff),
03231 BFD_JUMP_TABLE_RELOCS (coff),
03232 BFD_JUMP_TABLE_WRITE (coff),
03233 BFD_JUMP_TABLE_LINK (coff),
03234 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
03235
03236 & shcoff_small_vec,
03237
03238 (PTR) &bfd_coff_small_swap_table
03239 };
03240 #endif