diff options
author | mengqinggang <mengqinggang@loongson.cn> | 2024-02-28 17:42:36 +0800 |
---|---|---|
committer | liuzhensong <liuzhensong@loongson.cn> | 2024-03-19 14:14:47 +0800 |
commit | 97ce7870440d6b00181c2162ff5e56bb39b2e475 (patch) | |
tree | d62f13b8a4669786eb2915077adb523fc31ea4ab /gas/config | |
parent | b42aa684f6ff2bce9b8bc58aa89574723f17f1ce (diff) | |
download | binutils-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.c | 19 |
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. */ |