diff mbox series

riscv/disas: Fix disas output of upper immediates

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

Commit Message

Christoph Müllner July 11, 2023, 7:50 a.m. UTC
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>
---
 disas/riscv.c | 19 ++++++++++++++++---
 disas/riscv.h |  2 ++
 2 files changed, 18 insertions(+), 3 deletions(-)

Comments

Alistair Francis July 14, 2023, 2:50 a.m. UTC | #1
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
>
>
Alistair Francis July 14, 2023, 2:58 a.m. UTC | #2
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 mbox series

Patch

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"