]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/riscv/riscv/db_disasm.c
Implement pci_enable_msi() and pci_disable_msi() in the LinuxKPI.
[FreeBSD/FreeBSD.git] / sys / riscv / riscv / db_disasm.c
1 /*-
2  * Copyright (c) 2016-2018 Ruslan Bukin <br@bsdpad.com>
3  * All rights reserved.
4  *
5  * Portions of this software were developed by SRI International and the
6  * University of Cambridge Computer Laboratory under DARPA/AFRL contract
7  * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Portions of this software were developed by the University of Cambridge
10  * Computer Laboratory as part of the CTSRD Project, with support from the
11  * UK Higher Education Innovation Fund (HEIF).
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <ddb/ddb.h>
41 #include <ddb/db_access.h>
42 #include <ddb/db_sym.h>
43
44 #include <machine/encoding.h>
45
46 #define X_RA    1
47 #define X_SP    2
48 #define X_GP    3
49 #define X_TP    4
50 #define X_T0    5
51 #define X_T1    6
52 #define X_T2    7
53 #define X_T3    28
54
55 #define RD_SHIFT        7
56 #define RD_MASK         (0x1f << RD_SHIFT)
57 #define RS1_SHIFT       15
58 #define RS1_MASK        (0x1f << RS1_SHIFT)
59 #define RS2_SHIFT       20
60 #define RS2_MASK        (0x1f << RS2_SHIFT)
61 #define IMM_SHIFT       20
62 #define IMM_MASK        (0xfff << IMM_SHIFT)
63
64 static char *reg_name[32] = {
65         "zero", "ra",   "sp",   "gp",   "tp",   "t0",   "t1",   "t2",
66         "s0",   "s1",   "a0",   "a1",   "a2",   "a3",   "a4",   "a5",
67         "a6",   "a7",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
68         "s8",   "s9",   "s10",  "s11",  "t3",   "t4",   "t5",   "t6"
69 };
70
71 static char *fp_reg_name[32] = {
72         "ft0", "ft1", "ft2",  "ft3",  "ft4", "ft5", "ft6",  "ft7",
73         "fs0", "fs1", "fa0",  "fa1",  "fa2", "fa3", "fa4",  "fa5",
74         "fa6", "fa7", "fs2",  "fs3",  "fs4", "fs5", "fs6",  "fs7",
75         "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"
76 };
77
78 struct riscv_op {
79         char *name;
80         char *fmt;
81         int match;
82         int mask;
83         int (*match_func)(struct riscv_op *op, uint32_t insn);
84 };
85
86 static int
87 m_op(struct riscv_op *op, uint32_t insn)
88 {
89
90         if (((insn ^ op->match) & op->mask) == 0)
91                 return (1);
92
93         return (0);
94 }
95
96 static struct riscv_op riscv_opcodes[] = {
97         /* Aliases first */
98         {"ret","", MATCH_JALR | (X_RA << RS1_SHIFT),
99             MASK_JALR | RD_MASK | RS1_MASK | IMM_MASK, m_op },
100
101         { "beq",        "s,t,p",        MATCH_BEQ, MASK_BEQ,            m_op },
102         { "bne",        "s,t,p",        MATCH_BNE, MASK_BNE,            m_op },
103         { "blt",        "s,t,p",        MATCH_BLT, MASK_BLT,            m_op },
104         { "bge",        "s,t,p",        MATCH_BGE, MASK_BGE,            m_op },
105         { "bltu",       "s,t,p",        MATCH_BLTU, MASK_BLTU,          m_op },
106         { "bgeu",       "s,t,p",        MATCH_BGEU, MASK_BGEU,          m_op },
107         { "jalr",       "d,o(s)",       MATCH_JALR, MASK_JALR,          m_op },
108         { "jal",        "d,a",          MATCH_JAL, MASK_JAL,            m_op },
109         { "lui",        "d,u",          MATCH_LUI, MASK_LUI,            m_op },
110         { "auipc",      "d,u",          MATCH_AUIPC, MASK_AUIPC,        m_op },
111         { "addi",       "d,s,j",        MATCH_ADDI, MASK_ADDI,          m_op },
112         { "slli",       "d,s,>",        MATCH_SLLI, MASK_SLLI,          m_op },
113         { "slti",       "d,s,j",        MATCH_SLTI, MASK_SLTI,          m_op },
114         { "sltiu",      "d,s,j",        MATCH_SLTIU, MASK_SLTIU,        m_op },
115         { "xori",       "d,s,j",        MATCH_XORI, MASK_XORI,          m_op },
116         { "srli",       "d,s,>",        MATCH_SRLI, MASK_SRLI,          m_op },
117         { "srai",       "d,s,>",        MATCH_SRAI, MASK_SRAI,          m_op },
118         { "ori",        "d,s,j",        MATCH_ORI, MASK_ORI,            m_op },
119         { "andi",       "d,s,j",        MATCH_ANDI, MASK_ANDI,          m_op },
120         { "add",        "d,s,t",        MATCH_ADD, MASK_ADD,            m_op },
121         { "sub",        "d,s,t",        MATCH_SUB, MASK_SUB,            m_op },
122         { "sll",        "d,s,t",        MATCH_SLL, MASK_SLL,            m_op },
123         { "slt",        "d,s,t",        MATCH_SLT, MASK_SLT,            m_op },
124         { "sltu",       "d,s,t",        MATCH_SLTU, MASK_SLTU,          m_op },
125         { "xor",        "d,s,t",        MATCH_XOR, MASK_XOR,            m_op },
126         { "srl",        "d,s,t",        MATCH_SRL, MASK_SRL,            m_op },
127         { "sra",        "d,s,t",        MATCH_SRA, MASK_SRA,            m_op },
128         { "or",         "d,s,t",        MATCH_OR, MASK_OR,              m_op },
129         { "and",        "d,s,t",        MATCH_AND, MASK_AND,            m_op },
130         { "addiw",      "d,s,j",        MATCH_ADDIW, MASK_ADDIW,        m_op },
131         { "slliw",      "d,s,<",        MATCH_SLLIW, MASK_SLLIW,        m_op },
132         { "srliw",      "d,s,<",        MATCH_SRLIW, MASK_SRLIW,        m_op },
133         { "sraiw",      "d,s,<",        MATCH_SRAIW, MASK_SRAIW,        m_op },
134         { "addw",       "d,s,t",        MATCH_ADDW, MASK_ADDW,          m_op },
135         { "subw",       "d,s,t",        MATCH_SUBW, MASK_SUBW,          m_op },
136         { "sllw",       "d,s,t",        MATCH_SLLW, MASK_SLLW,          m_op },
137         { "srlw",       "d,s,t",        MATCH_SRLW, MASK_SRLW,          m_op },
138         { "sraw",       "d,s,t",        MATCH_SRAW, MASK_SRAW,          m_op },
139         { "lb",         "d,o(s)",       MATCH_LB, MASK_LB,              m_op },
140         { "lh",         "d,o(s)",       MATCH_LH, MASK_LH,              m_op },
141         { "lw",         "d,o(s)",       MATCH_LW, MASK_LW,              m_op },
142         { "ld",         "d,o(s)",       MATCH_LD, MASK_LD,              m_op },
143         { "lbu",        "d,o(s)",       MATCH_LBU, MASK_LBU,            m_op },
144         { "lhu",        "d,o(s)",       MATCH_LHU, MASK_LHU,            m_op },
145         { "lwu",        "d,o(s)",       MATCH_LWU, MASK_LWU,            m_op },
146         { "sb",         "t,q(s)",       MATCH_SB, MASK_SB,              m_op },
147         { "sh",         "t,q(s)",       MATCH_SH, MASK_SH,              m_op },
148         { "sw",         "t,q(s)",       MATCH_SW, MASK_SW,              m_op },
149         { "sd",         "t,q(s)",       MATCH_SD, MASK_SD,              m_op },
150         { "fence",      "P,Q",          MATCH_FENCE, MASK_FENCE,        m_op },
151         { "fence.i",    "",             MATCH_FENCE_I, MASK_FENCE_I,    m_op },
152         { "mul",        "d,s,t",        MATCH_MUL, MASK_MUL,            m_op },
153         { "mulh",       "d,s,t",        MATCH_MULH, MASK_MULH,          m_op },
154         { "mulhsu",     "d,s,t",        MATCH_MULHSU, MASK_MULHSU,      m_op },
155         { "mulhu",      "d,s,t",        MATCH_MULHU, MASK_MULHU,        m_op },
156         { "div",        "d,s,t",        MATCH_DIV, MASK_DIV,            m_op },
157         { "divu",       "d,s,t",        MATCH_DIVU, MASK_DIVU,          m_op },
158         { "rem",        "d,s,t",        MATCH_REM, MASK_REM,            m_op },
159         { "remu",       "d,s,t",        MATCH_REMU, MASK_REMU,          m_op },
160         { "mulw",       "d,s,t",        MATCH_MULW, MASK_MULW,          m_op },
161         { "divw",       "d,s,t",        MATCH_DIVW, MASK_DIVW,          m_op },
162         { "divuw",      "d,s,t",        MATCH_DIVUW, MASK_DIVUW,        m_op },
163         { "remw",       "d,s,t",        MATCH_REMW, MASK_REMW,          m_op },
164         { "remuw",      "d,s,t",        MATCH_REMUW, MASK_REMUW,        m_op },
165         { "amoadd.w",   "d,t,0(s)",     MATCH_AMOADD_W, MASK_AMOADD_W,  m_op },
166         { "amoxor.w",   "d,t,0(s)",     MATCH_AMOXOR_W, MASK_AMOXOR_W,  m_op },
167         { "amoor.w",    "d,t,0(s)",     MATCH_AMOOR_W, MASK_AMOOR_W,    m_op },
168         { "amoand.w",   "d,t,0(s)",     MATCH_AMOAND_W, MASK_AMOAND_W,  m_op },
169         { "amomin.w",   "d,t,0(s)",     MATCH_AMOMIN_W, MASK_AMOMIN_W,  m_op },
170         { "amomax.w",   "d,t,0(s)",     MATCH_AMOMAX_W, MASK_AMOMAX_W,  m_op },
171         { "amominu.w",  "d,t,0(s)",     MATCH_AMOMINU_W, MASK_AMOMINU_W,m_op },
172         { "amomaxu.w",  "d,t,0(s)",     MATCH_AMOMAXU_W, MASK_AMOMAXU_W,m_op },
173         { "amoswap.w",  "d,t,0(s)",     MATCH_AMOSWAP_W, MASK_AMOSWAP_W,m_op },
174         { "lr.w",       "d,0(s)",       MATCH_LR_W, MASK_LR_W,          m_op },
175         { "sc.w",       "d,t,0(s)",     MATCH_SC_W, MASK_SC_W,          m_op },
176         { "amoadd.d",   "d,t,0(s)",     MATCH_AMOADD_D, MASK_AMOADD_D,  m_op },
177         { "amoxor.d",   "d,t,0(s)",     MATCH_AMOXOR_D, MASK_AMOXOR_D,  m_op },
178         { "amoor.d",    "d,t,0(s)",     MATCH_AMOOR_D, MASK_AMOOR_D,    m_op },
179         { "amoand.d",   "d,t,0(s)",     MATCH_AMOAND_D, MASK_AMOAND_D,  m_op },
180         { "amomin.d",   "d,t,0(s)",     MATCH_AMOMIN_D, MASK_AMOMIN_D,  m_op },
181         { "amomax.d",   "d,t,0(s)",     MATCH_AMOMAX_D, MASK_AMOMAX_D,  m_op },
182         { "amominu.d",  "d,t,0(s)",     MATCH_AMOMINU_D, MASK_AMOMINU_D,m_op },
183         { "amomaxu.d",  "d,t,0(s)",     MATCH_AMOMAXU_D, MASK_AMOMAXU_D,m_op },
184         { "amoswap.d",  "d,t,0(s)",     MATCH_AMOSWAP_D, MASK_AMOSWAP_D,m_op },
185         { "lr.d",       "d,0(s)",       MATCH_LR_D, MASK_LR_D,          m_op },
186         { "sc.d",       "d,t,0(s)",     MATCH_SC_D, MASK_SC_D,          m_op },
187         { "ecall",      "",             MATCH_ECALL, MASK_ECALL,        m_op },
188         { "ebreak",     "",             MATCH_EBREAK, MASK_EBREAK,      m_op },
189         { "uret",       "",             MATCH_URET, MASK_URET,          m_op },
190         { "sret",       "",             MATCH_SRET, MASK_SRET,          m_op },
191         { "mret",       "",             MATCH_MRET, MASK_MRET,          m_op },
192         { "dret",       "",             MATCH_DRET, MASK_DRET,          m_op },
193         { "sfence.vma", "",     MATCH_SFENCE_VMA, MASK_SFENCE_VMA,      m_op },
194         { "wfi",        "",             MATCH_WFI, MASK_WFI,            m_op },
195         { "csrrw",      "d,E,s",        MATCH_CSRRW, MASK_CSRRW,        m_op },
196         { "csrrs",      "d,E,s",        MATCH_CSRRS, MASK_CSRRS,        m_op },
197         { "csrrc",      "d,E,s",        MATCH_CSRRC, MASK_CSRRC,        m_op },
198         { "csrrwi",     "d,E,Z",        MATCH_CSRRWI, MASK_CSRRWI,      m_op },
199         { "csrrsi",     "d,E,Z",        MATCH_CSRRSI, MASK_CSRRSI,      m_op },
200         { "csrrci",     "d,E,Z",        MATCH_CSRRCI, MASK_CSRRCI,      m_op },
201         { "fadd.s",     "D,S,T",        MATCH_FADD_S, MASK_FADD_S,      m_op },
202         { "fsub.s",     "D,S,T",        MATCH_FSUB_S, MASK_FSUB_S,      m_op },
203         { "fmul.s",     "D,S,T",        MATCH_FMUL_S, MASK_FMUL_S,      m_op },
204         { "fdiv.s",     "D,S,T",        MATCH_FDIV_S, MASK_FDIV_S,      m_op },
205         { "fsgnj.s",    "D,S,T",        MATCH_FSGNJ_S, MASK_FSGNJ_S,    m_op },
206         { "fsgnjn.s",   "D,S,T",        MATCH_FSGNJN_S, MASK_FSGNJN_S,  m_op },
207         { "fsgnjx.s",   "D,S,T",        MATCH_FSGNJX_S, MASK_FSGNJX_S,  m_op },
208         { "fmin.s",     "D,S,T",        MATCH_FMIN_S, MASK_FMIN_S,      m_op },
209         { "fmax.s",     "D,S,T",        MATCH_FMAX_S, MASK_FMAX_S,      m_op },
210         { "fsqrt.s",    "D,S",          MATCH_FSQRT_S, MASK_FSQRT_S,    m_op },
211         { "fadd.d",     "D,S,T",        MATCH_FADD_D, MASK_FADD_D,      m_op },
212         { "fsub.d",     "D,S,T",        MATCH_FSUB_D, MASK_FSUB_D,      m_op },
213         { "fmul.d",     "D,S,T",        MATCH_FMUL_D, MASK_FMUL_D,      m_op },
214         { "fdiv.d",     "D,S,T",        MATCH_FDIV_D, MASK_FDIV_D,      m_op },
215         { "fsgnj.d",    "D,S,T",        MATCH_FSGNJ_D, MASK_FSGNJ_D,    m_op },
216         { "fsgnjn.d",   "D,S,T",        MATCH_FSGNJN_D, MASK_FSGNJN_D,  m_op },
217         { "fsgnjx.d",   "D,S,T",        MATCH_FSGNJX_D, MASK_FSGNJX_D,  m_op },
218         { "fmin.d",     "D,S,T",        MATCH_FMIN_D, MASK_FMIN_D,      m_op },
219         { "fmax.d",     "D,S,T",        MATCH_FMAX_D, MASK_FMAX_D,      m_op },
220         { "fcvt.s.d",   "D,S",          MATCH_FCVT_S_D, MASK_FCVT_S_D,  m_op },
221         { "fcvt.d.s",   "D,S",          MATCH_FCVT_D_S, MASK_FCVT_D_S,  m_op },
222         { "fsqrt.d",    "D,S",          MATCH_FSQRT_D, MASK_FSQRT_D,    m_op },
223         { "fadd.q",     "D,S,T",        MATCH_FADD_Q, MASK_FADD_Q,      m_op },
224         { "fsub.q",     "D,S,T",        MATCH_FSUB_Q, MASK_FSUB_Q,      m_op },
225         { "fmul.q",     "D,S,T",        MATCH_FMUL_Q, MASK_FMUL_Q,      m_op },
226         { "fdiv.q",     "D,S,T",        MATCH_FDIV_Q, MASK_FDIV_Q,      m_op },
227         { "fsgnj.q",    "D,S,T",        MATCH_FSGNJ_Q, MASK_FSGNJ_Q,    m_op },
228         { "fsgnjn.q",   "D,S,T",        MATCH_FSGNJN_Q, MASK_FSGNJN_Q,  m_op },
229         { "fsgnjx.q",   "D,S,T",        MATCH_FSGNJX_Q, MASK_FSGNJX_Q,  m_op },
230         { "fmin.q",     "D,S,T",        MATCH_FMIN_Q, MASK_FMIN_Q,      m_op },
231         { "fmax.q",     "D,S,T",        MATCH_FMAX_Q, MASK_FMAX_Q,      m_op },
232         { "fcvt.s.q",   "D,S",          MATCH_FCVT_S_Q, MASK_FCVT_S_Q,  m_op },
233         { "fcvt.q.s",   "D,S",          MATCH_FCVT_Q_S, MASK_FCVT_Q_S,  m_op },
234         { "fcvt.d.q",   "D,S",          MATCH_FCVT_D_Q, MASK_FCVT_D_Q,  m_op },
235         { "fcvt.q.d",   "D,S",          MATCH_FCVT_Q_D, MASK_FCVT_Q_D,  m_op },
236         { "fsqrt.q",    "D,S",          MATCH_FSQRT_Q, MASK_FSQRT_Q,    m_op },
237         { "fle.s",      "d,S,T",        MATCH_FLE_S, MASK_FLE_S,        m_op },
238         { "flt.s",      "d,S,T",        MATCH_FLT_S, MASK_FLT_S,        m_op },
239         { "feq.s",      "d,S,T",        MATCH_FEQ_S, MASK_FEQ_S,        m_op },
240         { "fle.d",      "d,S,T",        MATCH_FLE_D, MASK_FLE_D,        m_op },
241         { "flt.d",      "d,S,T",        MATCH_FLT_D, MASK_FLT_D,        m_op },
242         { "feq.d",      "d,S,T",        MATCH_FEQ_D, MASK_FEQ_D,        m_op },
243         { "fle.q",      "d,S,T",        MATCH_FLE_Q, MASK_FLE_Q,        m_op },
244         { "flt.q",      "d,S,T",        MATCH_FLT_Q, MASK_FLT_Q,        m_op },
245         { "feq.q",      "d,S,T",        MATCH_FEQ_Q, MASK_FEQ_Q,        m_op },
246         { "fcvt.w.s",   "d,S",          MATCH_FCVT_W_S, MASK_FCVT_W_S,  m_op },
247         { "fcvt.wu.s",  "d,S",          MATCH_FCVT_WU_S, MASK_FCVT_WU_S,m_op },
248         { "fcvt.l.s",   "d,S",          MATCH_FCVT_L_S, MASK_FCVT_L_S,  m_op },
249         { "fcvt.lu.s",  "d,S",          MATCH_FCVT_LU_S, MASK_FCVT_LU_S,m_op },
250         { "fmv.x.w",    "d,S",          MATCH_FMV_X_W, MASK_FMV_X_W,    m_op },
251         { "fclass.s",   "d,S",          MATCH_FCLASS_S, MASK_FCLASS_S,  m_op },
252         { "fcvt.w.d",   "d,S",          MATCH_FCVT_W_D, MASK_FCVT_W_D,  m_op },
253         { "fcvt.wu.d",  "d,S",          MATCH_FCVT_WU_D, MASK_FCVT_WU_D,m_op },
254         { "fcvt.l.d",   "d,S",          MATCH_FCVT_L_D, MASK_FCVT_L_D,  m_op },
255         { "fcvt.lu.d",  "d,S",          MATCH_FCVT_LU_D, MASK_FCVT_LU_D,m_op },
256         { "fmv.x.d",    "d,S",          MATCH_FMV_X_D, MASK_FMV_X_D,    m_op },
257         { "fclass.d",   "d,S",          MATCH_FCLASS_D, MASK_FCLASS_D,  m_op },
258         { "fcvt.w.q",   "d,S",          MATCH_FCVT_W_Q, MASK_FCVT_W_Q,  m_op },
259         { "fcvt.wu.q",  "d,S",          MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q,m_op },
260         { "fcvt.l.q",   "d,S",          MATCH_FCVT_L_Q, MASK_FCVT_L_Q,  m_op },
261         { "fcvt.lu.q",  "d,S",          MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q,m_op },
262         { "fmv.x.q",    "d,S",          MATCH_FMV_X_Q, MASK_FMV_X_Q,    m_op },
263         { "fclass.q",   "d,S",          MATCH_FCLASS_Q, MASK_FCLASS_Q,  m_op },
264         { "fcvt.s.w",   "D,s",          MATCH_FCVT_S_W, MASK_FCVT_S_W,  m_op },
265         { "fcvt.s.wu",  "D,s",          MATCH_FCVT_S_WU, MASK_FCVT_S_WU,m_op },
266         { "fcvt.s.l",   "D,s",          MATCH_FCVT_S_L, MASK_FCVT_S_L,  m_op },
267         { "fcvt.s.lu",  "D,s",          MATCH_FCVT_S_LU, MASK_FCVT_S_LU,m_op },
268         { "fmv.w.x",    "D,s",          MATCH_FMV_W_X, MASK_FMV_W_X,    m_op },
269         { "fcvt.d.w",   "D,s",          MATCH_FCVT_D_W, MASK_FCVT_D_W,  m_op },
270         { "fcvt.d.wu",  "D,s",          MATCH_FCVT_D_WU, MASK_FCVT_D_WU,m_op },
271         { "fcvt.d.l",   "D,s",          MATCH_FCVT_D_L, MASK_FCVT_D_L,  m_op },
272         { "fcvt.d.lu",  "D,s",          MATCH_FCVT_D_LU, MASK_FCVT_D_LU,m_op },
273         { "fmv.d.x",    "D,s",          MATCH_FMV_D_X, MASK_FMV_D_X,    m_op },
274         { "fcvt.q.w",   "D,s",          MATCH_FCVT_Q_W, MASK_FCVT_Q_W,  m_op },
275         { "fcvt.q.wu",  "D,s",          MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU,m_op },
276         { "fcvt.q.l",   "D,s",          MATCH_FCVT_Q_L, MASK_FCVT_Q_L,  m_op },
277         { "fcvt.q.lu",  "D,s",          MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU,m_op },
278         { "fmv.q.x",    "D,s",          MATCH_FMV_Q_X, MASK_FMV_Q_X,    m_op },
279         { "flw",        "D,o(s)",       MATCH_FLW, MASK_FLW,            m_op },
280         { "fld",        "D,o(s)",       MATCH_FLD, MASK_FLD,            m_op },
281         { "flq",        "D,o(s)",       MATCH_FLQ, MASK_FLQ,            m_op },
282         { "fsw",        "T,q(s)",       MATCH_FSW, MASK_FSW,            m_op },
283         { "fsd",        "T,q(s)",       MATCH_FSD, MASK_FSD,            m_op },
284         { "fsq",        "T,q(s)",       MATCH_FSQ, MASK_FSQ,            m_op },
285         { "fmadd.s",    "D,S,T,R",      MATCH_FMADD_S, MASK_FMADD_S,    m_op },
286         { "fmsub.s",    "D,S,T,R",      MATCH_FMSUB_S, MASK_FMSUB_S,    m_op },
287         { "fnmsub.s",   "D,S,T,R",      MATCH_FNMSUB_S, MASK_FNMSUB_S,  m_op },
288         { "fnmadd.s",   "D,S,T,R",      MATCH_FNMADD_S, MASK_FNMADD_S,  m_op },
289         { "fmadd.d",    "D,S,T,R",      MATCH_FMADD_D, MASK_FMADD_D,    m_op },
290         { "fmsub.d",    "D,S,T,R",      MATCH_FMSUB_D, MASK_FMSUB_D,    m_op },
291         { "fnmsub.d",   "D,S,T,R",      MATCH_FNMSUB_D, MASK_FNMSUB_D,  m_op },
292         { "fnmadd.d",   "D,S,T,R",      MATCH_FNMADD_D, MASK_FNMADD_D,  m_op },
293         { "fmadd.q",    "D,S,T,R",      MATCH_FMADD_Q, MASK_FMADD_Q,    m_op },
294         { "fmsub.q",    "D,S,T,R",      MATCH_FMSUB_Q, MASK_FMSUB_Q,    m_op },
295         { "fnmsub.q",   "D,S,T,R",      MATCH_FNMSUB_Q, MASK_FNMSUB_Q,  m_op },
296         { "fnmadd.q",   "D,S,T,R",      MATCH_FNMADD_Q, MASK_FNMADD_Q,  m_op },
297         { NULL, NULL, 0, 0, NULL },
298 };
299
300 static struct riscv_op riscv_c_opcodes[] = {
301         /* Aliases first */
302         { "ret","",MATCH_C_JR | (X_RA << RD_SHIFT), MASK_C_JR | RD_MASK, m_op},
303
304         /* C-Compressed ISA Extension Instructions */
305         { "c.nop",      "",             MATCH_C_NOP, MASK_C_NOP,        m_op },
306         { "c.ebreak",   "",             MATCH_C_EBREAK, MASK_C_EBREAK,  m_op },
307         { "c.jr",       "d",            MATCH_C_JR, MASK_C_JR,          m_op },
308         { "c.jalr",     "d",            MATCH_C_JALR, MASK_C_JALR,      m_op },
309         { "c.jal",      "Ca",           MATCH_C_JAL, MASK_C_JAL,        m_op },
310         { "c.ld",       "Ct,Cl(Cs)",    MATCH_C_LD, MASK_C_LD,          m_op },
311         { "c.sd",       "Ct,Cl(Cs)",    MATCH_C_SD, MASK_C_SD,          m_op },
312         { "c.addiw",    "d,Co",         MATCH_C_ADDIW, MASK_C_ADDIW,    m_op },
313         { "c.ldsp",     "d,Cn(Cc)",     MATCH_C_LDSP, MASK_C_LDSP,      m_op },
314         { "c.sdsp",     "CV,CN(Cc)",    MATCH_C_SDSP, MASK_C_SDSP,      m_op },
315         { "c.addi4spn", "",     MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN,      m_op },
316         { "c.addi16sp", "",     MATCH_C_ADDI16SP, MASK_C_ADDI16SP,      m_op },
317         { "c.fld",      "CD,Cl(Cs)",    MATCH_C_FLD, MASK_C_FLD,        m_op },
318         { "c.lw",       "Ct,Ck(Cs)",    MATCH_C_LW, MASK_C_LW,          m_op },
319         { "c.flw",      "CD,Ck(Cs)",    MATCH_C_FLW, MASK_C_FLW,        m_op },
320         { "c.fsd",      "CD,Cl(Cs)",    MATCH_C_FSD, MASK_C_FSD,        m_op },
321         { "c.sw",       "Ct,Ck(Cs)",    MATCH_C_SW, MASK_C_SW,          m_op },
322         { "c.fsw",      "CD,Ck(Cs)",    MATCH_C_FSW, MASK_C_FSW,        m_op },
323         { "c.addi",     "d,Co",         MATCH_C_ADDI, MASK_C_ADDI,      m_op },
324         { "c.li",       "d,Co",         MATCH_C_LI, MASK_C_LI,          m_op },
325         { "c.lui",      "d,Cu",         MATCH_C_LUI, MASK_C_LUI,        m_op },
326         { "c.srli",     "Cs,C>",        MATCH_C_SRLI, MASK_C_SRLI,      m_op },
327         { "c.srai",     "Cs,C>",        MATCH_C_SRAI, MASK_C_SRAI,      m_op },
328         { "c.andi",     "Cs,Co",        MATCH_C_ANDI, MASK_C_ANDI,      m_op },
329         { "c.sub",      "Cs,Ct",        MATCH_C_SUB, MASK_C_SUB,        m_op },
330         { "c.xor",      "Cs,Ct",        MATCH_C_XOR, MASK_C_XOR,        m_op },
331         { "c.or",       "Cs,Ct",        MATCH_C_OR, MASK_C_OR,          m_op },
332         { "c.and",      "Cs,Ct",        MATCH_C_AND, MASK_C_AND,        m_op },
333         { "c.subw",     "Cs,Ct",        MATCH_C_SUBW, MASK_C_SUBW,      m_op },
334         { "c.addw",     "Cs,Ct",        MATCH_C_ADDW, MASK_C_ADDW,      m_op },
335         { "c.j",        "Ca",           MATCH_C_J, MASK_C_J,            m_op },
336         { "c.beqz",     "Cs,Cp",        MATCH_C_BEQZ, MASK_C_BEQZ,      m_op },
337         { "c.bnez",     "Cs,Cp",        MATCH_C_BNEZ, MASK_C_BNEZ,      m_op },
338         { "c.slli",     "d,C>",         MATCH_C_SLLI, MASK_C_SLLI,      m_op },
339         { "c.fldsp",    "D,Cn(Cc)",     MATCH_C_FLDSP, MASK_C_FLDSP,    m_op },
340         { "c.lwsp",     "d,Cm(Cc)",     MATCH_C_LWSP, MASK_C_LWSP,      m_op },
341         { "c.flwsp",    "D,Cm(Cc)",     MATCH_C_FLWSP, MASK_C_FLWSP,    m_op },
342         { "c.mv",       "d,CV",         MATCH_C_MV, MASK_C_MV,          m_op },
343         { "c.add",      "d,CV",         MATCH_C_ADD, MASK_C_ADD,        m_op },
344         { "c.fsdsp",    "CT,CN(Cc)",    MATCH_C_FSDSP, MASK_C_FSDSP,    m_op },
345         { "c.swsp",     "CV,CM(Cc)",    MATCH_C_SWSP, MASK_C_SWSP,      m_op },
346         { "c.fswsp",    "CT,CM(Cc)",    MATCH_C_FSWSP, MASK_C_FSWSP,    m_op },
347         { NULL, NULL, 0, 0, NULL },
348 };
349
350 static int
351 oprint(struct riscv_op *op, vm_offset_t loc, int insn)
352 {
353         uint32_t rd, rs1, rs2, rs3;
354         uint32_t val;
355         const char *csr_name;
356         int imm;
357         char *p;
358
359         p = op->fmt;
360
361         rd = (insn & RD_MASK) >> RD_SHIFT;
362         rs1 = (insn & RS1_MASK) >> RS1_SHIFT;
363         rs2 = (insn & RS2_MASK) >> RS2_SHIFT;
364
365         db_printf("%s\t", op->name);
366
367         while (*p) {
368                 switch (*p) {
369                 case 'C':       /* C-Compressed ISA extension */
370                         switch (*++p) {
371                         case 't':
372                                 rd = (insn >> 2) & 0x7;
373                                 rd += 0x8;
374                                 db_printf("%s", reg_name[rd]);
375                                 break;
376                         case 's':
377                                 rs2 = (insn >> 7) & 0x7;
378                                 rs2 += 0x8;
379                                 db_printf("%s", reg_name[rs2]);
380                                 break;
381                         case 'l':
382                                 imm = ((insn >> 10) & 0x7) << 3;
383                                 imm |= ((insn >> 5) & 0x3) << 6;
384                                 if (imm & (1 << 8))
385                                         imm |= 0xffffff << 8;
386                                 db_printf("%d", imm);
387                                 break;
388                         case 'k':
389                                 imm = ((insn >> 10) & 0x7) << 3;
390                                 imm |= ((insn >> 6) & 0x1) << 2;
391                                 imm |= ((insn >> 5) & 0x1) << 6;
392                                 if (imm & (1 << 8))
393                                         imm |= 0xffffff << 8;
394                                 db_printf("%d", imm);
395                                 break;
396                         case 'c':
397                                 db_printf("sp");
398                                 break;
399                         case 'n':
400                                 imm = ((insn >> 5) & 0x3) << 3;
401                                 imm |= ((insn >> 12) & 0x1) << 5;
402                                 imm |= ((insn >> 2) & 0x7) << 6;
403                                 if (imm & (1 << 8))
404                                         imm |= 0xffffff << 8;
405                                 db_printf("%d", imm);
406                                 break;
407                         case 'N':
408                                 imm = ((insn >> 10) & 0x7) << 3;
409                                 imm |= ((insn >> 7) & 0x7) << 6;
410                                 if (imm & (1 << 8))
411                                         imm |= 0xffffff << 8;
412                                 db_printf("%d", imm);
413                                 break;
414                         case 'u':
415                                 imm = ((insn >> 2) & 0x1f) << 0;
416                                 imm |= ((insn >> 12) & 0x1) << 5;
417                                 if (imm & (1 << 5))
418                                         imm |= (0x7ffffff << 5); /* sign ext */
419                                 db_printf("0x%lx", imm);
420                                 break;
421                         case 'o':
422                                 imm = ((insn >> 2) & 0x1f) << 0;
423                                 imm |= ((insn >> 12) & 0x1) << 5;
424                                 if (imm & (1 << 5))
425                                         imm |= (0x7ffffff << 5); /* sign ext */
426                                 db_printf("%d", imm);
427                                 break;
428                         case 'a':
429                                 /* imm[11|4|9:8|10|6|7|3:1|5] << 2 */
430                                 imm = ((insn >> 3) & 0x7) << 1;
431                                 imm |= ((insn >> 11) & 0x1) << 4;
432                                 imm |= ((insn >> 2) & 0x1) << 5;
433                                 imm |= ((insn >> 7) & 0x1) << 6;
434                                 imm |= ((insn >> 6) & 0x1) << 7;
435                                 imm |= ((insn >> 9) & 0x3) << 8;
436                                 imm |= ((insn >> 8) & 0x1) << 10;
437                                 imm |= ((insn >> 12) & 0x1) << 11;
438                                 if (imm & (1 << 11))
439                                         imm |= (0xfffff << 12); /* sign ext */
440                                 db_printf("0x%lx", (loc + imm));
441                                 break;
442                         case 'V':
443                                 rs2 = (insn >> 2) & 0x1f;
444                                 db_printf("%s", reg_name[rs2]);
445                                 break;
446                         case '>':
447                                 imm = ((insn >> 2) & 0x1f) << 0;
448                                 imm |= ((insn >> 12) & 0x1) << 5;
449                                 db_printf("%d", imm);
450                         };
451                         break;
452                 case 'd':
453                         db_printf("%s", reg_name[rd]);
454                         break;
455                 case 'D':
456                         db_printf("%s", fp_reg_name[rd]);
457                         break;
458                 case 's':
459                         db_printf("%s", reg_name[rs1]);
460                         break;
461                 case 'S':
462                         db_printf("%s", fp_reg_name[rs1]);
463                         break;
464                 case 't':
465                         db_printf("%s", reg_name[rs2]);
466                         break;
467                 case 'T':
468                         db_printf("%s", fp_reg_name[rs2]);
469                         break;
470                 case 'R':
471                         rs3 = (insn >> 27) & 0x1f;
472                         db_printf("%s", fp_reg_name[rs3]);
473                         break;
474                 case 'Z':
475                         imm = (insn >> 15) & 0x1f;
476                         db_printf("%d", imm);
477                         break;
478                 case 'p':
479                         imm = ((insn >> 8) & 0xf) << 1;
480                         imm |= ((insn >> 25) & 0x3f) << 5;
481                         imm |= ((insn >> 7) & 0x1) << 11;
482                         imm |= ((insn >> 31) & 0x1) << 12;
483                         if (imm & (1 << 12))
484                                 imm |= (0xfffff << 12); /* sign extend */
485                         db_printf("0x%016lx", (loc + imm));
486                         break;
487                 case '(':
488                 case ')':
489                 case '[':
490                 case ']':
491                 case ',':
492                         db_printf("%c", *p);
493                         break;
494                 case '0':
495                         if (!p[1])
496                                 db_printf("%c", *p);
497                         break;
498                         
499                 case 'o':
500                         imm = (insn >> 20) & 0xfff;
501                         if (imm & (1 << 11))
502                                 imm |= (0xfffff << 12); /* sign extend */
503                         db_printf("%d", imm);
504                         break;
505                 case 'q':
506                         imm = (insn >> 7) & 0x1f;
507                         imm |= ((insn >> 25) & 0x7f) << 5;
508                         if (imm & (1 << 11))
509                                 imm |= (0xfffff << 12); /* sign extend */
510                         db_printf("%d", imm);
511                         break;
512                 case 'a':
513                         /* imm[20|10:1|11|19:12] << 12 */
514                         imm = ((insn >> 21) & 0x3ff) << 1;
515                         imm |= ((insn >> 20) & 0x1) << 11;
516                         imm |= ((insn >> 12) & 0xff) << 12;
517                         imm |= ((insn >> 31) & 0x1) << 20;
518                         if (imm & (1 << 20))
519                                 imm |= (0xfff << 20);   /* sign extend */
520                         db_printf("0x%lx", (loc + imm));
521                         break;
522                 case 'u':
523                         /* imm[31:12] << 12 */
524                         imm = (insn >> 12) & 0xfffff;
525                         if (imm & (1 << 20))
526                                 imm |= (0xfff << 20);   /* sign extend */
527                         db_printf("0x%lx", imm);
528                         break;
529                 case 'j':
530                         /* imm[11:0] << 20 */
531                         imm = (insn >> 20) & 0xfff;
532                         if (imm & (1 << 11))
533                                 imm |= (0xfffff << 12); /* sign extend */
534                         db_printf("%d", imm);
535                         break;
536                 case '>':
537                         val = (insn >> 20) & 0x3f;
538                         db_printf("0x%x", val);
539                         break;
540                 case '<':
541                         val = (insn >> 20) & 0x1f;
542                         db_printf("0x%x", val);
543                         break;
544                 case 'E':
545                         val = (insn >> 20) & 0xfff;
546                         csr_name = NULL;
547                         switch (val) {
548 #define DECLARE_CSR(name, num) case num: csr_name = #name; break;
549 #include "machine/encoding.h"
550 #undef DECLARE_CSR
551                         }
552                         if (csr_name)
553                                 db_printf("%s", csr_name);
554                         else
555                                 db_printf("0x%x", val);
556                         break;
557                 case 'P':
558                         if (insn & (1 << 27)) db_printf("i");
559                         if (insn & (1 << 26)) db_printf("o");
560                         if (insn & (1 << 25)) db_printf("r");
561                         if (insn & (1 << 24)) db_printf("w");
562                         break;
563                 case 'Q':
564                         if (insn & (1 << 23)) db_printf("i");
565                         if (insn & (1 << 22)) db_printf("o");
566                         if (insn & (1 << 21)) db_printf("r");
567                         if (insn & (1 << 20)) db_printf("w");
568                         break;
569                 }
570
571                 p++;
572         }
573
574         return (0);
575 }
576
577 vm_offset_t
578 db_disasm(vm_offset_t loc, bool altfmt)
579 {
580         struct riscv_op *op;
581         uint32_t insn;
582         int j;
583
584         insn = db_get_value(loc, 4, 0);
585         for (j = 0; riscv_opcodes[j].name != NULL; j++) {
586                 op = &riscv_opcodes[j];
587                 if (op->match_func(op, insn)) {
588                         oprint(op, loc, insn);
589                         return(loc + 4);
590                 }
591         };
592
593         insn = db_get_value(loc, 2, 0);
594         for (j = 0; riscv_c_opcodes[j].name != NULL; j++) {
595                 op = &riscv_c_opcodes[j];
596                 if (op->match_func(op, insn)) {
597                         oprint(op, loc, insn);
598                         break;
599                 }
600         };
601
602         return(loc + 2);
603 }