Skip to content

Commit

Permalink
disas/riscv: Disassemble reserved compressed encodings as illegal
Browse files Browse the repository at this point in the history
Due to the design of the disassembler, the immediate is not
known during decoding of the opcode; so to handle compressed
encodings with reserved immediate values (non-zero), we need
to add an additional check during decompression to match
reserved encodings with zero immediates and translate them
into the illegal instruction.

The following compressed opcodes have reserved encodings with
zero immediates: c.addi4spn, c.addi, c.lui, c.addi16sp, c.srli,
c.srai, c.andi and c.slli

Signed-off-by: Michael Clark <[email protected]>
Signed-off-by: Alistair Francis <[email protected]>
[Palmer: Broke long lines]
Reviewed-by: Palmer Dabbelt <[email protected]>
Signed-off-by: Palmer Dabbelt <[email protected]>
  • Loading branch information
Michael Clark authored and palmer-dabbelt committed Jun 27, 2019
1 parent 28a4df9 commit f88222d
Showing 1 changed file with 45 additions and 17 deletions.
62 changes: 45 additions & 17 deletions disas/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -504,14 +504,19 @@ typedef struct {
const rvc_constraint *constraints;
} rv_comp_data;

enum {
rvcd_imm_nz = 0x1
};

typedef struct {
const char * const name;
const rv_codec codec;
const char * const format;
const rv_comp_data *pseudo;
const int decomp_rv32;
const int decomp_rv64;
const int decomp_rv128;
const short decomp_rv32;
const short decomp_rv64;
const short decomp_rv128;
const short decomp_data;
} rv_opcode_data;

/* register names */
Expand Down Expand Up @@ -1011,22 +1016,29 @@ const rv_opcode_data opcode_data[] = {
{ "fcvt.q.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
{ "fmv.x.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
{ "fmv.q.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 },
{ "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
{ "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi,
rv_op_addi, rv_op_addi, rvcd_imm_nz },
{ "c.fld", rv_codec_cl_ld, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, 0 },
{ "c.lw", rv_codec_cl_lw, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw },
{ "c.flw", rv_codec_cl_lw, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 },
{ "c.fsd", rv_codec_cs_sd, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, rv_op_fsd, 0 },
{ "c.sw", rv_codec_cs_sw, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw },
{ "c.fsw", rv_codec_cs_sw, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 },
{ "c.nop", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
{ "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
{ "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi,
rv_op_addi, rvcd_imm_nz },
{ "c.jal", rv_codec_cj_jal, rv_fmt_rd_offset, NULL, rv_op_jal, 0, 0 },
{ "c.li", rv_codec_ci_li, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
{ "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
{ "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui, rv_op_lui },
{ "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli, rv_op_srli, rv_op_srli },
{ "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai, rv_op_srai, rv_op_srai },
{ "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi, rv_op_andi, rv_op_andi },
{ "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi,
rv_op_addi, rv_op_addi, rvcd_imm_nz },
{ "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui,
rv_op_lui, rvcd_imm_nz },
{ "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli,
rv_op_srli, rv_op_srli, rvcd_imm_nz },
{ "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai,
rv_op_srai, rv_op_srai, rvcd_imm_nz },
{ "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi,
rv_op_andi, rv_op_andi, rvcd_imm_nz },
{ "c.sub", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_sub, rv_op_sub, rv_op_sub },
{ "c.xor", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_xor, rv_op_xor, rv_op_xor },
{ "c.or", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_or, rv_op_or, rv_op_or },
Expand All @@ -1036,7 +1048,8 @@ const rv_opcode_data opcode_data[] = {
{ "c.j", rv_codec_cj, rv_fmt_rd_offset, NULL, rv_op_jal, rv_op_jal, rv_op_jal },
{ "c.beqz", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_beq, rv_op_beq, rv_op_beq },
{ "c.bnez", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_bne, rv_op_bne, rv_op_bne },
{ "c.slli", rv_codec_ci_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_slli, rv_op_slli, rv_op_slli },
{ "c.slli", rv_codec_ci_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_slli,
rv_op_slli, rv_op_slli, rvcd_imm_nz },
{ "c.fldsp", rv_codec_ci_ldsp, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, rv_op_fld },
{ "c.lwsp", rv_codec_ci_lwsp, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw },
{ "c.flwsp", rv_codec_ci_lwsp, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 },
Expand Down Expand Up @@ -2795,26 +2808,41 @@ static void decode_inst_decompress_rv32(rv_decode *dec)
{
int decomp_op = opcode_data[dec->op].decomp_rv32;
if (decomp_op != rv_op_illegal) {
dec->op = decomp_op;
dec->codec = opcode_data[decomp_op].codec;
if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz)
&& dec->imm == 0) {
dec->op = rv_op_illegal;
} else {
dec->op = decomp_op;
dec->codec = opcode_data[decomp_op].codec;
}
}
}

static void decode_inst_decompress_rv64(rv_decode *dec)
{
int decomp_op = opcode_data[dec->op].decomp_rv64;
if (decomp_op != rv_op_illegal) {
dec->op = decomp_op;
dec->codec = opcode_data[decomp_op].codec;
if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz)
&& dec->imm == 0) {
dec->op = rv_op_illegal;
} else {
dec->op = decomp_op;
dec->codec = opcode_data[decomp_op].codec;
}
}
}

static void decode_inst_decompress_rv128(rv_decode *dec)
{
int decomp_op = opcode_data[dec->op].decomp_rv128;
if (decomp_op != rv_op_illegal) {
dec->op = decomp_op;
dec->codec = opcode_data[decomp_op].codec;
if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz)
&& dec->imm == 0) {
dec->op = rv_op_illegal;
} else {
dec->op = decomp_op;
dec->codec = opcode_data[decomp_op].codec;
}
}
}

Expand Down

0 comments on commit f88222d

Please sign in to comment.