Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/riscv Add a ddb disassembler for riscv.



details:   https://anonhg.NetBSD.org/src/rev/f5f1d83f435e
branches:  trunk
changeset: 378471:f5f1d83f435e
user:      dholland <dholland%NetBSD.org@localhost>
date:      Wed Apr 14 06:32:20 2021 +0000

description:
Add a ddb disassembler for riscv.

builds, but not really tested yet.

diffstat:

 sys/arch/riscv/include/db_machdep.h |    13 +-
 sys/arch/riscv/include/insn.h       |   734 +++++++++++++++++---
 sys/arch/riscv/riscv/db_disasm.c    |  1253 ++++++++++++++++++++++++++++++++++-
 sys/arch/riscv/riscv/db_machdep.c   |    37 +-
 4 files changed, 1892 insertions(+), 145 deletions(-)

diffs (truncated from 2241 to 300 lines):

diff -r 9eb8ac769e8f -r f5f1d83f435e sys/arch/riscv/include/db_machdep.h
--- a/sys/arch/riscv/include/db_machdep.h       Wed Apr 14 05:43:09 2021 +0000
+++ b/sys/arch/riscv/include/db_machdep.h       Wed Apr 14 06:32:20 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: db_machdep.h,v 1.2 2017/11/06 03:47:48 christos Exp $ */
+/* $NetBSD: db_machdep.h,v 1.3 2021/04/14 06:32:20 dholland Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -62,6 +62,17 @@ extern const uint32_t __cpu_Debugger_ins
 #define        BKPT_SIZE       (sizeof(uint32_t))      /* size of breakpoint inst */
 #define        BKPT_SET(inst, addr)    (BKPT_INST)
 
+/*
+ * XXX with the C extension there's also a 16-bit-wide breakpoint
+ * instruction, the idea being that you use it when inserting a
+ * breakpoint into a stream of 16-bit instructions, but it looks like
+ * MI ddb can't cope with having two sizes :-(
+ */
+#if 0
+#define BKPT_INST_2    0x9002
+#define BKPT_SIZE_2    (sizeof(uint16_t))
+#endif
+
 #define        IS_BREAKPOINT_TRAP(type, code)  ((type) == CAUSE_BREAKPOINT)
 #define IS_WATCHPOINT_TRAP(type, code) (0)
 
diff -r 9eb8ac769e8f -r f5f1d83f435e sys/arch/riscv/include/insn.h
--- a/sys/arch/riscv/include/insn.h     Wed Apr 14 05:43:09 2021 +0000
+++ b/sys/arch/riscv/include/insn.h     Wed Apr 14 06:32:20 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: insn.h,v 1.2 2020/11/04 07:09:45 skrll Exp $ */
+/* $NetBSD: insn.h,v 1.3 2021/04/14 06:32:20 dholland Exp $ */
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -32,8 +32,14 @@
 #ifndef _RISCV_INSN_H_
 #define _RISCV_INSN_H_
 
