This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
[PATCH]: Add %page and %addr modifier to gas HC11
- From: Stephane Carrez <stcarrez at nerim dot fr>
- To: binutils at sources dot redhat dot com
- Date: Sat, 05 Apr 2003 14:46:10 +0200
- Subject: [PATCH]: Add %page and %addr modifier to gas HC11
Hi!
I committed the following patch to:
- add a %addr(expr) and %page(expr) modifiers for memory bank support.
%addr() represents the physical address of the symbol within the memory window
(-> BFD_RELOC_M68HC11_LO16)
%page() represents the page number where the symbol is defined
(-> BFD_RELOC_M68HC11_PAGE)
- fix a bug when assembling: 'leax sym,x' and 'sym' is a symbol defined
in the same section. It was treated as a PC-reloc offset but the semantic
is really the address of 'sym' (this insn does: x := x + sym)
- make sure the relocs are against their symbols and not the section.
This is important for linker relaxation and for trampoline generation.
For the BFD_RELOC_32, this is temporary until I update the bfd reloc part
(according to Alan recommendation back in october)
Stephane
2003-04-05 Stephane Carrez <stcarrez at nerim dot fr>
* 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.
Index: config/tc-m68hc11.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-m68hc11.c,v
retrieving revision 1.38
diff -u -p -r1.38 tc-m68hc11.c
--- config/tc-m68hc11.c 23 Jan 2003 12:51:05 -0000 1.38
+++ config/tc-m68hc11.c 5 Apr 2003 12:42:36 -0000
@@ -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, se
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;
}