From: Stephane Carrez Date: Sat, 5 Apr 2003 12:43:45 +0000 (+0000) Subject: * config/tc-m68hc11.c (M6811_OP_CALL_ADDR): New internal define. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=577300cea4d52e936112015eba1760e3aa9ff3b7;p=binutils-gdb.git * config/tc-m68hc11.c (M6811_OP_CALL_ADDR): New internal define. (M6811_OP_PAGE_ADDR): New internal define. (get_operand): New modifier %page and %addr to obtain page and address part of a far-function. (fixup8): Use BFD_RELOC_M68HC11_PAGE for a %page modifier; don't complain on overflow for the BFD_RELOC_M68HC11_PAGE and truncation relocs. (fixup16): Use BFD_RELOC_M68HC11_LO16 for a %addr modifier. (find_opcode): Add comment. (md_estimate_size_before_relax): Force relocation of STATE_UNDEXED_OFFSET types when the symbol is not absolute. (tc_m68hc11_fix_adjustable): Check for BFD_RELOC_M68HC11_LO16 instead of BFD_RELOC_LO16; temporarily make the BFD_RELOC_32 on the symbol itself so that DWARF2 strings are merged correctly. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 5a2a3226cf9..dde3c48dda8 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,20 @@ +2003-04-05 Stephane Carrez + + * config/tc-m68hc11.c (M6811_OP_CALL_ADDR): New internal define. + (M6811_OP_PAGE_ADDR): New internal define. + (get_operand): New modifier %page and %addr to obtain page and + address part of a far-function. + (fixup8): Use BFD_RELOC_M68HC11_PAGE for a %page modifier; don't + complain on overflow for the BFD_RELOC_M68HC11_PAGE and truncation + relocs. + (fixup16): Use BFD_RELOC_M68HC11_LO16 for a %addr modifier. + (find_opcode): Add comment. + (md_estimate_size_before_relax): Force relocation of + STATE_UNDEXED_OFFSET types when the symbol is not absolute. + (tc_m68hc11_fix_adjustable): Check for BFD_RELOC_M68HC11_LO16 + instead of BFD_RELOC_LO16; temporarily make the BFD_RELOC_32 + on the symbol itself so that DWARF2 strings are merged correctly. + 2003-04-04 Svein E. Seldal * config/obj-coff.h (TARGET_FORMAT): Namespace cleanup, changed diff --git a/gas/config/tc-m68hc11.c b/gas/config/tc-m68hc11.c index 08e1a6e316d..ec349b60c4b 100644 --- a/gas/config/tc-m68hc11.c +++ b/gas/config/tc-m68hc11.c @@ -989,6 +989,8 @@ register_name () return reg_number; } +#define M6811_OP_CALL_ADDR 0x00800000 +#define M6811_OP_PAGE_ADDR 0x04000000 /* Parse a string of operands and return an array of expressions. @@ -1054,6 +1056,24 @@ get_operand (oper, which, opmode) p += 3; mode |= M6811_OP_LOW_ADDR; } + /* %page modifier is used to obtain only the page number + of the address of a function. */ + else if (strncmp (p, "%page", 5) == 0) + { + p += 5; + mode |= M6811_OP_PAGE_ADDR; + } + + /* %addr modifier is used to obtain the physical address part + of the function (16-bit). For 68HC12 the function will be + mapped in the 16K window at 0x8000 and the value will be + within that window (although the function address may not fit + in 16-bit). See bfd/elf32-m68hc12.c for the translation. */ + else if (strncmp (p, "%addr", 5) == 0) + { + p += 5; + mode |= M6811_OP_CALL_ADDR; + } } else if (*p == '.' && (p[1] == '+' || p[1] == '-')) { @@ -1086,6 +1106,12 @@ get_operand (oper, which, opmode) as_bad (_("Spurious `,' or bad indirect register addressing mode.")); return -1; } + /* Handle 68HC12 page specification in 'call foo,%page(bar)'. */ + else if ((opmode & M6812_OP_PAGE) && strncmp (p, "%page", 5) == 0) + { + p += 5; + mode = M6811_OP_PAGE_ADDR | M6812_OP_PAGE | M6811_OP_IND16; + } input_line_pointer = p; if (mode == M6811_OP_NONE || mode == M6812_OP_D_IDX) @@ -1422,16 +1448,24 @@ fixup8 (oper, mode, opmode) } else { - /* Now create an 8-bit fixup. If there was some %hi or %lo - modifier, generate the reloc accordingly. */ - fix_new_exp (frag_now, f - frag_now->fr_literal, 1, - oper, FALSE, - ((opmode & M6811_OP_HIGH_ADDR) - ? BFD_RELOC_M68HC11_HI8 - : ((opmode & M6811_OP_LOW_ADDR) - ? BFD_RELOC_M68HC11_LO8 - : ((mode & M6812_OP_PAGE) - ? BFD_RELOC_M68HC11_PAGE : BFD_RELOC_8)))); + fixS *fixp; + int reloc; + + /* Now create an 8-bit fixup. If there was some %hi, %lo + or %page modifier, generate the reloc accordingly. */ + if (opmode & M6811_OP_HIGH_ADDR) + reloc = BFD_RELOC_M68HC11_HI8; + else if (opmode & M6811_OP_LOW_ADDR) + reloc = BFD_RELOC_M68HC11_LO8; + else if (opmode & M6811_OP_PAGE_ADDR) + reloc = BFD_RELOC_M68HC11_PAGE; + else + reloc = BFD_RELOC_8; + + fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 1, + oper, FALSE, reloc); + if (reloc != BFD_RELOC_8) + fixp->fx_no_overflow = 1; } number_to_chars_bigendian (f, 0, 1); } @@ -1465,18 +1499,27 @@ fixup16 (oper, mode, opmode) else if (oper->X_op != O_register) { fixS *fixp; + int reloc; + + if ((opmode & M6811_OP_CALL_ADDR) && (mode & M6811_OP_IMM16)) + reloc = BFD_RELOC_M68HC11_LO16; + else if (mode & M6812_OP_JUMP_REL16) + reloc = BFD_RELOC_16_PCREL; + else if (mode & M6812_OP_PAGE) + reloc = BFD_RELOC_M68HC11_LO16; + else + reloc = BFD_RELOC_16; /* Now create a 16-bit fixup. */ fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2, oper, - (mode & M6812_OP_JUMP_REL16 ? TRUE : FALSE), - (mode & M6812_OP_JUMP_REL16 - ? BFD_RELOC_16_PCREL - : (mode & M6812_OP_PAGE) - ? BFD_RELOC_M68HC11_LO16 : BFD_RELOC_16)); + reloc == BFD_RELOC_16_PCREL, + reloc); number_to_chars_bigendian (f, 0, 2); - if (mode & M6812_OP_JUMP_REL16) + if (reloc == BFD_RELOC_16_PCREL) fixp->fx_pcrel_adjust = 2; + if (reloc == BFD_RELOC_M68HC11_LO16) + fixp->fx_no_overflow = 1; } else { @@ -2405,6 +2448,11 @@ find_opcode (opc, operands, nb_operands) if (i >= opc->min_operands) { opcode = find (opc, operands, i); + + /* Another special case for 'call foo,page' instructions. + Since we support 'call foo' and 'call foo,page' we must look + if the optional page specification is present otherwise we will + assemble immediately and treat the page spec as garbage. */ if (opcode && !(opcode->format & M6812_OP_PAGE)) return opcode; @@ -2996,7 +3044,9 @@ md_estimate_size_before_relax (fragP, segment) if (RELAX_LENGTH (fragP->fr_subtype) == STATE_UNDF) { if (S_GET_SEGMENT (fragP->fr_symbol) != segment - || !relaxable_symbol (fragP->fr_symbol)) + || !relaxable_symbol (fragP->fr_symbol) + || (segment != absolute_section + && RELAX_STATE (fragP->fr_subtype) == STATE_INDEXED_OFFSET)) { /* Non-relaxable cases. */ int old_fr_fix; @@ -3211,15 +3261,15 @@ tc_m68hc11_fix_adjustable (fixP) case BFD_RELOC_M68HC11_RL_GROUP: case BFD_RELOC_VTABLE_INHERIT: case BFD_RELOC_VTABLE_ENTRY: + case BFD_RELOC_32: /* The memory bank addressing translation also needs the original symbol. */ - case BFD_RELOC_LO16: + case BFD_RELOC_M68HC11_LO16: case BFD_RELOC_M68HC11_PAGE: case BFD_RELOC_M68HC11_24: return 0; - case BFD_RELOC_32: default: return 1; }