@@ -158,6 +158,13 @@ typedef enum {
rv_codec_css_sqsp,
rv_codec_k_bs,
rv_codec_k_rnum,
+ rv_codec_zcb_ext,
+ rv_codec_zcb_mul,
+ rv_codec_zcb_lb,
+ rv_codec_zcb_lh,
+ rv_codec_zcmp_cm_pushpop,
+ rv_codec_zcmp_cm_mv,
+ rv_codec_zcmt_jt,
} rv_codec;
typedef enum {
@@ -560,6 +567,26 @@ typedef enum {
rv_op_zip = 396,
rv_op_xperm4 = 397,
rv_op_xperm8 = 398,
+ rv_op_c_zext_b = 399,
+ rv_op_c_sext_b = 400,
+ rv_op_c_zext_h = 401,
+ rv_op_c_sext_h = 402,
+ rv_op_c_zext_w = 403,
+ rv_op_c_not = 404,
+ rv_op_c_mul = 405,
+ rv_op_c_lbu = 406,
+ rv_op_c_lhu = 407,
+ rv_op_c_lh = 408,
+ rv_op_c_sb = 409,
+ rv_op_c_sh = 410,
+ rv_op_cm_push = 411,
+ rv_op_cm_pop = 412,
+ rv_op_cm_popret = 413,
+ rv_op_cm_popretz = 414,
+ rv_op_cm_mva01s = 415,
+ rv_op_cm_mvsa01 = 416,
+ rv_op_cm_jt = 417,
+ rv_op_cm_jalt = 418,
} rv_op;
/* structures */
@@ -581,6 +608,7 @@ typedef struct {
uint8_t rl;
uint8_t bs;
uint8_t rnum;
+ uint8_t rlist;
} rv_decode;
typedef struct {
@@ -658,6 +686,10 @@ static const char rv_freg_name_sym[32][5] = {
#define rv_fmt_rs2_offset "O\t2,o"
#define rv_fmt_rs1_rs2_bs "O\t1,2,b"
#define rv_fmt_rd_rs1_rnum "O\t0,1,n"
+#define rv_fmt_rs1_rs2_zce_ldst "O\t2,i(1)"
+#define rv_fmt_push_rlist "O\tl,-i"
+#define rv_fmt_pop_rlist "O\tl,i"
+#define rv_fmt_zcmt_index "O\ti"
/* pseudo-instruction constraints */
@@ -1283,7 +1315,27 @@ const rv_opcode_data opcode_data[] = {
{ "unzip", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "zip", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
{ "xperm4", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
- { "xperm8", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }
+ { "xperm8", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
+ { "c.zext.b", rv_codec_zcb_ext, rv_fmt_rd, NULL, 0 },
+ { "c.sext.b", rv_codec_zcb_ext, rv_fmt_rd, NULL, 0 },
+ { "c.zext.h", rv_codec_zcb_ext, rv_fmt_rd, NULL, 0 },
+ { "c.sext.h", rv_codec_zcb_ext, rv_fmt_rd, NULL, 0 },
+ { "c.zext.w", rv_codec_zcb_ext, rv_fmt_rd, NULL, 0 },
+ { "c.not", rv_codec_zcb_ext, rv_fmt_rd, NULL, 0 },
+ { "c.mul", rv_codec_zcb_mul, rv_fmt_rd_rs2, NULL, 0, 0 },
+ { "c.lbu", rv_codec_zcb_lb, rv_fmt_rs1_rs2_zce_ldst, NULL, 0, 0, 0 },
+ { "c.lhu", rv_codec_zcb_lh, rv_fmt_rs1_rs2_zce_ldst, NULL, 0, 0, 0 },
+ { "c.lh", rv_codec_zcb_lh, rv_fmt_rs1_rs2_zce_ldst, NULL, 0, 0, 0 },
+ { "c.sb", rv_codec_zcb_lb, rv_fmt_rs1_rs2_zce_ldst, NULL, 0, 0, 0 },
+ { "c.sh", rv_codec_zcb_lh, rv_fmt_rs1_rs2_zce_ldst, NULL, 0, 0, 0 },
+ { "cm.push", rv_codec_zcmp_cm_pushpop, rv_fmt_push_rlist, NULL, 0, 0 },
+ { "cm.pop", rv_codec_zcmp_cm_pushpop, rv_fmt_pop_rlist, NULL, 0, 0 },
+ { "cm.popret", rv_codec_zcmp_cm_pushpop, rv_fmt_pop_rlist, NULL, 0, 0, 0 },
+ { "cm.popretz", rv_codec_zcmp_cm_pushpop, rv_fmt_pop_rlist, NULL, 0, 0 },
+ { "cm.mva01s", rv_codec_zcmp_cm_mv, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
+ { "cm.mvsa01", rv_codec_zcmp_cm_mv, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
+ { "cm.jt", rv_codec_zcmt_jt, rv_fmt_zcmt_index, NULL, 0 },
+ { "cm.jalt", rv_codec_zcmt_jt, rv_fmt_zcmt_index, NULL, 0 },
};
/* CSR names */
@@ -1298,6 +1350,7 @@ static const char *csr_name(int csrno)
case 0x0004: return "uie";
case 0x0005: return "utvec";
case 0x0015: return "seed";
+ case 0x0017: return "jvt";
case 0x0040: return "uscratch";
case 0x0041: return "uepc";
case 0x0042: return "ucause";
@@ -1517,6 +1570,24 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
op = rv_op_c_ld;
}
break;
+ case 4:
+ switch ((inst >> 10) & 0b111) {
+ case 0: op = rv_op_c_lbu; break;
+ case 1:
+ if (((inst >> 6) & 1) == 0) {
+ op = rv_op_c_lhu;
+ } else {
+ op = rv_op_c_lh;
+ }
+ break;
+ case 2: op = rv_op_c_sb; break;
+ case 3:
+ if (((inst >> 6) & 1) == 0) {
+ op = rv_op_c_sh;
+ }
+ break;
+ }
+ break;
case 5:
if (isa == rv128) {
op = rv_op_c_sq;
@@ -1573,6 +1644,17 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
case 3: op = rv_op_c_and; break;
case 4: op = rv_op_c_subw; break;
case 5: op = rv_op_c_addw; break;
+ case 6: op = rv_op_c_mul; break;
+ case 7:
+ switch ((inst >> 2) & 0b111) {
+ case 0: op = rv_op_c_zext_b; break;
+ case 1: op = rv_op_c_sext_b; break;
+ case 2: op = rv_op_c_zext_h; break;
+ case 3: op = rv_op_c_sext_h; break;
+ case 4: op = rv_op_c_zext_w; break;
+ case 5: op = rv_op_c_not; break;
+ }
+ break;
}
break;
}
@@ -1628,6 +1710,30 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
op = rv_op_c_sqsp;
} else {
op = rv_op_c_fsdsp;
+ if (((inst >> 12) & 0b01)) {
+ switch ((inst >> 8) & 0b01111) {
+ case 8: op = rv_op_cm_push; break;
+ case 10: op = rv_op_cm_pop; break;
+ case 12: op = rv_op_cm_popretz; break;
+ case 14: op = rv_op_cm_popret; break;
+ }
+ } else {
+ switch ((inst >> 10) & 0b011) {
+ case 0:
+ if (((inst >> 2) & 0xFF) >= 32) {
+ op = rv_op_cm_jalt;
+ } else {
+ op = rv_op_cm_jt;
+ }
+ break;
+ case 3:
+ switch ((inst >> 5) & 0b011) {
+ case 1: op = rv_op_cm_mvsa01; break;
+ case 3: op = rv_op_cm_mva01s; break;
+ }
+ break;
+ }
+ }
}
break;
case 6: op = rv_op_c_swsp; break;
@@ -2338,6 +2444,21 @@ static uint32_t operand_crs2q(rv_inst inst)
return (inst << 59) >> 61;
}
+static uint32_t calculate_xreg(uint32_t sreg)
+{
+ return sreg < 2 ? sreg + 8 : sreg + 16;
+}
+
+static uint32_t operand_sreg1(rv_inst inst)
+{
+ return calculate_xreg((inst << 54) >> 61);
+}
+
+static uint32_t operand_sreg2(rv_inst inst)
+{
+ return calculate_xreg((inst << 59) >> 61);
+}
+
static uint32_t operand_crd(rv_inst inst)
{
return (inst << 52) >> 59;
@@ -2540,6 +2661,97 @@ static uint32_t operand_rnum(rv_inst inst)
return (inst << 40) >> 60;
}
+static uint32_t operand_uimm_c_lb(rv_inst inst)
+{
+ return (((inst << 58) >> 63) << 1) |
+ ((inst << 57) >> 63);
+}
+
+static uint32_t operand_uimm_c_lh(rv_inst inst)
+{
+ return (((inst << 58) >> 63) << 1);
+}
+
+static uint32_t operand_zcmp_spimm(rv_inst inst)
+{
+ return ((inst << 60) >> 62) << 4;
+}
+
+static uint32_t operand_zcmp_rlist(rv_inst inst)
+{
+ return ((inst << 56) >> 60);
+}
+
+static uint32_t calculate_stack_adj(rv_isa isa, uint32_t rlist, uint32_t spimm)
+{
+ uint32_t stack_adj_base = 0;
+ if (isa == rv64) {
+ switch (rlist) {
+ case 15:
+ stack_adj_base = 112;
+ break;
+ case 14:
+ stack_adj_base = 96;
+ break;
+ case 13:
+ case 12:
+ stack_adj_base = 80;
+ break;
+ case 11:
+ case 10:
+ stack_adj_base = 64;
+ break;
+ case 9:
+ case 8:
+ stack_adj_base = 48;
+ break;
+ case 7:
+ case 6:
+ stack_adj_base = 32;
+ break;
+ case 5:
+ case 4:
+ stack_adj_base = 16;
+ break;
+ }
+ } else {
+ switch (rlist) {
+ case 15:
+ stack_adj_base = 64;
+ break;
+ case 14:
+ case 13:
+ case 12:
+ stack_adj_base = 48;
+ break;
+ case 11:
+ case 10:
+ case 9:
+ case 8:
+ stack_adj_base = 32;
+ break;
+ case 7:
+ case 6:
+ case 5:
+ case 4:
+ stack_adj_base = 16;
+ break;
+ }
+ }
+ return stack_adj_base + spimm;
+}
+
+static uint32_t operand_zcmp_stack_adj(rv_inst inst, rv_isa isa)
+{
+ return calculate_stack_adj(isa, operand_zcmp_rlist(inst),
+ operand_zcmp_spimm(inst));
+}
+
+static uint32_t operand_tbl_index(rv_inst inst)
+{
+ return ((inst << 54) >> 56);
+}
+
/* decode operands */
static void decode_inst_operands(rv_decode *dec, rv_isa isa)
@@ -2829,6 +3041,34 @@ static void decode_inst_operands(rv_decode *dec, rv_isa isa)
dec->rs1 = operand_rs1(inst);
dec->rnum = operand_rnum(inst);
break;
+ case rv_codec_zcb_lb:
+ dec->rs1 = operand_crs1q(inst) + 8;
+ dec->rs2 = operand_crs2q(inst) + 8;
+ dec->imm = operand_uimm_c_lb(inst);
+ break;
+ case rv_codec_zcb_lh:
+ dec->rs1 = operand_crs1q(inst) + 8;
+ dec->rs2 = operand_crs2q(inst) + 8;
+ dec->imm = operand_uimm_c_lh(inst);
+ break;
+ case rv_codec_zcb_ext:
+ dec->rd = operand_crs1q(inst) + 8;
+ break;
+ case rv_codec_zcb_mul:
+ dec->rd = operand_crs1rdq(inst) + 8;
+ dec->rs2 = operand_crs2q(inst) + 8;
+ break;
+ case rv_codec_zcmp_cm_pushpop:
+ dec->imm = operand_zcmp_stack_adj(inst, isa);
+ dec->rlist = operand_zcmp_rlist(inst);
+ break;
+ case rv_codec_zcmp_cm_mv:
+ dec->rd = operand_sreg1(inst);
+ dec->rs2 = operand_sreg2(inst);
+ break;
+ case rv_codec_zcmt_jt:
+ dec->imm = operand_tbl_index(inst);
+ break;
};
}
@@ -2988,6 +3228,9 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
case ')':
append(buf, ")", buflen);
break;
+ case '-':
+ append(buf, "-", buflen);
+ break;
case 'b':
snprintf(tmp, sizeof(tmp), "%d", dec->bs);
append(buf, tmp, buflen);
@@ -3113,6 +3356,48 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
append(buf, ".rl", buflen);
}
break;
+ case 'l': {
+ switch(dec->rlist) {
+ case 4:
+ snprintf(tmp, sizeof(tmp), "{ra}");
+ break;
+ case 5:
+ snprintf(tmp, sizeof(tmp), "{ra, s0}");
+ break;
+ case 6:
+ snprintf(tmp, sizeof(tmp), "{ra, s0-s1}");
+ break;
+ case 7:
+ snprintf(tmp, sizeof(tmp), "{ra, s0-s2}");
+ break;
+ case 8:
+ snprintf(tmp, sizeof(tmp), "{ra, s0-s3}");
+ break;
+ case 9:
+ snprintf(tmp, sizeof(tmp), "{ra, s0-s4}");
+ break;
+ case 10:
+ snprintf(tmp, sizeof(tmp), "{ra, s0-s5}");
+ break;
+ case 11:
+ snprintf(tmp, sizeof(tmp), "{ra, s0-s6}");
+ break;
+ case 12:
+ snprintf(tmp, sizeof(tmp), "{ra, s0-s7}");
+ break;
+ case 13:
+ snprintf(tmp, sizeof(tmp), "{ra, s0-s8}");
+ break;
+ case 14:
+ snprintf(tmp, sizeof(tmp), "{ra, s0-s9}");
+ break;
+ case 15:
+ snprintf(tmp, sizeof(tmp), "{ra, s0-s11}");
+ break;
+ }
+ append(buf, tmp, buflen);
+ break;
+ }
default:
break;
}