mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
disas/riscv.c: add disasm support for Zc*
Zcmp/Zcmt instructions will override disasm for c.fld*/c.fsd* instructions currently. Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn> Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-Id: <20230307081403.61950-10-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
d364c0ab68
commit
2c71d02e17
1 changed files with 227 additions and 1 deletions
228
disas/riscv.c
228
disas/riscv.c
|
@ -163,6 +163,13 @@ typedef enum {
|
|||
rv_codec_v_i,
|
||||
rv_codec_vsetvli,
|
||||
rv_codec_vsetivli,
|
||||
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 {
|
||||
|
@ -935,6 +942,26 @@ typedef enum {
|
|||
rv_op_vsetvli = 766,
|
||||
rv_op_vsetivli = 767,
|
||||
rv_op_vsetvl = 768,
|
||||
rv_op_c_zext_b = 769,
|
||||
rv_op_c_sext_b = 770,
|
||||
rv_op_c_zext_h = 771,
|
||||
rv_op_c_sext_h = 772,
|
||||
rv_op_c_zext_w = 773,
|
||||
rv_op_c_not = 774,
|
||||
rv_op_c_mul = 775,
|
||||
rv_op_c_lbu = 776,
|
||||
rv_op_c_lhu = 777,
|
||||
rv_op_c_lh = 778,
|
||||
rv_op_c_sb = 779,
|
||||
rv_op_c_sh = 780,
|
||||
rv_op_cm_push = 781,
|
||||
rv_op_cm_pop = 782,
|
||||
rv_op_cm_popret = 783,
|
||||
rv_op_cm_popretz = 784,
|
||||
rv_op_cm_mva01s = 785,
|
||||
rv_op_cm_mvsa01 = 786,
|
||||
rv_op_cm_jt = 787,
|
||||
rv_op_cm_jalt = 788,
|
||||
} rv_op;
|
||||
|
||||
/* structures */
|
||||
|
@ -958,6 +985,7 @@ typedef struct {
|
|||
uint8_t rnum;
|
||||
uint8_t vm;
|
||||
uint32_t vzimm;
|
||||
uint8_t rlist;
|
||||
} rv_decode;
|
||||
|
||||
typedef struct {
|
||||
|
@ -1071,6 +1099,10 @@ static const char rv_vreg_name_sym[32][4] = {
|
|||
#define rv_fmt_vd_vm "O\tDm"
|
||||
#define rv_fmt_vsetvli "O\t0,1,v"
|
||||
#define rv_fmt_vsetivli "O\t0,u,v"
|
||||
#define rv_fmt_rs1_rs2_zce_ldst "O\t2,i(1)"
|
||||
#define rv_fmt_push_rlist "O\tx,-i"
|
||||
#define rv_fmt_pop_rlist "O\tx,i"
|
||||
#define rv_fmt_zcmt_index "O\ti"
|
||||
|
||||
/* pseudo-instruction constraints */
|
||||
|
||||
|
@ -2066,7 +2098,27 @@ const rv_opcode_data opcode_data[] = {
|
|||
{ "vsext.vf8", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, rv_op_vsext_vf8, rv_op_vsext_vf8, 0 },
|
||||
{ "vsetvli", rv_codec_vsetvli, rv_fmt_vsetvli, NULL, rv_op_vsetvli, rv_op_vsetvli, 0 },
|
||||
{ "vsetivli", rv_codec_vsetivli, rv_fmt_vsetivli, NULL, rv_op_vsetivli, rv_op_vsetivli, 0 },
|
||||
{ "vsetvl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, rv_op_vsetvl, rv_op_vsetvl, 0 }
|
||||
{ "vsetvl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, rv_op_vsetvl, rv_op_vsetvl, 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 */
|
||||
|
@ -2085,6 +2137,7 @@ static const char *csr_name(int csrno)
|
|||
case 0x000a: return "vxrm";
|
||||
case 0x000f: return "vcsr";
|
||||
case 0x0015: return "seed";
|
||||
case 0x0017: return "jvt";
|
||||
case 0x0040: return "uscratch";
|
||||
case 0x0041: return "uepc";
|
||||
case 0x0042: return "ucause";
|
||||
|
@ -2307,6 +2360,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;
|
||||
|
@ -2363,6 +2434,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;
|
||||
}
|
||||
|
@ -2418,6 +2500,46 @@ 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:
|
||||
if (((inst >> 4) & 0b01111) >= 4) {
|
||||
op = rv_op_cm_push;
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (((inst >> 4) & 0b01111) >= 4) {
|
||||
op = rv_op_cm_pop;
|
||||
}
|
||||
break;
|
||||
case 12:
|
||||
if (((inst >> 4) & 0b01111) >= 4) {
|
||||
op = rv_op_cm_popretz;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
if (((inst >> 4) & 0b01111) >= 4) {
|
||||
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;
|
||||
|
@ -3662,6 +3784,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;
|
||||
|
@ -3884,6 +4021,46 @@ static uint32_t operand_vm(rv_inst inst)
|
|||
return (inst << 38) >> 63;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int xlen_bytes_log2 = isa == rv64 ? 3 : 2;
|
||||
int regs = rlist == 15 ? 13 : rlist - 3;
|
||||
uint32_t stack_adj_base = ROUND_UP(regs << xlen_bytes_log2, 16);
|
||||
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)
|
||||
|
@ -4200,6 +4377,34 @@ static void decode_inst_operands(rv_decode *dec, rv_isa isa)
|
|||
dec->imm = operand_vimm(inst);
|
||||
dec->vzimm = operand_vzimm10(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;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -4359,6 +4564,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);
|
||||
|
@ -4542,6 +4750,24 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
|
|||
append(buf, vma, buflen);
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
switch (dec->rlist) {
|
||||
case 4:
|
||||
snprintf(tmp, sizeof(tmp), "{ra}");
|
||||
break;
|
||||
case 5:
|
||||
snprintf(tmp, sizeof(tmp), "{ra, s0}");
|
||||
break;
|
||||
case 15:
|
||||
snprintf(tmp, sizeof(tmp), "{ra, s0-s11}");
|
||||
break;
|
||||
default:
|
||||
snprintf(tmp, sizeof(tmp), "{ra, s0-s%d}", dec->rlist - 5);
|
||||
break;
|
||||
}
|
||||
append(buf, tmp, buflen);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue