Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/riscv Make the riscv disassembler work, as best as ...



details:   https://anonhg.NetBSD.org/src/rev/c004a221ddc4
branches:  trunk
changeset: 378631:c004a221ddc4
user:      dholland <dholland%NetBSD.org@localhost>
date:      Mon Apr 19 07:55:59 2021 +0000

description:
Make the riscv disassembler work, as best as I can test from amd64 userspace.

diffstat:

 sys/arch/riscv/include/insn.h    |   20 +-
 sys/arch/riscv/riscv/db_disasm.c |  425 +++++++++++++++++++++++++++++---------
 2 files changed, 339 insertions(+), 106 deletions(-)

diffs (truncated from 779 to 300 lines):

diff -r 607eb9dea100 -r c004a221ddc4 sys/arch/riscv/include/insn.h
--- a/sys/arch/riscv/include/insn.h     Mon Apr 19 06:29:13 2021 +0000
+++ b/sys/arch/riscv/include/insn.h     Mon Apr 19 07:55:59 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: insn.h,v 1.3 2021/04/14 06:32:20 dholland Exp $ */
+/* $NetBSD: insn.h,v 1.4 2021/04/19 07:55:59 dholland Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -241,16 +241,16 @@ union riscv_insn {
  * Quadrant 1 goes FUNCT3 -> FUNCT2a -> FUNCT3b,
  * Quadrant 2 goes FUNCT3 -> FUNCT1b.
  */
-#define INSN16_FUNCT3(insn)    (((insn) && 0xe000) >> 13)
-#define INSN16_FUNCT2a(insn)   (((insn) && 0x0c00) >> 10)
-#define INSN16_FUNCT1b(insn)   (((insn) && 0x1000) >> 12)
-#define INSN16_FUNCT2b(insn)   (((insn) && 0x0060) >> 5)
+#define INSN16_FUNCT3(insn)    (((insn) & 0xe000) >> 13)
+#define INSN16_FUNCT2a(insn)   (((insn) & 0x0c00) >> 10)
+#define INSN16_FUNCT1b(insn)   (((insn) & 0x1000) >> 12)
+#define INSN16_FUNCT2b(insn)   (((insn) & 0x0060) >> 5)
 #define INSN16_FUNCT3c(insn)   \
        ((INSN16_FUNCT1b(insn) << 2) | INSN16_FUNCT2b(insn))
 
 /* full-size register fields */
 #define INSN16_RS1(insn)       (((insn) & 0x0f80) >> 7)  /* bits 7-11 */
-#define INSN16_RS2(insn)       (((insn) & 0x007c) >> 7)  /* bits 2-6 */
+#define INSN16_RS2(insn)       (((insn) & 0x007c) >> 2)  /* bits 2-6 */
 
 /* small register fields, for registers 8-15 */
 #define INSN16_RS1x(insn)      ((((insn) & 0x0380) >> 7) + 8)  /* bits 7-9 */
