Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ Spike supports the following RISC-V ISA features:
- CMO extension, v1.0
- Debug v0.14
- Smepmp extension v1.0
- Zca extension, v1.0
- Zcb extension, v1.0
- Zcf extension, v1.0
- Zcd extension, v1.0
- Zcmp extension, v1.0

As a Spike extension, the remainder of the proposed
[Bit-Manipulation Extensions](https://github.com/riscv/riscv-bitmanip)
Expand Down
121 changes: 112 additions & 9 deletions disasm/disasm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ struct : public arg_t {
}
} load_address;

struct : public arg_t {
std::string to_string(insn_t insn) const {
return std::to_string((int)insn.rvc_lbimm()) + '(' + xpr_name[insn.rvc_rs1s()] + ')';
}
} rvb_b_address;

struct : public arg_t {
std::string to_string(insn_t insn) const {
return std::to_string((int)insn.rvc_lhimm()) + '(' + xpr_name[insn.rvc_rs1s()] + ')';
}
} rvb_h_address;

struct : public arg_t {
std::string to_string(insn_t insn) const {
return std::to_string((int)insn.s_imm()) + '(' + xpr_name[insn.rs1()] + ')';
Expand All @@ -45,6 +57,52 @@ struct : public arg_t {
}
} xrs1;

struct : public arg_t {
std::string to_string(insn_t insn) const {
return std::to_string((uint32_t)insn.rvc_index());
}
} rvcm_jt_index;

struct : public arg_t {
std::string to_string(insn_t insn) const {
int rlist = insn.rvc_rlist();
if (rlist >= 4) {
switch(rlist) {
case 4: return "{ra}";
case 5: return "{ra, s0}";
case 15: return "{ra, s0-s11}";
default: return "{ra, s0-s" + std::to_string(rlist - 5)+'}';
}
} else {
return "unsupport rlist";
}
}
} rvcm_pushpop_rlist;

struct : public arg_t {
std::string to_string(insn_t insn) const {
return '-' + std::to_string(insn.zcmp_stack_adjustment(32));
}
} rvcm_push_stack_adj_32;

struct : public arg_t {
std::string to_string(insn_t insn) const {
return '-' + std::to_string(insn.zcmp_stack_adjustment(64));
}
} rvcm_push_stack_adj_64;

struct : public arg_t {
std::string to_string(insn_t insn) const {
return std::to_string(insn.zcmp_stack_adjustment(32));
}
} rvcm_pop_stack_adj_32;

struct : public arg_t {
std::string to_string(insn_t insn) const {
return std::to_string(insn.zcmp_stack_adjustment(64));
}
} rvcm_pop_stack_adj_64;

struct : public arg_t {
std::string to_string(insn_t insn) const {
return xpr_name[insn.rs2()];
Expand Down Expand Up @@ -1193,7 +1251,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
}

// ext-c
if (isa->extension_enabled('C')) {
if (isa->extension_enabled(EXT_ZCA)) {
DISASM_INSN("c.ebreak", c_add, mask_rd | mask_rvc_rs2, {});
add_insn(new disasm_insn_t("ret", match_c_jr | match_rd_ra, mask_c_jr | mask_rd | mask_rvc_imm, {}));
DISASM_INSN("c.jr", c_jr, mask_rvc_imm, {&rvc_rs1});
Expand All @@ -1217,21 +1275,13 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
DISASM_INSN("c.or", c_or, 0, {&rvc_rs1s, &rvc_rs2s});
DISASM_INSN("c.xor", c_xor, 0, {&rvc_rs1s, &rvc_rs2s});
DISASM_INSN("c.lwsp", c_lwsp, 0, {&xrd, &rvc_lwsp_address});
DISASM_INSN("c.fld", c_fld, 0, {&rvc_fp_rs2s, &rvc_ld_address});
DISASM_INSN("c.swsp", c_swsp, 0, {&rvc_rs2, &rvc_swsp_address});
DISASM_INSN("c.lw", c_lw, 0, {&rvc_rs2s, &rvc_lw_address});
DISASM_INSN("c.sw", c_sw, 0, {&rvc_rs2s, &rvc_lw_address});
DISASM_INSN("c.beqz", c_beqz, 0, {&rvc_rs1s, &rvc_branch_target});
DISASM_INSN("c.bnez", c_bnez, 0, {&rvc_rs1s, &rvc_branch_target});
DISASM_INSN("c.j", c_j, 0, {&rvc_jump_target});
DISASM_INSN("c.fldsp", c_fldsp, 0, {&frd, &rvc_ldsp_address});
DISASM_INSN("c.fsd", c_fsd, 0, {&rvc_fp_rs2s, &rvc_ld_address});
DISASM_INSN("c.fsdsp", c_fsdsp, 0, {&rvc_fp_rs2, &rvc_sdsp_address});
if (isa->get_max_xlen() == 32) {
DISASM_INSN("c.flw", c_flw, 0, {&rvc_fp_rs2s, &rvc_lw_address});
DISASM_INSN("c.flwsp", c_flwsp, 0, {&frd, &rvc_lwsp_address});
DISASM_INSN("c.fsw", c_fsw, 0, {&rvc_fp_rs2s, &rvc_lw_address});
DISASM_INSN("c.fswsp", c_fswsp, 0, {&rvc_fp_rs2, &rvc_swsp_address});
DISASM_INSN("c.jal", c_jal, 0, {&rvc_jump_target});
} else {
DISASM_INSN("c.ld", c_ld, 0, {&rvc_rs2s, &rvc_ld_address});
Expand All @@ -1242,6 +1292,59 @@ void disassembler_t::add_instructions(const isa_parser_t* isa)
}
}

if (isa->extension_enabled(EXT_ZCD) && isa->extension_enabled('D')) {
DISASM_INSN("c.fld", c_fld, 0, {&rvc_fp_rs2s, &rvc_ld_address});
DISASM_INSN("c.fldsp", c_fldsp, 0, {&frd, &rvc_ldsp_address});
DISASM_INSN("c.fsd", c_fsd, 0, {&rvc_fp_rs2s, &rvc_ld_address});
DISASM_INSN("c.fsdsp", c_fsdsp, 0, {&rvc_fp_rs2, &rvc_sdsp_address});
}

if (isa->extension_enabled(EXT_ZCF) && isa->extension_enabled('F')) {
DISASM_INSN("c.flw", c_flw, 0, {&rvc_fp_rs2s, &rvc_lw_address});
DISASM_INSN("c.flwsp", c_flwsp, 0, {&frd, &rvc_lwsp_address});
DISASM_INSN("c.fsw", c_fsw, 0, {&rvc_fp_rs2s, &rvc_lw_address});
DISASM_INSN("c.fswsp", c_fswsp, 0, {&rvc_fp_rs2, &rvc_swsp_address});
}

if (isa->extension_enabled(EXT_ZCB)) {
DISASM_INSN("c.zext.b", c_zext_b, 0, {&rvc_rs1s});
DISASM_INSN("c.sext.b", c_sext_b, 0, {&rvc_rs1s});
DISASM_INSN("c.zext.h", c_zext_h, 0, {&rvc_rs1s});
DISASM_INSN("c.sext.h", c_sext_h, 0, {&rvc_rs1s});
if (isa->get_max_xlen() == 64) {
DISASM_INSN("c.zext.w", c_zext_w, 0, {&rvc_rs1s});
}
DISASM_INSN("c.not", c_not, 0, {&rvc_rs1s});
DISASM_INSN("c.mul", c_mul, 0, {&rvc_rs1s, &rvc_rs2s});
DISASM_INSN("c.lbu", c_lbu, 0, {&rvc_rs2s, &rvb_b_address});
DISASM_INSN("c.lhu", c_lhu, 0, {&rvc_rs2s, &rvb_h_address});
DISASM_INSN("c.lh", c_lh, 0, {&rvc_rs2s, &rvb_h_address});
DISASM_INSN("c.sb", c_sb, 0, {&rvc_rs2s, &rvb_b_address});
DISASM_INSN("c.sh", c_sh, 0, {&rvc_rs2s, &rvb_h_address});
}

if (isa->extension_enabled(EXT_ZCMP)) {
if (isa->get_max_xlen() == 32) {
DISASM_INSN("cm.push", cm_push, 0, {&rvcm_pushpop_rlist, &rvcm_push_stack_adj_32});
DISASM_INSN("cm.pop", cm_pop, 0, {&rvcm_pushpop_rlist, &rvcm_pop_stack_adj_32});
DISASM_INSN("cm.popret", cm_popret, 0, {&rvcm_pushpop_rlist, &rvcm_pop_stack_adj_32});
DISASM_INSN("cm.popretz", cm_popretz, 0, {&rvcm_pushpop_rlist, &rvcm_pop_stack_adj_32});
} else {
DISASM_INSN("cm.push", cm_push, 0, {&rvcm_pushpop_rlist, &rvcm_push_stack_adj_64});
DISASM_INSN("cm.pop", cm_pop, 0, {&rvcm_pushpop_rlist, &rvcm_pop_stack_adj_64});
DISASM_INSN("cm.popret", cm_popret, 0, {&rvcm_pushpop_rlist, &rvcm_pop_stack_adj_64});
DISASM_INSN("cm.popretz", cm_popretz, 0, {&rvcm_pushpop_rlist, &rvcm_pop_stack_adj_64});
}

DISASM_INSN("cm.mva01s", cm_mva01s, 0, {&rvc_rs1s, &rvc_rs2s});
DISASM_INSN("cm.mvsa01", cm_mvsa01, 0, {&rvc_rs1s, &rvc_rs2s});
}

if (isa->extension_enabled(EXT_ZCMT)) {
DISASM_INSN("cm.jt", cm_jalt, 0x380, {&rvcm_jt_index});
DISASM_INSN("cm.jalt", cm_jalt, 0, {&rvcm_jt_index});
}

if (isa->extension_enabled('V')) {
DISASM_INSN("vsetivli", vsetivli, 0, {&xrd, &zimm5, &v_vtype});
DISASM_INSN("vsetvli", vsetvli, 0, {&xrd, &xrs1, &v_vtype});
Expand Down
82 changes: 81 additions & 1 deletion riscv/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ const int NCSR = 4096;

#define X_RA 1
#define X_SP 2
#define X_S0 8
#define X_A0 10
#define X_A1 11
#define X_Sn 16

#define VCSR_VXRM_SHIFT 1
#define VCSR_VXRM (0x3 << VCSR_VXRM_SHIFT)
Expand Down Expand Up @@ -74,6 +78,8 @@ const int NCSR = 4096;
#define MAX_INSN_LENGTH 8
#define PC_ALIGN 2

#define Sn(n) ((n) < 2 ? X_S0 + (n) : X_Sn + (n))

typedef uint64_t insn_bits_t;
class insn_t
{
Expand Down Expand Up @@ -117,6 +123,16 @@ class insn_t
uint64_t rvc_rs1s() { return 8 + x(7, 3); }
uint64_t rvc_rs2s() { return 8 + x(2, 3); }

uint64_t rvc_lbimm() { return (x(5, 1) << 1) + x(6, 1); }
uint64_t rvc_lhimm() { return (x(5, 1) << 1); }

uint64_t rvc_sreg1() { return x(7, 3); }
uint64_t rvc_sreg2() { return x(2, 3); }
uint64_t rvc_rlist() { return x(4, 4); }
uint64_t rvc_spimm() { return x(2, 2) << 4; }

uint64_t rvc_index() { return x(2, 8); }

uint64_t v_vm() { return x(25, 1); }
uint64_t v_wd() { return x(26, 1); }
uint64_t v_nf() { return x(29, 3); }
Expand All @@ -141,6 +157,53 @@ class insn_t
uint64_t p_imm5() { return x(20, 5); }
uint64_t p_imm6() { return x(20, 6); }

uint64_t zcmp_regmask() {
unsigned mask = 0;
uint64_t rlist = rvc_rlist();

if (rlist >= 4)
mask |= 1U << X_RA;

for (uint i = 5; i <= rlist; i++)
mask |= 1U << Sn(i - 5);

if (rlist == 15)
mask |= 1U << Sn(11);

return mask;
}

uint64_t zcmp_stack_adjustment(int xlen) {
reg_t stack_adj_base = 0;
switch (rvc_rlist()) {
case 15:
stack_adj_base += 16;
case 14:
if (xlen == 64)
stack_adj_base += 16;
case 13:
case 12:
stack_adj_base += 16;
case 11:
case 10:
if (xlen == 64)
stack_adj_base += 16;
case 9:
case 8:
stack_adj_base += 16;
case 7:
case 6:
if (xlen == 64)
stack_adj_base += 16;
case 5:
case 4:
stack_adj_base += 16;
break;
}

return stack_adj_base + rvc_spimm();
}

private:
insn_bits_t b;
uint64_t x(int lo, int len) { return (b >> lo) & ((insn_bits_t(1) << len) - 1); }
Expand Down Expand Up @@ -223,6 +286,12 @@ class regfile_t
#define RVC_FRS2S READ_FREG(insn.rvc_rs2s())
#define RVC_SP READ_REG(X_SP)

// Zc* macros
#define RVC_SREG1 (Sn(insn.rvc_sreg1()))
#define RVC_SREG2 (Sn(insn.rvc_sreg2()))
#define SP READ_REG(X_SP)
#define RA READ_REG(X_RA)

// FPU macros
#define FRS1 READ_FREG(insn.rs1())
#define FRS2 READ_FREG(insn.rs2())
Expand All @@ -232,7 +301,7 @@ class regfile_t
#define dirty_vs_state STATE.sstatus->dirty(SSTATUS_VS)
#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 JUMP_TARGET (pc + insn.uj_imm())
Expand Down Expand Up @@ -290,6 +359,17 @@ class regfile_t
throw trap_virtual_instruction(insn.bits()); \
} while (0);

#define require_zcmp_pushpop \
do { \
require_extension(EXT_ZCMP); \
reg_t rlist = insn.rvc_rlist(); \
require(rlist >= 4); \
\
if (p->extension_enabled('E')) { \
require(rlist <= 6); \
} \
} while (0);

#define set_fp_exceptions ({ if (softfloat_exceptionFlags) { \
STATE.fflags->write(STATE.fflags->read() | softfloat_exceptionFlags); \
} \
Expand Down
Loading