riscv/disas: Fix disas output of upper immediates
The GNU assembler produces the following output for instructions with upper immediates: 00002597 auipc a1,0x2 000024b7 lui s1,0x2 6409 lui s0,0x2 # c.lui The immediate operands of upper immediates are not shifted. However, the QEMU disassembler prints them shifted: 00002597 auipc a1,8192 000024b7 lui s1,8192 6409 lui s0,8192 # c.lui The current implementation extracts the immediate bits and shifts the by 12, so the internal representation of the immediate is the actual immediate. However, the immediates are later printed using rv_fmt_rd_imm or rv_fmt_rd_offset, which don't undo the shift. Let's fix this by using specific output formats for instructions with upper immediates, that take care of the shift. Signed-off-by: Christoph Müllner <christoph.muellner@vrull.eu> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-Id: <20230711075051.1531007-1-christoph.muellner@vrull.eu> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
542c8776ca
commit
36df75a0a9
@ -1135,8 +1135,8 @@ static const rv_comp_data rvcp_fsgnjx_q[] = {
|
||||
|
||||
const rv_opcode_data rvi_opcode_data[] = {
|
||||
{ "illegal", rv_codec_illegal, rv_fmt_none, NULL, 0, 0, 0 },
|
||||
{ "lui", rv_codec_u, rv_fmt_rd_imm, NULL, 0, 0, 0 },
|
||||
{ "auipc", rv_codec_u, rv_fmt_rd_offset, NULL, 0, 0, 0 },
|
||||
{ "lui", rv_codec_u, rv_fmt_rd_uimm, NULL, 0, 0, 0 },
|
||||
{ "auipc", rv_codec_u, rv_fmt_rd_uoffset, NULL, 0, 0, 0 },
|
||||
{ "jal", rv_codec_uj, rv_fmt_rd_offset, rvcp_jal, 0, 0, 0 },
|
||||
{ "jalr", rv_codec_i, rv_fmt_rd_rs1_offset, rvcp_jalr, 0, 0, 0 },
|
||||
{ "beq", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_beq, 0, 0, 0 },
|
||||
@ -1382,7 +1382,7 @@ const rv_opcode_data rvi_opcode_data[] = {
|
||||
rv_op_addi },
|
||||
{ "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,
|
||||
{ "c.lui", rv_codec_ci_lui, rv_fmt_rd_uimm, 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 },
|
||||
@ -4694,6 +4694,19 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
|
||||
dec->pc + dec->imm);
|
||||
append(buf, tmp, buflen);
|
||||
break;
|
||||
case 'U':
|
||||
fmt++;
|
||||
snprintf(tmp, sizeof(tmp), "%d", dec->imm >> 12);
|
||||
append(buf, tmp, buflen);
|
||||
if (*fmt == 'o') {
|
||||
while (strlen(buf) < tab * 2) {
|
||||
append(buf, " ", buflen);
|
||||
}
|
||||
snprintf(tmp, sizeof(tmp), "# 0x%" PRIx64,
|
||||
dec->pc + dec->imm);
|
||||
append(buf, tmp, buflen);
|
||||
}
|
||||
break;
|
||||
case 'c': {
|
||||
const char *name = csr_name(dec->imm & 0xfff);
|
||||
if (name) {
|
||||
|
@ -227,7 +227,9 @@ enum {
|
||||
#define rv_fmt_pred_succ "O\tp,s"
|
||||
#define rv_fmt_rs1_rs2 "O\t1,2"
|
||||
#define rv_fmt_rd_imm "O\t0,i"
|
||||
#define rv_fmt_rd_uimm "O\t0,Ui"
|
||||
#define rv_fmt_rd_offset "O\t0,o"
|
||||
#define rv_fmt_rd_uoffset "O\t0,Uo"
|
||||
#define rv_fmt_rd_rs1_rs2 "O\t0,1,2"
|
||||
#define rv_fmt_frd_rs1 "O\t3,1"
|
||||
#define rv_fmt_frd_rs1_rs2 "O\t3,1,2"
|
||||
|
Loading…
Reference in New Issue
Block a user