📄 tc-mn10300.c
字号:
/* This must be a format S4 "jmp" instruction. */ unsigned long temp = ((insn & 0xffffff) << 8) | (extension & 0xff); number_to_chars_bigendian (f, (insn >> 24) & 0xff, 1); number_to_chars_littleendian (f + 1, temp, 4); } else if (opcode->format == FMT_S6) { unsigned long temp = ((insn & 0xffffff) << 8) | ((extension >> 16) & 0xff); number_to_chars_bigendian (f, (insn >> 24) & 0xff, 1); number_to_chars_littleendian (f + 1, temp, 4); number_to_chars_bigendian (f + 5, (extension >> 8) & 0xff, 1); number_to_chars_bigendian (f + 6, extension & 0xff, 1); } else if (opcode->format == FMT_D2 && opcode->opcode != 0xfaf80000 && opcode->opcode != 0xfaf00000 && opcode->opcode != 0xfaf40000) { /* A format D2 instruction where the 16bit immediate is really a single 16bit value, not two 8bit values. */ number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2); number_to_chars_littleendian (f + 2, insn & 0xffff, 2); } else if (opcode->format == FMT_D2) { /* A format D2 instruction where the 16bit immediate is really two 8bit immediates. */ number_to_chars_bigendian (f, insn, 4); } else if (opcode->format == FMT_D4) { unsigned long temp = ((insn & 0xffff) << 16) | (extension & 0xffff); number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2); number_to_chars_littleendian (f + 2, temp, 4); } else if (opcode->format == FMT_D5) { unsigned long temp = (((insn & 0xffff) << 16) | ((extension >> 8) & 0xffff)); number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2); number_to_chars_littleendian (f + 2, temp, 4); number_to_chars_bigendian (f + 6, extension & 0xff, 1); } else if (opcode->format == FMT_D8) { unsigned long temp = ((insn & 0xff) << 16) | (extension & 0xffff); number_to_chars_bigendian (f, (insn >> 8) & 0xffffff, 3); number_to_chars_bigendian (f + 3, (temp & 0xff), 1); number_to_chars_littleendian (f + 4, temp >> 8, 2); } else if (opcode->format == FMT_D9) { unsigned long temp = ((insn & 0xff) << 24) | (extension & 0xffffff); number_to_chars_bigendian (f, (insn >> 8) & 0xffffff, 3); number_to_chars_littleendian (f + 3, temp, 4); } /* Create any fixups. */ for (i = 0; i < fc; i++) { const struct mn10300_operand *operand; operand = &mn10300_operands[fixups[i].opindex]; if (fixups[i].reloc != BFD_RELOC_UNUSED) { reloc_howto_type *reloc_howto; int size; int offset; fixS *fixP; reloc_howto = bfd_reloc_type_lookup (stdoutput, fixups[i].reloc); if (!reloc_howto) abort (); size = bfd_get_reloc_size (reloc_howto); if (size < 1 || size > 4) abort (); offset = 4 - size; fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, size, &fixups[i].exp, reloc_howto->pc_relative, fixups[i].reloc); } else { int reloc, pcrel, reloc_size, offset; fixS *fixP; reloc = BFD_RELOC_NONE; /* How big is the reloc? Remember SPLIT relocs are implicitly 32bits. */ if ((operand->flags & MN10300_OPERAND_SPLIT) != 0) reloc_size = 32; else if ((operand->flags & MN10300_OPERAND_24BIT) != 0) reloc_size = 24; else reloc_size = operand->bits; /* Is the reloc pc-relative? */ pcrel = (operand->flags & MN10300_OPERAND_PCREL) != 0; offset = size - (reloc_size + operand->shift) / 8; /* Choose a proper BFD relocation type. */ if (pcrel) { if (reloc_size == 32) reloc = BFD_RELOC_32_PCREL; else if (reloc_size == 16) reloc = BFD_RELOC_16_PCREL; else if (reloc_size == 8) reloc = BFD_RELOC_8_PCREL; else abort (); } else { if (reloc_size == 32) reloc = BFD_RELOC_32; else if (reloc_size == 16) reloc = BFD_RELOC_16; else if (reloc_size == 8) reloc = BFD_RELOC_8; else abort (); } /* Convert the size of the reloc into what fix_new_exp wants. */ reloc_size = reloc_size / 8; if (reloc_size == 8) reloc_size = 0; else if (reloc_size == 16) reloc_size = 1; else if (reloc_size == 32) reloc_size = 2; fixP = fix_new_exp (frag_now, f - frag_now->fr_literal + offset, reloc_size, &fixups[i].exp, pcrel, ((bfd_reloc_code_real_type) reloc)); if (pcrel) fixP->fx_offset += offset; } } dwarf2_emit_insn (size); }}/* If while processing a fixup, a reloc really needs to be created then it is done here. */arelent *tc_gen_reloc (seg, fixp) asection *seg ATTRIBUTE_UNUSED; fixS *fixp;{ arelent *reloc; reloc = (arelent *) xmalloc (sizeof (arelent)); reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); if (reloc->howto == (reloc_howto_type *) NULL) { as_bad_where (fixp->fx_file, fixp->fx_line, _("reloc %d not supported by object file format"), (int) fixp->fx_r_type); return NULL; } reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; if (fixp->fx_addsy && fixp->fx_subsy) { /* If we got a difference between two symbols, and the subtracted symbol is in the current section, use a PC-relative relocation. If both symbols are in the same section, the difference would have already been simplified to a constant. */ if (S_GET_SEGMENT (fixp->fx_subsy) == seg) { reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->addend = (reloc->address - S_GET_VALUE (fixp->fx_subsy) + fixp->fx_offset); switch (fixp->fx_r_type) { case BFD_RELOC_8: reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_8_PCREL); return reloc; case BFD_RELOC_16: reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16_PCREL); return reloc; case BFD_RELOC_24: reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_24_PCREL); return reloc; case BFD_RELOC_32: reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32_PCREL); return reloc; default: /* Try to compute the absolute value below. */ break; } } if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy)) || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section) { as_bad_where (fixp->fx_file, fixp->fx_line, "Difference of symbols in different sections is not supported"); return NULL; } reloc->sym_ptr_ptr = (asymbol **) &bfd_abs_symbol; reloc->addend = (S_GET_VALUE (fixp->fx_addsy) - S_GET_VALUE (fixp->fx_subsy) + fixp->fx_offset); } else { reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); reloc->addend = fixp->fx_offset; } return reloc;}intmd_estimate_size_before_relax (fragp, seg) fragS *fragp; asection *seg;{ if (fragp->fr_subtype == 6 && (!S_IS_DEFINED (fragp->fr_symbol) || seg != S_GET_SEGMENT (fragp->fr_symbol))) fragp->fr_subtype = 7; else if (fragp->fr_subtype == 8 && (!S_IS_DEFINED (fragp->fr_symbol) || seg != S_GET_SEGMENT (fragp->fr_symbol))) fragp->fr_subtype = 9; else if (fragp->fr_subtype == 10 && (!S_IS_DEFINED (fragp->fr_symbol) || seg != S_GET_SEGMENT (fragp->fr_symbol))) fragp->fr_subtype = 12; if (fragp->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0])) abort (); return md_relax_table[fragp->fr_subtype].rlx_length;}longmd_pcrel_from (fixp) fixS *fixp;{ if (fixp->fx_addsy != (symbolS *) NULL && !S_IS_DEFINED (fixp->fx_addsy)) { /* The symbol is undefined. Let the linker figure it out. */ return 0; } return fixp->fx_frag->fr_address + fixp->fx_where;}intmd_apply_fix3 (fixp, valuep, seg) fixS *fixp; valueT *valuep; segT seg;{ char *fixpos = fixp->fx_where + fixp->fx_frag->fr_literal; int size = 0; int value; assert (fixp->fx_r_type < BFD_RELOC_UNUSED); /* This should never happen. */ if (seg->flags & SEC_ALLOC) abort (); /* The value we are passed in *valuep includes the symbol values. Since we are using BFD_ASSEMBLER, if we are doing this relocation the code in write.c is going to call bfd_install_relocation, which is also going to use the symbol value. That means that if the reloc is fully resolved we want to use *valuep since bfd_install_relocation is not being used. However, if the reloc is not fully resolved we do not want to use *valuep, and must use fx_offset instead. However, if the reloc is PC relative, we do want to use *valuep since it includes the result of md_pcrel_from. */ if (fixp->fx_addsy == (symbolS *) NULL || fixp->fx_pcrel) value = *valuep; else value = fixp->fx_offset; /* If the fix is relative to a symbol which is not defined, or not in the same segment as the fix, we cannot resolve it here. */ if (fixp->fx_addsy != NULL && (! S_IS_DEFINED (fixp->fx_addsy) || (S_GET_SEGMENT (fixp->fx_addsy) != seg))) { fixp->fx_done = 0; return 0; } switch (fixp->fx_r_type) { case BFD_RELOC_8: case BFD_RELOC_8_PCREL: size = 1; break; case BFD_RELOC_16: case BFD_RELOC_16_PCREL: size = 2; break; case BFD_RELOC_32: case BFD_RELOC_32_PCREL: size = 4; break; case BFD_RELOC_VTABLE_INHERIT: case BFD_RELOC_VTABLE_ENTRY: fixp->fx_done = 0; return 1; case BFD_RELOC_NONE: default: as_bad_where (fixp->fx_file, fixp->fx_line, _("Bad relocation fixup type (%d)"), fixp->fx_r_type); } md_number_to_chars (fixpos, value, size); /* If a symbol remains, pass the fixup, as a reloc, onto the linker. */ if (fixp->fx_addsy == NULL) fixp->fx_done = 1; return 0;}/* Return nonzero if the fixup in FIXP will require a relocation, even it if appears that the fixup could be completely handled within GAS. */intmn10300_force_relocation (fixp) struct fix *fixp;{ if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) return 1; /* Do not adjust relocations involving symbols in code sections, because it breaks linker relaxations. This could be fixed in the linker, but this fix is simpler, and it pretty much only affects object size a little bit. */ if ((S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_CODE) && fixp->fx_subsy && S_GET_SEGMENT (fixp->fx_addsy) == S_GET_SEGMENT (fixp->fx_subsy)) return 1; return 0;}/* Return zero if the fixup in fixp should be left alone and not adjusted. */booleanmn10300_fix_adjustable (fixp) struct fix *fixp;{ /* Prevent all adjustments to global symbols. */ if (S_IS_EXTERN (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)) return 0; if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) return 0; /* Do not adjust relocations involving symbols in code sections, because it breaks linker relaxations. This could be fixed in the linker, but this fix is simpler, and it pretty much only affects object size a little bit. */ if (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_CODE) return 0; return 1;}/* Insert an operand value into an instruction. */static voidmn10300_insert_operand (insnp, extensionp, operand, val, file, line, shift) unsigned long *insnp; unsigned long *extensionp; const struct mn10300_operand *operand; offsetT val; char *file; unsigned int line; unsigned int shift;{ /* No need to check 32bit operands for a bit. Note that MN10300_OPERAND_SPLIT is an implicit 32bit operand. */ if (operand->bits != 32 && (operand->flags & MN10300_OPERAND_SPLIT) == 0) { long min, max; offsetT test; int bits; bits = operand->bits; if (operand->flags & MN10300_OPERAND_24BIT) bits = 24; if ((operand->flags & MN10300_OPERAND_SIGNED) != 0) { max = (1 << (bits - 1)) - 1; min = - (1 << (bits - 1)); } else { max = (1 << bits) - 1; min = 0; } test = val; if (test < (offsetT) min || test > (offsetT) max) { const char *err = _("operand out of range (%s not between %ld and %ld)"); char buf[100]; sprint_value (buf, test); if (file == (char *) NULL) as_warn (err, buf, min, max); else as_warn_where (file, line, err, buf, min, max); } } if ((operand->flags & MN10300_OPERAND_SPLIT) != 0) { *insnp |= (val >> (32 - operand->bits)) & ((1 << operand->bits) - 1); *extensionp |= ((val & ((1 << (32 - operand->bits)) - 1)) << operand->shift); } else if ((operand->flags & MN10300_OPERAND_24BIT) != 0) { *insnp |= (val >> (24 - operand->bits)) & ((1 << operand->bits) - 1); *extensionp |= ((val & ((1 << (24 - operand->bits)) - 1)) << operand->shift); } else if ((operand->flags & MN10300_OPERAND_EXTENDED) == 0) { *insnp |= (((long) val & ((1 << operand->bits) - 1)) << (operand->shift + shift)); if ((operand->flags & MN10300_OPERAND_REPEATED) != 0) *insnp |= (((long) val & ((1 << operand->bits) - 1)) << (operand->shift + shift + operand->bits)); } else { *extensionp |= (((long) val & ((1 << operand->bits) - 1)) << (operand->shift + shift)); if ((operand->flags & MN10300_OPERAND_REPEATED) != 0) *extensionp |= (((long) val & ((1 << operand->bits) - 1)) << (operand->shift + shift + operand->bits)); }}static unsigned longcheck_operand (insn, operand, val) unsigned long insn ATTRIBUTE_UNUSED; const struct mn10300_operand *operand; offsetT val;{ /* No need to check 32bit operands for a bit. Note that MN10300_OPERAND_SPLIT is an implicit 32bit operand. */ if (operand->bits != 32 && (operand->flags & MN10300_OPERAND_SPLIT) == 0) { long min, max; offsetT test; int bits; bits = operand->bits; if (operand->flags & MN10300_OPERAND_24BIT) bits = 24; if ((operand->flags & MN10300_OPERAND_SIGNED) != 0) { max = (1 << (bits - 1)) - 1; min = - (1 << (bits - 1)); } else { max = (1 << bits) - 1; min = 0; } test = val; if (test < (offsetT) min || test > (offsetT) max) return 0; else return 1; } return 1;}static voidset_arch_mach (mach) int mach;{ if (!bfd_set_arch_mach (stdoutput, bfd_arch_mn10300, mach)) as_warn (_("could not set architecture and machine")); current_machine = mach;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -