Skip to content

Commit 2dcaaf6

Browse files
committed
Add decoder for RVV instructions
1 parent a00c49f commit 2dcaaf6

File tree

6 files changed

+265
-1
lines changed

6 files changed

+265
-1
lines changed

src/decode.c

+180-1
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 */
@@ -1791,6 +1801,165 @@ static inline bool op_cfsw(rv_insn_t *ir, const uint32_t insn)
17911801
#define op_cflwsp OP_UNIMP
17921802
#endif /* RV32_HAS(EXT_C) && RV32_HAS(EXT_F) */
17931803

1804+
static inline bool op_ivv(rv_insn_t *ir, const uint32_t insn) {
1805+
#define MASK 0xfc00707f
1806+
#define MATCH_VADD_VI 0x3057
1807+
#define MATCH_VAND_VI 0x24003057
1808+
#define MATCH_VMADC_VI 0x46003057
1809+
#define MATCH_VMSEQ_VI 0x60003057
1810+
#define MATCH_VMSGT_VI 0x7c003057
1811+
#define MATCH_VMSGTU_VI 0x78003057
1812+
#define MATCH_VMSLE_VI 0x74003057
1813+
#define MATCH_VMSLEU_VI 0x70003057
1814+
#define MATCH_VMSNE_VI 0x64003057
1815+
#define MATCH_VOR_VI 0x28003057
1816+
#define MATCH_VRGATHER_VI 0x30003057
1817+
#define MATCH_VRSUB_VI 0xc003057
1818+
#define MATCH_VSADD_VI 0x84003057
1819+
#define MATCH_VSADDU_VI 0x80003057
1820+
#define MATCH_VSLIDEDOWN_VI 0x3c003057
1821+
#define MATCH_VSLIDEUP_VI 0x38003057
1822+
#define MATCH_VSLL_VI 0x94003057
1823+
#define MATCH_VSRA_VI 0xa4003057
1824+
#define MATCH_VSRL_VI 0xa0003057
1825+
#define MATCH_VSSRA_VI 0xac003057
1826+
#define MATCH_VSSRL_VI 0xa8003057
1827+
#define MATCH_VXOR_VI 0x2c003057
1828+
1829+
ir->rs1 = decode_rs1(insn);
1830+
ir->rs2 = decode_rs2(insn);
1831+
ir->vm = decode_rvv_vm(insn);
1832+
switch (insn & MASK) {
1833+
case MATCH_VADD_VI:
1834+
ir->opcode = rv_insn_vadd_vi;
1835+
break;
1836+
case MATCH_VAND_VI:
1837+
ir->opcode = rv_insn_vand_vi;
1838+
break;
1839+
case MATCH_VMADC_VI:
1840+
ir->opcode = rv_insn_vmadc_vi;
1841+
break;
1842+
case MATCH_VMSEQ_VI:
1843+
ir->opcode = rv_insn_vmseq_vi;
1844+
break;
1845+
case MATCH_VMSGT_VI:
1846+
ir->opcode = rv_insn_vmsgt_vi;
1847+
break;
1848+
case MATCH_VMSGTU_VI:
1849+
ir->opcode = rv_insn_vmsgtu_vi;
1850+
break;
1851+
case MATCH_VMSLE_VI:
1852+
ir->opcode = rv_insn_vmsle_vi;
1853+
break;
1854+
case MATCH_VMSLEU_VI:
1855+
ir->opcode = rv_insn_vmsleu_vi;
1856+
break;
1857+
case MATCH_VMSNE_VI:
1858+
ir->opcode = rv_insn_vmsne_vi;
1859+
break;
1860+
case MATCH_VOR_VI:
1861+
ir->opcode = rv_insn_vor_vi;
1862+
break;
1863+
case MATCH_VRGATHER_VI:
1864+
ir->opcode = rv_insn_vrgather_vi;
1865+
break;
1866+
case MATCH_VRSUB_VI:
1867+
ir->opcode = rv_insn_vrsub_vi;
1868+
break;
1869+
case MATCH_VSADD_VI:
1870+
ir->opcode = rv_insn_vsadd_vi;
1871+
break;
1872+
case MATCH_VSADDU_VI:
1873+
ir->opcode = rv_insn_vsaddu_vi;
1874+
break;
1875+
case MATCH_VSLIDEDOWN_VI:
1876+
ir->opcode = rv_insn_vslidedown_vi;
1877+
break;
1878+
case MATCH_VSLIDEUP_VI:
1879+
ir->opcode = rv_insn_vslideup_vi;
1880+
break;
1881+
case MATCH_VSLL_VI:
1882+
ir->opcode = rv_insn_vsll_vi;
1883+
break;
1884+
case MATCH_VSRA_VI:
1885+
ir->opcode = rv_insn_vsra_vi;
1886+
break;
1887+
case MATCH_VSRL_VI:
1888+
ir->opcode = rv_insn_vsrl_vi;
1889+
break;
1890+
case MATCH_VSSRA_VI:
1891+
ir->opcode = rv_insn_vssra_vi;
1892+
break;
1893+
case MATCH_VSSRL_VI:
1894+
ir->opcode = rv_insn_vssrl_vi;
1895+
break;
1896+
case MATCH_VXOR_VI:
1897+
ir->opcode = rv_insn_vxor_vi;
1898+
break;
1899+
default:
1900+
return false;
1901+
}
1902+
}
1903+
1904+
static inline bool op_fvv(rv_insn_t *ir, const uint32_t insn) {}
1905+
static inline bool op_mvv(rv_insn_t *ir, const uint32_t insn) {}
1906+
static inline bool op_ivi(rv_insn_t *ir, const uint32_t insn) {}
1907+
static inline bool op_ivx(rv_insn_t *ir, const uint32_t insn) {}
1908+
static inline bool op_fvf(rv_insn_t *ir, const uint32_t insn) {}
1909+
static inline bool op_mvx(rv_insn_t *ir, const uint32_t insn) {}
1910+
1911+
/* OP: RVV
1912+
* opcode is 0x57
1913+
* 31 26 25 24 20 19 15 14 12 11 7 6 0
1914+
* funct6 | vm | vs2 | vs1 | 0 0 0 (funct3) | vd |1010111| OP-V (OPIVV)
1915+
* funct6 | vm | vs2 | vs1 | 0 0 1 (funct3) | vd/rd |1010111| OP-V (OPFVV)
1916+
* funct6 | vm | vs2 | vs1 | 0 1 0 (funct3) | vd/rd |1010111| OP-V (OPMVV)
1917+
* funct6 | vm | vs2 | imm[4:0] | 0 1 1 (funct3) | vd |1010111| OP-V (OPIVI)
1918+
* funct6 | vm | vs2 | rs1 | 1 0 0 (funct3) | vd |1010111| OP-V (OPIVX)
1919+
* funct6 | vm | vs2 | rs1 | 1 0 1 (funct3) | vd |1010111| OP-V (OPFVF)
1920+
* funct6 | vm | vs2 | rs1 | 1 1 0 (funct3) | vd/rd |1010111| OP-V (OPMVX)
1921+
* 6 1 5 5 3 5 7
1922+
*
1923+
* Where 'vm' is the bit indicates whether masking is enabled
1924+
* see https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#531-mask-encoding
1925+
*
1926+
* reference:
1927+
* https://github.com/riscv/riscv-isa-manual/blob/main/src/images/wavedrom/valu-format.edn
1928+
* https://github.com/riscv/riscv-isa-manual/blob/main/src/images/wavedrom/v-inst-table.edn
1929+
* https://observablehq.com/@drom/risc-v-v
1930+
*
1931+
* funct3
1932+
* | 0 | 0 | 0 | OPIVV | vector-vector | N/A
1933+
* | 0 | 0 | 1 | OPFVV | vector-vector | N/A
1934+
* | 0 | 1 | 0 | OPMVV | vector-vector | N/A
1935+
* | 0 | 1 | 1 | OPIVI | vector-immediate | `imm[4:0]`
1936+
* | 1 | 0 | 0 | OPIVX | vector-scalar | GPR `x` register `rs1`
1937+
* | 1 | 0 | 1 | OPFVF | vector-scalar | FP `f` register `rs1`
1938+
* | 1 | 1 | 0 | OPMVX | vector-scalar | GPR `x` register `rs1`
1939+
*/
1940+
static inline bool op_v(rv_insn_t *ir, const uint32_t insn)
1941+
{
1942+
uint32_t funct3_mask = 0x7000;
1943+
switch (insn & funct3_mask) {
1944+
case 0:
1945+
return op_ivv(ir, insn);
1946+
case 1:
1947+
return op_fvv(ir, insn);
1948+
case 2:
1949+
return op_mvv(ir, insn);
1950+
case 3:
1951+
return op_ivi(ir, insn);
1952+
case 4:
1953+
return op_ivx(ir, insn);
1954+
case 5:
1955+
return op_fvf(ir, insn);
1956+
case 6:
1957+
return op_mvx(ir, insn);
1958+
default:
1959+
return false;
1960+
}
1961+
}
1962+
17941963
/* handler for all unimplemented opcodes */
17951964
static inline bool op_unimp(rv_insn_t *ir UNUSED, uint32_t insn UNUSED)
17961965
{
@@ -1800,18 +1969,28 @@ static inline bool op_unimp(rv_insn_t *ir UNUSED, uint32_t insn UNUSED)
18001969
/* RV32 decode handler type */
18011970
typedef bool (*decode_t)(rv_insn_t *ir, uint32_t insn);
18021971

1972+
#if RV32_HAS(EXT_RVV)
1973+
#define MASK_OPCODE_RVV 0x57
1974+
#endif
18031975
/* decode RISC-V instruction */
18041976
bool rv_decode(rv_insn_t *ir, uint32_t insn)
18051977
{
18061978
assert(ir);
18071979

1980+
#if RV32_HAS(EXT_RVV)
1981+
if (insn & MASK_OPCODE_RVV) {
1982+
return op_v(ir, insn);
1983+
}
1984+
#endif
1985+
18081986
#define OP_UNIMP op_unimp
18091987
#define OP(insn) op_##insn
18101988

18111989
/* RV32 base opcode map */
18121990
/* clang-format off */
18131991
static const decode_t rv_jump_table[] = {
1814-
// 000 001 010 011 100 101 110 111
1992+
// insn[4:2]
1993+
// 000 001 010 011 100 101 110 111 // insn[6:5]
18151994
OP(load), OP(load_fp), OP(unimp), OP(misc_mem), OP(op_imm), OP(auipc), OP(unimp), OP(unimp), // 00
18161995
OP(store), OP(store_fp), OP(unimp), OP(amo), OP(op), OP(lui), OP(unimp), OP(unimp), // 01
18171996
OP(madd), OP(msub), OP(nmsub), OP(nmadd), OP(op_fp), OP(unimp), OP(unimp), OP(unimp), // 10

src/decode.h

+28
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,30 @@ enum op_field {
149149
_(fcvtswu, 0, 4, 0, ENC(rs1, rs2, rd)) \
150150
_(fmvwx, 0, 4, 0, ENC(rs1, rs2, rd)) \
151151
) \
152+
IIF(RV32_HAS(EXT_RVV))( \
153+
_(vadd_vi, 0, 4, 0, ENC(r1, r2, rd)) \
154+
_(vand_vi, 0, 4, 0, ENC(r1, r2, rd)) \
155+
_(vmadc_vi, 0, 4, 0, ENC(r1, r2, rd)) \
156+
_(vmseq_vi, 0, 4, 0, ENC(r1, r2, rd)) \
157+
_(vmsgt_vi, 0, 4, 0, ENC(r1, r2, rd)) \
158+
_(vmsgtu_vi, 0, 4, 0, ENC(r1, r2, rd)) \
159+
_(vmsle_vi, 0, 4, 0, ENC(r1, r2, rd)) \
160+
_(vmsleu_vi, 0, 4, 0, ENC(r1, r2, rd)) \
161+
_(vmsne_vi, 0, 4, 0, ENC(r1, r2, rd)) \
162+
_(vor_vi, 0, 4, 0, ENC(r1, r2, rd)) \
163+
_(vrgather_vi, 0, 4, 0, ENC(r1, r2, rd)) \
164+
_(vrsub_vi, 0, 4, 0, ENC(r1, r2, rd)) \
165+
_(vsadd_vi, 0, 4, 0, ENC(r1, r2, rd)) \
166+
_(vsaddu_vi, 0, 4, 0, ENC(r1, r2, rd)) \
167+
_(vslidedown_vi, 0, 4, 0, ENC(r1, r2, rd)) \
168+
_(vslideup_vi, 0, 4, 0, ENC(r1, r2, rd)) \
169+
_(vsll_vi, 0, 4, 0, ENC(r1, r2, rd)) \
170+
_(vsra_vi, 0, 4, 0, ENC(r1, r2, rd)) \
171+
_(vsrl_vi, 0, 4, 0, ENC(r1, r2, rd)) \
172+
_(vssra_vi, 0, 4, 0, ENC(r1, r2, rd)) \
173+
_(vssrl_vi, 0, 4, 0, ENC(r1, r2, rd)) \
174+
_(vxor_vi, 0, 4, 0, ENC(r1, r2, rd)) \
175+
) \
152176
/* RV32C Standard Extension */ \
153177
IIF(RV32_HAS(EXT_C))( \
154178
_(caddi4spn, 0, 2, 1, ENC(rd)) \
@@ -294,6 +318,7 @@ typedef struct rv_insn {
294318
int32_t imm;
295319
uint8_t rs3;
296320
};
321+
// uses as both scalar registers and vector registers
297322
uint8_t rd, rs1, rs2;
298323
/* store IR list */
299324
uint8_t opcode;
@@ -315,6 +340,9 @@ typedef struct rv_insn {
315340
uint8_t rm;
316341
#endif
317342

343+
#if RV32_HAS(EXT_RVV)
344+
uint8_t vm;
345+
#endif
318346
/* fuse operation */
319347
int32_t imm2;
320348
opcode_fuse_t *fuse;

src/emulate.c

+3
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,9 @@ static bool has_loops = false;
414414
}
415415

416416
#include "rv32_template.c"
417+
#if RV32_HAS(EXT_RVV)
418+
#include "rv32_rvv_template.c"
419+
#endif
417420
#undef RVOP
418421

419422
/* multiple LUI */

src/feature.h

+5
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@
3737
#define RV32_FEATURE_Zifencei 1
3838
#endif
3939

40+
#define RV32_FEATURE_EXT_RVV 1
41+
#ifndef RV32_FEATURE_EXT_RVV
42+
// #define RV32_FEATURE_EXT_RVV 1
43+
#endif
44+
4045
/* Experimental SDL oriented system calls */
4146
#ifndef RV32_FEATURE_SDL
4247
#define RV32_FEATURE_SDL 1

src/rv32_constopt.c

+25
Original file line numberDiff line numberDiff line change
@@ -1037,3 +1037,28 @@ CONSTOPT(cflw, {})
10371037
/* C.FSW */
10381038
CONSTOPT(cfsw, {})
10391039
#endif
1040+
1041+
#if RV32_HAS(EXT_RVV)
1042+
CONSTOPT(vadd_vi, {})
1043+
CONSTOPT(vand_vi, {})
1044+
CONSTOPT(vmadc_vi, {})
1045+
CONSTOPT(vmseq_vi, {})
1046+
CONSTOPT(vmsgt_vi, {})
1047+
CONSTOPT(vmsgtu_vi, {})
1048+
CONSTOPT(vmsle_vi, {})
1049+
CONSTOPT(vmsleu_vi, {})
1050+
CONSTOPT(vmsne_vi, {})
1051+
CONSTOPT(vor_vi, {})
1052+
CONSTOPT(vrgather_vi, {})
1053+
CONSTOPT(vrsub_vi, {})
1054+
CONSTOPT(vsadd_vi, {})
1055+
CONSTOPT(vsaddu_vi, {})
1056+
CONSTOPT(vslidedown_vi, {})
1057+
CONSTOPT(vslideup_vi, {})
1058+
CONSTOPT(vsll_vi, {})
1059+
CONSTOPT(vsra_vi, {})
1060+
CONSTOPT(vsrl_vi, {})
1061+
CONSTOPT(vssra_vi, {})
1062+
CONSTOPT(vssrl_vi, {})
1063+
CONSTOPT(vxor_vi, {})
1064+
#endif

src/rv32_rvv_template.c

+24
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)