aboutsummaryrefslogtreecommitdiff
path: root/gas/config
diff options
context:
space:
mode:
authormengqinggang <mengqinggang@loongson.cn>2024-02-28 17:42:36 +0800
committerliuzhensong <liuzhensong@loongson.cn>2024-03-19 14:14:47 +0800
commit97ce7870440d6b00181c2162ff5e56bb39b2e475 (patch)
treed62f13b8a4669786eb2915077adb523fc31ea4ab /gas/config
parentb42aa684f6ff2bce9b8bc58aa89574723f17f1ce (diff)
downloadbinutils-97ce7870440d6b00181c2162ff5e56bb39b2e475.zip
binutils-97ce7870440d6b00181c2162ff5e56bb39b2e475.tar.gz
binutils-97ce7870440d6b00181c2162ff5e56bb39b2e475.tar.bz2
LoongArch: Add relaxation for R_LARCH_CALL36
This relaxation is effective for both macro instructions (call36, tail36) and explicit relocation instructions (pcaddu18i + jirl). call36 f -> bl f R_LARCH_CALL36 -> R_LARCH_B26 tail36 $t0, f -> b f R_LARCH_CALL36 -> R_LARCH_B26
Diffstat (limited to 'gas/config')
-rw-r--r--gas/config/tc-loongarch.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 68afa79..30aefce 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -116,6 +116,8 @@ const char *md_shortopts = "O::g::G:";
static const char default_arch[] = DEFAULT_ARCH;
+static bool call36 = 0;
+
/* The lowest 4-bit is the bytes of instructions. */
#define RELAX_BRANCH_16 0xc0000014
#define RELAX_BRANCH_21 0xc0000024
@@ -720,7 +722,8 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
|| BFD_RELOC_LARCH_TLS_LE_HI20 == reloc_type
|| BFD_RELOC_LARCH_TLS_LE_LO12 == reloc_type
|| BFD_RELOC_LARCH_TLS_LE64_LO20 == reloc_type
- || BFD_RELOC_LARCH_TLS_LE64_HI12 == reloc_type))
+ || BFD_RELOC_LARCH_TLS_LE64_HI12 == reloc_type
+ || BFD_RELOC_LARCH_CALL36 == reloc_type))
{
ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
ip->reloc_info[ip->reloc_num].value = const_0;
@@ -1016,6 +1019,20 @@ append_fixed_insn (struct loongarch_cl_insn *insn)
char *f = frag_more (insn->insn_length);
move_insn (insn, frag_now, f - frag_now->fr_literal);
+
+ if (call36)
+ {
+ if (strcmp (insn->name, "jirl") == 0)
+ {
+ /* See comment at end of append_fixp_and_insn. */
+ frag_wane (frag_now);
+ frag_new (0);
+ }
+ call36 = 0;
+ }
+
+ if (BFD_RELOC_LARCH_CALL36 == insn->reloc_info[0].type)
+ call36 = 1;
}
/* Add instructions based on the worst-case scenario firstly. */