Skip to content

Commit 29dabe4

Browse files
committed
Add support for Zbs single-bit instructions extension
Add support for the RISC-V Zbs single-bit instructions extension. This extension introduces instructions for efficient manipulation of individual bits, enabling optimized operations in bit-level processing and control. Supporting the Zbs extension improves compatibility with the RISC-V specification and enhances performance in tasks requiring precise single-bit operations.
1 parent 23a234d commit 29dabe4

File tree

7 files changed

+228
-0
lines changed

7 files changed

+228
-0
lines changed

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ $(call set-feature, Zbb)
119119
ENABLE_Zbc ?= 1
120120
$(call set-feature, Zbc)
121121

122+
# Zbs Single-bit instructions
123+
ENABLE_Zbs ?= 1
124+
$(call set-feature, Zbs)
125+
122126
ENABLE_FULL4G ?= 0
123127

124128
# Experimental SDL oriented system calls

src/decode.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,20 @@ static inline bool op_op_imm(rv_insn_t *ir, const uint32_t insn)
485485
ir->opcode = rv_insn_sexth;
486486
return true;
487487
}
488+
#endif
489+
#if RV32_HAS(Zbs)
490+
if (ir->imm >> 5 == 0b0100100) { /* bclri */
491+
ir->opcode = rv_insn_bclri;
492+
return true;
493+
}
494+
if (ir->imm >> 5 == 0b0110100) { /* binvi */
495+
ir->opcode = rv_insn_binvi;
496+
return true;
497+
}
498+
if (ir->imm >> 5 == 0b0010100) { /* bseti */
499+
ir->opcode = rv_insn_bseti;
500+
return true;
501+
}
488502
#endif
489503
ir->opcode = rv_insn_slli;
490504
if (unlikely(ir->imm & (1 << 5)))
@@ -513,6 +527,12 @@ static inline bool op_op_imm(rv_insn_t *ir, const uint32_t insn)
513527
ir->opcode = rv_insn_rev8;
514528
return true;
515529
}
530+
#endif
531+
#if RV32_HAS(Zbs)
532+
if (ir->imm >> 5 == 0b0100100) { /* bexti */
533+
ir->opcode = rv_insn_bexti;
534+
return true;
535+
}
516536
#endif
517537
/* SLL, SRL, and SRA perform logical left, logical right, and
518538
* arithmetic right shifts on the value in register rs1.
@@ -787,6 +807,31 @@ static inline bool op_op(rv_insn_t *ir, const uint32_t insn)
787807
break;
788808
#endif /* RV32_HAS(Zbb) */
789809

810+
#if RV32_HAS(Zbs)
811+
case 0b0100100:
812+
switch (funct3) {
813+
case 0b001: /* bclr */
814+
ir->opcode = rv_insn_bclr;
815+
break;
816+
case 0b101: /* bext */
817+
ir->opcode = rv_insn_bext;
818+
break;
819+
default: /* illegal instruction */
820+
return false;
821+
}
822+
break;
823+
case 0b0110100:
824+
if (unlikely(funct3 != 0b001))
825+
return false;
826+
ir->opcode = rv_insn_binv;
827+
break;
828+
case 0b0010100:
829+
if (unlikely(funct3 != 0b001))
830+
return false;
831+
ir->opcode = rv_insn_bset;
832+
break;
833+
#endif /* RV32_HAS(Zbs) */
834+
790835
case 0b0100000:
791836
switch (funct3) {
792837
case 0b000: /* SUB: Substract */

src/decode.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ enum op_field {
130130
_(clmulh, 0, 4, 0, ENC(rs1, rs2, rd)) \
131131
_(clmulr, 0, 4, 0, ENC(rs1, rs2, rd)) \
132132
) \
133+
/* RV32 Zbs Standard Extension */ \
134+
IIF(RV32_HAS(Zbs))( \
135+
_(bclr, 0, 4, 0, ENC(rs1, rs2, rd)) \
136+
_(bclri, 0, 4, 0, ENC(rs1, rs2, rd)) \
137+
_(bext, 0, 4, 0, ENC(rs1, rs2, rd)) \
138+
_(bexti, 0, 4, 0, ENC(rs1, rs2, rd)) \
139+
_(binv, 0, 4, 0, ENC(rs1, rs2, rd)) \
140+
_(binvi, 0, 4, 0, ENC(rs1, rs2, rd)) \
141+
_(bset, 0, 4, 0, ENC(rs1, rs2, rd)) \
142+
_(bseti, 0, 4, 0, ENC(rs1, rs2, rd)) \
143+
) \
133144
/* RV32M Standard Extension */ \
134145
IIF(RV32_HAS(EXT_M))( \
135146
_(mul, 0, 4, 1, ENC(rs1, rs2, rd)) \

src/feature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@
5252
#define RV32_FEATURE_Zbc 1
5353
#endif
5454

55+
/* Zbs Single-bit instructions */
56+
#ifndef RV32_FEATURE_Zbs
57+
#define RV32_FEATURE_Zbs 1
58+
#endif
59+
5560
/* Experimental SDL oriented system calls */
5661
#ifndef RV32_FEATURE_SDL
5762
#define RV32_FEATURE_SDL 1

src/rv32_constopt.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,3 +1189,54 @@ CONSTOPT(clmulr, {
11891189
info->is_constant[ir->rd] = false;
11901190
})
11911191
#endif
1192+
1193+
#if RV32_HAS(Zbs)
1194+
/* BCLR */
1195+
CONSTOPT(bclr, {
1196+
if (ir->rd)
1197+
info->is_constant[ir->rd] = false;
1198+
})
1199+
1200+
/* BCLRI */
1201+
CONSTOPT(bclri, {
1202+
if (ir->rd)
1203+
info->is_constant[ir->rd] = false;
1204+
})
1205+
1206+
/* BEXT */
1207+
CONSTOPT(bext, {
1208+
if (ir->rd)
1209+
info->is_constant[ir->rd] = false;
1210+
})
1211+
1212+
/* BEXTI */
1213+
CONSTOPT(bexti, {
1214+
if (ir->rd)
1215+
info->is_constant[ir->rd] = false;
1216+
})
1217+
1218+
/* BINV */
1219+
CONSTOPT(binv, {
1220+
if (ir->rd)
1221+
info->is_constant[ir->rd] = false;
1222+
})
1223+
1224+
/* BINVI */
1225+
CONSTOPT(binvi, {
1226+
if (ir->rd)
1227+
info->is_constant[ir->rd] = false;
1228+
})
1229+
1230+
/* BSET */
1231+
CONSTOPT(bset, {
1232+
if (ir->rd)
1233+
info->is_constant[ir->rd] = false;
1234+
})
1235+
1236+
/* BSETI */
1237+
CONSTOPT(bseti, {
1238+
if (ir->rd)
1239+
info->is_constant[ir->rd] = false;
1240+
})
1241+
1242+
#endif

src/rv32_template.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2885,3 +2885,97 @@ RVOP(
28852885
}))
28862886

