This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[patch] rl78: add %code() pseudo-op
- From: DJ Delorie <dj at redhat dot com>
- To: binutils at sourceware dot org
- Date: Wed, 27 Feb 2013 16:39:23 -0500
- Subject: [patch] rl78: add %code() pseudo-op
The RL78 has a 20-bit address space. Symbols in certain pages can be
accessed with 16-bit relocs and the page offset is "assumed".
However, the default for data is different than the default for code.
This patch adds a %code() pseudo-op that tells the linker that the
symbol's default page is the code page, not the data page, so that the
16-bit PLT jump tables can be properly created. The failure case was
when a code label happened to be in the data page - the linker would
truncate the value to 16-bits but the chip would access that offset in
the code page instead, causing a fault.
Committed.
* reloc.c (BFD_RELOC_RL78_CODE): Add.
* libbfd.h: Regenerate.
* bfd-in2.h: Regenerate.
* elf32-rl78.c (rl78_elf_relocate_section): Handle weak code
references in compuated relocs.
* config/tc-rl78.c (reloc_function): Add %code -> BFD_RELOC_RL78_CODE.
(rl78_op): Handle %code().
(rl78_cons_fix_new): Likewise, but ignore for 20-bit operands.
(tc_gen_reloc): Likwise; convert to a computed reloc.
(md_apply_fix): Likewise.
Index: bfd/bfd-in2.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in2.h,v
retrieving revision 1.598
diff -p -U5 -r1.598 bfd-in2.h
--- bfd/bfd-in2.h 6 Feb 2013 23:22:07 -0000 1.598
+++ bfd/bfd-in2.h 27 Feb 2013 21:08:15 -0000
@@ -4237,10 +4237,11 @@ in .byte hlo8(symbol) */
BFD_RELOC_RL78_ABS16UL,
BFD_RELOC_RL78_RELAX,
BFD_RELOC_RL78_HI16,
BFD_RELOC_RL78_HI8,
BFD_RELOC_RL78_LO16,
+ BFD_RELOC_RL78_CODE,
/* Renesas RX Relocations. */
BFD_RELOC_RX_NEG8,
BFD_RELOC_RX_NEG16,
BFD_RELOC_RX_NEG24,
Index: bfd/elf32-rl78.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-rl78.c,v
retrieving revision 1.11
diff -p -U5 -r1.11 elf32-rl78.c
--- bfd/elf32-rl78.c 10 Jan 2013 20:03:53 -0000 1.11
+++ bfd/elf32-rl78.c 27 Feb 2013 21:08:15 -0000
@@ -776,10 +776,12 @@ rl78_elf_relocate_section
|| h->root.type == bfd_link_hash_defweak))
RL78_STACK_PUSH (h->root.u.def.value
+ sec->output_section->vma
+ sec->output_offset
+ rel->r_addend);
+ else if (h->root.type == bfd_link_hash_undefweak)
+ RL78_STACK_PUSH (0);
else
_bfd_error_handler (_("Warning: RL78_SYM reloc with an unknown symbol"));
}
break;
Index: bfd/libbfd.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd.h,v
retrieving revision 1.292
diff -p -U5 -r1.292 libbfd.h
--- bfd/libbfd.h 11 Feb 2013 05:30:53 -0000 1.292
+++ bfd/libbfd.h 27 Feb 2013 21:08:16 -0000
@@ -1968,10 +1968,11 @@ static const char *const bfd_reloc_code_
"BFD_RELOC_RL78_ABS16UL",
"BFD_RELOC_RL78_RELAX",
"BFD_RELOC_RL78_HI16",
"BFD_RELOC_RL78_HI8",
"BFD_RELOC_RL78_LO16",
+ "BFD_RELOC_RL78_CODE",
"BFD_RELOC_RX_NEG8",
"BFD_RELOC_RX_NEG16",
"BFD_RELOC_RX_NEG24",
"BFD_RELOC_RX_NEG32",
"BFD_RELOC_RX_16_OP",
Index: bfd/reloc.c
===================================================================
RCS file: /cvs/src/src/bfd/reloc.c,v
retrieving revision 1.242
diff -p -U5 -r1.242 reloc.c
--- bfd/reloc.c 6 Feb 2013 23:22:08 -0000 1.242
+++ bfd/reloc.c 27 Feb 2013 21:08:17 -0000
@@ -4558,10 +4558,12 @@ ENUMX
BFD_RELOC_RL78_HI16
ENUMX
BFD_RELOC_RL78_HI8
ENUMX
BFD_RELOC_RL78_LO16
+ENUMX
+ BFD_RELOC_RL78_CODE
ENUMDOC
Renesas RL78 Relocations.
ENUM
BFD_RELOC_RX_NEG8
Index: gas/config/tc-rl78.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-rl78.c,v
retrieving revision 1.5
diff -p -U5 -r1.5 tc-rl78.c
--- gas/config/tc-rl78.c 29 Jan 2013 22:17:53 -0000 1.5
+++ gas/config/tc-rl78.c 27 Feb 2013 21:08:18 -0000
@@ -192,10 +192,13 @@ rl78_op (expressionS exp, int nbytes, in
}
}
}
else
{
+ if (nbytes > 2
+ && exp.X_md == BFD_RELOC_RL78_CODE)
+ exp.X_md = 0;
rl78_op_fixup (exp, rl78_bytes.n_ops * 8, nbytes * 8, type);
memset (rl78_bytes.ops + rl78_bytes.n_ops, 0, nbytes);
rl78_bytes.n_ops += nbytes;
}
}
@@ -335,10 +338,11 @@ static struct
char * fname;
int reloc;
}
reloc_functions[] =
{
+ { "code", BFD_RELOC_RL78_CODE },
{ "lo16", BFD_RELOC_RL78_LO16 },
{ "hi16", BFD_RELOC_RL78_HI16 },
{ "hi8", BFD_RELOC_RL78_HI8 },
{ 0, 0 }
};
@@ -554,10 +558,14 @@ rl78_cons_fix_new (fragS * frag,
return;
}
switch (exp->X_md)
{
+ case BFD_RELOC_RL78_CODE:
+ if (size == 2)
+ type = exp->X_md;
+ break;
case BFD_RELOC_RL78_LO16:
case BFD_RELOC_RL78_HI16:
if (size != 2)
as_bad (_("%%hi16/%%lo16 only applies to .short or .hword"));
type = exp->X_md;
@@ -663,10 +671,15 @@ tc_gen_reloc (asection * seg ATTRIBUTE_U
SYM0 ();
OP (OP_NEG);
OP (ABS32);
break;
+ case BFD_RELOC_RL78_CODE:
+ SYM0 ();
+ OP (ABS16);
+ break;
+
case BFD_RELOC_RL78_LO16:
SYM0 ();
OPIMM (0xffff);
OP (OP_AND);
OP (ABS16);
@@ -769,10 +782,11 @@ md_apply_fix (struct fix * f ATTRIBUTE_U
op[0] = val;
break;
case BFD_RELOC_16:
case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_RL78_CODE:
op[0] = val;
op[1] = val >> 8;
break;
case BFD_RELOC_24: