diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 20 | ||||
-rw-r--r-- | gas/config/rl78-parse.y | 30 | ||||
-rw-r--r-- | gas/config/tc-rl78.c | 77 | ||||
-rw-r--r-- | gas/config/tc-rl78.h | 2 | ||||
-rw-r--r-- | gas/doc/c-rl78.texi | 3 |
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. |