diff options
author | Stephane Carrez <stcarrez@nerim.fr> | 2003-04-05 12:43:45 +0000 |
---|---|---|
committer | Stephane Carrez <stcarrez@nerim.fr> | 2003-04-05 12:43:45 +0000 |
commit | 577300cea4d52e936112015eba1760e3aa9ff3b7 (patch) | |
tree | df221c72d25c01d6b7bc22e229e14f3ab1bfa12f /gas/config/tc-m68hc11.c | |
parent | 6eb79af08fcc6d41e1164ae9b3a0b0120b0b5130 (diff) | |
download | gdb-577300cea4d52e936112015eba1760e3aa9ff3b7.zip gdb-577300cea4d52e936112015eba1760e3aa9ff3b7.tar.gz gdb-577300cea4d52e936112015eba1760e3aa9ff3b7.tar.bz2 |
* 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.
Diffstat (limited to 'gas/config/tc-m68hc11.c')
-rw-r--r-- | gas/config/tc-m68hc11.c | 88 |
1 files changed, 69 insertions, 19 deletions
diff --git a/gas/config/tc-m68hc11.c b/gas/config/tc-m68hc11.c index 08e1a6e..ec349b6 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; } |