+/*
+ * I have corrected and updated this, but it's the wrong way to do it.
+ * It's still used by ddb_machdep.c but that code should be fixed to
+ * use the newer stuff below. - dholland
+ */
 union riscv_insn {
        uint32_t val;
+       /* register ops */
        struct {
                unsigned int r_opcode : 7;
                unsigned int r_rd : 5;
@@ -42,14 +48,26 @@ union riscv_insn {
                unsigned int r_rs2 : 5;
                unsigned int r_funct7 : 7;
        } type_r;
+       /* 32-bit shifts */
        struct {
-               unsigned int rs_opcode : 7;
-               unsigned int rs_rd : 5;
-               unsigned int rs_funct3 : 3;
-               unsigned int rs_rs1 : 5;
-               unsigned int rs_shmat : 6;
-               unsigned int rs_funct6 : 6;
-       } type_rs;
+               unsigned int rs32_opcode : 7;
+               unsigned int rs32_rd : 5;
+               unsigned int rs32_funct3 : 3;
+               unsigned int rs32_rs1 : 5;
+               unsigned int rs32_shamt : 5;
+               unsigned int rs32_funct7 : 7;
+       } type_rs32;
+       /* 64-bit shifts */
+       struct {
+               unsigned int rs64_opcode : 7;
+               unsigned int rs64_rd : 5;
+               unsigned int rs64_funct3 : 3;
+               unsigned int rs64_rs1 : 5;
+               unsigned int rs64_shamt : 6;
+               unsigned int rs64_zero : 1;
+               unsigned int rs64_funct5 : 5;
+       } type_rs64;
+       /* atomics */
        struct {
                unsigned int ra_opcode : 7;
                unsigned int ra_rd : 5;
@@ -58,17 +76,29 @@ union riscv_insn {
                unsigned int ra_rs2 : 5;
                unsigned int ra_rl : 1;
                unsigned int ra_aq : 1;
-               unsigned int ra_funct5 : 6;
+               unsigned int ra_funct5 : 5;
        } type_ra;
+       /* certain fpu ops */
        struct {
                unsigned int rf_opcode : 7;
                unsigned int rf_rd : 5;
                unsigned int rf_rm : 3;
                unsigned int rf_rs1 : 5;
                unsigned int rf_rs2 : 5;
-               unsigned int rf_funct2 : 2;
-               unsigned int rf_rs3 : 5;
+               unsigned int rf_size : 2;
+               unsigned int rf_funct5 : 5;
        } type_rf;
+       /* other fpu ops */
+       struct {
+               unsigned int rf4_opcode : 7;
+               unsigned int rf4_rd : 5;
+               unsigned int rf4_rm : 3;
+               unsigned int rf4_rs1 : 5;
+               unsigned int rf4_rs2 : 5;
+               unsigned int rf4_size : 2;
+               unsigned int rf4_rs3 : 5;
+       } type_rf4;
+       /* immediates */
        struct {
                unsigned int i_opcode : 7;
                unsigned int i_rd : 5;
@@ -76,6 +106,7 @@ union riscv_insn {
                unsigned int i_rs1 : 5;
                signed int i_imm11to0 : 12;
        } type_i;
+       /* stores */
        struct {
                unsigned int s_opcode : 7;
                unsigned int s_imm4_to_0 : 5;
@@ -84,33 +115,241 @@ union riscv_insn {
                unsigned int s_rs2 : 5;
                signed int s_imm11_to_5 : 7;
        } type_s;
+       /* branches */
        struct {
-               unsigned int sb_opcode : 7;
-               unsigned int sb_imm11 : 1;
-               unsigned int sb_imm4to1 : 4;
-               unsigned int sb_funct3 : 3;
-               unsigned int sb_rs1 : 5;
-               unsigned int sb_rs2 : 5;
-               unsigned int sb_imm10to5 : 6;
-               signed int sb_imm12 : 1;
-       } type_sb;
+               unsigned int b_opcode : 7;
+               unsigned int b_imm11 : 1;
+               unsigned int b_imm4to1 : 4;
+               unsigned int b_funct3 : 3;
+               unsigned int b_rs1 : 5;
+               unsigned int b_rs2 : 5;
+               unsigned int b_imm10to5 : 6;
+               signed int b_imm12 : 1;
+       } type_b;
+       /* large immediate constants */
        struct {
                unsigned int u_opcode : 7;
                unsigned int u_rd : 5;
                signed int u_imm31to12 : 20;
        } type_u;
+       /* large immediate jumps */
        struct {
-               unsigned int uj_opcode : 7;
-               unsigned int uj_rd : 5;
-               unsigned int uj_imm19to12 : 9;
-               unsigned int uj_imm11 : 1;
-               unsigned int uj_imm10to1 : 9;
-               signed int uj_imm20 : 1;
-       } type_uj;
+               unsigned int j_opcode : 7;
+               unsigned int j_rd : 5;
+               unsigned int j_imm19to12 : 9;
+               unsigned int j_imm11 : 1;
+               unsigned int j_imm10to1 : 9;
+               signed int j_imm20 : 1;
+       } type_j;
 };
 
+/*
+ * old macro still in use with the above
+ * (XXX, doesn't handle 16-bit instructions)
+ */
+
 #define OPCODE_P(i, x)         (((i) & 0b1111111) == ((OPCODE_##x<<2)|0b11))
 
+////////////////////////////////////////////////////////////
+
+/*
+ * Instruction size
+ */
+
+/* cumulative size tests */
+#define INSN_SIZE_IS_16(insn) (((insn) & 0b11) != 0b11)
+#define INSN_SIZE_IS_32(insn) (((insn) & 0b11100) != 0b11100)
+#define INSN_SIZE_IS_48(insn) (((insn) & 0b100000) != 0b100000)
+#define INSN_SIZE_IS_64(insn) (((insn) & 0b1000000) != 0b1000000)
+
+/* returns 1-5 for the number of uint16s */
+#define INSN_HALFWORDS(insn) \
+       (INSN_SIZE_IS_16(insn) ? 1 : \
+        INSN_SIZE_IS_32(insn) ? 2 : \
+        INSN_SIZE_IS_48(insn) ? 3 : \
+        INSN_SIZE_IS_64(insn) ? 4 : \
+        5)
+
+#define INSN_SIZE(insn) (INSN_HALFWORDS(insn) * sizeof(uint16_t))
+
+/*
+ * sign-extend x from the bottom k bits
+ */
+#define SIGNEXT32(x, k) ( \
+               ( ((x) & (1U << ((k)-1))) ? (0xffffffffU << (k)) : 0U) | \
+               ((x) & (0xffffffffU >> (32 - (k))))                      \
+       )
+
+/*
+ * Field extractors for 32-bit instructions
+ */
+
+#define INSN_OPCODE32(insn)    (((insn) & 0x0000007f) >> 2)
+#define INSN_RD(insn)          (((insn) & 0x00000f80) >> 7)
+#define INSN_FUNCT3(insn)      (((insn) & 0x00007000) >> 12)
+#define INSN_RS1(insn)         (((insn) & 0x000f8000) >> 15)
+#define INSN_RS2(insn)         (((insn) & 0x01f00000) >> 20)
+#define INSN_FUNCT7(insn)      (((insn) & 0xfe000000) >> 25)
+
+/* U-type immediate, just the top bits of the instruction */
+#define INSN_IMM_U(insn)        ((insn) & 0xfffff000)
+
+/* I-type immediate, upper 12 bits sign-extended */
+#define INSN_IMM_I(insn)       SIGNEXT32(((insn) & 0xfff00000) >> 20, 12)
+
+/* S-type immediate (stores), pasted from funct7 field and rd field */
+#define INSN_IMM_S_raw(insn)   ((INSN_FUNCT7(insn) << 5) | INSN_RD(insn))
+#define INSN_IMM_S(insn)       SIGNEXT32(INSN_IMM_S_raw(insn), 12)
+
+/* B-type immediate (branches), pasted messily from funct7 and rd fields */
+#define INSN_IMM_B_raw(insn)                   \
+       (((insn & 0x80000000) >> (31-12)) |     \
+        ((insn & 0x00000080) << (11-7))  |     \
+        ((insn & 0x7e000000) >> (25-5))  |     \
+        ((insn & 0x00000f00) >> (8-1)))
+#define INSN_IMM_B(insn)       SIGNEXT32(INSN_IMM_B_raw(insn), 13)
+
+/* J-type immediate (jumps), rehash of the U immediate field */
+#define INSN_IMM_J_raw(insn)                   \
+       (((insn & 0x80000000) >> (31-20)) |     \
+        ((insn & 0x000ff000) >> (12-12)) |     \
+        ((insn & 0x00100000) >> (20-11)) |     \
+        ((insn & 0x7fe00000) >> (21-1)))
+#define INSN_IMM_J(insn)       SIGNEXT32(INSN_IMM_J_raw(insn), 21)
+
+/*
+ * Field extractors for 16-bit instructions
+ */
+
+#define INSN16_QUADRANT(insn)  ((insn) & 0b11)
+
+/*
+ * In the manual there's
+ *    FUNCT3 (bits 13-15)
+ *    FUNCT4 (bits 12-15)
+ *    FUNCT6 (bits 10-15)
+ *    FUNCT2 (bits 5-6)
+ *
+ * but this does not reflect the actual usage correctly. So I've got
+ *    FUNCT3 (bits 13-15)
+ *    FUNCT2a (bits 10-11)
+ *    FUNCT1b (bit 12)
+ *    FUNCT2b (bits 5-6)
+ *    FUNCT3b (FUNCT1b pasted to FUNCT3b)
+ *
+ * Quadrant 0 just uses FUNCT3;
+ * 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_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 */
+
+/* small register fields, for registers 8-15 */
+#define INSN16_RS1x(insn)      ((((insn) & 0x0380) >> 7) + 8)  /* bits 7-9 */
+#define INSN16_RS2x(insn)      ((((insn) & 0x001c) >> 2) + 8)  /* bits 2-4 */
+
+/* CI format immediates, for word/double/quad offsets, zero-extended */
+#define INSN16_IMM_CI_W(insn) \
+       ((((insn) & 0b0001000000000000) >> (12-5)) |    \
+        (((insn) & 0b0000000001110000) >> (4-2)) |     \
+        (((insn) & 0b0000000000001100) << (6-2)))
+#define INSN16_IMM_CI_D(insn) \
+       ((((insn) & 0b0001000000000000) >> (12-5)) |    \
+        (((insn) & 0b0000000001100000) >> (4-2)) |     \
+        (((insn) & 0b0000000000011100) << (6-2)))
+#define INSN16_IMM_CI_Q(insn) \
+       ((((insn) & 0b0001000000000000) >> (12-5)) |    \
+        (((insn) & 0b0000000001000000) >> (4-2)) |     \
+        (((insn) & 0b0000000000111100) << (6-2)))



Home | Main Index | Thread Index | Old Index