28872887
#endif
2888+
2889+
/* RV32Zbs Standard Extension */
2890+
2891+
#if RV32_HAS(Zbs)
2892+
2893+
/* BCLR */
2894+
RVOP(
2895+
bclr,
2896+
{
2897+
const unsigned int index = rv->X[ir->rs2] & (32 - 1);
2898+
rv->X[ir->rd] = rv->X[ir->rs1] & (~(1U << index));
2899+
},
2900+
GEN({
2901+
assert; /* FIXME: Implement */
2902+
}))
2903+
2904+
/* BCLRI */
2905+
RVOP(
2906+
bclri,
2907+
{
2908+
const unsigned int index = ir->imm & (32 - 1);
2909+
rv->X[ir->rd] = rv->X[ir->rs1] & (~(1U << index));
2910+
},
2911+
GEN({
2912+
assert; /* FIXME: Implement */
2913+
}))
2914+
2915+
/* BEXT */
2916+
RVOP(
2917+
bext,
2918+
{
2919+
const unsigned int index = rv->X[ir->rs2] & (32 - 1);
2920+
rv->X[ir->rd] = (rv->X[ir->rs1] >> index) & 1;
2921+
},
2922+
GEN({
2923+
assert; /* FIXME: Implement */
2924+
}))
2925+
2926+
/* BEXTI */
2927+
RVOP(
2928+
bexti,
2929+
{
2930+
const unsigned int index = ir->imm & (32 - 1);
2931+
rv->X[ir->rd] = (rv->X[ir->rs1] >> index) & 1;
2932+
},
2933+
GEN({
2934+
assert; /* FIXME: Implement */
2935+
}))
2936+
2937+
/* BINV */
2938+
RVOP(
2939+
binv,
2940+
{
2941+
const unsigned int index = rv->X[ir->rs2] & (32 - 1);
2942+
rv->X[ir->rd] = rv->X[ir->rs1] ^ (1U << index);
2943+
},
2944+
GEN({
2945+
assert; /* FIXME: Implement */
2946+
}))
2947+
2948+
/* BINVI */
2949+
RVOP(
2950+
binvi,
2951+
{
2952+
const unsigned int index = ir->imm & (32 - 1);
2953+
rv->X[ir->rd] = rv->X[ir->rs1] ^ (1U << index);
2954+
},
2955+
GEN({
2956+
assert; /* FIXME: Implement */
2957+
}))
2958+
2959+
/* BSET */
2960+
RVOP(
2961+
bset,
2962+
{
2963+
const unsigned int index = rv->X[ir->rs2] & (32 - 1);
2964+
rv->X[ir->rd] = rv->X[ir->rs1] | (1U << index);
2965+
},
2966+
GEN({
2967+
assert; /* FIXME: Implement */
2968+
}))
2969+
2970+
/* BSETI */
2971+
RVOP(
2972+
bseti,
2973+
{
2974+
const unsigned int index = ir->imm & (32 - 1);
2975+
rv->X[ir->rd] = rv->X[ir->rs1] | (1U << index);
2976+
},
2977+
GEN({
2978+
assert; /* FIXME: Implement */
2979+
}))
2980+
2981+
#endif

src/t2c_template.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,24 @@ T2C_OP(clmulh, { __UNREACHABLE; })
847847
T2C_OP(clmulr, { __UNREACHABLE; })
848848
#endif
849849

850+
#if RV32_HAS(Zbs)
851+
T2C_OP(bclr, { __UNREACHABLE; })
852+
853+
T2C_OP(bclri, { __UNREACHABLE; })
854+
855+
T2C_OP(bext, { __UNREACHABLE; })
856+
857+
T2C_OP(bexti, { __UNREACHABLE; })
858+
859+
T2C_OP(binv, { __UNREACHABLE; })
860+
861+
T2C_OP(binvi, { __UNREACHABLE; })
862+
863+
T2C_OP(bset, { __UNREACHABLE; })
864+
865+
T2C_OP(bseti, { __UNREACHABLE; })
866+
#endif
867+
850868
T2C_OP(fuse1, {
851869
opcode_fuse_t *fuse = ir->fuse;
852870
for (int i = 0; i < ir->imm2; i++) {

0 commit comments

Comments
 (0)