Skip to content

Commit d4f9e0e

Browse files
committed
Add decoder for RVV instructions
1 parent d8bf69a commit d4f9e0e

File tree

6 files changed

+280
-1
lines changed

6 files changed

+280
-1
lines changed

src/decode.c

Lines changed: 197 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ static inline uint32_t decode_r4type_rs3(const uint32_t insn)
118118
}
119119
#endif
120120

121+
#if RV32_HAS(EXT_RVV)
122+
/* decode RVV vm field
123+
* vm = inst[25]
124+
*/
125+
static inline uint32_t decode_rvv_vm(const uint32_t insn)
126+
{
127+
return (insn >> 25) & 0x1;
128+
}
129+
#endif
130+
121131
#if RV32_HAS(EXT_C)
122132
enum {
123133
/* clang-format off */
@@ -1971,6 +1981,183 @@ static inline bool op_cfsw(rv_insn_t *ir, const uint32_t insn)
19711981
#define op_cflwsp OP_UNIMP
19721982
#endif /* RV32_HAS(EXT_C) && RV32_HAS(EXT_F) */
19731983

1984+
static inline bool op_ivv(rv_insn_t *ir, const uint32_t insn) {
1985+
#define MASK 0xfc00707f
1986+
#define MATCH_VADD_VI 0x3057
1987+
#define MATCH_VAND_VI 0x24003057
1988+
#define MATCH_VMADC_VI 0x46003057
1989+
#define MATCH_VMSEQ_VI 0x60003057
1990+
#define MATCH_VMSGT_VI 0x7c003057
1991+
#define MATCH_VMSGTU_VI 0x78003057
1992+
#define MATCH_VMSLE_VI 0x74003057
1993+
#define MATCH_VMSLEU_VI 0x70003057
1994+
#define MATCH_VMSNE_VI 0x64003057
1995+
#define MATCH_VOR_VI 0x28003057
1996+
#define MATCH_VRGATHER_VI 0x30003057
1997+
#define MATCH_VRSUB_VI 0xc003057
1998+
#define MATCH_VSADD_VI 0x84003057
1999+
#define MATCH_VSADDU_VI 0x80003057
2000+
#define MATCH_VSLIDEDOWN_VI 0x3c003057
2001+
#define MATCH_VSLIDEUP_VI 0x38003057
2002+
#define MATCH_VSLL_VI 0x94003057
2003+
#define MATCH_VSRA_VI 0xa4003057
2004+
#define MATCH_VSRL_VI 0xa0003057
2005+
#define MATCH_VSSRA_VI 0xac003057
2006+
#define MATCH_VSSRL_VI 0xa8003057
2007+
#define MATCH_VXOR_VI 0x2c003057
2008+
2009+
ir->rs1 = decode_rs1(insn);
2010+
ir->rs2 = decode_rs2(insn);
2011+
ir->vm = decode_rvv_vm(insn);
2012+
switch (insn & MASK) {
2013+
case MATCH_VADD_VI:
2014+
ir->opcode = rv_insn_vadd_vi;
2015+
break;
2016+
case MATCH_VAND_VI:
2017+
ir->opcode = rv_insn_vand_vi;
2018+
break;
2019+
case MATCH_VMADC_VI:
2020+
ir->opcode = rv_insn_vmadc_vi;
2021+
break;
2022+
case MATCH_VMSEQ_VI:
2023+
ir->opcode = rv_insn_vmseq_vi;
2024+
break;
2025+
case MATCH_VMSGT_VI:
2026+
ir->opcode = rv_insn_vmsgt_vi;
2027+
break;
2028+
case MATCH_VMSGTU_VI:
2029+
ir->opcode = rv_insn_vmsgtu_vi;
2030+
break;
2031+
case MATCH_VMSLE_VI:
2032+
ir->opcode = rv_insn_vmsle_vi;
2033+
break;
2034+
case MATCH_VMSLEU_VI:
2035+
ir->opcode = rv_insn_vmsleu_vi;
2036+
break;
2037+
case MATCH_VMSNE_VI:
2038+
ir->opcode = rv_insn_vmsne_vi;
2039+
break;
2040+
case MATCH_VOR_VI:
2041+
ir->opcode = rv_insn_vor_vi;
2042+
break;
2043+
case MATCH_VRGATHER_VI:
2044+
ir->opcode = rv_insn_vrgather_vi;
2045+
break;
2046+
case MATCH_VRSUB_VI:
2047+
ir->opcode = rv_insn_vrsub_vi;
2048+
break;
2049+
case MATCH_VSADD_VI:
2050+
ir->opcode = rv_insn_vsadd_vi;
2051+
break;
2052+
case MATCH_VSADDU_VI:
2053+
ir->opcode = rv_insn_vsaddu_vi;
2054+
break;
2055+
case MATCH_VSLIDEDOWN_VI:
2056+
ir->opcode = rv_insn_vslidedown_vi;
2057+
break;
2058+
case MATCH_VSLIDEUP_VI:
2059+
ir->opcode = rv_insn_vslideup_vi;
2060+
break;
2061+
case MATCH_VSLL_VI:
2062+
ir->opcode = rv_insn_vsll_vi;
2063+
break;
2064+
case MATCH_VSRA_VI:
2065+
ir->opcode = rv_insn_vsra_vi;
2066+
break;
2067+
case MATCH_VSRL_VI:
2068+
ir->opcode = rv_insn_vsrl_vi;
2069+
break;
2070+
case MATCH_VSSRA_VI:
2071+
ir->opcode = rv_insn_vssra_vi;
2072+
break;
2073+
case MATCH_VSSRL_VI:
2074+
ir->opcode = rv_insn_vssrl_vi;
2075+
break;
2076+
case MATCH_VXOR_VI:
2077+
ir->opcode = rv_insn_vxor_vi;
2078+
break;
2079+
default:
2080+
return false;
2081+
}
2082+
}
2083+
2084+
static inline bool op_fvv(rv_insn_t *ir, const uint32_t insn) {}
2085+
static inline bool op_mvv(rv_insn_t *ir, const uint32_t insn) {}
2086+
static inline bool op_ivi(rv_insn_t *ir, const uint32_t insn) {}
2087+
static inline bool op_ivx(rv_insn_t *ir, const uint32_t insn) {}
2088+
static inline bool op_fvf(rv_insn_t *ir, const uint32_t insn) {}
2089+
static inline bool op_mvx(rv_insn_t *ir, const uint32_t insn) {}
2090+
2091+
/* OP: RVV
2092+
* opcode is 0x57 for VALU and VCFG
2093+
*
2094+
* VALU format:
2095+
* 31 26 25 24 20 19 15 14 12 11 7 6 0
2096+
* funct6 | vm | vs2 | vs1 | 0 0 0 (funct3) | vd |1010111| OP-V (OPIVV)
2097+
* funct6 | vm | vs2 | vs1 | 0 0 1 (funct3) | vd/rd |1010111| OP-V (OPFVV)
2098+
* funct6 | vm | vs2 | vs1 | 0 1 0 (funct3) | vd/rd |1010111| OP-V (OPMVV)
2099+
* funct6 | vm | vs2 | imm[4:0] | 0 1 1 (funct3) | vd |1010111| OP-V (OPIVI)
2100+
* funct6 | vm | vs2 | rs1 | 1 0 0 (funct3) | vd |1010111| OP-V (OPIVX)
2101+
* funct6 | vm | vs2 | rs1 | 1 0 1 (funct3) | vd |1010111| OP-V (OPFVF)
2102+
* funct6 | vm | vs2 | rs1 | 1 1 0 (funct3) | vd/rd |1010111| OP-V (OPMVX)
2103+
* 6 1 5 5 3 5 7
2104+
*
2105+
* Where 'vm' is the bit indicates whether masking is enabled
2106+
* see https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#531-mask-encoding
2107+
*
2108+
* VMEM format:
2109+
*
2110+
* 31 29 28 27 26 25 24 20 19 15 14 12 11 7 6 0
2111+
* nf | mew| mop | vm | lumop | rs1 | width | vd |0000111| VL* unit-stride
2112+
* nf | mew| mop | vm | rs2 | rs1 | width | vd |0000111| VLS* strided
2113+
* nf | mew| mop | vm | vs2 | rs1 | width | vd |0000111| VLX* indexed
2114+
* 3 1 2 1 5 5 3 5 7
2115+
*
2116+
* VCFG format:
2117+
*
2118+
* 31 30 25 24 20 19 15 14 12 11 7 6 0
2119+
* 0 | zimm[10:0] | rs1 | 1 1 1 | rd |1010111| vsetvli
2120+
* 1 | 1| zimm[ 9:0] | uimm[4:0]| 1 1 1 | rd |1010111| vsetivli
2121+
* 1 | 000000 | rs2 | rs1 | 1 1 1 | rd |1010111| vsetvl
2122+
* 1 6 5 5 3 5 7
2123+
*
2124+
* reference:
2125+
* https://github.com/riscv/riscv-isa-manual/blob/main/src/images/wavedrom/valu-format.edn
2126+
* https://github.com/riscv/riscv-isa-manual/blob/main/src/images/wavedrom/v-inst-table.edn
2127+
* https://observablehq.com/@drom/risc-v-v
2128+
*
2129+
* funct3
2130+
* | 0 | 0 | 0 | OPIVV | vector-vector | N/A
2131+
* | 0 | 0 | 1 | OPFVV | vector-vector | N/A
2132+
* | 0 | 1 | 0 | OPMVV | vector-vector | N/A
2133+
* | 0 | 1 | 1 | OPIVI | vector-immediate | `imm[4:0]`
2134+
* | 1 | 0 | 0 | OPIVX | vector-scalar | GPR `x` register `rs1`
2135+
* | 1 | 0 | 1 | OPFVF | vector-scalar | FP `f` register `rs1`
2136+
* | 1 | 1 | 0 | OPMVX | vector-scalar | GPR `x` register `rs1`
2137+
*/
2138+
static inline bool op_v(rv_insn_t *ir, const uint32_t insn)
2139+
{
2140+
uint32_t funct3_mask = 0x7000;
2141+
switch (insn & funct3_mask) {
2142+
case 0:
2143+
return op_ivv(ir, insn);
2144+
case 1:
2145+
return op_fvv(ir, insn);
2146+
case 2:
2147+
return op_mvv(ir, insn);
2148+
case 3:
2149+
return op_ivi(ir, insn);
2150+
case 4:
2151+
return op_ivx(ir, insn);
2152+
case 5:
2153+
return op_fvf(ir, insn);
2154+
case 6:
2155+
return op_mvx(ir, insn);
2156+
default:
2157+
return false;
2158+
}
2159+
}
2160+
19742161
/* handler for all unimplemented opcodes */
19752162
static inline bool op_unimp(rv_insn_t *ir UNUSED, uint32_t insn UNUSED)
19762163
{
@@ -1985,13 +2172,22 @@ bool rv_decode(rv_insn_t *ir, uint32_t insn)
19852172
{
19862173
assert(ir);
19872174

2175+
#if RV32_HAS(EXT_RVV)
2176+
#define MASK_OPCODE_RVV 0x57
2177+
#define MASK_OPCODE_RVV_VMEM 0x57
2178+
if (insn & MASK_OPCODE_RVV) {
2179+
return op_v(ir, insn);
2180+
}
2181+
#endif
2182+
19882183
#define OP_UNIMP op_unimp
19892184
#define OP(insn) op_##insn
19902185

19912186
/* RV32 base opcode map */
19922187
/* clang-format off */
19932188
static const decode_t rv_jump_table[] = {
1994-
// 000 001 010 011 100 101 110 111
2189+
// insn[4:2]
2190+
// 000 001 010 011 100 101 110 111 // insn[6:5]
19952191
OP(load), OP(load_fp), OP(unimp), OP(misc_mem), OP(op_imm), OP(auipc), OP(unimp), OP(unimp), // 00
19962192
OP(store), OP(store_fp), OP(unimp), OP(amo), OP(op), OP(lui), OP(unimp), OP(unimp), // 01
19972193
OP(madd), OP(msub), OP(nmsub), OP(nmadd), OP(op_fp), OP(unimp), OP(unimp), OP(unimp), // 10

src/decode.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,30 @@ enum op_field {
195195
_(fcvtswu, 0, 4, 0, ENC(rs1, rs2, rd)) \
196196
_(fmvwx, 0, 4, 0, ENC(rs1, rs2, rd)) \
197197
) \
198+
IIF(RV32_HAS(EXT_RVV))( \
199+
_(vadd_vi, 0, 4, 0, ENC(r1, r2, rd)) \
200+
_(vand_vi, 0, 4, 0, ENC(r1, r2, rd)) \
201+
_(vmadc_vi, 0, 4, 0, ENC(r1, r2, rd)) \
202+
_(vmseq_vi, 0, 4, 0, ENC(r1, r2, rd)) \
203+
_(vmsgt_vi, 0, 4, 0, ENC(r1, r2, rd)) \
204+
_(vmsgtu_vi, 0, 4, 0, ENC(r1, r2, rd)) \
205+
_(vmsle_vi, 0, 4, 0, ENC(r1, r2, rd)) \
206+
_(vmsleu_vi, 0, 4, 0, ENC(r1, r2, rd)) \
207+
_(vmsne_vi, 0, 4, 0, ENC(r1, r2, rd)) \
208+
_(vor_vi, 0, 4, 0, ENC(r1, r2, rd)) \
209+
_(vrgather_vi, 0, 4, 0, ENC(r1, r2, rd)) \
210+
_(vrsub_vi, 0, 4, 0, ENC(r1, r2, rd)) \
211+
_(vsadd_vi, 0, 4, 0, ENC(r1, r2, rd)) \
212+
_(vsaddu_vi, 0, 4, 0, ENC(r1, r2, rd)) \
213+
_(vslidedown_vi, 0, 4, 0, ENC(r1, r2, rd)) \
214+
_(vslideup_vi, 0, 4, 0, ENC(r1, r2, rd)) \
215+
_(vsll_vi, 0, 4, 0, ENC(r1, r2, rd)) \
216+
_(vsra_vi, 0, 4, 0, ENC(r1, r2, rd)) \
217+
_(vsrl_vi, 0, 4, 0, ENC(r1, r2, rd)) \
218+
_(vssra_vi, 0, 4, 0, ENC(r1, r2, rd)) \
219+
_(vssrl_vi, 0, 4, 0, ENC(r1, r2, rd)) \
220+
_(vxor_vi, 0, 4, 0, ENC(r1, r2, rd)) \
221+
) \
198222
/* RV32C Standard Extension */ \
199223
IIF(RV32_HAS(EXT_C))( \
200224
_(caddi4spn, 0, 2, 1, ENC(rd)) \
@@ -340,6 +364,7 @@ typedef struct rv_insn {
340364
int32_t imm;
341365
uint8_t rs3;
342366
};
367+
// uses as both scalar registers and vector registers
343368
uint8_t rd, rs1, rs2;
344369
/* store IR list */
345370
uint8_t opcode;
@@ -361,6 +386,9 @@ typedef struct rv_insn {
361386
uint8_t rm;
362387
#endif
363388

389+
#if RV32_HAS(EXT_RVV)
390+
uint8_t vm;
391+
#endif
364392
/* fuse operation */
365393
int32_t imm2;
366394
opcode_fuse_t *fuse;

src/emulate.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,9 @@ static uint32_t peripheral_update_ctr = 64;
401401
}
402402

403403
#include "rv32_template.c"
404+
#if RV32_HAS(EXT_RVV)
405+
#include "rv32_rvv_template.c"
406+
#endif
404407
#undef RVOP
405408

406409
/* multiple LUI */

src/feature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@
5555
/* Zbs Single-bit instructions */
5656
#ifndef RV32_FEATURE_Zbs
5757
#define RV32_FEATURE_Zbs 1
58+
59+
/* RVV instructions */
60+
#define RV32_FEATURE_EXT_RVV 1
61+
#ifndef RV32_FEATURE_EXT_RVV
62+
// #define RV32_FEATURE_EXT_RVV 1
5863
#endif
5964

6065
/* Experimental SDL oriented system calls */

src/rv32_constopt.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,4 +1239,27 @@ CONSTOPT(bseti, {
12391239
info->is_constant[ir->rd] = false;
12401240
})
12411241

1242+
#if RV32_HAS(EXT_RVV)
1243+
CONSTOPT(vadd_vi, {})
1244+
CONSTOPT(vand_vi, {})
1245+
CONSTOPT(vmadc_vi, {})
1246+
CONSTOPT(vmseq_vi, {})
1247+
CONSTOPT(vmsgt_vi, {})
1248+
CONSTOPT(vmsgtu_vi, {})
1249+
CONSTOPT(vmsle_vi, {})
1250+
CONSTOPT(vmsleu_vi, {})
1251+
CONSTOPT(vmsne_vi, {})
1252+
CONSTOPT(vor_vi, {})
1253+
CONSTOPT(vrgather_vi, {})
1254+
CONSTOPT(vrsub_vi, {})
1255+
CONSTOPT(vsadd_vi, {})
1256+
CONSTOPT(vsaddu_vi, {})
1257+
CONSTOPT(vslidedown_vi, {})
1258+
CONSTOPT(vslideup_vi, {})
1259+
CONSTOPT(vsll_vi, {})
1260+
CONSTOPT(vsra_vi, {})
1261+
CONSTOPT(vsrl_vi, {})
1262+
CONSTOPT(vssra_vi, {})
1263+
CONSTOPT(vssrl_vi, {})
1264+
CONSTOPT(vxor_vi, {})
12421265
#endif

src/rv32_rvv_template.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* RV32 RVV Instruction Set */
2+
3+
RVOP(vadd_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
4+
RVOP(vand_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
5+
RVOP(vmadc_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
6+
RVOP(vmseq_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
7+
RVOP(vmsgt_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
8+
RVOP(vmsgtu_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
9+
RVOP(vmsle_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
10+
RVOP(vmsleu_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
11+
RVOP(vmsne_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
12+
RVOP(vor_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
13+
RVOP(vrgather_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
14+
RVOP(vrsub_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
15+
RVOP(vsadd_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
16+
RVOP(vsaddu_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
17+
RVOP(vslidedown_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
18+
RVOP(vslideup_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
19+
RVOP(vsll_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
20+
RVOP(vsra_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
21+
RVOP(vsrl_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
22+
RVOP(vssra_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
23+
RVOP(vssrl_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))
24+
RVOP(vxor_vi, { rv->X[rv_reg_zero] = 0; }, GEN({/* no operation */}))

0 commit comments

Comments
 (0)