Skip to content

Commit 61d77ff

Browse files
committed
Add support for Zbc carry-less multiplication extension
Add support for the RISC-V Zbc carry-less multiplication extension. This extension introduces instructions for carry-less multiplication, enabling efficient operations in cryptographic algorithms, error-correcting codes, and other specialized applications. Supporting the Zbc extension improves compatibility with the RISC-V specification and enables optimized handling of carry-less multiplication tasks.
1 parent 42a6ad8 commit 61d77ff

File tree

7 files changed

+107
-1
lines changed

7 files changed

+107
-1
lines changed

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ $(call set-feature, Zba)
115115
ENABLE_Zbb ?= 1
116116
$(call set-feature, Zbb)
117117

118+
# Zbc Carry-less multiplication
119+
ENABLE_Zbc ?= 1
120+
$(call set-feature, Zbc)
121+
118122
ENABLE_FULL4G ?= 0
119123

120124
# Experimental SDL oriented system calls

src/decode.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ static inline bool op_op(rv_insn_t *ir, const uint32_t insn)
725725
break;
726726
#endif /* RV32_HAS(Zba) */
727727

728-
#if RV32_HAS(Zbb)
728+
#if RV32_HAS(Zbb) || RV32_HAS(Zbc)
729729
/* inst funct7 rs2 rs1 funct3 rd opcode
730730
* ------+-------+---+---+------+--+-------
731731
* MAX 0000101 rs2 rs1 110 rd 0110011
@@ -737,6 +737,7 @@ static inline bool op_op(rv_insn_t *ir, const uint32_t insn)
737737
*/
738738
case 0b0000101:
739739
switch (funct3) {
740+
#if RV32_HAS(Zbb)
740741
case 0b110: /* max */
741742
ir->opcode = rv_insn_max;
742743
break;
@@ -749,10 +750,24 @@ static inline bool op_op(rv_insn_t *ir, const uint32_t insn)
749750
case 0b101: /* minu */
750751
ir->opcode = rv_insn_minu;
751752
break;
753+
#endif
754+
#if RV32_HAS(Zbc)
755+
case 0b001: /*clmul */
756+
ir->opcode = rv_insn_clmul;
757+
break;
758+
case 0b011: /*clmulh */
759+
ir->opcode = rv_insn_clmulh;
760+
break;
761+
case 0b010: /*clmulr */
762+
ir->opcode = rv_insn_clmulr;
763+
break;
764+
#endif
752765
default: /* illegal instruction */
753766
return false;
754767
}
755768
break;
769+
#endif
770+
#if RV32_HAS(Zbb)
756771
case 0b0110000:
757772
switch (funct3) {
758773
case 0b001: /* rol */

src/decode.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ enum op_field {
123123
_(rori, 0, 4, 0, ENC(rs1, rd)) \
124124
_(orcb, 0, 4, 0, ENC(rs1, rd)) \
125125
_(rev8, 0, 4, 0, ENC(rs1, rd)) \
126+
) \
127+
/* RV32 Zbc Standard Extension */ \
128+
IIF(RV32_HAS(Zbc))( \
129+
_(clmul, 0, 4, 0, ENC(rs1, rs2, rd)) \
130+
_(clmulh, 0, 4, 0, ENC(rs1, rs2, rd)) \
131+
_(clmulr, 0, 4, 0, ENC(rs1, rs2, rd)) \
126132
) \
127133
/* RV32M Standard Extension */ \
128134
IIF(RV32_HAS(EXT_M))( \

src/feature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@
4747
#define RV32_FEATURE_Zbb 1
4848
#endif
4949

50+
/* Zbc Carry-less multiplication */
51+
#ifndef RV32_FEATURE_Zbc
52+
#define RV32_FEATURE_Zbc 1
53+
#endif
54+
5055
/* Experimental SDL oriented system calls */
5156
#ifndef RV32_FEATURE_SDL
5257
#define RV32_FEATURE_SDL 1

src/rv32_constopt.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,3 +1169,23 @@ CONSTOPT(rev8, {
11691169
info->is_constant[ir->rd] = false;
11701170
})
11711171
#endif
1172+
1173+
#if RV32_HAS(Zbc)
1174+
/* CLMUL */
1175+
CONSTOPT(clmul, {
1176+
if (ir->rd)
1177+
info->is_constant[ir->rd] = false;
1178+
})
1179+
1180+
/* CLMULH */
1181+
CONSTOPT(clmulh, {
1182+
if (ir->rd)
1183+
info->is_constant[ir->rd] = false;
1184+
})
1185+
1186+
/* CLMULR */
1187+
CONSTOPT(clmulr, {
1188+
if (ir->rd)
1189+
info->is_constant[ir->rd] = false;
1190+
})
1191+
#endif

src/rv32_template.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2837,3 +2837,51 @@ RVOP(
28372837
}))
28382838

28392839
#endif
2840+
2841+
/* RV32Zbc Standard Extension */
2842+
2843+
#if RV32_HAS(Zbc)
2844+
2845+
/* CLMUL */
2846+
RVOP(
2847+
clmul,
2848+
{
2849+
uint32_t output = 0;
2850+
for (int i = 0; i < 32; i++)
2851+
if ((rv->X[ir->rs2] >> i) & 1)
2852+
output ^= rv->X[ir->rs1] << i;
2853+
rv->X[ir->rd] = output;
2854+
},
2855+
GEN({
2856+
assert; /* FIXME: Implement */
2857+
}))
2858+
2859+
/* CLMULH */
2860+
RVOP(
2861+
clmulh,
2862+
{
2863+
uint32_t output = 0;
2864+
for (int i = 1; i < 32; i++)
2865+
if ((rv->X[ir->rs2] >> i) & 1)
2866+
output ^= rv->X[ir->rs1] >> (32 - i);
2867+
rv->X[ir->rd] = output;
2868+
},
2869+
GEN({
2870+
assert; /* FIXME: Implement */
2871+
}))
2872+
2873+
/* CLMULR */
2874+
RVOP(
2875+
clmulr,
2876+
{
2877+
uint32_t output = 0;
2878+
for (int i = 0; i < 32; i++)
2879+
if ((rv->X[ir->rs2] >> i) & 1)
2880+
output ^= rv->X[ir->rs1] >> (32 - i - 1);
2881+
rv->X[ir->rd] = output;
2882+
},
2883+
GEN({
2884+
assert; /* FIXME: Implement */
2885+
}))
2886+
2887+
#endif

src/t2c_template.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,14 @@ T2C_OP(orcb, { __UNREACHABLE; })
839839
T2C_OP(rev8, { __UNREACHABLE; })
840840
#endif
841841

842+
#if RV32_HAS(Zbc)
843+
T2C_OP(clmul, { __UNREACHABLE; })
844+
845+
T2C_OP(clmulh, { __UNREACHABLE; })
846+
847+
T2C_OP(clmulr, { __UNREACHABLE; })
848+
#endif
849+
842850
T2C_OP(fuse1, {
843851
opcode_fuse_t *fuse = ir->fuse;
844852
for (int i = 0; i < ir->imm2; i++) {

0 commit comments

Comments
 (0)