Skip to content

Commit

Permalink
ZC: fix issue openhwgroup#55.
Browse files Browse the repository at this point in the history
GAS tries to relax a conditional branch by flipping the condition bit
and setting the offset to a two-instruction-length constant.

relax
    bne	t5,t3,.Lfar_away
to
    beq	t5,t3,8 # a constant value
    j .Lfar_away

To solve this issue, we add a local symbol right after the `j`
instruction, and then the linker can help adjust bytes during
linker relaxation.
  • Loading branch information
linsinan1995 authored and edward-jones committed Jul 21, 2023
1 parent 02ec8cd commit c549628
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 2 deletions.
39 changes: 37 additions & 2 deletions gas/config/tc-riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -5328,7 +5328,24 @@ md_convert_frag_branch (fragS *fragp)
/* Invert the branch condition. Branch over the jump. */
insn = bfd_getl16 (buf);
insn ^= MATCH_C_BEQZ ^ MATCH_C_BNEZ;
insn |= ENCODE_CBTYPE_IMM (6);

if (riscv_subset_supports (&riscv_rps_as, "zcmt"))
{
symbolS *sym = symbol_new (FAKE_LABEL_NAME , now_seg, fragp,
fragp->fr_fix + fragp->fr_var);
fixp = fix_new (fragp,
buf - (bfd_byte *)fragp->fr_literal,
2,
sym,
0,
false,
BFD_RELOC_RISCV_RVC_BRANCH);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
}
else
insn |= ENCODE_CBTYPE_IMM (6);

bfd_putl16 (insn, buf);
buf += 2;
goto jump;
Expand All @@ -5355,7 +5372,25 @@ md_convert_frag_branch (fragS *fragp)
/* Invert the branch condition. Branch over the jump. */
insn = bfd_getl32 (buf);
insn ^= MATCH_BEQ ^ MATCH_BNE;
insn |= ENCODE_BTYPE_IMM (8);

if (riscv_subset_supports (&riscv_rps_as, "zcmt"))
{
symbolS *sym = (symbolS *) local_symbol_make (
FAKE_LABEL_NAME, now_seg, fragp,
fragp->fr_fix + fragp->fr_var);
fixp = fix_new (fragp,
buf - (bfd_byte *)fragp->fr_literal,
4,
sym,
0,
false,
BFD_RELOC_12_PCREL);
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
}
else
insn |= ENCODE_BTYPE_IMM (8);

bfd_putl32 (insn, buf);
buf += 4;

Expand Down
19 changes: 19 additions & 0 deletions gas/testsuite/gas/riscv/zc-zcmt-relax-branch.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#as: -march=rv32g_zca_zcmt
#source: zc-zcmt-relax-branch.s
#objdump: -dr -Mno-aliases

.*:[ ]+file format .*


Disassembly of section .text:

0+000 <target>:
[ ]*[0-9a-f]+:[ ]+00940263[ ]+beq[ ]+s0,s1,4.+
[^:]+: R_RISCV_BRANCH[ ]+NORMAL

0+4 <NORMAL>:
[ ]*[0-9a-f]+:[ ]+00941463[ ]+bne[ ]+s0,s1,c.+
[^:]+: R_RISCV_BRANCH[ ]+\.L0
[ ]*[0-9a-f]+:[ ]+0000006f[ ]+jal[ ]+zero,8.+
[^:]+: R_RISCV_JAL[ ]+\*ABS\*\-0x4
[ ]*[0-9a-f]+:[ ]+8082[ ]+c.jr[ ]+ra
6 changes: 6 additions & 0 deletions gas/testsuite/gas/riscv/zc-zcmt-relax-branch.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.option norelax
target:
beq s0,s1,NORMAL
NORMAL:
beq s0,s1,-4
ret
31 changes: 31 additions & 0 deletions gas/testsuite/gas/riscv/zc-zcmt-relax-c-branch.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#as: -march=rv32g_zca_zcmt
#source: zc-zcmt-relax-c-branch.s
#objdump: -dr -Mno-aliases

.*:[ ]+file format .*


Disassembly of section .text:

0+000 <target>:
[ ]*[0-9a-f]+:[ ]+c009[ ]+c.beqz[ ]+s0,2.+
[^:]+: R_RISCV_RVC_BRANCH[ ]+C_BRANCH_RANGE

0+2 <C_BRANCH_RANGE>:
[ ]*[0-9a-f]+:[ ]+10041263[ ]+bne[ ]+s0,zero,106.+
[^:]+: R_RISCV_BRANCH[ ]+EXPAND_TO_BRANCH
#...

.+ <EXPAND_TO_BRANCH>:
[ ]*[0-9a-f]+:[ ]+c019[ ]+c.beqz[ ]+s0,10c.+
[^:]+: R_RISCV_RVC_BRANCH[ ]+\.L0
[ ]*[0-9a-f]+:[ ]+0040106f[ ]+jal[ ]+zero,110c.+
[^:]+: R_RISCV_JAL[ ]+FLIP_C_BRANCH_AND_JUMP
#...

.+ <FLIP_C_BRANCH_AND_JUMP>:
[ ]*[0-9a-f]+:[ ]+00041463[ ]+bne[ ]+s0,zero,1114.+
[^:]+: R_RISCV_BRANCH[ ]+\.L0
[ ]*[0-9a-f]+:[ ]+0000006f[ ]+jal[ ]+zero,1110.+
[^:]+: R_RISCV_JAL[ ]+\*ABS\*\-0x4
[ ]*[0-9a-f]+:[ ]+8082[ ]+c.jr[ ]+ra

0 comments on commit c549628

Please sign in to comment.