uint64_t rvc_rd() { return rd(); }
uint64_t rvc_rs1() { return rd(); }
uint64_t rvc_rs2() { return x(2, 5); }
- uint64_t rvc_rds() { return 8 + x(10, 3); }
uint64_t rvc_rs1s() { return 8 + x(7, 3); }
uint64_t rvc_rs2s() { return 8 + x(2, 3); }
private:
#define READ_REG(reg) STATE.XPR[reg]
#define RS1 READ_REG(insn.rs1())
#define RS2 READ_REG(insn.rs2())
-#define WRITE_REG(reg, value) STATE.XPR.write(reg, value)
#define WRITE_RD(value) WRITE_REG(insn.rd(), value)
-#ifdef RISCV_ENABLE_COMMITLOG
- #undef WRITE_REG
- #define WRITE_REG(reg, value) ({ \
- reg_t wdata = (value); /* value is a func with side-effects */ \
- STATE.log_reg_write = (commit_log_reg_t){(reg) << 1, wdata}; \
- STATE.XPR.write(reg, wdata); \
- })
+#ifndef RISCV_ENABLE_COMMITLOG
+# define WRITE_REG(reg, value) STATE.XPR.write(reg, value)
+# define WRITE_FREG(reg, value) DO_WRITE_FREG(reg, value)
+#else
+# define WRITE_REG(reg, value) ({ \
+ reg_t wdata = (value); /* value may have side effects */ \
+ STATE.log_reg_write = (commit_log_reg_t){(reg) << 1, wdata}; \
+ STATE.XPR.write(reg, wdata); \
+ })
+# define WRITE_FREG(reg, value) ({ \
+ freg_t wdata = (value); /* value may have side effects */ \
+ STATE.log_reg_write = (commit_log_reg_t){((reg) << 1) | 1, wdata}; \
+ DO_WRITE_FREG(reg, wdata); \
+ })
#endif
// RVC macros
-#define WRITE_RVC_RDS(value) WRITE_REG(insn.rvc_rds(), value)
-#define WRITE_RVC_RS1S(value) WRITE_REG(insn.rvc_rs1s(), value)
#define WRITE_RVC_RS2S(value) WRITE_REG(insn.rvc_rs2s(), value)
+#define WRITE_RVC_FRS2S(value) WRITE_FREG(insn.rvc_rs2s(), value)
#define RVC_RS1 READ_REG(insn.rvc_rs1())
#define RVC_RS2 READ_REG(insn.rvc_rs2())
#define RVC_RS1S READ_REG(insn.rvc_rs1s())
#define RVC_RS2S READ_REG(insn.rvc_rs2s())
+#define RVC_FRS2 STATE.FPR[insn.rvc_rs2()]
+#define RVC_FRS2S STATE.FPR[insn.rvc_rs2s()]
#define RVC_SP READ_REG(X_SP)
// FPU macros
#define FRS3 STATE.FPR[insn.rs3()]
#define dirty_fp_state (STATE.mstatus |= MSTATUS_FS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD))
#define dirty_ext_state (STATE.mstatus |= MSTATUS_XS | (xlen == 64 ? MSTATUS64_SD : MSTATUS32_SD))
-#define do_write_frd(value) (STATE.FPR.write(insn.rd(), value), dirty_fp_state)
-
-#ifndef RISCV_ENABLE_COMMITLOG
-# define WRITE_FRD(value) do_write_frd(value)
-#else
-# define WRITE_FRD(value) ({ \
- freg_t wdata = (value); /* value may have side effects */ \
- STATE.log_reg_write = (commit_log_reg_t){(insn.rd() << 1) | 1, wdata}; \
- do_write_frd(wdata); \
- })
-#endif
+#define DO_WRITE_FREG(reg, value) (STATE.FPR.write(reg, value), dirty_fp_state)
+#define WRITE_FRD(value) WRITE_FREG(insn.rd(), value)
#define SHAMT (insn.i_imm() & 0x3F)
#define BRANCH_TARGET (pc + insn.sb_imm())
#define MASK_BNE 0x707f
#define MATCH_C_ADD 0x1000
#define MASK_C_ADD 0xf003
-#define MATCH_C_ADD3 0xa000
-#define MASK_C_ADD3 0xe063
#define MATCH_C_ADDI 0xc002
#define MASK_C_ADDI 0xe003
-#define MATCH_C_ADDI4SPN 0xa001
+#define MATCH_C_ADDI4SPN 0x8000
#define MASK_C_ADDI4SPN 0xe003
#define MATCH_C_ADDIW 0xe002
#define MASK_C_ADDIW 0xe003
-#define MATCH_C_ADDW 0x9000
+#define MATCH_C_ADDW 0x8001
#define MASK_C_ADDW 0xf003
-#define MATCH_C_AND3 0xa060
-#define MASK_C_AND3 0xe063
#define MATCH_C_BEQZ 0x4002
#define MASK_C_BEQZ 0xe003
#define MATCH_C_BNEZ 0x6002
#define MASK_C_BNEZ 0xe003
+#define MATCH_C_FLD 0xa000
+#define MASK_C_FLD 0xe003
+#define MATCH_C_FLDSP 0xa001
+#define MASK_C_FLDSP 0xe003
+#define MATCH_C_FLW 0xe000
+#define MASK_C_FLW 0xe003
+#define MATCH_C_FLWSP 0xe001
+#define MASK_C_FLWSP 0xe003
+#define MATCH_C_FSD 0x2000
+#define MASK_C_FSD 0xe003
+#define MATCH_C_FSDSP 0x2001
+#define MASK_C_FSDSP 0xe003
+#define MATCH_C_FSW 0x6000
+#define MASK_C_FSW 0xe003
+#define MATCH_C_FSWSP 0x6001
+#define MASK_C_FSWSP 0xe003
#define MATCH_C_J 0x2
#define MASK_C_J 0xe003
#define MATCH_C_JAL 0x2002
#define MASK_C_JAL 0xe003
-#define MATCH_C_LD 0xe000
-#define MASK_C_LD 0xe003
-#define MATCH_C_LDSP 0xe001
-#define MASK_C_LDSP 0xe003
#define MATCH_C_LI 0x8002
#define MASK_C_LI 0xe003
#define MATCH_C_LUI 0xa002
#define MASK_C_LWSP 0xe003
#define MATCH_C_MV 0x0
#define MASK_C_MV 0xf003
-#define MATCH_C_OR3 0xa040
-#define MASK_C_OR3 0xe063
-#define MATCH_C_SD 0x6000
-#define MASK_C_SD 0xe003
-#define MATCH_C_SDSP 0x6001
-#define MASK_C_SDSP 0xe003
#define MATCH_C_SLLI 0x1
#define MASK_C_SLLI 0xe003
-#define MATCH_C_SLLIW 0x8001
-#define MASK_C_SLLIW 0xe003
-#define MATCH_C_SRAI 0x2000
-#define MASK_C_SRAI 0xe003
-#define MATCH_C_SRLI 0x2001
-#define MASK_C_SRLI 0xe003
-#define MATCH_C_SUB 0x8000
-#define MASK_C_SUB 0xf003
-#define MATCH_C_SUB3 0xa020
-#define MASK_C_SUB3 0xe063
#define MATCH_C_SW 0x4000
#define MASK_C_SW 0xe003
#define MATCH_C_SWSP 0x4001
DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
DECLARE_INSN(bne, MATCH_BNE, MASK_BNE)
DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD)
-DECLARE_INSN(c_add3, MATCH_C_ADD3, MASK_C_ADD3)
DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI)
DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN)
DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW)
DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW)
-DECLARE_INSN(c_and3, MATCH_C_AND3, MASK_C_AND3)
DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
+DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD)
+DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP)
+DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW)
+DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP)
+DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD)
+DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP)
+DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW)
+DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP)
DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL)
-DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD)
-DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP)
DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI)
DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI)
DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW)
DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP)
DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV)
-DECLARE_INSN(c_or3, MATCH_C_OR3, MASK_C_OR3)
-DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD)
-DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP)
DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI)
-DECLARE_INSN(c_slliw, MATCH_C_SLLIW, MASK_C_SLLIW)
-DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI)
-DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI)
-DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB)
-DECLARE_INSN(c_sub3, MATCH_C_SUB3, MASK_C_SUB3)
DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW)
DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP)
DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
require_extension('C');
-require(insn.rvc_rs2() != 0);
-if (insn.rvc_rd() == 0) { // c.ebreak
- throw trap_breakpoint();
+if (insn.rvc_rs2() == 0) {
+ if (insn.rvc_rs1() == 0) { // c.ebreak
+ throw trap_breakpoint();
+ } else { // c.jalr
+ reg_t tmp = npc;
+ set_pc(RVC_RS1 & ~reg_t(1));
+ WRITE_REG(X_RA, tmp);
+ }
} else {
WRITE_RD(sext_xlen(RVC_RS1 + RVC_RS2));
}
+++ /dev/null
-require_extension('C');
-WRITE_RVC_RDS(sext_xlen(RVC_RS1S + RVC_RS2S));
require_extension('C');
-if (insn.rvc_rd() == 0) { // c.addi16sp
- WRITE_REG(X_SP, sext_xlen(RVC_SP + insn.rvc_addi16sp_imm()));
-} else {
- require(insn.rvc_imm() != 0);
- WRITE_RD(sext_xlen(RVC_RS1 + insn.rvc_imm()));
-}
+WRITE_RD(sext_xlen(RVC_RS1 + insn.rvc_imm()));
require_extension('C');
-if (xlen == 32) {
- WRITE_RD(RVC_RS1 & insn.rvc_imm()); // c.andi
-} else {
- require(insn.rvc_rd() != 0);
- WRITE_RD(sext32(RVC_RS1 + insn.rvc_imm()));
-}
+WRITE_RD(sext32(RVC_RS1 + insn.rvc_imm()));
require_extension('C');
require_rv64;
-require(insn.rvc_rd() != 0 && insn.rvc_rs2() != 0);
WRITE_RD(sext32(RVC_RS1 + RVC_RS2));
+++ /dev/null
-require_extension('C');
-WRITE_RVC_RDS(RVC_RS1S & RVC_RS2S);
--- /dev/null
+require_extension('C');
+require_extension('D');
+require_fp;
+WRITE_RVC_FRS2S(MMU.load_int64(RVC_RS1S + insn.rvc_ld_imm()));
--- /dev/null
+require_extension('C');
+require_extension('D');
+require_fp;
+WRITE_FRD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm()));
--- /dev/null
+require_extension('C');
+if (xlen == 32) {
+ require_extension('F');
+ require_fp;
+ WRITE_RVC_FRS2S(MMU.load_int32(RVC_RS1S + insn.rvc_lw_imm()));
+} else {
+ WRITE_RVC_RS2S(MMU.load_int64(RVC_RS1S + insn.rvc_ld_imm()));
+}
--- /dev/null
+require_extension('C');
+if (xlen == 32) {
+ require_extension('F');
+ require_fp;
+ WRITE_FRD(MMU.load_int32(RVC_SP + insn.rvc_lwsp_imm()));
+} else {
+ require(insn.rvc_rd() != 0);
+ WRITE_RD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm()));
+}
--- /dev/null
+require_extension('C');
+require_extension('D');
+require_fp;
+MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_FRS2S);
--- /dev/null
+require_extension('C');
+require_extension('D');
+require_fp;
+MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_FRS2);
--- /dev/null
+require_extension('C');
+if (xlen == 32) {
+ require_extension('F');
+ require_fp;
+ MMU.store_uint32(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S);
+} else {
+ MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S);
+}
--- /dev/null
+require_extension('C');
+if (xlen == 32) {
+ require_extension('F');
+ require_fp;
+ MMU.store_uint32(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2);
+} else {
+ MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2);
+}
+++ /dev/null
-require_extension('C');
-require_rv64;
-WRITE_RVC_RS2S(MMU.load_int64(RVC_RS1S + insn.rvc_ld_imm()));
+++ /dev/null
-require_extension('C');
-if (xlen == 32) {
- if (sreg_t(RVC_RS1S) >= 0) // c.bgez
- set_pc(pc + insn.rvc_b_imm());
-} else {
- require(insn.rvc_rd() != 0);
- WRITE_RD(MMU.load_int64(RVC_SP + insn.rvc_ldsp_imm()));
-}
require_extension('C');
require(insn.rvc_rd() != 0);
-if (insn.rvc_imm() == 0) { // c.jr
- set_pc(RVC_RS1 & ~reg_t(1));
-} else {
- WRITE_RD(insn.rvc_imm());
-}
+WRITE_RD(insn.rvc_imm());
require_extension('C');
-require(insn.rvc_rd() != 0);
-if (insn.rvc_imm() == 0) { // c.jalr
- reg_t tmp = npc;
- set_pc(RVC_RS1 & ~reg_t(1));
- WRITE_REG(X_RA, tmp);
+if (insn.rvc_rd() == 0) { // c.addi16sp
+ WRITE_REG(X_SP, sext_xlen(RVC_SP + insn.rvc_addi16sp_imm()));
} else {
WRITE_RD(insn.rvc_imm() << 12);
}
require_extension('C');
-require(insn.rvc_rd() != 0);
-WRITE_RD(RVC_RS2);
+if (insn.rvc_rs2() == 0) {
+ require(insn.rvc_rd() != 0);
+ set_pc(RVC_RS1 & ~reg_t(1));
+} else {
+ WRITE_RD(RVC_RS2);
+}
+++ /dev/null
-require_extension('C');
-WRITE_RVC_RDS(RVC_RS1S | RVC_RS2S);
+++ /dev/null
-require_extension('C');
-if (xlen == 32) {
- int32_t res;
- switch ((insn.bits() >> 10) & 7) {
- case 0:
- switch ((insn.bits() >> 5) & 3) {
- case 0: res = RVC_RS1S ^ RVC_RS2S; // c.xor
- case 1: res = int32_t(RVC_RS1S) >> (RVC_RS2S & 0x1f); // c.sra
- default: require(0);
- }
- WRITE_RVC_RS1S(res);
- break;
-
- case 1:
- switch ((insn.bits() >> 5) & 3) {
- case 0: res = RVC_RS1S << (RVC_RS2S & 0x1f); // c.sll
- case 1: res = uint32_t(RVC_RS1S) >> (RVC_RS2S & 0x1f); // c.srl
- case 2: res = int32_t(RVC_RS1S) < int32_t(RVC_RS2S); // c.slt
- case 3: res = uint32_t(RVC_RS1S) < uint32_t(RVC_RS2S); // c.sltu
- }
- WRITE_RVC_RS1S(res);
- break;
-
- case 3:
- switch ((insn.bits() >> 5) & 3) {
- case 0: res = RVC_RS1S << (RVC_RS2S & 0x1f); // c.sllr
- case 1: res = uint32_t(RVC_RS1S) >> (RVC_RS2S & 0x1f); // c.srlr
- case 2: res = int32_t(RVC_RS1S) < int32_t(RVC_RS2S); // c.sltr
- case 3: res = uint32_t(RVC_RS1S) < uint32_t(RVC_RS2S); // c.sltur
- }
- WRITE_RVC_RS2S(res);
- break;
-
- default: require(0);
- }
-} else {
- MMU.store_uint64(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S);
-}
+++ /dev/null
-require_extension('C');
-if (xlen == 32) {
- if (sreg_t(RVC_RS1S) < 0) // c.bltz
- set_pc(pc + insn.rvc_b_imm());
-} else {
- MMU.store_uint64(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2);
-}
+++ /dev/null
-require_extension('C');
-if (xlen == 32) {
- switch ((insn.bits() >> 5) & 3) {
- case 0: WRITE_RVC_RS2S(sext_xlen(RVC_RS1S + insn.rvc_simm3())); // c.addin
- case 1: WRITE_RVC_RS2S(sext_xlen(RVC_RS1S ^ insn.rvc_simm3())); // c.xorin
- case 2: WRITE_RVC_RS2S(sext_xlen(RVC_RS1S | insn.rvc_simm3())); // c.orin
- case 3: WRITE_RVC_RS2S(sext_xlen(RVC_RS1S & insn.rvc_simm3())); // c.andin
- }
-} else {
- require(insn.rvc_rd() != 0);
- require(insn.rvc_imm() < 32);
- WRITE_RD(sext32(RVC_RS1 << insn.rvc_imm()));
-}
+++ /dev/null
-require_extension('C');
-require(insn.rvc_imm() < xlen);
-WRITE_RD(sext_xlen(sext_xlen(RVC_RS1) >> insn.rvc_imm()));
+++ /dev/null
-require_extension('C');
-require(insn.rvc_imm() < xlen);
-WRITE_RD(sext_xlen(zext_xlen(RVC_RS1) >> insn.rvc_imm()));
+++ /dev/null
-require_extension('C');
-require(insn.rvc_rd() != 0 && insn.rvc_rs2() != 0);
-WRITE_RD(sext_xlen(RVC_RS1 - RVC_RS2));
+++ /dev/null
-require_extension('C');
-WRITE_RVC_RDS(sext_xlen(RVC_RS1S - RVC_RS2S));
}
} rvc_rs2s;
-struct : public arg_t {
- std::string to_string(insn_t insn) const {
- return xpr_name[insn.rvc_rds()];
- }
-} rvc_rds;
-
struct : public arg_t {
std::string to_string(insn_t insn) const {
return xpr_name[X_SP];
DISASM_INSN("add", c_add, 0, {&xrd, &xrd, &rvc_rs1});
DISASM_INSN("addw", c_addw, 0, {&xrd, &xrd, &rvc_rs1});
DISASM_INSN("lw", c_lwsp, 0, {&xrd, &rvc_lwsp_address});
- DISASM_INSN("ld", c_ldsp, 0, {&xrd, &rvc_ldsp_address});
+ DISASM_INSN("flw", c_flwsp, 0, {&xrd, &rvc_lwsp_address});
DISASM_INSN("sw", c_swsp, 0, {&rvc_rs2, &rvc_swsp_address});
- DISASM_INSN("sd", c_sdsp, 0, {&rvc_rs2, &rvc_sdsp_address});
+ DISASM_INSN("fsw", c_fswsp, 0, {&rvc_rs2, &rvc_swsp_address});
DISASM_INSN("lw", c_lw, 0, {&rvc_rs2s, &rvc_lw_address});
- DISASM_INSN("ld", c_ld, 0, {&rvc_rs2s, &rvc_ld_address});
+ DISASM_INSN("flw", c_flw, 0, {&rvc_rs2s, &rvc_lw_address});
DISASM_INSN("sw", c_sw, 0, {&rvc_rs2s, &rvc_lw_address});
- DISASM_INSN("sd", c_sd, 0, {&rvc_rs2s, &rvc_ld_address});
+ DISASM_INSN("fsw", c_fsw, 0, {&rvc_rs2s, &rvc_lw_address});
DISASM_INSN("beqz", c_beqz, 0, {&rvc_rs1s, &rvc_branch_target});
DISASM_INSN("bnez", c_bnez, 0, {&rvc_rs1s, &rvc_branch_target});
DISASM_INSN("j", c_j, 0, {&rvc_jump_target});