aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog20
-rw-r--r--gas/config/rl78-parse.y30
-rw-r--r--gas/config/tc-rl78.c77
-rw-r--r--gas/config/tc-rl78.h2
-rw-r--r--gas/doc/c-rl78.texi3
5 files changed, 106 insertions, 26 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 8a50708..6fb81a1 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,23 @@
+2015-12-08 DJ Delorie <dj@redhat.com>
+
+ * config/rl78-parse.y: Make all branches relaxable via
+ rl78_linkrelax_branch().
+ * config/tc-rl78.c (rl78_linkrelax_branch): Mark all relaxable
+ branches with relocs.
+ (options): Add OPTION_NORELAX.
+ (md_longopts): Add -mnorelax.
+ (md_parse_option): Support OPTION_NORELAX.
+ (op_type_T): Add bh, sk, call, and br.
+ (rl78_opcode_type): Likewise.
+ (rl78_relax_frag): Fix not-relaxing logic. Add sk.
+ (md_convert_frag): Fix relocation handling.
+ (tc_gen_reloc): Strip relax relocs when not linker relaxing.
+ (md_apply_fix): Defer overflow handling for anything that needs a
+ PLT, to the linker.
+ * config/tc-rl78.h (TC_FORCE_RELOCATION): Force all relocations to
+ the linker when linker relaxing.
+ * doc/c-rl78.texi (norelax): Add.
+
2015-12-07 Alan Modra <amodra@gmail.com>
* config/tc-ppc.c (md_apply_fix): Localize variables. Reduce casts.
diff --git a/gas/config/rl78-parse.y b/gas/config/rl78-parse.y
index b879581..ff017cf 100644
--- a/gas/config/rl78-parse.y
+++ b/gas/config/rl78-parse.y
@@ -294,22 +294,22 @@ statement :
/* ---------------------------------------------------------------------- */
| BC '$' EXPR
- { B1 (0xdc); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
+ { B1 (0xdc); PC1 ($3); rl78_linkrelax_branch (); }
| BNC '$' EXPR
- { B1 (0xde); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
+ { B1 (0xde); PC1 ($3); rl78_linkrelax_branch (); }
| BZ '$' EXPR
- { B1 (0xdd); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
+ { B1 (0xdd); PC1 ($3); rl78_linkrelax_branch (); }
| BNZ '$' EXPR
- { B1 (0xdf); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
+ { B1 (0xdf); PC1 ($3); rl78_linkrelax_branch (); }
| BH '$' EXPR
- { B2 (0x61, 0xc3); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
+ { B2 (0x61, 0xc3); PC1 ($3); rl78_linkrelax_branch (); }
| BNH '$' EXPR
- { B2 (0x61, 0xd3); PC1 ($3); rl78_relax (RL78_RELAX_BRANCH, 0); }
+ { B2 (0x61, 0xd3); PC1 ($3); rl78_linkrelax_branch (); }
/* ---------------------------------------------------------------------- */
@@ -337,7 +337,7 @@ statement :
{ B2 (0x61, 0xcb); }
| BR '$' EXPR
- { B1 (0xef); PC1 ($3); }
+ { B1 (0xef); PC1 ($3); rl78_linkrelax_branch (); }
| BR '$' '!' EXPR
{ B1 (0xee); PC2 ($4); rl78_linkrelax_branch (); }
@@ -1022,22 +1022,22 @@ statement :
/* ---------------------------------------------------------------------- */
| SKC
- { B2 (0x61, 0xc8); rl78_linkrelax_branch (); }
+ { B2 (0x61, 0xc8); rl78_relax (RL78_RELAX_BRANCH, 0); }
| SKH
- { B2 (0x61, 0xe3); rl78_linkrelax_branch (); }
+ { B2 (0x61, 0xe3); rl78_relax (RL78_RELAX_BRANCH, 0); }
| SKNC
- { B2 (0x61, 0xd8); rl78_linkrelax_branch (); }
+ { B2 (0x61, 0xd8); rl78_relax (RL78_RELAX_BRANCH, 0); }
| SKNH
- { B2 (0x61, 0xf3); rl78_linkrelax_branch (); }
+ { B2 (0x61, 0xf3); rl78_relax (RL78_RELAX_BRANCH, 0); }
| SKNZ
- { B2 (0x61, 0xf8); rl78_linkrelax_branch (); }
+ { B2 (0x61, 0xf8); rl78_relax (RL78_RELAX_BRANCH, 0); }
| SKZ
- { B2 (0x61, 0xe8); rl78_linkrelax_branch (); }
+ { B2 (0x61, 0xe8); rl78_relax (RL78_RELAX_BRANCH, 0); }
/* ---------------------------------------------------------------------- */
@@ -1161,8 +1161,8 @@ andor1 : AND1 { $$ = 0x05; rl78_bit_insn = 1; }
| XOR1 { $$ = 0x07; rl78_bit_insn = 1; }
;
-bt_bf : BT { $$ = 0x02; rl78_bit_insn = 1; rl78_relax (RL78_RELAX_BRANCH, 0); }
- | BF { $$ = 0x04; rl78_bit_insn = 1; rl78_relax (RL78_RELAX_BRANCH, 0); }
+bt_bf : BT { $$ = 0x02; rl78_bit_insn = 1; rl78_linkrelax_branch (); }
+ | BF { $$ = 0x04; rl78_bit_insn = 1; rl78_linkrelax_branch (); }
| BTCLR { $$ = 0x00; rl78_bit_insn = 1; }
;
diff --git a/gas/config/tc-rl78.c b/gas/config/tc-rl78.c
index 9fbaa42..ad04795 100644
--- a/gas/config/tc-rl78.c
+++ b/gas/config/tc-rl78.c
@@ -102,6 +102,7 @@ rl78_linkrelax_addr16 (void)
void
rl78_linkrelax_branch (void)
{
+ rl78_relax (RL78_RELAX_BRANCH, 0);
rl78_bytes.link_relax |= RL78_RELAXA_BRA;
}
@@ -280,6 +281,7 @@ rl78_field (int val, int pos, int sz)
enum options
{
OPTION_RELAX = OPTION_MD_BASE,
+ OPTION_NORELAX,
OPTION_G10,
OPTION_G13,
OPTION_G14,
@@ -294,6 +296,7 @@ const char * md_shortopts = RL78_SHORTOPTS;
struct option md_longopts[] =
{
{"relax", no_argument, NULL, OPTION_RELAX},
+ {"norelax", no_argument, NULL, OPTION_NORELAX},
{"mg10", no_argument, NULL, OPTION_G10},
{"mg13", no_argument, NULL, OPTION_G13},
{"mg14", no_argument, NULL, OPTION_G14},
@@ -312,6 +315,9 @@ md_parse_option (int c, char * arg ATTRIBUTE_UNUSED)
case OPTION_RELAX:
linkrelax = 1;
return 1;
+ case OPTION_NORELAX:
+ linkrelax = 0;
+ return 1;
case OPTION_G10:
elf_flags &= ~ E_FLAG_RL78_CPU_MASK;
@@ -757,7 +763,10 @@ typedef enum
OT_bt_sfr,
OT_bt_es,
OT_bc,
- OT_bh
+ OT_bh,
+ OT_sk,
+ OT_call,
+ OT_br,
} op_type_T;
/* We're looking for these types of relaxations:
@@ -780,8 +789,10 @@ typedef enum
a different size later. */
static op_type_T
-rl78_opcode_type (char * op)
+rl78_opcode_type (char * ops)
{
+ unsigned char *op = (unsigned char *)ops;
+
if (op[0] == 0x31
&& ((op[1] & 0x0f) == 0x05
|| (op[1] & 0x0f) == 0x03))
@@ -805,6 +816,20 @@ rl78_opcode_type (char * op)
&& (op[1] & 0xef) == 0xc3)
return OT_bh;
+ if (op[0] == 0x61
+ && (op[1] & 0xcf) == 0xc8)
+ return OT_sk;
+
+ if (op[0] == 0x61
+ && (op[1] & 0xef) == 0xe3)
+ return OT_sk;
+
+ if (op[0] == 0xfc)
+ return OT_call;
+
+ if ((op[0] & 0xec) == 0xec)
+ return OT_br;
+
return OT_other;
}
@@ -901,6 +926,11 @@ rl78_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
fragP->tc_frag_data->relax[ri].type != RL78_RELAX_BRANCH,
& sym_addr))
{
+ /* If we don't expect the linker to do relaxing, don't emit
+ expanded opcodes that only the linker will relax. */
+ if (!linkrelax)
+ return newsize - oldsize;
+
/* If we don't, we must use the maximum size for the linker. */
switch (fragP->tc_frag_data->relax[ri].type)
{
@@ -920,7 +950,10 @@ rl78_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
case OT_bh:
newsize = 6;
break;
- case OT_other:
+ case OT_sk:
+ newsize = 2;
+ break;
+ default:
newsize = oldsize;
break;
}
@@ -967,7 +1000,10 @@ rl78_relax_frag (segT segment ATTRIBUTE_UNUSED, fragS * fragP, long stretch)
else
newsize = 6;
break;
- case OT_other:
+ case OT_sk:
+ newsize = 2;
+ break;
+ default:
newsize = oldsize;
break;
}
@@ -1062,6 +1098,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
case OPCODE (OT_bt, 3): /* BT A,$ - no change. */
disp -= 3;
op[2] = disp;
+ reloc_type = keep_reloc ? BFD_RELOC_8_PCREL : BFD_RELOC_NONE;
break;
case OPCODE (OT_bt, 6): /* BT A,$ - long version. */
@@ -1079,6 +1116,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
case OPCODE (OT_bt_sfr, 4): /* BT PSW,$ - no change. */
disp -= 4;
op[3] = disp;
+ reloc_type = keep_reloc ? BFD_RELOC_8_PCREL : BFD_RELOC_NONE;
break;
case OPCODE (OT_bt_sfr, 7): /* BT PSW,$ - long version. */
@@ -1096,6 +1134,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
case OPCODE (OT_bt_es, 4): /* BT ES:[HL],$ - no change. */
disp -= 4;
op[3] = disp;
+ reloc_type = keep_reloc ? BFD_RELOC_8_PCREL : BFD_RELOC_NONE;
break;
case OPCODE (OT_bt_es, 7): /* BT PSW,$ - long version. */
@@ -1113,6 +1152,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
case OPCODE (OT_bc, 2): /* BC $ - no change. */
disp -= 2;
op[1] = disp;
+ reloc_type = keep_reloc ? BFD_RELOC_8_PCREL : BFD_RELOC_NONE;
break;
case OPCODE (OT_bc, 5): /* BC $ - long version. */
@@ -1130,6 +1170,7 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
case OPCODE (OT_bh, 3): /* BH $ - no change. */
disp -= 3;
op[2] = disp;
+ reloc_type = keep_reloc ? BFD_RELOC_8_PCREL : BFD_RELOC_NONE;
break;
case OPCODE (OT_bh, 6): /* BC $ - long version. */
@@ -1144,11 +1185,13 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
reloc_adjust = 2;
break;
- default:
- fprintf(stderr, "Missed case %d %d at 0x%lx\n",
- rl78_opcode_type (fragP->fr_opcode), fragP->fr_subtype, mypc);
- abort ();
+ case OPCODE (OT_sk, 2): /* SK<cond> - no change */
+ reloc_type = keep_reloc ? BFD_RELOC_16_PCREL : BFD_RELOC_NONE;
+ break;
+ default:
+ reloc_type = fix ? fix->fx_r_type : BFD_RELOC_NONE;
+ break;
}
break;
@@ -1215,6 +1258,12 @@ tc_gen_reloc (asection * seg ATTRIBUTE_UNUSED, fixS * fixp)
return reloc;
}
+ if (fixp->fx_r_type == BFD_RELOC_RL78_RELAX && !linkrelax)
+ {
+ reloc[0] = NULL;
+ return reloc;
+ }
+
if (fixp->fx_subsy
&& S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
{
@@ -1376,6 +1425,11 @@ md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
char * op;
unsigned long val;
+ /* We always defer overflow checks for these to the linker, as it
+ needs to do PLT stuff. */
+ if (f->fx_r_type == BFD_RELOC_RL78_CODE)
+ f->fx_no_overflow = 1;
+
if (f->fx_addsy && S_FORCE_RELOC (f->fx_addsy, 1))
return;
if (f->fx_subsy && S_FORCE_RELOC (f->fx_subsy, 1))
@@ -1384,13 +1438,16 @@ md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
op = f->fx_frag->fr_literal + f->fx_where;
val = (unsigned long) * t;
+ if (f->fx_addsy == NULL)
+ f->fx_done = 1;
+
switch (f->fx_r_type)
{
case BFD_RELOC_NONE:
break;
case BFD_RELOC_RL78_RELAX:
- f->fx_done = 1;
+ f->fx_done = 0;
break;
case BFD_RELOC_8_PCREL:
@@ -1461,8 +1518,6 @@ md_apply_fix (struct fix * f ATTRIBUTE_UNUSED,
break;
}
- if (f->fx_addsy == NULL)
- f->fx_done = 1;
}
valueT
diff --git a/gas/config/tc-rl78.h b/gas/config/tc-rl78.h
index b9ede61..82f798e 100644
--- a/gas/config/tc-rl78.h
+++ b/gas/config/tc-rl78.h
@@ -99,3 +99,5 @@ extern void rl78_elf_final_processing (void);
|| TC_FORCE_RELOCATION (FIX))
#define DWARF2_USE_FIXED_ADVANCE_PC 1
+
+#define TC_FORCE_RELOCATION(FIX) (linkrelax)
diff --git a/gas/doc/c-rl78.texi b/gas/doc/c-rl78.texi
index 5cb568f..49e4ee4 100644
--- a/gas/doc/c-rl78.texi
+++ b/gas/doc/c-rl78.texi
@@ -28,6 +28,9 @@
@item relax
Enable support for link-time relaxation.
+@item norelax
+Disable support for link-time relaxation (default).
+
@item mg10
Mark the generated binary as targeting the G10 variant of the RL78
architecture.