-#ifdef OBJ_COFF
-
-int
-tc_coff_sizemachdep (frag)
- fragS *frag;
-{
- return md_relax_table[frag->fr_subtype].rlx_length;
-}
-
-#endif /* OBJ_COFF */
-
-#ifndef BFD_ASSEMBLER
-#ifdef OBJ_COFF
-
-/* Map BFD relocs to SH COFF relocs. */
-
-struct reloc_map
-{
- bfd_reloc_code_real_type bfd_reloc;
- int sh_reloc;
-};
-
-static const struct reloc_map coff_reloc_map[] =
-{
- { BFD_RELOC_32, R_SH_IMM32 },
- { BFD_RELOC_16, R_SH_IMM16 },
- { BFD_RELOC_8, R_SH_IMM8 },
- { BFD_RELOC_SH_PCDISP8BY2, R_SH_PCDISP8BY2 },
- { BFD_RELOC_SH_PCDISP12BY2, R_SH_PCDISP },
- { BFD_RELOC_SH_IMM4, R_SH_IMM4 },
- { BFD_RELOC_SH_IMM4BY2, R_SH_IMM4BY2 },
- { BFD_RELOC_SH_IMM4BY4, R_SH_IMM4BY4 },
- { BFD_RELOC_SH_IMM8, R_SH_IMM8 },
- { BFD_RELOC_SH_IMM8BY2, R_SH_IMM8BY2 },
- { BFD_RELOC_SH_IMM8BY4, R_SH_IMM8BY4 },
- { BFD_RELOC_SH_PCRELIMM8BY2, R_SH_PCRELIMM8BY2 },
- { BFD_RELOC_SH_PCRELIMM8BY4, R_SH_PCRELIMM8BY4 },
- { BFD_RELOC_8_PCREL, R_SH_SWITCH8 },
- { BFD_RELOC_SH_SWITCH16, R_SH_SWITCH16 },
- { BFD_RELOC_SH_SWITCH32, R_SH_SWITCH32 },
- { BFD_RELOC_SH_USES, R_SH_USES },
- { BFD_RELOC_SH_COUNT, R_SH_COUNT },
- { BFD_RELOC_SH_ALIGN, R_SH_ALIGN },
- { BFD_RELOC_SH_CODE, R_SH_CODE },
- { BFD_RELOC_SH_DATA, R_SH_DATA },
- { BFD_RELOC_SH_LABEL, R_SH_LABEL },
- { BFD_RELOC_UNUSED, 0 }
-};
-
-/* Adjust a reloc for the SH. This is similar to the generic code,
- but does some minor tweaking. */
-
-void
-sh_coff_reloc_mangle (seg, fix, intr, paddr)
- segment_info_type *seg;
- fixS *fix;
- struct internal_reloc *intr;
- unsigned int paddr;
-{
- symbolS *symbol_ptr = fix->fx_addsy;
- symbolS *dot;
-
- intr->r_vaddr = paddr + fix->fx_frag->fr_address + fix->fx_where;
-
- if (! SWITCH_TABLE (fix))
- {
- const struct reloc_map *rm;
-
- for (rm = coff_reloc_map; rm->bfd_reloc != BFD_RELOC_UNUSED; rm++)
- if (rm->bfd_reloc == (bfd_reloc_code_real_type) fix->fx_r_type)
- break;
- if (rm->bfd_reloc == BFD_RELOC_UNUSED)
- as_bad_where (fix->fx_file, fix->fx_line,
- _("Can not represent %s relocation in this object file format"),
- bfd_get_reloc_code_name (fix->fx_r_type));
- intr->r_type = rm->sh_reloc;
- intr->r_offset = 0;
- }
- else
- {
- know (sh_relax);
-
- if (fix->fx_r_type == BFD_RELOC_16)
- intr->r_type = R_SH_SWITCH16;
- else if (fix->fx_r_type == BFD_RELOC_8)
- intr->r_type = R_SH_SWITCH8;
- else if (fix->fx_r_type == BFD_RELOC_32)
- intr->r_type = R_SH_SWITCH32;
- else
- abort ();
-
- /* For a switch reloc, we set r_offset to the difference between
- the reloc address and the subtrahend. When the linker is
- doing relaxing, it can use the determine the starting and
- ending points of the switch difference expression. */
- intr->r_offset = intr->r_vaddr - S_GET_VALUE (fix->fx_subsy);
- }
-
- /* PC relative relocs are always against the current section. */
- if (symbol_ptr == NULL)
- {
- switch (fix->fx_r_type)
- {
- case BFD_RELOC_SH_PCRELIMM8BY2:
- case BFD_RELOC_SH_PCRELIMM8BY4:
- case BFD_RELOC_SH_PCDISP8BY2:
- case BFD_RELOC_SH_PCDISP12BY2:
- case BFD_RELOC_SH_USES:
- symbol_ptr = seg->dot;
- break;
- default:
- break;
- }
- }
-
- if (fix->fx_r_type == BFD_RELOC_SH_USES)
- {
- /* We can't store the offset in the object file, since this
- reloc does not take up any space, so we store it in r_offset.
- The fx_addnumber field was set in md_apply_fix3. */
- intr->r_offset = fix->fx_addnumber;
- }
- else if (fix->fx_r_type == BFD_RELOC_SH_COUNT)
- {
- /* We can't store the count in the object file, since this reloc
- does not take up any space, so we store it in r_offset. The
- fx_offset field was set when the fixup was created in
- sh_coff_frob_file. */
- intr->r_offset = fix->fx_offset;
- /* This reloc is always absolute. */
- symbol_ptr = NULL;
- }
- else if (fix->fx_r_type == BFD_RELOC_SH_ALIGN)
- {
- /* Store the alignment in the r_offset field. */
- intr->r_offset = fix->fx_offset;
- /* This reloc is always absolute. */
- symbol_ptr = NULL;
- }
- else if (fix->fx_r_type == BFD_RELOC_SH_CODE
- || fix->fx_r_type == BFD_RELOC_SH_DATA
- || fix->fx_r_type == BFD_RELOC_SH_LABEL)
- {
- /* These relocs are always absolute. */
- symbol_ptr = NULL;
- }
-
- /* Turn the segment of the symbol into an offset. */
- if (symbol_ptr != NULL)
- {
- dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
- if (dot != NULL)
- intr->r_symndx = dot->sy_number;
- else
- intr->r_symndx = symbol_ptr->sy_number;
- }
- else
- intr->r_symndx = -1;
-}
-
-#endif /* OBJ_COFF */
-#endif /* ! BFD_ASSEMBLER */
-
-#ifdef BFD_ASSEMBLER
-