diff --git a/src/decode.c b/src/decode.c index 2003e6f8e..2814bd92a 100644 --- a/src/decode.c +++ b/src/decode.c @@ -1668,15 +1668,92 @@ static inline bool op_cbnez(rv_insn_t *ir, const uint32_t insn) #define op_cbnez OP_UNIMP #endif /* RV32_HAS(EXT_C) */ -/* TODO: RV32C.F support */ -#define op_cfldsp OP_UNIMP -#define op_cflwsp OP_UNIMP -#define op_cfswsp OP_UNIMP -#define op_cfsdsp OP_UNIMP -#define op_cfld OP_UNIMP -#define op_cflw OP_UNIMP +#if RV32_HAS(EXT_C) && RV32_HAS(EXT_F) +/* C.FLWSP: CI-format + * 15 13 12 11 7 6 2 1 0 + * | funct3 | imm | rd | imm | op | + */ +static inline bool op_cflwsp(rv_insn_t *ir, const uint32_t insn) +{ + /* inst funct3 imm rd imm op + * -------+------+-------+-----+-------------+-- + * C.FLWSP 001 uimm[5] rd uimm[4:2|7:6] 10 + */ + uint16_t tmp = 0; + tmp |= (insn & 0x70) >> 2; + tmp |= (insn & 0x0c) << 4; + tmp |= (insn & 0x1000) >> 7; + ir->imm = tmp; + ir->rd = c_decode_rd(insn); + ir->opcode = rv_insn_cflwsp; + return true; +} + +/* C.FSWSP: CSS-Format + * 15 13 12 7 6 2 1 0 + * | funct3 | imm | rs2 | op | + */ +static inline bool op_cfswsp(rv_insn_t *ir, const uint32_t insn) +{ + /* inst funct3 imm rs2 op + * -------+------+-------------+---+-- + * C.FSWSP 111 uimm[5:2|7:6] rs2 10 + */ + ir->imm = (insn & 0x1e00) >> 7 | (insn & 0x180) >> 1; + ir->rs2 = c_decode_rs2(insn); + ir->opcode = rv_insn_cfswsp; + return true; +} + +/* C.LW: CL-format + * 15 13 12 10 9 7 6 5 4 2 1 0 + * | funct3 | imm | rs1' | imm | rd' | op | + */ +static inline bool op_cflw(rv_insn_t *ir, const uint32_t insn) +{ + /* inst funct3 imm rs1' imm rd' op + * -----+------+---------+----+---------+---+-- + * C.FLW 010 uimm[5:3] rs1' uimm[7:6] rd' 00 + */ + uint16_t tmp = 0; + tmp |= (insn & 0b0000000001000000) >> 4; + tmp |= (insn & FC_IMM_12_10) >> 7; + tmp |= (insn & 0b0000000000100000) << 1; + ir->imm = tmp; + ir->rd = c_decode_rdc(insn) | 0x08; + ir->rs1 = c_decode_rs1c(insn) | 0x08; + ir->opcode = rv_insn_cflw; + return true; +} + +/* C.FSW: CS-format + * 15 13 12 10 9 7 6 5 4 2 1 0 + * | funct3 | imm | rs1' | imm | rs2' | op | + */ +static inline bool op_cfsw(rv_insn_t *ir, const uint32_t insn) +{ + /* inst funct3 imm rs1' imm rs2' op + * -----+------+---------+----+---------+----+-- + * C.FSW 110 uimm[5:3] rs1' uimm[2|6] rs2' 00 + */ + uint32_t tmp = 0; + /* ....xxxx....xxxx */ + tmp |= (insn & 0b0000000001000000) >> 4; + tmp |= (insn & FC_IMM_12_10) >> 7; + tmp |= (insn & 0b0000000000100000) << 1; + ir->imm = tmp; + ir->rs1 = c_decode_rs1c(insn) | 0x08; + ir->rs2 = c_decode_rs2c(insn) | 0x08; + ir->opcode = rv_insn_cfsw; + return true; +} + +#else /* !(RV32_HAS(EXT_C) && RV32_HAS(EXT_F)) */ #define op_cfsw OP_UNIMP -#define op_cfsd OP_UNIMP +#define op_cflw OP_UNIMP +#define op_cfswsp OP_UNIMP +#define op_cflwsp OP_UNIMP +#endif /* RV32_HAS(EXT_C) && RV32_HAS(EXT_F) */ /* handler for all unimplemented opcodes */ static inline bool op_unimp(rv_insn_t *ir UNUSED, uint32_t insn UNUSED) @@ -1710,11 +1787,11 @@ bool rv_decode(rv_insn_t *ir, uint32_t insn) static const decode_t rvc_jump_table[] = { // 00 01 10 11 OP(caddi4spn), OP(caddi), OP(cslli), OP(unimp), // 000 - OP(cfld), OP(cjal), OP(cfldsp), OP(unimp), // 001 + OP(unimp), OP(cjal), OP(unimp), OP(unimp), // 001 OP(clw), OP(cli), OP(clwsp), OP(unimp), // 010 OP(cflw), OP(clui), OP(cflwsp), OP(unimp), // 011 OP(unimp), OP(cmisc_alu), OP(ccr), OP(unimp), // 100 - OP(cfsd), OP(cj), OP(cfsdsp), OP(unimp), // 101 + OP(unimp), OP(cj), OP(unimp), OP(unimp), // 101 OP(csw), OP(cbeqz), OP(cswsp), OP(unimp), // 110 OP(cfsw), OP(cbnez), OP(cfswsp), OP(unimp), // 111 }; diff --git a/src/decode.h b/src/decode.h index 11458cf43..e1a4bc2f3 100644 --- a/src/decode.h +++ b/src/decode.h @@ -176,6 +176,11 @@ enum op_field { _(cjalr, 1, 2, 1, ENC(rs1, rs2, rd)) \ _(cadd, 0, 2, 1, ENC(rs1, rs2, rd)) \ _(cswsp, 0, 2, 1, ENC(rs2)) \ + /* RV32FC Instruction */ \ + _(cflwsp, 0, 2, 1, ENC(rd)) \ + _(cfswsp, 0, 2, 1, ENC(rs2)) \ + _(cflw, 0, 2, 1, ENC(rs1, rd)) \ + _(cfsw, 0, 2, 1, ENC(rs1, rs2)) \ ) /* clang-format on */ diff --git a/src/rv32_constopt.c b/src/rv32_constopt.c index f1d2321b7..14a957b35 100644 --- a/src/rv32_constopt.c +++ b/src/rv32_constopt.c @@ -979,3 +979,19 @@ CONSTOPT(cadd, { /* C.SWSP */ CONSTOPT(cswsp, {}) #endif + +/* RV32FC Standard Extension */ + +#if RV32_HAS(EXT_F) && RV32_HAS(EXT_C) +/* C.FLWSP */ +CONSTOPT(cflwsp, {}) + +/* C.FSWSP */ +CONSTOPT(cfswsp, {}) + +/* C.FLW */ +CONSTOPT(cflw, {}) + +/* C.FSW */ +CONSTOPT(cfsw, {}) +#endif diff --git a/src/rv32_template.c b/src/rv32_template.c index 591dcbc7b..767f9caf9 100644 --- a/src/rv32_template.c +++ b/src/rv32_template.c @@ -2272,3 +2272,49 @@ RVOP( st, S32, TMP1, TMP0, 0; })) #endif + +#if RV32_HAS(EXT_C) && RV32_HAS(EXT_F) +/* C.FLWSP */ +RVOP( + cflwsp, + { + const uint32_t addr = rv->X[rv_reg_sp] + ir->imm; + rv->F[ir->rd].v = rv->io.mem_read_w(addr); + }, + GEN({ + assert; /* FIXME: Implement */ + })) + +/* C.FSWSP */ +RVOP( + cfswsp, + { + const uint32_t addr = rv->X[rv_reg_sp] + ir->imm; + rv->io.mem_write_w(addr, rv->F[ir->rs2].v); + }, + GEN({ + assert; /* FIXME: Implement */ + })) + +/* C.FLW */ +RVOP( + cflw, + { + const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm; + rv->F[ir->rd].v = rv->io.mem_read_w(addr); + }, + GEN({ + assert; /* FIXME: Implement */ + })) + +/* C.FSW */ +RVOP( + cfsw, + { + const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm; + rv->io.mem_write_w(addr, rv->F[ir->rs2].v); + }, + GEN({ + assert; /* FIXME: Implement */ + })) +#endif