You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Aug 17, 2022. It is now read-only.
I am currently trying to compress a cond branch instruction decbnez to c.decbnez in zce extension. However, it seems a bit different from the current way to replace a instruction with c.* one in riscv_ip, since c.decbnez can only do backward jump (so we need to get the offset to determine if we can replace decbnez insn), and offset field is a nzuimm instead of a signed immediate in decbnez.
My current solution is to manually calculate the offset between the branch instruction and label location, and it seems to succeed to output the result.
zceb.s
zceb.o
a.out
also, do not compress if branch to .L3 (what we expect)
a.out
code snippet:
@@ -1250,6 +1278,52 @@ riscv_apply_const_reloc (bfd_reloc_code_real_type reloc_type, bfd_vma value)
}
}
+/* Extra compression routine for Code Size Reduction Extension */+void+zce_compress_pass (struct riscv_cl_insn *ip, expressionS *address_expr,+ bfd_reloc_code_real_type *reloc_type)+{+ int rd;+ long label_loc, insn_loc, offset;++ /* only deal with decbnez to c.debnze currently */+ if (*reloc_type != BFD_RELOC_RISCV_DECBNEZ)+ return;++ /* check if+ addressing field+ 1. addressing expr is a label+ 2. the label is located above the inst (if it is defined)+ 3. the length of offset to label is valid+ rd field+ 4. regno of rd ranges from 8 to 15 + */+ if (address_expr->X_add_symbol+ && S_IS_DEFINED (address_expr->X_add_symbol))+ {+ label_loc = S_GET_VALUE (address_expr->X_add_symbol);+ insn_loc = frag_more (0) - frag_now->fr_literal;+ offset = insn_loc - label_loc;++ /* extract rd regno */+ rd = (ip->insn_opcode >> OP_SH_RD) & OP_MASK_RD;+ /* offset in c.decbnez should be positive */+ if (offset == 0)+ return;+ /* check if the offset length is valid */+ if (VALID_ZCE_C_DECBNEZ_IMM (offset)+ && (rd >= 8 && rd <= 15))+ {+ /* new encoding for c.decbnez */+ ip->insn_opcode = MATCH_C_DECBNEZ \+ | ((rd-8) << OP_SH_CRS1S) \+ | ENCODE_ZCE_C_DECBNEZ_SCALE (EXTRACT_ZCE_DECBNEZ_SCALE (ip->insn_opcode)) \+ | ENCODE_ZCE_C_DECBNEZ_IMM (offset);+ *reloc_type = BFD_RELOC_RISCV_C_DECBNEZ;+ }+ }+}+@@ -2760,7 +2946,14 @@ md_assemble (char *str)
if (insn.insn_mo->pinfo == INSN_MACRO)
macro (&insn, &imm_expr, &imm_reloc);
else
+ {+ if (insn.insn_mo->insn_class == INSN_CLASS_ZCEE \+ || insn.insn_mo->insn_class == INSN_CLASS_ZCEA \+ || insn.insn_mo->insn_class == INSN_CLASS_ZCEB)+ zce_compress_pass (&insn, &imm_expr, &imm_reloc);
append_insn (&insn, &imm_expr, imm_reloc);
+ }+
}
Also, another solution I try is to replace decbnez instruction when applying the fixup to elf write buffer (md_apply_fix), and put the following 2 bytes as c.nop (it looks unsafe to modify the byte length in the elf write buf), and add a reloc table to tell the linker to delete it to get the result like below (maybe need to change to r_riscv_relax and add implementation in linker side)
I am quite noob on Binutils, and it would be great that if someone can give me some feedback. Thx!
The text was updated successfully, but these errors were encountered:
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Hi all,
I am currently trying to compress a cond branch instruction decbnez to c.decbnez in zce extension. However, it seems a bit different from the current way to replace a instruction with c.* one in riscv_ip, since c.decbnez can only do backward jump (so we need to get the offset to determine if we can replace decbnez insn), and offset field is a nzuimm instead of a signed immediate in decbnez.
My current solution is to manually calculate the offset between the branch instruction and label location, and it seems to succeed to output the result.
zceb.s
zceb.o
a.out
also, do not compress if branch to .L3 (what we expect)
a.out
code snippet:
full patch for decbnez:
https://gist.github.com/linsinan1995/d4ac3f90df65501675abb29998536a0f
Also, another solution I try is to replace decbnez instruction when applying the fixup to elf write buffer (md_apply_fix), and put the following 2 bytes as c.nop (it looks unsafe to modify the byte length in the elf write buf), and add a reloc table to tell the linker to delete it to get the result like below (maybe need to change to r_riscv_relax and add implementation in linker side)
I am quite noob on Binutils, and it would be great that if someone can give me some feedback. Thx!
The text was updated successfully, but these errors were encountered: