Message ID | 20230711075051.1531007-1-christoph.muellner@vrull.eu (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | riscv/disas: Fix disas output of upper immediates | expand |
On Tue, Jul 11, 2023 at 5:52 PM Christoph Muellner <christoph.muellner@vrull.eu> wrote: > > From: Christoph Müllner <christoph.muellner@vrull.eu> > > 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> Alistair > --- > disas/riscv.c | 19 ++++++++++++++++--- > disas/riscv.h | 2 ++ > 2 files changed, 18 insertions(+), 3 deletions(-) > > diff --git a/disas/riscv.c b/disas/riscv.c > index cd7b6e86a7..3873a69157 100644 > --- a/disas/riscv.c > +++ b/disas/riscv.c > @@ -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) { > diff --git a/disas/riscv.h b/disas/riscv.h > index 9cf901fc1e..8abb578b51 100644 > --- a/disas/riscv.h > +++ b/disas/riscv.h > @@ -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" > -- > 2.41.0 > >
On Tue, Jul 11, 2023 at 5:52 PM Christoph Muellner <christoph.muellner@vrull.eu> wrote: > > From: Christoph Müllner <christoph.muellner@vrull.eu> > > 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> Thanks! Applied to riscv-to-apply.next Alistair > --- > disas/riscv.c | 19 ++++++++++++++++--- > disas/riscv.h | 2 ++ > 2 files changed, 18 insertions(+), 3 deletions(-) > > diff --git a/disas/riscv.c b/disas/riscv.c > index cd7b6e86a7..3873a69157 100644 > --- a/disas/riscv.c > +++ b/disas/riscv.c > @@ -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) { > diff --git a/disas/riscv.h b/disas/riscv.h > index 9cf901fc1e..8abb578b51 100644 > --- a/disas/riscv.h > +++ b/disas/riscv.h > @@ -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" > -- > 2.41.0 > >
diff --git a/disas/riscv.c b/disas/riscv.c index cd7b6e86a7..3873a69157 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -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) { diff --git a/disas/riscv.h b/disas/riscv.h index 9cf901fc1e..8abb578b51 100644 --- a/disas/riscv.h +++ b/disas/riscv.h @@ -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"