@@ -422,6 +422,12 @@ union riscv_insn {
 #define OPFP_D                 0b01
 #define OPFP_Q                 0b11
 
+// in some instructions they're an integer operand size instead
+#define OPFP_W                 0b00
+#define OPFP_WU                        0b01
+#define OPFP_L                 0b10
+#define OPFP_LU                        0b11
+
 // primary is AMO (0b01011, 11), top 5 bits
 // (bottom two bits are ACQUIRE and RELEASE flags respectively)
 // funct3 gives the operand size
@@ -644,7 +650,7 @@ union riscv_insn {
 
 #define OPCODE16_Q0    0b00    /* quadrant 0 */
 #define OPCODE16_Q1    0b01    /* quadrant 1 */
-#define OPCODE16_Q2    0b11    /* quadrant 2 */
+#define OPCODE16_Q2    0b10    /* quadrant 2 */
 
 /* quadrant 0 */
 #define Q0_ADDI4SPN    0b000
diff -r 607eb9dea100 -r c004a221ddc4 sys/arch/riscv/riscv/db_disasm.c
--- a/sys/arch/riscv/riscv/db_disasm.c  Mon Apr 19 06:29:13 2021 +0000
+++ b/sys/arch/riscv/riscv/db_disasm.c  Mon Apr 19 07:55:59 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: db_disasm.c,v 1.3 2021/04/14 06:32:20 dholland Exp $   */
+/*     $NetBSD: db_disasm.c,v 1.4 2021/04/19 07:55:59 dholland Exp $   */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 
-__RCSID("$NetBSD: db_disasm.c,v 1.3 2021/04/14 06:32:20 dholland Exp $");
+__RCSID("$NetBSD: db_disasm.c,v 1.4 2021/04/19 07:55:59 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -65,6 +65,11 @@ db_print_addr(db_addr_t loc)
        db_sym_t sym;
        const char *symname;
 
+/* hack for testing since the test program is ASLR'd */
+#ifndef _KERNEL
+       loc &= 0xfff;
+#endif
+
        diff = INT_MAX;
        symname = NULL;
        sym = db_search_symbol(loc, DB_STGY_ANY, &diff);
@@ -101,6 +106,30 @@ db_print_addr(db_addr_t loc)
 #define IN_Q1(op) COMBINE(op, OPCODE16_Q1)
 #define IN_Q2(op) COMBINE(op, OPCODE16_Q2)
 
+/*
+ * All the 16-bit immediate bit-wrangling is done in uint32_t, which
+ * is sufficient, but on RV64 the resulting values should be printed
+ * as 64-bit. Continuing the assumption that we're disassembling for
+ * the size we're built on, do nothing for RV32 and sign-extend from
+ * 32 to 64 for RV64. (And bail on RV128 since it's not clear what
+ * the C type sizes are going to be there anyway...)
+ */
+static
+unsigned long
+maybe_signext64(uint32_t x)
+{
+#if __riscv_xlen == 32
+       return x;
+#elif __riscv_xlen == 64
+       uint64_t xx;
+
+       xx = ((x & 0x80000000) ? 0xffffffff00000000 : 0) | x;
+       return xx;
+#else
+#error Oops.
+#endif
+}
+
 static
 int
 db_disasm_16(db_addr_t loc, uint32_t insn, bool altfmt)
@@ -110,10 +139,15 @@ db_disasm_16(db_addr_t loc, uint32_t ins
        uint32_t imm;
        unsigned rd, rs1, rs2;
 
+       //warnx("toot 0x%x", insn);
        switch (COMBINE(INSN16_FUNCT3(insn), INSN16_QUADRANT(insn))) {
            case IN_Q0(Q0_ADDI4SPN):
                rd = INSN16_RS2x(insn);
                imm = INSN16_IMM_CIW(insn);
+               if (imm == 0) {
+                       /* reserved (all bits 0 -> invalid) */
+                       return EINVAL;
+               }
                db_printf("c.addi4spn %s, 0x%x\n", riscv_registers[rd], imm);
                break;
            case IN_Q0(Q0_FLD_LQ):
@@ -183,11 +217,10 @@ db_disasm_16(db_addr_t loc, uint32_t ins
 #endif
                break;
            case IN_Q1(Q1_NOP_ADDI):
-               rd = INSN16_RS1x(insn);
+               rd = INSN16_RS1(insn);
                imm = INSN16_IMM_CI_K(insn);
                if (rd == 0 && imm == 0) {
-                       db_printf("c.nop %s, %d(%s)\n", riscv_registers[rs2],
-                                 (int32_t)imm, riscv_registers[rs1]);
+                       db_printf("c.nop\n");
                }
                else if (rd == 0 && imm != 0) {
                        /* undefined hint */
@@ -198,8 +231,10 @@ db_disasm_16(db_addr_t loc, uint32_t ins
                        return EINVAL;
                }
                else {
-                       db_printf("c.addi %s, %s, 0x%x\n", riscv_registers[rd],
-                                 riscv_registers[rd], imm);
+                       db_printf("c.addi %s, %s, 0x%lx\n",
+                                 riscv_registers[rd],
+                                 riscv_registers[rd],
+                                 maybe_signext64(imm));
                }
                break;
            case IN_Q1(Q1_JAL_ADDIW):
@@ -209,25 +244,29 @@ db_disasm_16(db_addr_t loc, uint32_t ins
                db_print_addr(loc + (int32_t)imm);
                db_printf("\n");
 #else
-               db_printf("c.addiw %s, %s, 0x%x\n", riscv_registers[rd],
-                         riscv_registers[rd], imm);
+               rd = INSN16_RS1(insn);
+               imm = INSN16_IMM_CI_K(insn);
+               db_printf("c.addiw %s, %s, 0x%lx\n", riscv_registers[rd],
+                         riscv_registers[rd], maybe_signext64(imm));
 #endif
                break;
            case IN_Q1(Q1_LI):
                rd = INSN16_RS1(insn);
                imm = INSN16_IMM_CI_K(insn);
-               db_printf("c.li %s, 0x%x\n", riscv_registers[rd], imm);
+               db_printf("c.li %s, 0x%lx\n", riscv_registers[rd],
+                         maybe_signext64(imm));
                break;
            case IN_Q1(Q1_ADDI16SP_LUI):
                rd = INSN16_RS1(insn);
                if (rd == 2/*sp*/) {
                        imm = INSN16_IMM_CI_K4(insn);
-                       db_printf("c.add16sp sp, 0x%x\n", imm);
+                       db_printf("c.add16sp sp, 0x%lx\n",
+                                 maybe_signext64(imm));
                }
                else {
                        imm = INSN16_IMM_CI_K12(insn);
-                       db_printf("c.lui %s, 0x%x\n", riscv_registers[rd],
-                                 imm);
+                       db_printf("c.lui %s, 0x%lx\n", riscv_registers[rd],
+                                 maybe_signext64(imm));
                }
                break;
            case IN_Q1(Q1_MISC):
@@ -258,7 +297,8 @@ db_disasm_16(db_addr_t loc, uint32_t ins
                                  riscv_registers[rd], imm);
                        break;
                    case Q1MISC_ANDI:
-                       db_printf("c.andi %s, %d\n", riscv_registers[rd], imm);
+                       db_printf("c.andi %s, 0x%lx\n", riscv_registers[rd],
+                                 maybe_signext64(imm));
                        break;
                    case Q1MISC_MORE:
                        rs2 = INSN16_RS2x(insn);
@@ -374,10 +414,10 @@ db_disasm_16(db_addr_t loc, uint32_t ins
 #endif
                break;
            case IN_Q2(Q2_MISC):
+               rs1 = INSN16_RS1(insn);
+               rs2 = INSN16_RS2(insn);
                switch (INSN16_FUNCT1b(insn)) {
                    case Q2MISC_JR_MV:
-                       rs1 = INSN16_RS1(insn);
-                       rs2 = INSN16_RS2(insn);
                        if (rs1 == 0) {
                                return EINVAL;
                        }
@@ -448,7 +488,7 @@ db_disasm_16(db_addr_t loc, uint32_t ins
 /* match flags */
 #define CHECK_F3       0x0001          /* check funct3 field */
 #define CHECK_F7       0x0002          /* check funct7 field */
-#define CHECK_F5       0x0004          /* check top of funct7 field only */
+#define CHECK_F5       0x0004          /* check tpo of funct7 field only */
 #define CHECK_RS2      0x0008          /* check rs2 as quaternary opcode */
 #define SHIFT32                0x0010          /* 32-bit immediate shift */
 #define SHIFT64                0x0020          /* 64-bit immediate shift */
@@ -460,7 +500,8 @@ db_disasm_16(db_addr_t loc, uint32_t ins
 #define F3ROUND                0x0800          /* expect fp rounding mode in funct3 */
 #define F7SIZE         0x1000          /* expect fp size in funct7:0-1 */
 #define RS2_FSIZE      0x2000          /* expect fp size in rs2 */
-#define FENCEFM                0x4000          /* fence mode in top 4 bits of imm */
+#define RS2_FSIZE_INT  0x4000          /* expect fp size in rs2 */
+#define FENCEFM                0x8000          /* fence mode in top 4 bits of imm */
 /* do not add more without increasing the field size below */
 
 #ifdef _LP64 /* disassembling ourself so can use our build flags... */
@@ -481,18 +522,20 @@ db_disasm_16(db_addr_t loc, uint32_t ins
 #define RD_FREG                0x100           /* rd is a fpu reg */
 #define RS1_FREG       0x200           /* rs1 is a fpu reg */
 #define RS2_FREG       0x400           /* rs2 is a fpu reg */
+#define ISCVT          0x800           /* is an fpu conversion op */
 /* do not add more without increasing the field size below */
 
 #define ALL_FREG (RD_FREG | RS1_FREG | RS2_FREG)
+#define RS12_FREG (RS1_FREG | RS2_FREG)
 
 /* entries for matching within a major opcode */
 struct riscv_disasm_insn {
        const char *name;
-       unsigned int matchflags: 15,
+       unsigned int matchflags: 16,
                funct3: 3,
                funct7: 7,
                rs2: 5;
-       unsigned int printflags: 11;
+       unsigned int printflags: 12;
 };
 
 /* format codes */
@@ -613,6 +656,7 @@ static const struct riscv_disasm_insn ri
 };
 
 static const struct riscv_disasm_insn riscv_disasm_opimm[] = {
+       INSN_F3("nop", OP_ADDSUB, RD_0 | RS1_0 | IMM_0, 0),
        INSN_F3("addi", OP_ADDSUB, 0, 0),
        INSN_F3("slti", OP_SLT, 0, 0),
        INSN_F3("sltiu", OP_SLTU, 0, 0),
@@ -632,16 +676,16 @@ static const struct riscv_disasm_insn ri
 };
 
 static const struct riscv_disasm_insn riscv_disasm_store[] = {
-       INSN_F3("sb", STORE_SB, 0, 0),
-       INSN_F3("sh", STORE_SH, 0, 0),
-       INSN_F3("sw", STORE_SW, 0, 0),
-       INSN_F3("sd", STORE_SD, 0, 0),
+       INSN_F3("sb", STORE_SB, 0, MEMORYIMM),
+       INSN_F3("sh", STORE_SH, 0, MEMORYIMM),
+       INSN_F3("sw", STORE_SW, 0, MEMORYIMM),
+       INSN_F3("sd", STORE_SD, 0, MEMORYIMM),
 };
 
 static const struct riscv_disasm_insn riscv_disasm_storefp[] = {
-       INSN_F3("fsw", STOREFP_FSW, 0, RS2_FREG),
-       INSN_F3("fsd", STOREFP_FSD, 0, RS2_FREG),
-       INSN_F3("fsq", STOREFP_FSQ, 0, RS2_FREG),
+       INSN_F3("fsw", STOREFP_FSW, 0, MEMORYIMM | RS2_FREG),
+       INSN_F3("fsd", STOREFP_FSD, 0, MEMORYIMM | RS2_FREG),
+       INSN_F3("fsq", STOREFP_FSQ, 0, MEMORYIMM | RS2_FREG),
 };
 
 static const struct riscv_disasm_insn riscv_disasm_branch[] = {
@@ -659,10 +703,10 @@ static const struct riscv_disasm_insn ri
        INSN_F3("csrr", SYSTEM_CSRRS, RS1_0, CSRIMM),
        INSN_F3("csrrs", SYSTEM_CSRRS, 0, CSRIMM),
        INSN_F3("csrrc", SYSTEM_CSRRC, 0, CSRIMM),
-       INSN_F3("csrwi", SYSTEM_CSRRW, RD_0, CSRIIMM),
-       INSN_F3("csrrwi", SYSTEM_CSRRW, 0, CSRIIMM),
-       INSN_F3("csrrsi", SYSTEM_CSRRS, 0, CSRIIMM),
-       INSN_F3("csrrci", SYSTEM_CSRRC, 0, CSRIIMM),
+       INSN_F3("csrwi", SYSTEM_CSRRWI, RD_0, CSRIIMM),
+       INSN_F3("csrrwi", SYSTEM_CSRRWI, 0, CSRIIMM),



Home | Main Index | Thread Index | Old Index