Sun May 23 23:22:55 2021 UTC ()
Improve ddb disassembly for mips (and riscv, cribbed from mips).

- use db_read_bytes to get instructions
- move the address check logic previously attached only to fetching
  instructions for disassembly to db_read_bytes (and db_write_bytes)

Motivated by related x86 changes this afternoon.

Note that the address check logic is not as sophisticated as what the
x86 code does, but it's what we had before. (Except that riscv will
now also try to fetch usermode instructions instead of just failing.)


(dholland)
diff -r1.42 -r1.43 src/sys/arch/mips/mips/db_disasm.c
diff -r1.93 -r1.94 src/sys/arch/mips/mips/db_interface.c
diff -r1.7 -r1.8 src/sys/arch/riscv/riscv/db_disasm.c
diff -r1.7 -r1.8 src/sys/arch/riscv/riscv/db_machdep.c

cvs diff -r1.42 -r1.43 src/sys/arch/mips/mips/db_disasm.c (switch to unified diff)

--- src/sys/arch/mips/mips/db_disasm.c 2021/04/12 11:35:22 1.42
+++ src/sys/arch/mips/mips/db_disasm.c 2021/05/23 23:22:55 1.43
@@ -1,920 +1,911 @@ @@ -1,920 +1,911 @@
1/* $NetBSD: db_disasm.c,v 1.42 2021/04/12 11:35:22 simonb Exp $ */ 1/* $NetBSD: db_disasm.c,v 1.43 2021/05/23 23:22:55 dholland Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1991, 1993 4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell. 8 * Ralph Campbell.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 * 33 *
34 * from: @(#)kadb.c 8.1 (Berkeley) 6/10/93 34 * from: @(#)kadb.c 8.1 (Berkeley) 6/10/93
35 */ 35 */
36 36
37#include <sys/cdefs.h> 37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.42 2021/04/12 11:35:22 simonb Exp $"); 38__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.43 2021/05/23 23:22:55 dholland Exp $");
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/cpu.h> 41#include <sys/cpu.h>
42#include <sys/systm.h> 42#include <sys/systm.h>
43 43
44#include <mips/locore.h> 44#include <mips/locore.h>
45#include <mips/mips_opcode.h> 45#include <mips/mips_opcode.h>
46#include <mips/reg.h> 46#include <mips/reg.h>
47 47
48#include <machine/db_machdep.h> 48#include <machine/db_machdep.h>
49 49
 50#include <ddb/db_access.h>
50#include <ddb/db_user.h> 51#include <ddb/db_user.h>
51#include <ddb/db_interface.h> 52#include <ddb/db_interface.h>
52#include <ddb/db_output.h> 53#include <ddb/db_output.h>
53#include <ddb/db_extern.h> 54#include <ddb/db_extern.h>
54#include <ddb/db_sym.h> 55#include <ddb/db_sym.h>
55 56
56static const char * const op_name[64] = { 57static const char * const op_name[64] = {
57/* 0 */ "spec", "regimm","j", "jal", "beq", "bne", "blez", "bgtz", 58/* 0 */ "spec", "regimm","j", "jal", "beq", "bne", "blez", "bgtz",
58/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui", 59/* 8 */ "addi", "addiu","slti", "sltiu","andi", "ori", "xori", "lui",
59/*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl", 60/*16 */ "cop0", "cop1", "cop2", "cop3", "beql", "bnel", "blezl","bgtzl",
60/*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37", 61/*24 */ "daddi","daddiu","ldl", "ldr", "op34", "op35", "op36", "op37",
61/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu", 62/*32 */ "lb", "lh", "lwl", "lw", "lbu", "lhu", "lwr", "lwu",
62/*40 */ "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache", 63/*40 */ "sb", "sh", "swl", "sw", "sdl", "sdr", "swr", "cache",
63#ifdef __OCTEON__ 64#ifdef __OCTEON__
64/*48 */ "ll", "lwc1", "bbit0", "lwc3", "lld", "ldc1", "bbit032", "ld", 65/*48 */ "ll", "lwc1", "bbit0", "lwc3", "lld", "ldc1", "bbit032", "ld",
65/*56 */ "sc", "swc1", "bbit1", "swc3", "scd", "sdc1", "bbit132", "sd" 66/*56 */ "sc", "swc1", "bbit1", "swc3", "scd", "sdc1", "bbit132", "sd"
66#else 67#else
67/*48 */ "ll", "lwc1", "lwc2", "lwc3", "lld", "ldc1", "ldc2", "ld", 68/*48 */ "ll", "lwc1", "lwc2", "lwc3", "lld", "ldc1", "ldc2", "ld",
68/*56 */ "sc", "swc1", "swc2", "swc3", "scd", "sdc1", "sdc2", "sd" 69/*56 */ "sc", "swc1", "swc2", "swc3", "scd", "sdc1", "sdc2", "sd"
69#endif 70#endif
70}; 71};
71 72
72static const char * const spec_name[64] = { 73static const char * const spec_name[64] = {
73/* 0 */ "sll", "movc1","srl", "sra", "sllv", "spec05","srlv","srav", 74/* 0 */ "sll", "movc1","srl", "sra", "sllv", "spec05","srlv","srav",
74/* 8 */ "jr", "jalr", "movz","movn","syscall","break","spec16","sync", 75/* 8 */ "jr", "jalr", "movz","movn","syscall","break","spec16","sync",
75/*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav", 76/*16 */ "mfhi", "mthi", "mflo", "mtlo", "dsllv","spec25","dsrlv","dsrav",
76/*24 */ "mult", "multu","div", "divu", "dmult","dmultu","ddiv","ddivu", 77/*24 */ "mult", "multu","div", "divu", "dmult","dmultu","ddiv","ddivu",
77/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor", 78/*32 */ "add", "addu", "sub", "subu", "and", "or", "xor", "nor",
78/*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu", 79/*40 */ "spec50","spec51","slt","sltu", "dadd","daddu","dsub","dsubu",
79/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67", 80/*48 */ "tge","tgeu","tlt","tltu","teq","spec65","tne","spec67",
80/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32" 81/*56 */ "dsll","spec71","dsrl","dsra","dsll32","spec75","dsrl32","dsra32"
81}; 82};
82 83
83static const char * const spec2_name[64] = { /* QED, MIPS32/64, etc. */ 84static const char * const spec2_name[64] = { /* QED, MIPS32/64, etc. */
84 [OP_MADD] = "madd", 85 [OP_MADD] = "madd",
85 [OP_MADDU] = "maddu", 86 [OP_MADDU] = "maddu",
86 [OP_MUL] = "mul", 87 [OP_MUL] = "mul",
87#ifdef __OCTEON__ 88#ifdef __OCTEON__
88 [OP_CVM_DMUL] = "dmul", 89 [OP_CVM_DMUL] = "dmul",
89#endif 90#endif
90 [OP_MSUB] = "msub", 91 [OP_MSUB] = "msub",
91 [OP_MSUBU] = "msubu", 92 [OP_MSUBU] = "msubu",
92 [OP_CLZ] = "clz", 93 [OP_CLZ] = "clz",
93 [OP_CLO] = "clo", 94 [OP_CLO] = "clo",
94 [OP_DCLZ] = "dclz", 95 [OP_DCLZ] = "dclz",
95 [OP_DCLO] = "dclo", 96 [OP_DCLO] = "dclo",
96#ifdef __OCTEON__ 97#ifdef __OCTEON__
97 [OP_CVM_BADDU] = "baddu", 98 [OP_CVM_BADDU] = "baddu",
98 [OP_CVM_POP] = "pop", 99 [OP_CVM_POP] = "pop",
99 [OP_CVM_DPOP] = "dpop", 100 [OP_CVM_DPOP] = "dpop",
100 [OP_CVM_CINS] = "cins", 101 [OP_CVM_CINS] = "cins",
101 [OP_CVM_CINS32] = "cins32", 102 [OP_CVM_CINS32] = "cins32",
102 [OP_CVM_EXTS] = "exts", 103 [OP_CVM_EXTS] = "exts",
103 [OP_CVM_EXTS32] = "exts32", 104 [OP_CVM_EXTS32] = "exts32",
104 [OP_CVM_SEQ] = "seq", 105 [OP_CVM_SEQ] = "seq",
105 [OP_CVM_SEQI] = "seqi", 106 [OP_CVM_SEQI] = "seqi",
106 [OP_CVM_SNE] = "sne", 107 [OP_CVM_SNE] = "sne",
107 [OP_CVM_SNEI] = "snei", 108 [OP_CVM_SNEI] = "snei",
108 [OP_CVM_SAA] = "saa", 109 [OP_CVM_SAA] = "saa",
109 [OP_CVM_SAAD] = "saad", 110 [OP_CVM_SAAD] = "saad",
110#endif 111#endif
111 [OP_SDBBP] = "sdbbp", 112 [OP_SDBBP] = "sdbbp",
112}; 113};
113 114
114static const char * const spec3_name[64] = { 115static const char * const spec3_name[64] = {
115 [OP_EXT] = "ext", 116 [OP_EXT] = "ext",
116 [OP_DEXTM] = "dextm", 117 [OP_DEXTM] = "dextm",
117 [OP_DEXTU] = "dextu", 118 [OP_DEXTU] = "dextu",
118 [OP_DEXT] = "dext", 119 [OP_DEXT] = "dext",
119 [OP_INS] = "ins", 120 [OP_INS] = "ins",
120 [OP_DINSM] = "dinsm", 121 [OP_DINSM] = "dinsm",
121 [OP_DINSU] = "dinsu", 122 [OP_DINSU] = "dinsu",
122 [OP_DINS] = "dins", 123 [OP_DINS] = "dins",
123 [OP_LWLE] = "lwle", 124 [OP_LWLE] = "lwle",
124 [OP_LWRE] = "lwre", 125 [OP_LWRE] = "lwre",
125 [OP_CACHEE] = "cachee", 126 [OP_CACHEE] = "cachee",
126 [OP_SBE] = "sbe", 127 [OP_SBE] = "sbe",
127 [OP_SHE] = "she", 128 [OP_SHE] = "she",
128 [OP_SCE] = "sce", 129 [OP_SCE] = "sce",
129 [OP_SWE] = "swe", 130 [OP_SWE] = "swe",
130 [OP_BSHFL] = "bshfl", 131 [OP_BSHFL] = "bshfl",
131 [OP_SWLE] = "swle", 132 [OP_SWLE] = "swle",
132 [OP_SWRE] = "swre", 133 [OP_SWRE] = "swre",
133 [OP_PREFE] = "prefe", 134 [OP_PREFE] = "prefe",
134 [OP_DBSHFL] = "dbshfl", 135 [OP_DBSHFL] = "dbshfl",
135 [OP_CACHE_R6] = "cache", 136 [OP_CACHE_R6] = "cache",
136 [OP_LBUE] = "lbue", 137 [OP_LBUE] = "lbue",
137 [OP_LHUE] = "lhue", 138 [OP_LHUE] = "lhue",
138 [OP_LBE] = "lbe", 139 [OP_LBE] = "lbe",
139 [OP_LHE] = "lhe", 140 [OP_LHE] = "lhe",
140 [OP_LLE] = "lle", 141 [OP_LLE] = "lle",
141 [OP_LWE] = "lwe", 142 [OP_LWE] = "lwe",
142 [OP_RDHWR] = "rdhwr", 143 [OP_RDHWR] = "rdhwr",
143}; 144};
144 145
145static const char * const regimm_name[32] = { 146static const char * const regimm_name[32] = {
146/* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?", 147/* 0 */ "bltz", "bgez", "bltzl", "bgezl", "?", "?", "?", "?",
147/* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?", 148/* 8 */ "tgei", "tgeiu", "tlti", "tltiu", "teqi", "?", "tnei", "?",
148/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?", 149/*16 */ "bltzal", "bgezal", "bltzall", "bgezall", "?", "?", "?", "?",
149/*24 */ "?", "?", "?", "?", "bposge32", "?", "?", "?", 150/*24 */ "?", "?", "?", "?", "bposge32", "?", "?", "?",
150}; 151};
151 152
152static const char * const cop1_name[64] = { 153static const char * const cop1_name[64] = {
153/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg", 154/* 0 */ "fadd", "fsub", "fmpy", "fdiv", "fsqrt","fabs", "fmov", "fneg",
154/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f", 155/* 8 */ "fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
155/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17", 156/*16 */ "fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
156/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f", 157/*24 */ "fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
157/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27", 158/*32 */ "fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
158/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f", 159/*40 */ "fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
159/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult", 160/*48 */ "fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
160 "fcmp.ole","fcmp.ule", 161 "fcmp.ole","fcmp.ule",
161/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge", 162/*56 */ "fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
162 "fcmp.le","fcmp.ngt" 163 "fcmp.le","fcmp.ngt"
163}; 164};
164 165
165static const char * const fmt_name[16] = { 166static const char * const fmt_name[16] = {
166 "s", "d", "e", "fmt3", 167 "s", "d", "e", "fmt3",
167 "w", "fmt5", "fmt6", "fmt7", 168 "w", "fmt5", "fmt6", "fmt7",
168 "fmt8", "fmt9", "fmta", "fmtb", 169 "fmt8", "fmt9", "fmta", "fmtb",
169 "fmtc", "fmtd", "fmte", "fmtf" 170 "fmtc", "fmtd", "fmte", "fmtf"
170}; 171};
171 172
172#if defined(__mips_n32) || defined(__mips_n64) 173#if defined(__mips_n32) || defined(__mips_n64)
173static const char * const reg_name[32] = { 174static const char * const reg_name[32] = {
174 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", 175 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
175 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", 176 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
176 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", 177 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
177 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" 178 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
178}; 179};
179#else 180#else
180static const char * const reg_name[32] = { 181static const char * const reg_name[32] = {
181 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", 182 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
182 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", 183 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
183 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", 184 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
184 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra" 185 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
185}; 186};
186#endif /* __mips_n32 || __mips_n64 */ 187#endif /* __mips_n32 || __mips_n64 */
187 188
188static const char * const c0_opname[64] = { 189static const char * const c0_opname[64] = {
189 "c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07", 190 "c0op00","tlbr", "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
190 "tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17", 191 "tlbp", "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
191 "rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27", 192 "rfe", "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
192 "eret", "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37", 193 "eret", "c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
193 "c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47", 194 "c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
194 "c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57", 195 "c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
195 "c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67", 196 "c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
196 "c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77", 197 "c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
197}; 198};
198 199
199static const char * const c0_reg[32] = { 200static const char * const c0_reg[32] = {
200 "index", "random", "tlblo0", "tlblo1", 201 "index", "random", "tlblo0", "tlblo1",
201 "context", "pagemask", "wired", "hwrena", 202 "context", "pagemask", "wired", "hwrena",
202 "badvaddr", "count", "tlbhi", "compare", 203 "badvaddr", "count", "tlbhi", "compare",
203 "status", "cause", "epc", "prid", 204 "status", "cause", "epc", "prid",
204 "config", "lladdr", "watchlo", "watchhi", 205 "config", "lladdr", "watchlo", "watchhi",
205 "xcontext", "cp0r21", "osscratch", "debug", 206 "xcontext", "cp0r21", "osscratch", "debug",
206 "depc", "perfcnt", "ecc", "cacheerr", 207 "depc", "perfcnt", "ecc", "cacheerr",
207 "taglo", "taghi", "errepc", "desave" 208 "taglo", "taghi", "errepc", "desave"
208}; 209};
209 210
210static void print_addr(db_addr_t); 211static void print_addr(db_addr_t);
211 212
212/* 213/*
213 * Disassemble instruction at 'loc'. 'altfmt' specifies an 214 * Disassemble instruction at 'loc'. 'altfmt' specifies an
214 * (optional) alternate format (altfmt for vax: don't assume 215 * (optional) alternate format (altfmt for vax: don't assume
215 * that each external label is a procedure entry mask). 216 * that each external label is a procedure entry mask).
216 * Return address of start of next instruction. 217 * Return address of start of next instruction.
217 * Since this function is used by 'examine' and by 'step' 218 * Since this function is used by 'examine' and by 'step'
218 * "next instruction" does NOT mean the next instruction to 219 * "next instruction" does NOT mean the next instruction to
219 * be executed but the 'linear' next instruction. 220 * be executed but the 'linear' next instruction.
220 */ 221 */
221#ifdef _LP64 
222#define DISASM_KERN_START MIPS_XKSEG_START 
223#else 
224#define DISASM_KERN_START MIPS_KSEG0_START 
225#endif 
226db_addr_t 222db_addr_t
227db_disasm(db_addr_t loc, bool altfmt) 223db_disasm(db_addr_t loc, bool altfmt)
228{ 224{
229 uint32_t instr; 225 uint32_t instr;
230 226
231 /* 227 /*
232 * Take some care with addresses to not UTLB here as it 228 * Take some care with addresses to not UTLB here as it
233 * loses the current debugging context. KSEG2 and XKSEG 229 * loses the current debugging context. KSEG2 and XKSEG
234 * are not checked. 230 * are not checked.
 231 * Update: db_read_bytes is supposed to do that, and now
 232 * does, so we can use that.
 233 *
 234 * XXX db_read_bytes_can't return failure but instead zeros
 235 * the output. That's ok here, but if ever improved the
 236 * proper thing here on error is to return the original loc.
235 */ 237 */
236 if (loc < (db_addr_t)DISASM_KERN_START) { 238 db_read_bytes(loc, sizeof(instr), (void *)&instr);
237#ifdef _KERNEL 
238 if (ufetch_32((void *)loc, &instr) != 0) { 
239 db_printf("invalid address.\n"); 
240 return loc; 
241 } 
242#else 
243 return loc; 
244#endif 
245 } else { 
246 instr = *(uint32_t *)loc; 
247 } 
248 239
249 return (db_disasm_insn(instr, loc, altfmt)); 240 return (db_disasm_insn(instr, loc, altfmt));
250} 241}
251 242
252 243
253/* 244/*
254 * Disassemble instruction 'insn' nominally at 'loc'. 245 * Disassemble instruction 'insn' nominally at 'loc'.
255 * 'loc' may in fact contain a breakpoint instruction. 246 * 'loc' may in fact contain a breakpoint instruction.
256 */ 247 */
257db_addr_t 248db_addr_t
258db_disasm_insn(int insn, db_addr_t loc, bool altfmt) 249db_disasm_insn(int insn, db_addr_t loc, bool altfmt)
259{ 250{
260 bool bdslot = false; 251 bool bdslot = false;
261 InstFmt i; 252 InstFmt i;
262 253
263 i.word = insn; 254 i.word = insn;
264 255
265 switch (i.JType.op) { 256 switch (i.JType.op) {
266 case OP_SPECIAL: { 257 case OP_SPECIAL: {
267 const char *name = spec_name[i.RType.func]; 258 const char *name = spec_name[i.RType.func];
268 259
269 /* Handle varations of NOPs */ 260 /* Handle varations of NOPs */
270 if ((i.RType.func == OP_SLL) && 261 if ((i.RType.func == OP_SLL) &&
271 (i.RType.rs == 0) && 262 (i.RType.rs == 0) &&
272 (i.RType.rt == 0) && 263 (i.RType.rt == 0) &&
273 (i.RType.rd == 0)) { 264 (i.RType.rd == 0)) {
274 switch (i.RType.shamt) { 265 switch (i.RType.shamt) {
275 case OP_SLL_NOP: 266 case OP_SLL_NOP:
276 db_printf("nop"); 267 db_printf("nop");
277 break; 268 break;
278 case OP_SLL_SSNOP: 269 case OP_SLL_SSNOP:
279 db_printf("ssnop"); 270 db_printf("ssnop");
280 break; 271 break;
281 case OP_SLL_EHB: 272 case OP_SLL_EHB:
282 db_printf("ehb"); 273 db_printf("ehb");
283 break; 274 break;
284 case OP_SLL_PAUSE: 275 case OP_SLL_PAUSE:
285 db_printf("pause"); 276 db_printf("pause");
286 break; 277 break;
287 default: 278 default:
288 db_printf("nop *"); /* "undefined" NOP */ 279 db_printf("nop *"); /* "undefined" NOP */
289 break; 280 break;
290 } 281 }
291 break; 282 break;
292 } 283 }
293 284
294 /* 285 /*
295 * The following are equivalents of a "move dst,src": 286 * The following are equivalents of a "move dst,src":
296 * addu dst,src,zero (in 32-bit mode) 287 * addu dst,src,zero (in 32-bit mode)
297 * daddu dst,src,zero (in 64-bit mode) 288 * daddu dst,src,zero (in 64-bit mode)
298 * or dst,src,zero (in 32- and 64-bit modes) 289 * or dst,src,zero (in 32- and 64-bit modes)
299 */ 290 */
300#ifdef __mips_o32 291#ifdef __mips_o32
301#define OP_MOVE_ADDU OP_ADDU 292#define OP_MOVE_ADDU OP_ADDU
302#else 293#else
303#define OP_MOVE_ADDU OP_DADDU 294#define OP_MOVE_ADDU OP_DADDU
304#endif 295#endif
305 if (true && 296 if (true &&
306 ((i.RType.func == OP_OR) || (i.RType.func == OP_MOVE_ADDU)) 297 ((i.RType.func == OP_OR) || (i.RType.func == OP_MOVE_ADDU))
307 && i.RType.rt == 0) { 298 && i.RType.rt == 0) {
308 db_printf("move\t%s,%s", 299 db_printf("move\t%s,%s",
309 reg_name[i.RType.rd], 300 reg_name[i.RType.rd],
310 reg_name[i.RType.rs]); 301 reg_name[i.RType.rs]);
311 break; 302 break;
312 } 303 }
313 304
314 if ((i.RType.func == OP_SRL || i.RType.func == OP_SRLV) 305 if ((i.RType.func == OP_SRL || i.RType.func == OP_SRLV)
315 && i.RType.rs == 1) { 306 && i.RType.rs == 1) {
316 name = (i.RType.func == OP_SRL) ? "rotr" : "rotrv"; 307 name = (i.RType.func == OP_SRL) ? "rotr" : "rotrv";
317 } else if ((i.RType.func == OP_DSRL || i.RType.func == OP_DSRLV) 308 } else if ((i.RType.func == OP_DSRL || i.RType.func == OP_DSRLV)
318 && i.RType.shamt == 1) { 309 && i.RType.shamt == 1) {
319 name = (i.RType.func == OP_DSRL) ? "drotr" : "drotrv"; 310 name = (i.RType.func == OP_DSRL) ? "drotr" : "drotrv";
320 } 311 }
321 312
322 db_printf("%s", name); 313 db_printf("%s", name);
323 switch (i.RType.func) { 314 switch (i.RType.func) {
324 case OP_SLL: 315 case OP_SLL:
325 case OP_SRL: 316 case OP_SRL:
326 case OP_SRA: 317 case OP_SRA:
327 case OP_DSLL: 318 case OP_DSLL:
328 case OP_DSRL: 319 case OP_DSRL:
329 case OP_DSRA: 320 case OP_DSRA:
330 case OP_DSLL32: 321 case OP_DSLL32:
331 case OP_DSRL32: 322 case OP_DSRL32:
332 case OP_DSRA32: 323 case OP_DSRA32:
333 db_printf("\t%s,%s,%d", 324 db_printf("\t%s,%s,%d",
334 reg_name[i.RType.rd], 325 reg_name[i.RType.rd],
335 reg_name[i.RType.rt], 326 reg_name[i.RType.rt],
336 i.RType.shamt); 327 i.RType.shamt);
337 break; 328 break;
338 329
339 case OP_SLLV: 330 case OP_SLLV:
340 case OP_SRLV: 331 case OP_SRLV:
341 case OP_SRAV: 332 case OP_SRAV:
342 case OP_DSLLV: 333 case OP_DSLLV:
343 case OP_DSRLV: 334 case OP_DSRLV:
344 case OP_DSRAV: 335 case OP_DSRAV:
345 db_printf("\t%s,%s,%s", 336 db_printf("\t%s,%s,%s",
346 reg_name[i.RType.rd], 337 reg_name[i.RType.rd],
347 reg_name[i.RType.rt], 338 reg_name[i.RType.rt],
348 reg_name[i.RType.rs]); 339 reg_name[i.RType.rs]);
349 break; 340 break;
350 341
351 case OP_MFHI: 342 case OP_MFHI:
352 case OP_MFLO: 343 case OP_MFLO:
353 db_printf("\t%s", reg_name[i.RType.rd]); 344 db_printf("\t%s", reg_name[i.RType.rd]);
354 break; 345 break;
355 346
356 case OP_JR: 347 case OP_JR:
357 case OP_JALR: 348 case OP_JALR:
358 db_printf("\t%s%s", reg_name[i.RType.rs], 349 db_printf("\t%s%s", reg_name[i.RType.rs],
359 (insn & __BIT(10)) ? ".hb" : ""); 350 (insn & __BIT(10)) ? ".hb" : "");
360 bdslot = true; 351 bdslot = true;
361 break; 352 break;
362 case OP_MTLO: 353 case OP_MTLO:
363 case OP_MTHI: 354 case OP_MTHI:
364 db_printf("\t%s", reg_name[i.RType.rs]); 355 db_printf("\t%s", reg_name[i.RType.rs]);
365 break; 356 break;
366 357
367 case OP_MULT: 358 case OP_MULT:
368 case OP_MULTU: 359 case OP_MULTU:
369 case OP_DMULT: 360 case OP_DMULT:
370 case OP_DMULTU: 361 case OP_DMULTU:
371 case OP_DIV: 362 case OP_DIV:
372 case OP_DIVU: 363 case OP_DIVU:
373 case OP_DDIV: 364 case OP_DDIV:
374 case OP_DDIVU: 365 case OP_DDIVU:
375 db_printf("\t%s,%s", 366 db_printf("\t%s,%s",
376 reg_name[i.RType.rs], 367 reg_name[i.RType.rs],
377 reg_name[i.RType.rt]); 368 reg_name[i.RType.rt]);
378 break; 369 break;
379 370
380 371
381 case OP_SYSCALL: 372 case OP_SYSCALL:
382 break; 373 break;
383 case OP_SYNC: 374 case OP_SYNC:
384 if (i.RType.shamt != 0) 375 if (i.RType.shamt != 0)
385 db_printf("\t%d", i.RType.shamt); 376 db_printf("\t%d", i.RType.shamt);
386 break; 377 break;
387 378
388 case OP_BREAK: 379 case OP_BREAK:
389 db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt); 380 db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt);
390 break; 381 break;
391 382
392 case OP_TEQ: 383 case OP_TEQ:
393 db_printf("\t%s,%s,%#x", 384 db_printf("\t%s,%s,%#x",
394 reg_name[i.RType.rs], 385 reg_name[i.RType.rs],
395 reg_name[i.RType.rt], 386 reg_name[i.RType.rt],
396 (i.RType.rd << 5) | i.RType.shamt); 387 (i.RType.rd << 5) | i.RType.shamt);
397 break; 388 break;
398 389
399 default: 390 default:
400 db_printf("\t%s,%s,%s", 391 db_printf("\t%s,%s,%s",
401 reg_name[i.RType.rd], 392 reg_name[i.RType.rd],
402 reg_name[i.RType.rs], 393 reg_name[i.RType.rs],
403 reg_name[i.RType.rt]); 394 reg_name[i.RType.rt]);
404 } 395 }
405 break; 396 break;
406 } 397 }
407 398
408 case OP_SPECIAL2: 399 case OP_SPECIAL2:
409 if (spec_name[i.RType.func] == NULL) { 400 if (spec_name[i.RType.func] == NULL) {
410 db_printf("spec2#%03o\t%s,%s", 401 db_printf("spec2#%03o\t%s,%s",
411 i.RType.func, 402 i.RType.func,
412 reg_name[i.RType.rs], 403 reg_name[i.RType.rs],
413 reg_name[i.RType.rt]); 404 reg_name[i.RType.rt]);
414 break; 405 break;
415 } 406 }
416 if (i.RType.func == OP_MUL 407 if (i.RType.func == OP_MUL
417#ifdef __OCTEON__ 408#ifdef __OCTEON__
418 || i.RType.func == OP_CVM_DMUL 409 || i.RType.func == OP_CVM_DMUL
419 || i.RType.func == OP_CVM_SEQ 410 || i.RType.func == OP_CVM_SEQ
420 || i.RType.func == OP_CVM_SNE 411 || i.RType.func == OP_CVM_SNE
421#endif 412#endif
422 || false) { 413 || false) {
423 db_printf("%s\t%s,%s,%s", 414 db_printf("%s\t%s,%s,%s",
424 spec2_name[i.RType.func], 415 spec2_name[i.RType.func],
425 reg_name[i.RType.rd], 416 reg_name[i.RType.rd],
426 reg_name[i.RType.rs], 417 reg_name[i.RType.rs],
427 reg_name[i.RType.rt]); 418 reg_name[i.RType.rt]);
428 break; 419 break;
429 } 420 }
430#ifdef __OCTEON__ 421#ifdef __OCTEON__
431 if (i.RType.func == OP_CVM_CINS 422 if (i.RType.func == OP_CVM_CINS
432 || i.RType.func == OP_CVM_CINS32 423 || i.RType.func == OP_CVM_CINS32
433 || i.RType.func == OP_CVM_EXTS 424 || i.RType.func == OP_CVM_EXTS
434 || i.RType.func == OP_CVM_EXTS32) { 425 || i.RType.func == OP_CVM_EXTS32) {
435 db_printf("%s\t%s,%s,%d,%d", 426 db_printf("%s\t%s,%s,%d,%d",
436 spec2_name[i.RType.func], 427 spec2_name[i.RType.func],
437 reg_name[i.RType.rt], 428 reg_name[i.RType.rt],
438 reg_name[i.RType.rs], 429 reg_name[i.RType.rs],
439 i.RType.shamt, 430 i.RType.shamt,
440 i.RType.rd); 431 i.RType.rd);
441 break; 432 break;
442 } 433 }
443 if (i.RType.func == OP_CVM_SEQI 434 if (i.RType.func == OP_CVM_SEQI
444 || i.RType.func == OP_CVM_SNEI) { 435 || i.RType.func == OP_CVM_SNEI) {
445 db_printf("%s\t%s,%s,%d", 436 db_printf("%s\t%s,%s,%d",
446 spec2_name[i.RType.func], 437 spec2_name[i.RType.func],
447 reg_name[i.RType.rs], 438 reg_name[i.RType.rs],
448 reg_name[i.RType.rt], 439 reg_name[i.RType.rt],
449 (short)i.IType.imm >> 6); 440 (short)i.IType.imm >> 6);
450 break; 441 break;
451 } 442 }
452 if (i.RType.func == OP_CVM_SAA 443 if (i.RType.func == OP_CVM_SAA
453 || i.RType.func == OP_CVM_SAAD) { 444 || i.RType.func == OP_CVM_SAAD) {
454 db_printf("%s\t%s,(%s)", 445 db_printf("%s\t%s,(%s)",
455 spec2_name[i.RType.func], 446 spec2_name[i.RType.func],
456 reg_name[i.RType.rt], 447 reg_name[i.RType.rt],
457 reg_name[i.RType.rs]); 448 reg_name[i.RType.rs]);
458 break; 449 break;
459 } 450 }
460#endif 451#endif
461 if (i.RType.func == OP_CLO 452 if (i.RType.func == OP_CLO
462 || i.RType.func == OP_DCLO 453 || i.RType.func == OP_DCLO
463#ifdef __OCTEON__ 454#ifdef __OCTEON__
464 || i.RType.func == OP_CVM_POP 455 || i.RType.func == OP_CVM_POP
465 || i.RType.func == OP_CVM_DPOP 456 || i.RType.func == OP_CVM_DPOP
466#endif 457#endif
467 || i.RType.func == OP_CLZ 458 || i.RType.func == OP_CLZ
468 || i.RType.func == OP_DCLZ) { 459 || i.RType.func == OP_DCLZ) {
469 db_printf("%s\t%s,%s", 460 db_printf("%s\t%s,%s",
470 spec2_name[i.RType.func], 461 spec2_name[i.RType.func],
471 reg_name[i.RType.rs], 462 reg_name[i.RType.rs],
472 reg_name[i.RType.rd]); 463 reg_name[i.RType.rd]);
473 break; 464 break;
474 } 465 }
475 db_printf("%s\t%s,%s", 466 db_printf("%s\t%s,%s",
476 spec2_name[i.RType.func], 467 spec2_name[i.RType.func],
477 reg_name[i.RType.rs], 468 reg_name[i.RType.rs],
478 reg_name[i.RType.rt]); 469 reg_name[i.RType.rt]);
479 break; 470 break;
480 471
481 case OP_SPECIAL3: 472 case OP_SPECIAL3:
482 if (spec3_name[i.RType.func] == NULL) { 473 if (spec3_name[i.RType.func] == NULL) {
483 db_printf("spec3#%03o\t%s,%s", 474 db_printf("spec3#%03o\t%s,%s",
484 i.RType.func, 475 i.RType.func,
485 reg_name[i.RType.rs], 476 reg_name[i.RType.rs],
486 reg_name[i.RType.rt]); 477 reg_name[i.RType.rt]);
487 break; 478 break;
488 } 479 }
489 if (i.RType.func <= OP_DINS) { 480 if (i.RType.func <= OP_DINS) {
490 int pos = i.RType.shamt; 481 int pos = i.RType.shamt;
491 int size = i.RType.rd - pos + 1; 482 int size = i.RType.rd - pos + 1;
492 size += (((i.RType.func & 3) == 1) ? 32 : 0); 483 size += (((i.RType.func & 3) == 1) ? 32 : 0);
493 pos += (((i.RType.func & 3) == 2) ? 32 : 0); 484 pos += (((i.RType.func & 3) == 2) ? 32 : 0);
494  485
495 db_printf("%s\t%s,%s,%d,%d", 486 db_printf("%s\t%s,%s,%d,%d",
496 spec3_name[i.RType.func], 487 spec3_name[i.RType.func],
497 reg_name[i.RType.rt], 488 reg_name[i.RType.rt],
498 reg_name[i.RType.rs], 489 reg_name[i.RType.rs],
499 pos, size); 490 pos, size);
500 break; 491 break;
501 } 492 }
502 if (i.RType.func == OP_RDHWR) { 493 if (i.RType.func == OP_RDHWR) {
503 db_printf("%s\t%s,$%d", 494 db_printf("%s\t%s,$%d",
504 spec3_name[i.RType.func], 495 spec3_name[i.RType.func],
505 reg_name[i.RType.rt], 496 reg_name[i.RType.rt],
506 i.RType.rd); 497 i.RType.rd);
507 break; 498 break;
508 } 499 }
509 if (i.RType.func == OP_BSHFL) { 500 if (i.RType.func == OP_BSHFL) {
510 if (i.RType.shamt == OP_BSHFL_SBH) { 501 if (i.RType.shamt == OP_BSHFL_SBH) {
511 db_printf("wsbh\t%s,%s", 502 db_printf("wsbh\t%s,%s",
512 reg_name[i.RType.rd], 503 reg_name[i.RType.rd],
513 reg_name[i.RType.rt]); 504 reg_name[i.RType.rt]);
514 } else if (i.RType.shamt == OP_BSHFL_SEB) { 505 } else if (i.RType.shamt == OP_BSHFL_SEB) {
515 db_printf("seb\t%s,%s", 506 db_printf("seb\t%s,%s",
516 reg_name[i.RType.rd], 507 reg_name[i.RType.rd],
517 reg_name[i.RType.rt]); 508 reg_name[i.RType.rt]);
518 } else if (i.RType.shamt == OP_BSHFL_SEH) { 509 } else if (i.RType.shamt == OP_BSHFL_SEH) {
519 db_printf("seh\t%s,%s", 510 db_printf("seh\t%s,%s",
520 reg_name[i.RType.rd], 511 reg_name[i.RType.rd],
521 reg_name[i.RType.rt]); 512 reg_name[i.RType.rt]);
522 } else { 513 } else {
523 db_printf("bshfl\t%s,%s,%d", 514 db_printf("bshfl\t%s,%s,%d",
524 reg_name[i.RType.rd], 515 reg_name[i.RType.rd],
525 reg_name[i.RType.rt], 516 reg_name[i.RType.rt],
526 i.RType.shamt); 517 i.RType.shamt);
527 } 518 }
528 break; 519 break;
529 } 520 }
530 if (i.RType.func == OP_DBSHFL) { 521 if (i.RType.func == OP_DBSHFL) {
531 if (i.RType.shamt == OP_BSHFL_SBH) { 522 if (i.RType.shamt == OP_BSHFL_SBH) {
532 db_printf("dsbh\t%s,%s", 523 db_printf("dsbh\t%s,%s",
533 reg_name[i.RType.rd], 524 reg_name[i.RType.rd],
534 reg_name[i.RType.rt]); 525 reg_name[i.RType.rt]);
535 } else if (i.RType.shamt == OP_BSHFL_SHD) { 526 } else if (i.RType.shamt == OP_BSHFL_SHD) {
536 db_printf("dshd\t%s,%s", 527 db_printf("dshd\t%s,%s",
537 reg_name[i.RType.rd], 528 reg_name[i.RType.rd],
538 reg_name[i.RType.rt]); 529 reg_name[i.RType.rt]);
539 } else { 530 } else {
540 db_printf("dbshfl\t%s,%s,%d", 531 db_printf("dbshfl\t%s,%s,%d",
541 reg_name[i.RType.rd], 532 reg_name[i.RType.rd],
542 reg_name[i.RType.rt], 533 reg_name[i.RType.rt],
543 i.RType.shamt); 534 i.RType.shamt);
544 } 535 }
545 break; 536 break;
546 } 537 }
547 switch (i.RType.func) { 538 switch (i.RType.func) {
548 case OP_LWLE: 539 case OP_LWLE:
549 case OP_LWRE: 540 case OP_LWRE:
550 case OP_CACHEE: 541 case OP_CACHEE:
551 case OP_SBE: 542 case OP_SBE:
552 case OP_SHE: 543 case OP_SHE:
553 case OP_SCE: 544 case OP_SCE:
554 case OP_SWE: 545 case OP_SWE:
555 case OP_SWLE: 546 case OP_SWLE:
556 case OP_SWRE: 547 case OP_SWRE:
557 case OP_PREFE: 548 case OP_PREFE:
558 case OP_CACHE_R6: 549 case OP_CACHE_R6:
559 case OP_LBUE: 550 case OP_LBUE:
560 case OP_LHUE: 551 case OP_LHUE:
561 case OP_LBE: 552 case OP_LBE:
562 case OP_LHE: 553 case OP_LHE:
563 case OP_LLE: 554 case OP_LLE:
564 case OP_LWE: 555 case OP_LWE:
565 db_printf("%s\t%s,%d(%s)", 556 db_printf("%s\t%s,%d(%s)",
566 spec3_name[i.RType.func], 557 spec3_name[i.RType.func],
567 reg_name[i.RType.rs], 558 reg_name[i.RType.rs],
568 i.S3OType.offset > 255 ? 559 i.S3OType.offset > 255 ?
569 -i.S3OType.offset : i.S3OType.offset, 560 -i.S3OType.offset : i.S3OType.offset,
570 reg_name[i.RType.rt]); 561 reg_name[i.RType.rt]);
571 break; 562 break;
572 default: 563 default:
573 db_printf("%s\t%s,%s", 564 db_printf("%s\t%s,%s",
574 spec3_name[i.RType.func], 565 spec3_name[i.RType.func],
575 reg_name[i.RType.rs], 566 reg_name[i.RType.rs],
576 reg_name[i.RType.rt]); 567 reg_name[i.RType.rt]);
577 } 568 }
578 break; 569 break;
579 570
580 case OP_REGIMM: 571 case OP_REGIMM:
581 db_printf("%s\t%s,", regimm_name[i.IType.rt], 572 db_printf("%s\t%s,", regimm_name[i.IType.rt],
582 reg_name[i.IType.rs]); 573 reg_name[i.IType.rs]);
583 if (i.IType.rt >= OP_TGEI && i.IType.rt <= OP_TNEI) { 574 if (i.IType.rt >= OP_TGEI && i.IType.rt <= OP_TNEI) {
584 db_printf("%d",(int16_t)i.IType.imm); 575 db_printf("%d",(int16_t)i.IType.imm);
585 break; 576 break;
586 } 577 }
587 goto pr_displ; 578 goto pr_displ;
588 579
589 case OP_BLEZ: 580 case OP_BLEZ:
590 case OP_BLEZL: 581 case OP_BLEZL:
591 case OP_BGTZ: 582 case OP_BGTZ:
592 case OP_BGTZL: 583 case OP_BGTZL:
593 db_printf("%s\t%s,", op_name[i.IType.op], 584 db_printf("%s\t%s,", op_name[i.IType.op],
594 reg_name[i.IType.rs]); 585 reg_name[i.IType.rs]);
595 goto pr_displ; 586 goto pr_displ;
596 587
597 case OP_BEQ: 588 case OP_BEQ:
598 case OP_BEQL: 589 case OP_BEQL:
599 if (i.IType.rs == 0 && i.IType.rt == 0) { 590 if (i.IType.rs == 0 && i.IType.rt == 0) {
600 db_printf("b\t"); 591 db_printf("b\t");
601 goto pr_displ; 592 goto pr_displ;
602 } 593 }
603 /* FALLTHROUGH */ 594 /* FALLTHROUGH */
604 case OP_BNE: 595 case OP_BNE:
605 case OP_BNEL: 596 case OP_BNEL:
606 db_printf("%s\t%s,%s,", op_name[i.IType.op], 597 db_printf("%s\t%s,%s,", op_name[i.IType.op],
607 reg_name[i.IType.rs], 598 reg_name[i.IType.rs],
608 reg_name[i.IType.rt]); 599 reg_name[i.IType.rt]);
609 pr_displ: 600 pr_displ:
610 print_addr(loc + 4 + ((short)i.IType.imm << 2)); 601 print_addr(loc + 4 + ((short)i.IType.imm << 2));
611 bdslot = true; 602 bdslot = true;
612 break; 603 break;
613 604
614 case OP_COP0: 605 case OP_COP0:
615 switch (i.RType.rs) { 606 switch (i.RType.rs) {
616 case OP_BCx: 607 case OP_BCx:
617 case OP_BCy: 608 case OP_BCy:
618 609
619 db_printf("bc0%c\t", 610 db_printf("bc0%c\t",
620 "ft"[i.RType.rt & COPz_BC_TRUE]); 611 "ft"[i.RType.rt & COPz_BC_TRUE]);
621 goto pr_displ; 612 goto pr_displ;
622 613
623 case OP_MT: 614 case OP_MT:
624 db_printf("mtc0\t%s,%s", 615 db_printf("mtc0\t%s,%s",
625 reg_name[i.RType.rt], 616 reg_name[i.RType.rt],
626 c0_reg[i.RType.rd]); 617 c0_reg[i.RType.rd]);
627 break; 618 break;
628 619
629 case OP_DMT: 620 case OP_DMT:
630 db_printf("dmtc0\t%s,%s", 621 db_printf("dmtc0\t%s,%s",
631 reg_name[i.RType.rt], 622 reg_name[i.RType.rt],
632 c0_reg[i.RType.rd]); 623 c0_reg[i.RType.rd]);
633 break; 624 break;
634 625
635 case OP_MF: 626 case OP_MF:
636 db_printf("mfc0\t%s,%s", 627 db_printf("mfc0\t%s,%s",
637 reg_name[i.RType.rt], 628 reg_name[i.RType.rt],
638 c0_reg[i.RType.rd]); 629 c0_reg[i.RType.rd]);
639 break; 630 break;
640 631
641 case OP_DMF: 632 case OP_DMF:
642 db_printf("dmfc0\t%s,%s", 633 db_printf("dmfc0\t%s,%s",
643 reg_name[i.RType.rt], 634 reg_name[i.RType.rt],
644 c0_reg[i.RType.rd]); 635 c0_reg[i.RType.rd]);
645 break; 636 break;
646 637
647 case OP_MFM: 638 case OP_MFM:
648 if (i.RType.rd == MIPS_COP_0_STATUS 639 if (i.RType.rd == MIPS_COP_0_STATUS
649 && i.RType.shamt == 0 640 && i.RType.shamt == 0
650 && (i.RType.func & 31) == 0) { 641 && (i.RType.func & 31) == 0) {
651 db_printf("%s", 642 db_printf("%s",
652 i.RType.func & 16 ? "ei" : "di"); 643 i.RType.func & 16 ? "ei" : "di");
653 if (i.RType.rt != 0) { 644 if (i.RType.rt != 0) {
654 db_printf("\t%s", 645 db_printf("\t%s",
655 reg_name[i.RType.rt]); 646 reg_name[i.RType.rt]);
656 } 647 }
657 break; 648 break;
658 } 649 }
659 /* FALLTHROUGH */ 650 /* FALLTHROUGH */
660 651
661 default: 652 default:
662 db_printf("%s", c0_opname[i.FRType.func]); 653 db_printf("%s", c0_opname[i.FRType.func]);
663 } 654 }
664 break; 655 break;
665 656
666 case OP_COP1: 657 case OP_COP1:
667 switch (i.RType.rs) { 658 switch (i.RType.rs) {
668 case OP_BCx: 659 case OP_BCx:
669 case OP_BCy: 660 case OP_BCy:
670 db_printf("bc1%c\t", 661 db_printf("bc1%c\t",
671 "ft"[i.RType.rt & COPz_BC_TRUE]); 662 "ft"[i.RType.rt & COPz_BC_TRUE]);
672 goto pr_displ; 663 goto pr_displ;
673 664
674 case OP_MT: 665 case OP_MT:
675 db_printf("mtc1\t%s,f%d", 666 db_printf("mtc1\t%s,f%d",
676 reg_name[i.RType.rt], 667 reg_name[i.RType.rt],
677 i.RType.rd); 668 i.RType.rd);
678 break; 669 break;
679 670
680 case OP_MF: 671 case OP_MF:
681 db_printf("mfc1\t%s,f%d", 672 db_printf("mfc1\t%s,f%d",
682 reg_name[i.RType.rt], 673 reg_name[i.RType.rt],
683 i.RType.rd); 674 i.RType.rd);
684 break; 675 break;
685 676
686 case OP_CT: 677 case OP_CT:
687 db_printf("ctc1\t%s,%d", 678 db_printf("ctc1\t%s,%d",
688 reg_name[i.RType.rt], 679 reg_name[i.RType.rt],
689 i.RType.rd); 680 i.RType.rd);
690 break; 681 break;
691 682
692 case OP_CF: 683 case OP_CF:
693 db_printf("cfc1\t%s,%d", 684 db_printf("cfc1\t%s,%d",
694 reg_name[i.RType.rt], 685 reg_name[i.RType.rt],
695 i.RType.rd); 686 i.RType.rd);
696 break; 687 break;
697 688
698 case OP_DMT: 689 case OP_DMT:
699 db_printf("dmtc1\t%s,f%d", 690 db_printf("dmtc1\t%s,f%d",
700 reg_name[i.RType.rt], 691 reg_name[i.RType.rt],
701 i.RType.rd); 692 i.RType.rd);
702 break; 693 break;
703 694
704 case OP_DMF: 695 case OP_DMF:
705 db_printf("dmfc1\t%s,f%d", 696 db_printf("dmfc1\t%s,f%d",
706 reg_name[i.RType.rt], 697 reg_name[i.RType.rt],
707 i.RType.rd); 698 i.RType.rd);
708 break; 699 break;
709 700
710 case OP_MTH: 701 case OP_MTH:
711 db_printf("mthc1\t%s,f%d", 702 db_printf("mthc1\t%s,f%d",
712 reg_name[i.RType.rt], 703 reg_name[i.RType.rt],
713 i.RType.rd); 704 i.RType.rd);
714 break; 705 break;
715 706
716 case OP_MFH: 707 case OP_MFH:
717 db_printf("mfhc1\t%s,f%d", 708 db_printf("mfhc1\t%s,f%d",
718 reg_name[i.RType.rt], 709 reg_name[i.RType.rt],
719 i.RType.rd); 710 i.RType.rd);
720 break; 711 break;
721 712
722 default: 713 default:
723 db_printf("%s.%s\tf%d,f%d,f%d", 714 db_printf("%s.%s\tf%d,f%d,f%d",
724 cop1_name[i.FRType.func], 715 cop1_name[i.FRType.func],
725 fmt_name[i.FRType.fmt], 716 fmt_name[i.FRType.fmt],
726 i.FRType.fd, i.FRType.fs, i.FRType.ft); 717 i.FRType.fd, i.FRType.fs, i.FRType.ft);
727 } 718 }
728 break; 719 break;
729 720
730 case OP_COP2: 721 case OP_COP2:
731 switch (i.RType.rs) { 722 switch (i.RType.rs) {
732 case OP_BCx: 723 case OP_BCx:
733 case OP_BCy: 724 case OP_BCy:
734 db_printf("bc2%c\t", 725 db_printf("bc2%c\t",
735 "ft"[i.RType.rt & COPz_BC_TRUE]); 726 "ft"[i.RType.rt & COPz_BC_TRUE]);
736 goto pr_displ; 727 goto pr_displ;
737 728
738 case OP_MT: 729 case OP_MT:
739 db_printf("mtc2\t%s,f%d", 730 db_printf("mtc2\t%s,f%d",
740 reg_name[i.RType.rt], 731 reg_name[i.RType.rt],
741 i.RType.rd); 732 i.RType.rd);
742 break; 733 break;
743 734
744 case OP_MF: 735 case OP_MF:
745 db_printf("mfc2\t%s,f%d", 736 db_printf("mfc2\t%s,f%d",
746 reg_name[i.RType.rt], 737 reg_name[i.RType.rt],
747 i.RType.rd); 738 i.RType.rd);
748 break; 739 break;
749 740
750 case OP_CT: 741 case OP_CT:
751 db_printf("ctc2\t%s,f%d", 742 db_printf("ctc2\t%s,f%d",
752 reg_name[i.RType.rt], 743 reg_name[i.RType.rt],
753 i.RType.rd); 744 i.RType.rd);
754 break; 745 break;
755 746
756 case OP_CF: 747 case OP_CF:
757 db_printf("cfc2\t%s,f%d", 748 db_printf("cfc2\t%s,f%d",
758 reg_name[i.RType.rt], 749 reg_name[i.RType.rt],
759 i.RType.rd); 750 i.RType.rd);
760 break; 751 break;
761 752
762 case OP_DMT: 753 case OP_DMT:
763 db_printf("dmtc2\t%s,f%d", 754 db_printf("dmtc2\t%s,f%d",
764 reg_name[i.RType.rt], 755 reg_name[i.RType.rt],
765 i.RType.rd); 756 i.RType.rd);
766 break; 757 break;
767 758
768 case OP_DMF: 759 case OP_DMF:
769 db_printf("dmfc2\t%s,f%d", 760 db_printf("dmfc2\t%s,f%d",
770 reg_name[i.RType.rt], 761 reg_name[i.RType.rt],
771 i.RType.rd); 762 i.RType.rd);
772 break; 763 break;
773 764
774 case OP_MTH: 765 case OP_MTH:
775 db_printf("mthc2\t%s,f%d", 766 db_printf("mthc2\t%s,f%d",
776 reg_name[i.RType.rt], 767 reg_name[i.RType.rt],
777 i.RType.rd); 768 i.RType.rd);
778 break; 769 break;
779 770
780 case OP_MFH: 771 case OP_MFH:
781 db_printf("mfhc2\t%s,f%d", 772 db_printf("mfhc2\t%s,f%d",
782 reg_name[i.RType.rt], 773 reg_name[i.RType.rt],
783 i.RType.rd); 774 i.RType.rd);
784 break; 775 break;
785 776
786 default: 777 default:
787 db_printf("%s\t%s,%s,%d", op_name[i.IType.op], 778 db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
788 reg_name[i.IType.rt], 779 reg_name[i.IType.rt],
789 reg_name[i.IType.rs], 780 reg_name[i.IType.rs],
790 (short)i.IType.imm); 781 (short)i.IType.imm);
791 } 782 }
792 break; 783 break;
793 784
794 case OP_J: 785 case OP_J:
795 case OP_JAL: 786 case OP_JAL:
796 case OP_JALX: 787 case OP_JALX:
797 db_printf("%s\t", op_name[i.JType.op]); 788 db_printf("%s\t", op_name[i.JType.op]);
798 print_addr((loc & ~0x0FFFFFFFL) | (i.JType.target << 2)); 789 print_addr((loc & ~0x0FFFFFFFL) | (i.JType.target << 2));
799 bdslot = true; 790 bdslot = true;
800 break; 791 break;
801 792
802#ifdef __OCTEON__ 793#ifdef __OCTEON__
803 case OP_CVM_BBIT0: 794 case OP_CVM_BBIT0:
804 case OP_CVM_BBIT032: 795 case OP_CVM_BBIT032:
805 case OP_CVM_BBIT1: 796 case OP_CVM_BBIT1:
806 case OP_CVM_BBIT132: 797 case OP_CVM_BBIT132:
807 db_printf("%s\t%s,%d,", 798 db_printf("%s\t%s,%d,",
808 op_name[i.IType.op], 799 op_name[i.IType.op],
809 reg_name[i.IType.rs], 800 reg_name[i.IType.rs],
810 i.IType.rt); 801 i.IType.rt);
811 goto pr_displ; 802 goto pr_displ;
812#else 803#else
813 case OP_LWC2: 804 case OP_LWC2:
814 case OP_LDC2: 805 case OP_LDC2:
815 case OP_SWC2: 806 case OP_SWC2:
816 case OP_SDC2: 807 case OP_SDC2:
817#endif 808#endif
818 809
819 case OP_LWC1: 810 case OP_LWC1:
820 case OP_SWC1: 811 case OP_SWC1:
821 case OP_LDC1: 812 case OP_LDC1:
822 case OP_SDC1: 813 case OP_SDC1:
823 db_printf("%s\tf%d,", op_name[i.IType.op], 814 db_printf("%s\tf%d,", op_name[i.IType.op],
824 i.IType.rt); 815 i.IType.rt);
825 goto loadstore; 816 goto loadstore;
826 817
827 case OP_LB: 818 case OP_LB:
828 case OP_LH: 819 case OP_LH:
829 case OP_LW: 820 case OP_LW:
830 case OP_LD: 821 case OP_LD:
831 case OP_LBU: 822 case OP_LBU:
832 case OP_LHU: 823 case OP_LHU:
833 case OP_LWU: 824 case OP_LWU:
834 case OP_SB: 825 case OP_SB:
835 case OP_SH: 826 case OP_SH:
836 case OP_SW: 827 case OP_SW:
837 case OP_SD: 828 case OP_SD:
838 db_printf("%s\t%s,", op_name[i.IType.op], 829 db_printf("%s\t%s,", op_name[i.IType.op],
839 reg_name[i.IType.rt]); 830 reg_name[i.IType.rt]);
840 loadstore: 831 loadstore:
841 db_printf("%d(%s)", (short)i.IType.imm, 832 db_printf("%d(%s)", (short)i.IType.imm,
842 reg_name[i.IType.rs]); 833 reg_name[i.IType.rs]);
843 break; 834 break;
844 835
845 case OP_ORI: 836 case OP_ORI:
846 case OP_XORI: 837 case OP_XORI:
847 if (i.IType.rs == 0) { 838 if (i.IType.rs == 0) {
848 db_printf("li\t%s,0x%x", 839 db_printf("li\t%s,0x%x",
849 reg_name[i.IType.rt], 840 reg_name[i.IType.rt],
850 i.IType.imm); 841 i.IType.imm);
851 break; 842 break;
852 } 843 }
853 /* FALLTHROUGH */ 844 /* FALLTHROUGH */
854 case OP_ANDI: 845 case OP_ANDI:
855 db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op], 846 db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op],
856 reg_name[i.IType.rt], 847 reg_name[i.IType.rt],
857 reg_name[i.IType.rs], 848 reg_name[i.IType.rs],
858 i.IType.imm); 849 i.IType.imm);
859 break; 850 break;
860 851
861 case OP_LUI: 852 case OP_LUI:
862 db_printf("%s\t%s,0x%x", op_name[i.IType.op], 853 db_printf("%s\t%s,0x%x", op_name[i.IType.op],
863 reg_name[i.IType.rt], 854 reg_name[i.IType.rt],
864 i.IType.imm); 855 i.IType.imm);
865 break; 856 break;
866 857
867 case OP_CACHE: 858 case OP_CACHE:
868 db_printf("%s\t0x%x,0x%x(%s)", 859 db_printf("%s\t0x%x,0x%x(%s)",
869 op_name[i.IType.op], 860 op_name[i.IType.op],
870 i.IType.rt, 861 i.IType.rt,
871 i.IType.imm, 862 i.IType.imm,
872 reg_name[i.IType.rs]); 863 reg_name[i.IType.rs]);
873 break; 864 break;
874 865
875 case OP_ADDI: 866 case OP_ADDI:
876 case OP_DADDI: 867 case OP_DADDI:
877 case OP_ADDIU: 868 case OP_ADDIU:
878 case OP_DADDIU: 869 case OP_DADDIU:
879 if (i.IType.rs == 0) { 870 if (i.IType.rs == 0) {
880 db_printf("li\t%s,%d", 871 db_printf("li\t%s,%d",
881 reg_name[i.IType.rt], 872 reg_name[i.IType.rt],
882 (short)i.IType.imm); 873 (short)i.IType.imm);
883 break; 874 break;
884 } 875 }
885 /* FALLTHROUGH */ 876 /* FALLTHROUGH */
886 default: 877 default:
887 db_printf("%s\t%s,%s,%d", op_name[i.IType.op], 878 db_printf("%s\t%s,%s,%d", op_name[i.IType.op],
888 reg_name[i.IType.rt], 879 reg_name[i.IType.rt],
889 reg_name[i.IType.rs], 880 reg_name[i.IType.rs],
890 (short)i.IType.imm); 881 (short)i.IType.imm);
891 } 882 }
892 db_printf("\n"); 883 db_printf("\n");
893 if (bdslot) { 884 if (bdslot) {
894 db_printf("\t\tbdslot:\t"); 885 db_printf("\t\tbdslot:\t");
895 db_disasm(loc+4, false); 886 db_disasm(loc+4, false);
896 return (loc + 8); 887 return (loc + 8);
897 } 888 }
898 return (loc + 4); 889 return (loc + 4);
899} 890}
900 891
901static void 892static void
902print_addr(db_addr_t loc) 893print_addr(db_addr_t loc)
903{ 894{
904 db_expr_t diff; 895 db_expr_t diff;
905 db_sym_t sym; 896 db_sym_t sym;
906 const char *symname; 897 const char *symname;
907 898
908 diff = INT_MAX; 899 diff = INT_MAX;
909 symname = NULL; 900 symname = NULL;
910 sym = db_search_symbol(loc, DB_STGY_ANY, &diff); 901 sym = db_search_symbol(loc, DB_STGY_ANY, &diff);
911 db_symbol_values(sym, &symname, 0); 902 db_symbol_values(sym, &symname, 0);
912 903
913 db_printf("%#"PRIxVADDR, loc); 904 db_printf("%#"PRIxVADDR, loc);
914 if (symname) { 905 if (symname) {
915 db_printf(" <%s", symname); 906 db_printf(" <%s", symname);
916 if (diff != 0) 907 if (diff != 0)
917 db_printf("+%#"DDB_EXPR_FMT"x", diff); 908 db_printf("+%#"DDB_EXPR_FMT"x", diff);
918 db_printf(">"); 909 db_printf(">");
919 } 910 }
920} 911}

cvs diff -r1.93 -r1.94 src/sys/arch/mips/mips/db_interface.c (switch to unified diff)

--- src/sys/arch/mips/mips/db_interface.c 2021/04/12 02:23:41 1.93
+++ src/sys/arch/mips/mips/db_interface.c 2021/05/23 23:22:55 1.94
@@ -1,1063 +1,1092 @@ @@ -1,1063 +1,1092 @@
1/* $NetBSD: db_interface.c,v 1.93 2021/04/12 02:23:41 mrg Exp $ */ 1/* $NetBSD: db_interface.c,v 1.94 2021/05/23 23:22:55 dholland Exp $ */
2 2
3/* 3/*
4 * Mach Operating System 4 * Mach Operating System
5 * Copyright (c) 1991,1990 Carnegie Mellon University 5 * Copyright (c) 1991,1990 Carnegie Mellon University
6 * All Rights Reserved. 6 * All Rights Reserved.
7 * 7 *
8 * Permission to use, copy, modify and distribute this software and its 8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright 9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the 10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions 11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation. 12 * thereof, and that both notices appear in supporting documentation.
13 * 13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 * 17 *
18 * Carnegie Mellon requests users of this software to return to 18 * Carnegie Mellon requests users of this software to return to
19 * 19 *
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science 21 * School of Computer Science
22 * Carnegie Mellon University 22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890 23 * Pittsburgh PA 15213-3890
24 * 24 *
25 * any improvements or extensions that they make and grant Carnegie Mellon 25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes. 26 * the rights to redistribute these changes.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.93 2021/04/12 02:23:41 mrg Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.94 2021/05/23 23:22:55 dholland Exp $");
31 31
32#ifdef _KERNEL_OPT 32#ifdef _KERNEL_OPT
33#include "opt_multiprocessor.h" 33#include "opt_multiprocessor.h"
34#include "opt_cputype.h" /* which mips CPUs do we support? */ 34#include "opt_cputype.h" /* which mips CPUs do we support? */
35#include "opt_ddb.h" 35#include "opt_ddb.h"
36#include "opt_kgdb.h" 36#include "opt_kgdb.h"
37#endif 37#endif
38 38
39#define __PMAP_PRIVATE 39#define __PMAP_PRIVATE
40 40
41#include <sys/types.h> 41#include <sys/types.h>
42#include <sys/systm.h> 42#include <sys/systm.h>
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/proc.h> 44#include <sys/proc.h>
45#include <sys/reboot.h> 45#include <sys/reboot.h>
46#include <sys/atomic.h> 46#include <sys/atomic.h>
47#include <sys/cpu.h> 47#include <sys/cpu.h>
48 48
49#include <uvm/uvm_extern.h> 49#include <uvm/uvm_extern.h>
50 50
51#include <mips/regnum.h> 51#include <mips/regnum.h>
52#include <mips/cache.h> 52#include <mips/cache.h>
53#include <mips/pcb.h> 53#include <mips/pcb.h>
54#include <mips/pte.h> 54#include <mips/pte.h>
55#include <mips/locore.h> 55#include <mips/locore.h>
56#include <mips/mips_opcode.h> 56#include <mips/mips_opcode.h>
57#include <dev/cons.h> 57#include <dev/cons.h>
58 58
59#include <machine/int_fmtio.h> 59#include <machine/int_fmtio.h>
60#include <machine/db_machdep.h> 60#include <machine/db_machdep.h>
61#include <ddb/db_access.h> 61#include <ddb/db_access.h>
62#include <ddb/db_user.h> 62#include <ddb/db_user.h>
63#ifndef KGDB 63#ifndef KGDB
64#include <ddb/db_command.h> 64#include <ddb/db_command.h>
65#include <ddb/db_output.h> 65#include <ddb/db_output.h>
66#include <ddb/db_sym.h> 66#include <ddb/db_sym.h>
67#include <ddb/db_extern.h> 67#include <ddb/db_extern.h>
68#include <ddb/db_interface.h> 68#include <ddb/db_interface.h>
69#include <ddb/db_lex.h> 69#include <ddb/db_lex.h>
70#include <ddb/db_run.h> /* for db_continue_cmd() proto */ 70#include <ddb/db_run.h> /* for db_continue_cmd() proto */
71#endif 71#endif
72 72
73#define NOCPU ~0 73#define NOCPU ~0
74volatile u_int ddb_cpu = NOCPU; 74volatile u_int ddb_cpu = NOCPU;
75 75
76int db_active = 0; 76int db_active = 0;
77#ifdef _KERNEL 77#ifdef _KERNEL
78db_regs_t ddb_regs; 78db_regs_t ddb_regs;
79#endif 79#endif
80 80
81#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 81#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
82static void db_watch_cmd(db_expr_t, bool, db_expr_t, const char *); 82static void db_watch_cmd(db_expr_t, bool, db_expr_t, const char *);
83static void db_unwatch_cmd(db_expr_t, bool, db_expr_t, const char *); 83static void db_unwatch_cmd(db_expr_t, bool, db_expr_t, const char *);
84#endif /* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */ 84#endif /* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
85 85
86#ifdef MULTIPROCESSOR 86#ifdef MULTIPROCESSOR
87static void db_mach_cpu_cmd(db_expr_t, bool, db_expr_t, const char *); 87static void db_mach_cpu_cmd(db_expr_t, bool, db_expr_t, const char *);
88#endif 88#endif
89 89
90void db_tlbdump_cmd(db_expr_t, bool, db_expr_t, const char *); 90void db_tlbdump_cmd(db_expr_t, bool, db_expr_t, const char *);
91void db_kvtophys_cmd(db_expr_t, bool, db_expr_t, const char *); 91void db_kvtophys_cmd(db_expr_t, bool, db_expr_t, const char *);
92void db_cp0dump_cmd(db_expr_t, bool, db_expr_t, const char *); 92void db_cp0dump_cmd(db_expr_t, bool, db_expr_t, const char *);
93#ifdef MIPS64_XLS 93#ifdef MIPS64_XLS
94void db_mfcr_cmd(db_expr_t, bool, db_expr_t, const char *); 94void db_mfcr_cmd(db_expr_t, bool, db_expr_t, const char *);
95void db_mtcr_cmd(db_expr_t, bool, db_expr_t, const char *); 95void db_mtcr_cmd(db_expr_t, bool, db_expr_t, const char *);
96#endif 96#endif
97 97
98paddr_t kvtophys(vaddr_t); 98paddr_t kvtophys(vaddr_t);
99 99
100#ifdef _KERNEL 100#ifdef _KERNEL
101CTASSERT(sizeof(ddb_regs) == sizeof(struct reg)); 101CTASSERT(sizeof(ddb_regs) == sizeof(struct reg));
102 102
103#ifndef KGDB 103#ifndef KGDB
104int 104int
105kdb_trap(int type, struct reg *regs) 105kdb_trap(int type, struct reg *regs)
106{ 106{
107 int s; 107 int s;
108 108
109 switch (type) { 109 switch (type) {
110 case T_WATCH: /* watchpoint */ 110 case T_WATCH: /* watchpoint */
111 case T_BREAK: /* breakpoint */ 111 case T_BREAK: /* breakpoint */
112 printf("kernel: %s trap\n", trap_names[type & 0x1f]); 112 printf("kernel: %s trap\n", trap_names[type & 0x1f]);
113 break; 113 break;
114 case -1: /* keyboard interrupt */ 114 case -1: /* keyboard interrupt */
115 printf("kernel: kdbint trap\n"); 115 printf("kernel: kdbint trap\n");
116 break; 116 break;
117 default: 117 default:
118 printf("kernel: %s trap\n", trap_names[type & 0x1f]); 118 printf("kernel: %s trap\n", trap_names[type & 0x1f]);
119 if (db_recover != 0) { 119 if (db_recover != 0) {
120 db_error("Faulted in DDB; continuing...\n"); 120 db_error("Faulted in DDB; continuing...\n");
121 /*NOTREACHED*/ 121 /*NOTREACHED*/
122 } 122 }
123 break; 123 break;
124 } 124 }
125 125
126 s = splhigh(); 126 s = splhigh();
127 127
128#if defined(MULTIPROCESSOR) 128#if defined(MULTIPROCESSOR)
129 bool first_in_ddb = false; 129 bool first_in_ddb = false;
130 const u_int cpu_me = cpu_number(); 130 const u_int cpu_me = cpu_number();
131 const u_int old_ddb_cpu = atomic_cas_uint(&ddb_cpu, NOCPU, cpu_me); 131 const u_int old_ddb_cpu = atomic_cas_uint(&ddb_cpu, NOCPU, cpu_me);
132 if (old_ddb_cpu == NOCPU) { 132 if (old_ddb_cpu == NOCPU) {
133 first_in_ddb = true; 133 first_in_ddb = true;
134 cpu_pause_others(); 134 cpu_pause_others();
135 } else { 135 } else {
136 if (old_ddb_cpu != cpu_me) { 136 if (old_ddb_cpu != cpu_me) {
137 KASSERT(cpu_is_paused(cpu_me)); 137 KASSERT(cpu_is_paused(cpu_me));
138 cpu_pause(regs); 138 cpu_pause(regs);
139 splx(s); 139 splx(s);
140 return 1; 140 return 1;
141 } 141 }
142 } 142 }
143 KASSERT(! cpu_is_paused(cpu_me)); 143 KASSERT(! cpu_is_paused(cpu_me));
144#endif 144#endif
145 145
146 ddb_regs = *regs; 146 ddb_regs = *regs;
147 db_active++; 147 db_active++;
148 cnpollc(1); 148 cnpollc(1);
149 db_trap(type & ~T_USER, 0 /*code*/); 149 db_trap(type & ~T_USER, 0 /*code*/);
150 cnpollc(0); 150 cnpollc(0);
151 db_active--; 151 db_active--;
152 *regs = ddb_regs; 152 *regs = ddb_regs;
153 153
154#if defined(MULTIPROCESSOR) 154#if defined(MULTIPROCESSOR)
155 if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) { 155 if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) {
156 cpu_resume_others(); 156 cpu_resume_others();
157 } else { 157 } else {
158 cpu_resume(ddb_cpu); 158 cpu_resume(ddb_cpu);
159 if (first_in_ddb) 159 if (first_in_ddb)
160 cpu_pause(regs); 160 cpu_pause(regs);
161 } 161 }
162#endif 162#endif
163 163
164 splx(s); 164 splx(s);
165 return 1; 165 return 1;
166} 166}
167 167
168void 168void
169cpu_Debugger(void) 169cpu_Debugger(void)
170{ 170{
171 171
172 __asm("break"); 172 __asm("break");
173} 173}
174#endif /* !KGDB */ 174#endif /* !KGDB */
175 175
176/* 176/*
177 * Read bytes from kernel address space for debugger. 177 * Read bytes from kernel address space for debugger.
178 */ 178 */
179void 179void
180db_read_bytes(vaddr_t addr, size_t size, char *data) 180db_read_bytes(vaddr_t addr, size_t size, char *data)
181{ 181{
182 const char *src = (char *)addr; 182 const char *src = (char *)addr;
 183 int err;
 184
 185 /*
 186 * If asked to fetch from userspace, do it safely.
 187 * Note that MIPS_KSEG0_START is the proper address for
 188 * both 32-bit and 64-bit kernels.
 189 */
 190 if (addr < (vaddr_t)MIPS_KSEG0_START) {
 191 err = copyin(src, data, size);
 192 if (err) {
 193#ifdef DDB
 194 db_printf("address %p is invalid\n", src);
 195#endif
 196 memset(data, 0, size);
 197 }
 198 return;
 199 }
183 200
184 if (size <= 8 && (size & (size-1)) == 0 && (addr & (size-1)) == 0 201 if (size <= 8 && (size & (size-1)) == 0 && (addr & (size-1)) == 0
185 && ((uintptr_t)data & (size-1)) == 0) { 202 && ((uintptr_t)data & (size-1)) == 0) {
186 if (size == sizeof(uint8_t)) 203 if (size == sizeof(uint8_t))
187 *(uint8_t *)data = *(const uint8_t *)src; 204 *(uint8_t *)data = *(const uint8_t *)src;
188 else if (size == sizeof(uint16_t)) 205 else if (size == sizeof(uint16_t))
189 *(uint16_t *)data = *(const uint16_t *)src; 206 *(uint16_t *)data = *(const uint16_t *)src;
190 else if (size == sizeof(uint32_t)) 207 else if (size == sizeof(uint32_t))
191 *(uint32_t *)data = *(const uint32_t *)src; 208 *(uint32_t *)data = *(const uint32_t *)src;
192 else 209 else
193 *(uint64_t *)data = *(const uint64_t *)src; 210 *(uint64_t *)data = *(const uint64_t *)src;
194 return; 211 return;
195 } 212 }
196 while (size--) 213 while (size--)
197 *data++ = *src++; 214 *data++ = *src++;
198} 215}
199 216
200/* 217/*
201 * Write bytes to kernel address space for debugger. 218 * Write bytes to kernel address space for debugger.
202 */ 219 */
203void 220void
204db_write_bytes(vaddr_t addr, size_t size, const char *data) 221db_write_bytes(vaddr_t addr, size_t size, const char *data)
205{ 222{
206 char *p = (char *)addr; 223 char *p = (char *)addr;
207 size_t n = size; 224 size_t n = size;
 225 int err;
 226
 227 /* If asked to fetch from userspace, do it safely */
 228 if (addr < (vaddr_t)MIPS_KSEG0_START) {
 229 err = copyout(data, p, size);
 230 if (err) {
 231#ifdef DDB
 232 db_printf("address %p is invalid\n", p);
 233#endif
 234 }
 235 return;
 236 }
208 237
209 if (size <= 8 && (size & (size-1)) == 0 && (addr & (size-1)) == 0 238 if (size <= 8 && (size & (size-1)) == 0 && (addr & (size-1)) == 0
210 && ((uintptr_t)data & (size-1)) == 0) { 239 && ((uintptr_t)data & (size-1)) == 0) {
211 if (size == sizeof(uint8_t)) 240 if (size == sizeof(uint8_t))
212 *(uint8_t *)p = *(const uint8_t *)data; 241 *(uint8_t *)p = *(const uint8_t *)data;
213 else if (size == sizeof(uint16_t)) 242 else if (size == sizeof(uint16_t))
214 *(uint16_t *)p = *(const uint16_t *)data; 243 *(uint16_t *)p = *(const uint16_t *)data;
215 else if (size == sizeof(uint32_t)) 244 else if (size == sizeof(uint32_t))
216 *(uint32_t *)p = *(const uint32_t *)data; 245 *(uint32_t *)p = *(const uint32_t *)data;
217 else 246 else
218 *(uint64_t *)p = *(const uint64_t *)data; 247 *(uint64_t *)p = *(const uint64_t *)data;
219 return; 248 return;
220 } 249 }
221 while (n--) 250 while (n--)
222 *p++ = *data++; 251 *p++ = *data++;
223 252
224 wbflush(); 253 wbflush();
225 mips_icache_sync_range(addr, size); 254 mips_icache_sync_range(addr, size);
226} 255}
227 256
228#ifndef KGDB 257#ifndef KGDB
229void 258void
230db_tlbdump_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 259db_tlbdump_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
231 const char *modif) 260 const char *modif)
232{ 261{
233 struct tlbmask tlb; 262 struct tlbmask tlb;
234 bool valid_only = false; 263 bool valid_only = false;
235 264
236 if (modif[0] == 'v') 265 if (modif[0] == 'v')
237 valid_only = true; 266 valid_only = true;
238 267
239#ifdef MIPS1 268#ifdef MIPS1
240 if (!MIPS_HAS_R4K_MMU) { 269 if (!MIPS_HAS_R4K_MMU) {
241 int i; 270 int i;
242 271
243 for (i = 0; i < mips_options.mips_num_tlb_entries; i++) { 272 for (i = 0; i < mips_options.mips_num_tlb_entries; i++) {
244 tlb_read_entry(i, &tlb); 273 tlb_read_entry(i, &tlb);
245 if (valid_only && !(tlb.tlb_lo1 & MIPS1_PG_V)) 274 if (valid_only && !(tlb.tlb_lo1 & MIPS1_PG_V))
246 continue; /* skip invalid TLBs */ 275 continue; /* skip invalid TLBs */
247 db_printf("TLB%c%2d Hi 0x%08x Lo 0x%08x", 276 db_printf("TLB%c%2d Hi 0x%08x Lo 0x%08x",
248 (tlb.tlb_lo1 & MIPS1_PG_V) ? ' ' : '*', 277 (tlb.tlb_lo1 & MIPS1_PG_V) ? ' ' : '*',
249 i, tlb.tlb_hi, 278 i, tlb.tlb_hi,
250 tlb.tlb_lo1 & MIPS1_PG_FRAME); 279 tlb.tlb_lo1 & MIPS1_PG_FRAME);
251 db_printf(" %c%c%c\n", 280 db_printf(" %c%c%c\n",
252 (tlb.tlb_lo1 & MIPS1_PG_D) ? 'D' : ' ', 281 (tlb.tlb_lo1 & MIPS1_PG_D) ? 'D' : ' ',
253 (tlb.tlb_lo1 & MIPS1_PG_G) ? 'G' : ' ', 282 (tlb.tlb_lo1 & MIPS1_PG_G) ? 'G' : ' ',
254 (tlb.tlb_lo1 & MIPS1_PG_N) ? 'N' : ' '); 283 (tlb.tlb_lo1 & MIPS1_PG_N) ? 'N' : ' ');
255 } 284 }
256 } 285 }
257#endif 286#endif
258#ifdef MIPS3_PLUS 287#ifdef MIPS3_PLUS
259 if (MIPS_HAS_R4K_MMU) { 288 if (MIPS_HAS_R4K_MMU) {
260 int i; 289 int i;
261 const int tlb_count_width = 290 const int tlb_count_width =
262 mips_options.mips_num_tlb_entries > 100 ? 3 : 2; 291 mips_options.mips_num_tlb_entries > 100 ? 3 : 2;
263 292
264 for (i = 0; i < mips_options.mips_num_tlb_entries; i++) { 293 for (i = 0; i < mips_options.mips_num_tlb_entries; i++) {
265 tlb_read_entry(i, &tlb); 294 tlb_read_entry(i, &tlb);
266 if (valid_only && 295 if (valid_only &&
267 !((tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V)) 296 !((tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V))
268 continue; /* skip invalid TLBs */ 297 continue; /* skip invalid TLBs */
269 298
270 db_printf("TLB%c%*d Hi 0x%08"PRIxVADDR" ", 299 db_printf("TLB%c%*d Hi 0x%08"PRIxVADDR" ",
271 (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*', 300 (tlb.tlb_lo0 | tlb.tlb_lo1) & MIPS3_PG_V ? ' ' : '*',
272 tlb_count_width, i, tlb.tlb_hi); 301 tlb_count_width, i, tlb.tlb_hi);
273 db_printf("Lo0=0x%09" PRIx64 " %c%c attr %x ", 302 db_printf("Lo0=0x%09" PRIx64 " %c%c attr %x ",
274 (uint64_t)mips_tlbpfn_to_paddr(tlb.tlb_lo0), 303 (uint64_t)mips_tlbpfn_to_paddr(tlb.tlb_lo0),
275 (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ', 304 (tlb.tlb_lo0 & MIPS3_PG_D) ? 'D' : ' ',
276 (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ', 305 (tlb.tlb_lo0 & MIPS3_PG_G) ? 'G' : ' ',
277 (int)(tlb.tlb_lo0 >> 3) & 7); 306 (int)(tlb.tlb_lo0 >> 3) & 7);
278 db_printf("Lo1=0x%09" PRIx64 " %c%c attr %x sz=%x\n", 307 db_printf("Lo1=0x%09" PRIx64 " %c%c attr %x sz=%x\n",
279 (uint64_t)mips_tlbpfn_to_paddr(tlb.tlb_lo1), 308 (uint64_t)mips_tlbpfn_to_paddr(tlb.tlb_lo1),
280 (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ', 309 (tlb.tlb_lo1 & MIPS3_PG_D) ? 'D' : ' ',
281 (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ', 310 (tlb.tlb_lo1 & MIPS3_PG_G) ? 'G' : ' ',
282 (int)(tlb.tlb_lo1 >> 3) & 7, 311 (int)(tlb.tlb_lo1 >> 3) & 7,
283 tlb.tlb_mask); 312 tlb.tlb_mask);
284 } 313 }
285 } 314 }
286#endif 315#endif
287} 316}
288 317
289void 318void
290db_kvtophys_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 319db_kvtophys_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
291 const char *modif) 320 const char *modif)
292{ 321{
293 322
294 if (!have_addr) 323 if (!have_addr)
295 return; 324 return;
296 if (VM_MIN_KERNEL_ADDRESS <= addr && addr < VM_MAX_KERNEL_ADDRESS) { 325 if (VM_MIN_KERNEL_ADDRESS <= addr && addr < VM_MAX_KERNEL_ADDRESS) {
297 /* 326 /*
298 * Cast the physical address -- some platforms, while 327 * Cast the physical address -- some platforms, while
299 * being ILP32, may be using 64-bit paddr_t's. 328 * being ILP32, may be using 64-bit paddr_t's.
300 */ 329 */
301 db_printf("0x%" DDB_EXPR_FMT "x -> 0x%" PRIx64 "\n", addr, 330 db_printf("0x%" DDB_EXPR_FMT "x -> 0x%" PRIx64 "\n", addr,
302 (uint64_t) kvtophys(addr)); 331 (uint64_t) kvtophys(addr));
303 } else 332 } else
304 db_printf("not a kernel virtual address\n"); 333 db_printf("not a kernel virtual address\n");
305} 334}
306 335
307#define FLDWIDTH 10 336#define FLDWIDTH 10
308 337
309#define SHOW32(reg, name) SHOW32SELECT(reg, 0, name) 338#define SHOW32(reg, name) SHOW32SELECT(reg, 0, name)
310#define SHOW64(reg, name) SHOW64SELECT(reg, 0, name) 339#define SHOW64(reg, name) SHOW64SELECT(reg, 0, name)
311#define SHOW32SEL(reg, name) SHOW32SELECT(reg, name) 340#define SHOW32SEL(reg, name) SHOW32SELECT(reg, name)
312#define SHOW64SEL(reg, name) SHOW64SELECT(reg, name) 341#define SHOW64SEL(reg, name) SHOW64SELECT(reg, name)
313 342
314#define SHOW32SELECT(num, sel, name) \ 343#define SHOW32SELECT(num, sel, name) \
315do { \ 344do { \
316 uint32_t __val; \ 345 uint32_t __val; \
317 \ 346 \
318 __asm volatile( \ 347 __asm volatile( \
319 ".set push \n\t" \ 348 ".set push \n\t" \
320 ".set mips32 \n\t" \ 349 ".set mips32 \n\t" \
321 "mfc0 %0,$%1,%2 \n\t" \ 350 "mfc0 %0,$%1,%2 \n\t" \
322 ".set pop \n\t" \ 351 ".set pop \n\t" \
323 : "=r"(__val) : "n"(num), "n"(sel)); \ 352 : "=r"(__val) : "n"(num), "n"(sel)); \
324 db_printf(" %s:%*s %#x\n", name, \ 353 db_printf(" %s:%*s %#x\n", name, \
325 FLDWIDTH - (int) strlen(name), "", __val); \ 354 FLDWIDTH - (int) strlen(name), "", __val); \
326} while (0) 355} while (0)
327 356
328/* XXX not 64-bit ABI safe! */ 357/* XXX not 64-bit ABI safe! */
329#define SHOW64SELECT(num, sel, name) \ 358#define SHOW64SELECT(num, sel, name) \
330do { \ 359do { \
331 uint64_t __val; \ 360 uint64_t __val; \
332 \ 361 \
333 KASSERT (CPUIS64BITS); \ 362 KASSERT (CPUIS64BITS); \
334 __asm volatile( \ 363 __asm volatile( \
335 ".set push \n\t" \ 364 ".set push \n\t" \
336 ".set mips64 \n\t" \ 365 ".set mips64 \n\t" \
337 ".set noat \n\t" \ 366 ".set noat \n\t" \
338 "dmfc0 %0,$%1,%2 \n\t" \ 367 "dmfc0 %0,$%1,%2 \n\t" \
339 ".set pop" \ 368 ".set pop" \
340 : "=r"(__val) : "n"(num), "n"(sel)); \ 369 : "=r"(__val) : "n"(num), "n"(sel)); \
341 db_printf(" %s:%*s %#"PRIx64"\n", name, \ 370 db_printf(" %s:%*s %#"PRIx64"\n", name, \
342 FLDWIDTH - (int) strlen(name), "", __val); \ 371 FLDWIDTH - (int) strlen(name), "", __val); \
343} while (0) 372} while (0)
344 373
345#define SET32(reg, name, val) \ 374#define SET32(reg, name, val) \
346do { \ 375do { \
347 \ 376 \
348 __asm volatile("mtc0 %0,$" ___STRING(reg) :: "r"(val)); \ 377 __asm volatile("mtc0 %0,$" ___STRING(reg) :: "r"(val)); \
349 if (name != NULL) \ 378 if (name != NULL) \
350 db_printf(" %s =%*s %#x\n", name, \ 379 db_printf(" %s =%*s %#x\n", name, \
351 FLDWIDTH - (int) strlen(name), "", val); \ 380 FLDWIDTH - (int) strlen(name), "", val); \
352} while (0) 381} while (0)
353 382
354#define SET64(reg, name) MIPS64_SET64(reg, 0, name) 383#define SET64(reg, name) MIPS64_SET64(reg, 0, name)
355 384
356#define MIPS64_SET32(num, sel, name, val) \ 385#define MIPS64_SET32(num, sel, name, val) \
357do { \ 386do { \
358 \ 387 \
359 __asm volatile( \ 388 __asm volatile( \
360 ".set push \n\t" \ 389 ".set push \n\t" \
361 ".set mips32 \n\t" \ 390 ".set mips32 \n\t" \
362 "mtc0 %0,$%1,%2 \n\t" \ 391 "mtc0 %0,$%1,%2 \n\t" \
363 ".set pop \n\t" \ 392 ".set pop \n\t" \
364 :: "r"(val), "n"(num), "n"(sel)); \ 393 :: "r"(val), "n"(num), "n"(sel)); \
365 if (name != NULL) \ 394 if (name != NULL) \
366 db_printf(" %s =%*s %#x\n", name, \ 395 db_printf(" %s =%*s %#x\n", name, \
367 FLDWIDTH - (int) strlen(name), "", val); \ 396 FLDWIDTH - (int) strlen(name), "", val); \
368} while (0) 397} while (0)
369 398
370/* XXX not 64-bit ABI safe! */ 399/* XXX not 64-bit ABI safe! */
371#define MIPS64_SET64(num, sel, name, val) \ 400#define MIPS64_SET64(num, sel, name, val) \
372do { \ 401do { \
373 \ 402 \
374 KASSERT (CPUIS64BITS); \ 403 KASSERT (CPUIS64BITS); \
375 __asm volatile( \ 404 __asm volatile( \
376 ".set push \n\t" \ 405 ".set push \n\t" \
377 ".set mips64 \n\t" \ 406 ".set mips64 \n\t" \
378 ".set noat \n\t" \ 407 ".set noat \n\t" \
379 "dmtc0 %0,$%1,%2 \n\t" \ 408 "dmtc0 %0,$%1,%2 \n\t" \
380 ".set pop" \ 409 ".set pop" \
381 :: "r"(val), "n"(num), "n"(sel)); \ 410 :: "r"(val), "n"(num), "n"(sel)); \
382 if (name != NULL) \ 411 if (name != NULL) \
383 db_printf(" %s =%*s %#"PRIx64"\n", name, \ 412 db_printf(" %s =%*s %#"PRIx64"\n", name, \
384 FLDWIDTH - (int) strlen(name), "", (uint64_t)val); \ 413 FLDWIDTH - (int) strlen(name), "", (uint64_t)val); \
385} while (0) 414} while (0)
386 415
387void 416void
388db_cp0dump_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 417db_cp0dump_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
389 const char *modif) 418 const char *modif)
390{ 419{
391 u_int cp0flags = mips_options.mips_cpu->cpu_cp0flags; 420 u_int cp0flags = mips_options.mips_cpu->cpu_cp0flags;
392 421
393 SHOW32(MIPS_COP_0_TLB_INDEX, "index"); 422 SHOW32(MIPS_COP_0_TLB_INDEX, "index");
394 SHOW32(MIPS_COP_0_TLB_RANDOM, "random"); 423 SHOW32(MIPS_COP_0_TLB_RANDOM, "random");
395 424
396 if (!MIPS_HAS_R4K_MMU) { 425 if (!MIPS_HAS_R4K_MMU) {
397 SHOW32(MIPS_COP_0_TLB_LOW, "entrylow"); 426 SHOW32(MIPS_COP_0_TLB_LOW, "entrylow");
398 } else { 427 } else {
399 if (CPUIS64BITS) { 428 if (CPUIS64BITS) {
400 SHOW64(MIPS_COP_0_TLB_LO0, "entrylo0"); 429 SHOW64(MIPS_COP_0_TLB_LO0, "entrylo0");
401 SHOW64(MIPS_COP_0_TLB_LO1, "entrylo1"); 430 SHOW64(MIPS_COP_0_TLB_LO1, "entrylo1");
402 } else { 431 } else {
403 SHOW32(MIPS_COP_0_TLB_LO0, "entrylo0"); 432 SHOW32(MIPS_COP_0_TLB_LO0, "entrylo0");
404 SHOW32(MIPS_COP_0_TLB_LO1, "entrylo1"); 433 SHOW32(MIPS_COP_0_TLB_LO1, "entrylo1");
405 } 434 }
406 } 435 }
407 436
408 if (CPUIS64BITS) { 437 if (CPUIS64BITS) {
409 SHOW64(MIPS_COP_0_TLB_CONTEXT, "context"); 438 SHOW64(MIPS_COP_0_TLB_CONTEXT, "context");
410 } else { 439 } else {
411 SHOW32(MIPS_COP_0_TLB_CONTEXT, "context"); 440 SHOW32(MIPS_COP_0_TLB_CONTEXT, "context");
412 } 441 }
413 442
414 if (MIPS_HAS_R4K_MMU) { 443 if (MIPS_HAS_R4K_MMU) {
415 SHOW32(MIPS_COP_0_TLB_PG_MASK, "pagemask"); 444 SHOW32(MIPS_COP_0_TLB_PG_MASK, "pagemask");
416 SHOW32(MIPS_COP_0_TLB_WIRED, "wired"); 445 SHOW32(MIPS_COP_0_TLB_WIRED, "wired");
417 } 446 }
418 447
419 if (CPUIS64BITS) { 448 if (CPUIS64BITS) {
420 SHOW64(MIPS_COP_0_BAD_VADDR, "badvaddr"); 449 SHOW64(MIPS_COP_0_BAD_VADDR, "badvaddr");
421 } else { 450 } else {
422 SHOW32(MIPS_COP_0_BAD_VADDR, "badvaddr"); 451 SHOW32(MIPS_COP_0_BAD_VADDR, "badvaddr");
423 } 452 }
424 453
425 if (mips_options.mips_cpu_arch >= CPU_ARCH_MIPS3) { 454 if (mips_options.mips_cpu_arch >= CPU_ARCH_MIPS3) {
426 SHOW32(MIPS_COP_0_COUNT, "count"); 455 SHOW32(MIPS_COP_0_COUNT, "count");
427 } 456 }
428 457
429 if ((cp0flags & MIPS_CP0FL_USE) != 0) { 458 if ((cp0flags & MIPS_CP0FL_USE) != 0) {
430 if ((cp0flags & MIPS_CP0FL_EIRR) != 0) 459 if ((cp0flags & MIPS_CP0FL_EIRR) != 0)
431 SHOW64SEL(MIPS_COP_0_EIRR, "eirr"); 460 SHOW64SEL(MIPS_COP_0_EIRR, "eirr");
432 if ((cp0flags & MIPS_CP0FL_EIMR) != 0) 461 if ((cp0flags & MIPS_CP0FL_EIMR) != 0)
433 SHOW64SEL(MIPS_COP_0_EIMR, "eimr"); 462 SHOW64SEL(MIPS_COP_0_EIMR, "eimr");
434 } 463 }
435 464
436 if (CPUIS64BITS) { 465 if (CPUIS64BITS) {
437 SHOW64(MIPS_COP_0_TLB_HI, "entryhi"); 466 SHOW64(MIPS_COP_0_TLB_HI, "entryhi");
438 } else { 467 } else {
439 SHOW32(MIPS_COP_0_TLB_HI, "entryhi"); 468 SHOW32(MIPS_COP_0_TLB_HI, "entryhi");
440 } 469 }
441 470
442 if (mips_options.mips_cpu_arch >= CPU_ARCH_MIPS3) { 471 if (mips_options.mips_cpu_arch >= CPU_ARCH_MIPS3) {
443 SHOW32(MIPS_COP_0_COMPARE, "compare"); 472 SHOW32(MIPS_COP_0_COMPARE, "compare");
444 } 473 }
445 474
446 SHOW32(MIPS_COP_0_STATUS, "status"); 475 SHOW32(MIPS_COP_0_STATUS, "status");
447 SHOW32(MIPS_COP_0_CAUSE, "cause"); 476 SHOW32(MIPS_COP_0_CAUSE, "cause");
448 477
449 if (CPUIS64BITS) { 478 if (CPUIS64BITS) {
450 SHOW64(MIPS_COP_0_EXC_PC, "epc"); 479 SHOW64(MIPS_COP_0_EXC_PC, "epc");
451 } else { 480 } else {
452 SHOW32(MIPS_COP_0_EXC_PC, "epc"); 481 SHOW32(MIPS_COP_0_EXC_PC, "epc");
453 } 482 }
454 483
455 SHOW32(MIPS_COP_0_PRID, "prid"); 484 SHOW32(MIPS_COP_0_PRID, "prid");
456 485
457 if ((cp0flags & MIPS_CP0FL_USE) != 0) { 486 if ((cp0flags & MIPS_CP0FL_USE) != 0) {
458 if ((cp0flags & MIPS_CP0FL_EBASE) != 0) 487 if ((cp0flags & MIPS_CP0FL_EBASE) != 0)
459 SHOW32SEL(MIPS_COP_0_EBASE, "ebase"); 488 SHOW32SEL(MIPS_COP_0_EBASE, "ebase");
460 if ((cp0flags & MIPS_CP0FL_CONFIG) != 0) 489 if ((cp0flags & MIPS_CP0FL_CONFIG) != 0)
461 SHOW32(MIPS_COP_0_CONFIG, "config"); 490 SHOW32(MIPS_COP_0_CONFIG, "config");
462 if ((cp0flags & MIPS_CP0FL_CONFIG1) != 0) 491 if ((cp0flags & MIPS_CP0FL_CONFIG1) != 0)
463 SHOW32SEL(MIPS_COP_0_CONFIG1, "config1"); 492 SHOW32SEL(MIPS_COP_0_CONFIG1, "config1");
464 if ((cp0flags & MIPS_CP0FL_CONFIG2) != 0) 493 if ((cp0flags & MIPS_CP0FL_CONFIG2) != 0)
465 SHOW32SEL(MIPS_COP_0_CONFIG2, "config2"); 494 SHOW32SEL(MIPS_COP_0_CONFIG2, "config2");
466 if ((cp0flags & MIPS_CP0FL_CONFIG3) != 0) 495 if ((cp0flags & MIPS_CP0FL_CONFIG3) != 0)
467 SHOW32SEL(MIPS_COP_0_CONFIG3, "config3"); 496 SHOW32SEL(MIPS_COP_0_CONFIG3, "config3");
468 if ((cp0flags & MIPS_CP0FL_CONFIG4) != 0) 497 if ((cp0flags & MIPS_CP0FL_CONFIG4) != 0)
469 SHOW32SEL(MIPS_COP_0_CONFIG4, "config4"); 498 SHOW32SEL(MIPS_COP_0_CONFIG4, "config4");
470 if ((cp0flags & MIPS_CP0FL_CONFIG5) != 0) 499 if ((cp0flags & MIPS_CP0FL_CONFIG5) != 0)
471 SHOW32SEL(MIPS_COP_0_CONFIG5, "config5"); 500 SHOW32SEL(MIPS_COP_0_CONFIG5, "config5");
472 if ((cp0flags & MIPS_CP0FL_CONFIG6) != 0) 501 if ((cp0flags & MIPS_CP0FL_CONFIG6) != 0)
473 SHOW32SEL(MIPS_COP_0_CONFIG6, "config6"); 502 SHOW32SEL(MIPS_COP_0_CONFIG6, "config6");
474 if ((cp0flags & MIPS_CP0FL_CONFIG7) != 0) 503 if ((cp0flags & MIPS_CP0FL_CONFIG7) != 0)
475 SHOW32SEL(MIPS_COP_0_CONFIG7, "config7"); 504 SHOW32SEL(MIPS_COP_0_CONFIG7, "config7");
476 if (CPUISMIPSNNR2) 505 if (CPUISMIPSNNR2)
477 SHOW32(MIPS_COP_0_HWRENA, "hwrena"); 506 SHOW32(MIPS_COP_0_HWRENA, "hwrena");
478 if (MIPS_HAS_USERLOCAL) 507 if (MIPS_HAS_USERLOCAL)
479 SHOW32SEL(MIPS_COP_0_USERLOCAL, "userlocal"); 508 SHOW32SEL(MIPS_COP_0_USERLOCAL, "userlocal");
480 } else { 509 } else {
481 SHOW32(MIPS_COP_0_CONFIG, "config"); 510 SHOW32(MIPS_COP_0_CONFIG, "config");
482#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 511#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
483 if (CPUISMIPSNN) { 512 if (CPUISMIPSNN) {
484 uint32_t val; 513 uint32_t val;
485 514
486 val = mipsNN_cp0_config1_read(); 515 val = mipsNN_cp0_config1_read();
487 db_printf(" config1: %#x\n", val); 516 db_printf(" config1: %#x\n", val);
488 } 517 }
489#endif 518#endif
490 } 519 }
491 520
492 if (MIPS_HAS_LLSC) { 521 if (MIPS_HAS_LLSC) {
493 if (MIPS_HAS_LLADDR) { 522 if (MIPS_HAS_LLADDR) {
494 if (CPUIS64BITS) 523 if (CPUIS64BITS)
495 SHOW64(MIPS_COP_0_LLADDR, "lladdr"); 524 SHOW64(MIPS_COP_0_LLADDR, "lladdr");
496 else 525 else
497 SHOW32(MIPS_COP_0_LLADDR, "lladdr"); 526 SHOW32(MIPS_COP_0_LLADDR, "lladdr");
498 } 527 }
499 } 528 }
500 529
501#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 530#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
502 for (int i=0; i < curcpu()->ci_cpuwatch_count; i++) { 531 for (int i=0; i < curcpu()->ci_cpuwatch_count; i++) {
503 const intptr_t lo = mipsNN_cp0_watchlo_read(i); 532 const intptr_t lo = mipsNN_cp0_watchlo_read(i);
504 const uint32_t hi = mipsNN_cp0_watchhi_read(i); 533 const uint32_t hi = mipsNN_cp0_watchhi_read(i);
505 db_printf(" %s%d:%*s %#" PRIxPTR "\t", 534 db_printf(" %s%d:%*s %#" PRIxPTR "\t",
506 "watchlo", i, FLDWIDTH - 8, "", lo); 535 "watchlo", i, FLDWIDTH - 8, "", lo);
507 db_printf(" %s%d:%*s %#" PRIx32 "\n", 536 db_printf(" %s%d:%*s %#" PRIx32 "\n",
508 "watchhi", i, FLDWIDTH - 8, "", hi); 537 "watchhi", i, FLDWIDTH - 8, "", hi);
509 } 538 }
510#endif 539#endif
511 540
512 if (CPUIS64BITS) { 541 if (CPUIS64BITS) {
513 SHOW64(MIPS_COP_0_TLB_XCONTEXT, "xcontext"); 542 SHOW64(MIPS_COP_0_TLB_XCONTEXT, "xcontext");
514 } 543 }
515 544
516 if (CPUISMIPSNN) { 545 if (CPUISMIPSNN) {
517 if (CPUIS64BITS) { 546 if (CPUIS64BITS) {
518 SHOW64(MIPS_COP_0_PERFCNT0_CTL, "perfcnt0ctl"); 547 SHOW64(MIPS_COP_0_PERFCNT0_CTL, "perfcnt0ctl");
519 SHOW64SEL(MIPS_COP_0_PERFCNT0_CNT, "perfcnt0cnt"); 548 SHOW64SEL(MIPS_COP_0_PERFCNT0_CNT, "perfcnt0cnt");
520 } else { 549 } else {
521 SHOW32(MIPS_COP_0_PERFCNT0_CTL, "perfcnt0ctl"); 550 SHOW32(MIPS_COP_0_PERFCNT0_CTL, "perfcnt0ctl");
522 SHOW32SEL(MIPS_COP_0_PERFCNT0_CNT, "perfcnt0cnt"); 551 SHOW32SEL(MIPS_COP_0_PERFCNT0_CNT, "perfcnt0cnt");
523 } 552 }
524 } 553 }
525 554
526 if (((cp0flags & MIPS_CP0FL_USE) == 0) || 555 if (((cp0flags & MIPS_CP0FL_USE) == 0) ||
527 ((cp0flags & MIPS_CP0FL_ECC) != 0)) 556 ((cp0flags & MIPS_CP0FL_ECC) != 0))
528 SHOW32(MIPS_COP_0_ECC, "ecc"); 557 SHOW32(MIPS_COP_0_ECC, "ecc");
529 558
530 if (((cp0flags & MIPS_CP0FL_USE) == 0) || 559 if (((cp0flags & MIPS_CP0FL_USE) == 0) ||
531 ((cp0flags & MIPS_CP0FL_CACHE_ERR) != 0)) 560 ((cp0flags & MIPS_CP0FL_CACHE_ERR) != 0))
532 SHOW32(MIPS_COP_0_CACHE_ERR, "cacherr"); 561 SHOW32(MIPS_COP_0_CACHE_ERR, "cacherr");
533 562
534 SHOW32(MIPS_COP_0_TAG_LO, "cachelo"); 563 SHOW32(MIPS_COP_0_TAG_LO, "cachelo");
535 SHOW32(MIPS_COP_0_TAG_HI, "cachehi"); 564 SHOW32(MIPS_COP_0_TAG_HI, "cachehi");
536 565
537 if (CPUIS64BITS) { 566 if (CPUIS64BITS) {
538 SHOW64(MIPS_COP_0_ERROR_PC, "errorpc"); 567 SHOW64(MIPS_COP_0_ERROR_PC, "errorpc");
539 } else { 568 } else {
540 SHOW32(MIPS_COP_0_ERROR_PC, "errorpc"); 569 SHOW32(MIPS_COP_0_ERROR_PC, "errorpc");
541 } 570 }
542} 571}
543 572
544#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 573#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
545static void 574static void
546db_watch_cmd(db_expr_t address, bool have_addr, db_expr_t count, 575db_watch_cmd(db_expr_t address, bool have_addr, db_expr_t count,
547 const char *modif) 576 const char *modif)
548{ 577{
549 struct cpu_info * const ci = curcpu(); 578 struct cpu_info * const ci = curcpu();
550 cpu_watchpoint_t *cwp; 579 cpu_watchpoint_t *cwp;
551 register_t mask=0; 580 register_t mask=0;
552 uint32_t asid; 581 uint32_t asid;
553 uint32_t mode; 582 uint32_t mode;
554 db_expr_t value; 583 db_expr_t value;
555 char str[6]; 584 char str[6];
556 585
557 if (!have_addr) { 586 if (!have_addr) {
558 db_printf("%-3s %-5s %-16s %4s %4s\n", 587 db_printf("%-3s %-5s %-16s %4s %4s\n",
559 "#", "MODE", "ADDR", "MASK", "ASID"); 588 "#", "MODE", "ADDR", "MASK", "ASID");
560 for (u_int i=0; i < ci->ci_cpuwatch_count; i++) { 589 for (u_int i=0; i < ci->ci_cpuwatch_count; i++) {
561 cwp = &ci->ci_cpuwatch_tab[i]; 590 cwp = &ci->ci_cpuwatch_tab[i];
562 mode = cwp->cw_mode; 591 mode = cwp->cw_mode;
563 if ((mode & CPUWATCH_RWX) == 0) 592 if ((mode & CPUWATCH_RWX) == 0)
564 continue; /* empty/disabled/invalid */ 593 continue; /* empty/disabled/invalid */
565 str[0] = (mode & CPUWATCH_READ) ? 'r' : '-'; 594 str[0] = (mode & CPUWATCH_READ) ? 'r' : '-';
566 str[1] = (mode & CPUWATCH_WRITE) ? 'w' : '-'; 595 str[1] = (mode & CPUWATCH_WRITE) ? 'w' : '-';
567 str[2] = (mode & CPUWATCH_EXEC) ? 'x' : '-'; 596 str[2] = (mode & CPUWATCH_EXEC) ? 'x' : '-';
568 str[3] = (mode & CPUWATCH_MASK) ? 'm' : '-'; 597 str[3] = (mode & CPUWATCH_MASK) ? 'm' : '-';
569 str[4] = (mode & CPUWATCH_ASID) ? 'a' : 'g'; 598 str[4] = (mode & CPUWATCH_ASID) ? 'a' : 'g';
570 str[5] = '\0'; 599 str[5] = '\0';
571 db_printf("%2u: %s %16" PRIxREGISTER 600 db_printf("%2u: %s %16" PRIxREGISTER
572 " %4" PRIxREGISTER " %4x\n", 601 " %4" PRIxREGISTER " %4x\n",
573 i, str, cwp->cw_addr, cwp->cw_mask, cwp->cw_asid); 602 i, str, cwp->cw_addr, cwp->cw_mask, cwp->cw_asid);
574 } 603 }
575 db_flush_lex(); 604 db_flush_lex();
576 return; 605 return;
577 } 606 }
578 607
579 cwp = cpuwatch_alloc(); 608 cwp = cpuwatch_alloc();
580 if (cwp == NULL) { 609 if (cwp == NULL) {
581 db_printf("no watchpoint available\n"); 610 db_printf("no watchpoint available\n");
582 db_flush_lex(); 611 db_flush_lex();
583 return; 612 return;
584 } 613 }
585 614
586 /* 615 /*
587 * parse modif to define mode 616 * parse modif to define mode
588 */ 617 */
589 KASSERT(modif != NULL); 618 KASSERT(modif != NULL);
590 mode = 0; 619 mode = 0;
591 for (int i=0; modif[i] != '\0'; i++) { 620 for (int i=0; modif[i] != '\0'; i++) {
592 switch(modif[i]) { 621 switch(modif[i]) {
593 case 'w': 622 case 'w':
594 mode |= CPUWATCH_WRITE; 623 mode |= CPUWATCH_WRITE;
595 break; 624 break;
596 case 'm': 625 case 'm':
597 mode |= CPUWATCH_MASK; 626 mode |= CPUWATCH_MASK;
598 break; 627 break;
599 case 'r': 628 case 'r':
600 mode |= CPUWATCH_READ; 629 mode |= CPUWATCH_READ;
601 break; 630 break;
602 case 'x': 631 case 'x':
603 mode |= CPUWATCH_EXEC; 632 mode |= CPUWATCH_EXEC;
604 break; 633 break;
605 case 'a': 634 case 'a':
606 mode |= CPUWATCH_ASID; 635 mode |= CPUWATCH_ASID;
607 break; 636 break;
608 } 637 }
609 } 638 }
610 if (mode == 0) { 639 if (mode == 0) {
611 db_printf("mode modifier(s) missing\n"); 640 db_printf("mode modifier(s) missing\n");
612 db_flush_lex(); 641 db_flush_lex();
613 return; 642 return;
614 } 643 }
615 644
616 /* 645 /*
617 * if mask mode is requested get the mask, 646 * if mask mode is requested get the mask,
618 */ 647 */
619 if (mode & CPUWATCH_MASK) { 648 if (mode & CPUWATCH_MASK) {
620 if (! db_expression(&value)) { 649 if (! db_expression(&value)) {
621 db_printf("mask missing\n"); 650 db_printf("mask missing\n");
622 db_flush_lex(); 651 db_flush_lex();
623 return; 652 return;
624 } 653 }
625 mask = (register_t)(value & __BITS(11, 3)); 654 mask = (register_t)(value & __BITS(11, 3));
626 } 655 }
627 656
628 /* 657 /*
629 * if asid mode is requested, get the asid; 658 * if asid mode is requested, get the asid;
630 * otherwise use global mode (and set asid=0) 659 * otherwise use global mode (and set asid=0)
631 */ 660 */
632 if (mode & CPUWATCH_ASID) { 661 if (mode & CPUWATCH_ASID) {
633 if (! db_expression(&value)) { 662 if (! db_expression(&value)) {
634 db_printf("asid missing\n"); 663 db_printf("asid missing\n");
635 db_flush_lex(); 664 db_flush_lex();
636 return; 665 return;
637 } 666 }
638 asid = (uint32_t)(value & __BITS(7,0)); 667 asid = (uint32_t)(value & __BITS(7,0));
639 } else { 668 } else {
640 asid = 0; 669 asid = 0;
641 } 670 }
642 671
643 if (mode & (CPUWATCH_MASK|CPUWATCH_ASID)) 672 if (mode & (CPUWATCH_MASK|CPUWATCH_ASID))
644 db_skip_to_eol(); 673 db_skip_to_eol();
645 else 674 else
646 db_flush_lex(); 675 db_flush_lex();
647 676
648 /* 677 /*
649 * store to the (volatile) table entry 678 * store to the (volatile) table entry
650 * other CPUs can see this and load when resuming from pause 679 * other CPUs can see this and load when resuming from pause
651 */ 680 */
652 cwp->cw_addr = (register_t)address; 681 cwp->cw_addr = (register_t)address;
653 cwp->cw_mask = (register_t)mask; 682 cwp->cw_mask = (register_t)mask;
654 cwp->cw_asid = asid; 683 cwp->cw_asid = asid;
655 cwp->cw_mode = mode; 684 cwp->cw_mode = mode;
656 685
657 /* 686 /*
658 * program the CPU watchpoint regs 687 * program the CPU watchpoint regs
659 */ 688 */
660 cpuwatch_set(cwp); 689 cpuwatch_set(cwp);
661} 690}
662 691
663static void 692static void
664db_unwatch_cmd(db_expr_t address, bool have_addr, db_expr_t count, 693db_unwatch_cmd(db_expr_t address, bool have_addr, db_expr_t count,
665 const char *modif) 694 const char *modif)
666{ 695{
667 struct cpu_info * const ci = curcpu(); 696 struct cpu_info * const ci = curcpu();
668 const bool unwatch_all = !have_addr; 697 const bool unwatch_all = !have_addr;
669 int n; 698 int n;
670 699
671 n = 0; 700 n = 0;
672 for (u_int i=0; i < ci->ci_cpuwatch_count; i++) { 701 for (u_int i=0; i < ci->ci_cpuwatch_count; i++) {
673 cpu_watchpoint_t * const cwp = &ci->ci_cpuwatch_tab[i]; 702 cpu_watchpoint_t * const cwp = &ci->ci_cpuwatch_tab[i];
674 if (unwatch_all || (cwp->cw_addr == (register_t)address)) { 703 if (unwatch_all || (cwp->cw_addr == (register_t)address)) {
675 cpuwatch_free(cwp); 704 cpuwatch_free(cwp);
676 n++; 705 n++;
677 } 706 }
678 } 707 }
679 if (n == 0) 708 if (n == 0)
680 db_printf("no watch found on address %#" PRIxREGISTER "\n", 709 db_printf("no watch found on address %#" PRIxREGISTER "\n",
681 (register_t)address); 710 (register_t)address);
682} 711}
683#endif /* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */ 712#endif /* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
684 713
685#ifdef MIPS64_XLS 714#ifdef MIPS64_XLS
686void 715void
687db_mfcr_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 716db_mfcr_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
688 const char *modif) 717 const char *modif)
689{ 718{
690 uint64_t value; 719 uint64_t value;
691 720
692 if ((mips_options.mips_cpu->cpu_flags & CPU_MIPS_HAVE_MxCR) == 0) { 721 if ((mips_options.mips_cpu->cpu_flags & CPU_MIPS_HAVE_MxCR) == 0) {
693 db_printf("mfcr not implemented on this CPU\n"); 722 db_printf("mfcr not implemented on this CPU\n");
694 return; 723 return;
695 } 724 }
696 725
697 if (!have_addr) { 726 if (!have_addr) {
698 db_printf("Address missing\n"); 727 db_printf("Address missing\n");
699 return; 728 return;
700 } 729 }
701 730
702 /* value = CR[addr] */ 731 /* value = CR[addr] */
703 __asm volatile( \ 732 __asm volatile( \
704 ".set push \n\t" \ 733 ".set push \n\t" \
705 ".set arch=xlr \n\t" \ 734 ".set arch=xlr \n\t" \
706 ".set noat \n\t" \ 735 ".set noat \n\t" \
707 "mfcr %0,%1 \n\t" \ 736 "mfcr %0,%1 \n\t" \
708 ".set pop \n\t" \ 737 ".set pop \n\t" \
709 : "=r"(value) : "r"(addr)); 738 : "=r"(value) : "r"(addr));
710 739
711 db_printf("control reg 0x%" DDB_EXPR_FMT "x = 0x%" PRIx64 "\n", 740 db_printf("control reg 0x%" DDB_EXPR_FMT "x = 0x%" PRIx64 "\n",
712 addr, value); 741 addr, value);
713} 742}
714 743
715void 744void
716db_mtcr_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 745db_mtcr_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
717 const char *modif) 746 const char *modif)
718{ 747{
719 db_expr_t value; 748 db_expr_t value;
720 749
721 if ((mips_options.mips_cpu->cpu_flags & CPU_MIPS_HAVE_MxCR) == 0) { 750 if ((mips_options.mips_cpu->cpu_flags & CPU_MIPS_HAVE_MxCR) == 0) {
722 db_printf("mtcr not implemented on this CPU\n"); 751 db_printf("mtcr not implemented on this CPU\n");
723 return; 752 return;
724 } 753 }
725 754
726 if ((!have_addr) || (! db_expression(&value))) { 755 if ((!have_addr) || (! db_expression(&value))) {
727 db_printf("Address missing\n"); 756 db_printf("Address missing\n");
728 db_flush_lex(); 757 db_flush_lex();
729 return; 758 return;
730 } 759 }
731 db_skip_to_eol(); 760 db_skip_to_eol();
732 761
733 /* CR[addr] = value */ 762 /* CR[addr] = value */
734 __asm volatile( \ 763 __asm volatile( \
735 ".set push \n\t" \ 764 ".set push \n\t" \
736 ".set arch=xlr \n\t" \ 765 ".set arch=xlr \n\t" \
737 ".set noat \n\t" \ 766 ".set noat \n\t" \
738 "mtcr %0,%1 \n\t" \ 767 "mtcr %0,%1 \n\t" \
739 ".set pop \n\t" \ 768 ".set pop \n\t" \
740 :: "r"(value), "r"(addr)); 769 :: "r"(value), "r"(addr));
741 770
742 db_printf("control reg 0x%" DDB_EXPR_FMT "x = 0x%" DDB_EXPR_FMT "x\n", 771 db_printf("control reg 0x%" DDB_EXPR_FMT "x = 0x%" DDB_EXPR_FMT "x\n",
743 addr, value); 772 addr, value);
744} 773}
745#endif /* MIPS64_XLS */ 774#endif /* MIPS64_XLS */
746 775
747#ifdef MIPS64_OCTEON 776#ifdef MIPS64_OCTEON
748#include <mips/cavium/dev/octeon_ciureg.h> 777#include <mips/cavium/dev/octeon_ciureg.h>
749 778
750#ifdef MULTIPROCESSOR 779#ifdef MULTIPROCESSOR
751static void 780static void
752db_mach_nmi_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 781db_mach_nmi_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
753 const char *modif) 782 const char *modif)
754{ 783{
755 CPU_INFO_ITERATOR cii; 784 CPU_INFO_ITERATOR cii;
756 struct cpu_info *ci; 785 struct cpu_info *ci;
757 786
758 if (!have_addr) { 787 if (!have_addr) {
759 db_printf("CPU not specific\n"); 788 db_printf("CPU not specific\n");
760 return; 789 return;
761 } 790 }
762 for (CPU_INFO_FOREACH(cii, ci)) { 791 for (CPU_INFO_FOREACH(cii, ci)) {
763 if (cpu_index(ci) == addr) 792 if (cpu_index(ci) == addr)
764 break; 793 break;
765 } 794 }
766 if (ci == NULL) { 795 if (ci == NULL) {
767 db_printf("CPU %ld not configured\n", (long)addr); 796 db_printf("CPU %ld not configured\n", (long)addr);
768 return; 797 return;
769 } 798 }
770 if (ci == curcpu()) { 799 if (ci == curcpu()) {
771 db_printf("CPU %ld is current cpu; request ignored\n", 800 db_printf("CPU %ld is current cpu; request ignored\n",
772 (long)addr); 801 (long)addr);
773 return; 802 return;
774 } 803 }
775 mips3_sd(MIPS_PHYS_TO_XKPHYS_UNCACHED(CIU_NMI), __BIT(ci->ci_cpuid)); 804 mips3_sd(MIPS_PHYS_TO_XKPHYS_UNCACHED(CIU_NMI), __BIT(ci->ci_cpuid));
776} 805}
777#endif 806#endif
778#endif 807#endif
779 808
780static void 809static void
781db_mach_reset_cmd(db_expr_t addr, bool have_addr, db_expr_t count, 810db_mach_reset_cmd(db_expr_t addr, bool have_addr, db_expr_t count,
782 const char *modif) 811 const char *modif)
783{ 812{
784 813
785 if (cpu_reset_address == NULL) { 814 if (cpu_reset_address == NULL) {
786 db_printf("cpu_reset_address is not set\n"); 815 db_printf("cpu_reset_address is not set\n");
787 return; 816 return;
788 } 817 }
789 818
790 cpu_reset_address(); 819 cpu_reset_address();
791} 820}
792 821
793const struct db_command db_machine_command_table[] = { 822const struct db_command db_machine_command_table[] = {
794#ifdef MULTIPROCESSOR 823#ifdef MULTIPROCESSOR
795 { DDB_ADD_CMD("cpu", db_mach_cpu_cmd, 0, 824 { DDB_ADD_CMD("cpu", db_mach_cpu_cmd, 0,
796 "switch to another cpu", "cpu#", NULL) }, 825 "switch to another cpu", "cpu#", NULL) },
797#endif 826#endif
798 { DDB_ADD_CMD("cp0", db_cp0dump_cmd, 0, 827 { DDB_ADD_CMD("cp0", db_cp0dump_cmd, 0,
799 "Dump CP0 registers.", 828 "Dump CP0 registers.",
800 NULL, NULL) }, 829 NULL, NULL) },
801 { DDB_ADD_CMD("kvtop", db_kvtophys_cmd, 0, 830 { DDB_ADD_CMD("kvtop", db_kvtophys_cmd, 0,
802 "Print the physical address for a given kernel virtual address", 831 "Print the physical address for a given kernel virtual address",
803 "address", 832 "address",
804 " address:\tvirtual address to look up") }, 833 " address:\tvirtual address to look up") },
805#ifdef MIPS64_XLS 834#ifdef MIPS64_XLS
806 { DDB_ADD_CMD("mfcr", db_mfcr_cmd, CS_NOREPEAT, 835 { DDB_ADD_CMD("mfcr", db_mfcr_cmd, CS_NOREPEAT,
807 "Dump processor control register", 836 "Dump processor control register",
808 NULL, NULL) }, 837 NULL, NULL) },
809 { DDB_ADD_CMD("mtcr", db_mtcr_cmd, CS_NOREPEAT|CS_MORE, 838 { DDB_ADD_CMD("mtcr", db_mtcr_cmd, CS_NOREPEAT|CS_MORE,
810 "Set processor control register", 839 "Set processor control register",
811 NULL, NULL) }, 840 NULL, NULL) },
812#endif 841#endif
813#if defined(MIPS64_OCTEON) && defined(MULTIPROCESSOR) 842#if defined(MIPS64_OCTEON) && defined(MULTIPROCESSOR)
814 { DDB_ADD_CMD("nmi", db_mach_nmi_cmd, CS_NOREPEAT, 843 { DDB_ADD_CMD("nmi", db_mach_nmi_cmd, CS_NOREPEAT,
815 "Send NMI to processor", 844 "Send NMI to processor",
816 "cpu#", NULL) }, 845 "cpu#", NULL) },
817#endif /* OCTEON + MP */ 846#endif /* OCTEON + MP */
818 { DDB_ADD_CMD("reset", db_mach_reset_cmd, CS_NOREPEAT, 847 { DDB_ADD_CMD("reset", db_mach_reset_cmd, CS_NOREPEAT,
819 "Initiate hardware reset", 848 "Initiate hardware reset",
820 NULL, NULL) }, 849 NULL, NULL) },
821 { DDB_ADD_CMD("tlb", db_tlbdump_cmd, 0, 850 { DDB_ADD_CMD("tlb", db_tlbdump_cmd, 0,
822 "Print out TLB entries. (only works with options DEBUG)", 851 "Print out TLB entries. (only works with options DEBUG)",
823 NULL, NULL) }, 852 NULL, NULL) },
824#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 853#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
825 { DDB_ADD_CMD("watch", db_watch_cmd, CS_MORE, 854 { DDB_ADD_CMD("watch", db_watch_cmd, CS_MORE,
826 "set cp0 watchpoint", 855 "set cp0 watchpoint",
827 "address <mask> <asid> </rwxma>", NULL) }, 856 "address <mask> <asid> </rwxma>", NULL) },
828 { DDB_ADD_CMD("unwatch",db_unwatch_cmd, 0, 857 { DDB_ADD_CMD("unwatch",db_unwatch_cmd, 0,
829 "delete cp0 watchpoint", 858 "delete cp0 watchpoint",
830 "address", NULL) }, 859 "address", NULL) },
831#endif /* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */ 860#endif /* (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0 */
832 { DDB_END_CMD }, 861 { DDB_END_CMD },
833}; 862};
834#endif /* !KGDB */ 863#endif /* !KGDB */
835 864
836/* 865/*
837 * Determine whether the instruction involves a delay slot. 866 * Determine whether the instruction involves a delay slot.
838 */ 867 */
839bool 868bool
840inst_branch(int inst) 869inst_branch(int inst)
841{ 870{
842 InstFmt i; 871 InstFmt i;
843 int delslt; 872 int delslt;
844 873
845 i.word = inst; 874 i.word = inst;
846 delslt = 0; 875 delslt = 0;
847 switch (i.JType.op) { 876 switch (i.JType.op) {
848 case OP_REGIMM: 877 case OP_REGIMM:
849 case OP_J: 878 case OP_J:
850 case OP_JAL: 879 case OP_JAL:
851#if MIPS64_OCTEON 880#if MIPS64_OCTEON
852 case OP_CVM_BBIT0: 881 case OP_CVM_BBIT0:
853 case OP_CVM_BBIT032: 882 case OP_CVM_BBIT032:
854 case OP_CVM_BBIT1: 883 case OP_CVM_BBIT1:
855 case OP_CVM_BBIT132: 884 case OP_CVM_BBIT132:
856#endif 885#endif
857 case OP_BEQ: 886 case OP_BEQ:
858 case OP_BNE: 887 case OP_BNE:
859 case OP_BLEZ: 888 case OP_BLEZ:
860 case OP_BGTZ: 889 case OP_BGTZ:
861 case OP_BEQL: 890 case OP_BEQL:
862 case OP_BNEL: 891 case OP_BNEL:
863 case OP_BLEZL: 892 case OP_BLEZL:
864 case OP_BGTZL: 893 case OP_BGTZL:
865 delslt = 1; 894 delslt = 1;
866 break; 895 break;
867 896
868 case OP_COP0: 897 case OP_COP0:
869 case OP_COP1: 898 case OP_COP1:
870 switch (i.RType.rs) { 899 switch (i.RType.rs) {
871 case OP_BCx: 900 case OP_BCx:
872 case OP_BCy: 901 case OP_BCy:
873 delslt = 1; 902 delslt = 1;
874 } 903 }
875 break; 904 break;
876 905
877 case OP_SPECIAL: 906 case OP_SPECIAL:
878 if (i.RType.op == OP_JR || i.RType.op == OP_JALR) 907 if (i.RType.op == OP_JR || i.RType.op == OP_JALR)
879 delslt = 1; 908 delslt = 1;
880 break; 909 break;
881 } 910 }
882 return delslt; 911 return delslt;
883} 912}
884 913
885/* 914/*
886 * Determine whether the instruction calls a function. 915 * Determine whether the instruction calls a function.
887 */ 916 */
888bool 917bool
889inst_call(int inst) 918inst_call(int inst)
890{ 919{
891 bool call; 920 bool call;
892 InstFmt i; 921 InstFmt i;
893 922
894 i.word = inst; 923 i.word = inst;
895 if (i.JType.op == OP_SPECIAL 924 if (i.JType.op == OP_SPECIAL
896 && ((i.RType.func == OP_JR && i.RType.rs != 31) || 925 && ((i.RType.func == OP_JR && i.RType.rs != 31) ||
897 i.RType.func == OP_JALR)) 926 i.RType.func == OP_JALR))
898 call = 1; 927 call = 1;
899 else if (i.JType.op == OP_JAL) 928 else if (i.JType.op == OP_JAL)
900 call = 1; 929 call = 1;
901 else 930 else
902 call = 0; 931 call = 0;
903 return call; 932 return call;
904} 933}
905 934
906/* 935/*
907 * Determine whether the instruction returns from a function (j ra). The 936 * Determine whether the instruction returns from a function (j ra). The
908 * compiler can use this construct for other jumps, but usually will not. 937 * compiler can use this construct for other jumps, but usually will not.
909 * This lets the ddb "next" command to work (also need inst_trap_return()). 938 * This lets the ddb "next" command to work (also need inst_trap_return()).
910 */ 939 */
911bool 940bool
912inst_return(int inst) 941inst_return(int inst)
913{ 942{
914 InstFmt i; 943 InstFmt i;
915 944
916 i.word = inst; 945 i.word = inst;
917 946
918 return (i.JType.op == OP_SPECIAL && i.RType.func == OP_JR && 947 return (i.JType.op == OP_SPECIAL && i.RType.func == OP_JR &&
919 i.RType.rs == 31); 948 i.RType.rs == 31);
920} 949}
921 950
922/* 951/*
923 * Determine whether the instruction makes a jump. 952 * Determine whether the instruction makes a jump.
924 */ 953 */
925bool 954bool
926inst_unconditional_flow_transfer(int inst) 955inst_unconditional_flow_transfer(int inst)
927{ 956{
928 InstFmt i; 957 InstFmt i;
929 bool jump; 958 bool jump;
930 959
931 i.word = inst; 960 i.word = inst;
932 jump = (i.JType.op == OP_J) || 961 jump = (i.JType.op == OP_J) ||
933 (i.JType.op == OP_SPECIAL && i.RType.func == OP_JR); 962 (i.JType.op == OP_SPECIAL && i.RType.func == OP_JR);
934 return jump; 963 return jump;
935} 964}
936 965
937/* 966/*
938 * Determine whether the instruction is a load/store as appropriate. 967 * Determine whether the instruction is a load/store as appropriate.
939 */ 968 */
940bool 969bool
941inst_load(int inst) 970inst_load(int inst)
942{ 971{
943 InstFmt i = { .word = inst, }; 972 InstFmt i = { .word = inst, };
944 973
945 /* 974 /*
946 * All loads are opcodes 04x or 06x. 975 * All loads are opcodes 04x or 06x.
947 */ 976 */
948 if ((i.JType.op & 050) != 040) 977 if ((i.JType.op & 050) != 040)
949 return false; 978 return false;
950 979
951 /* 980 /*
952 * Except these this opcode is not a load. 981 * Except these this opcode is not a load.
953 */ 982 */
954 return i.JType.op != OP_PREF; 983 return i.JType.op != OP_PREF;
955} 984}
956 985
957bool 986bool
958inst_store(int inst) 987inst_store(int inst)
959{ 988{
960 InstFmt i = { .word = inst, }; 989 InstFmt i = { .word = inst, };
961 990
962 /* 991 /*
963 * All stores are opcodes 05x or 07x. 992 * All stores are opcodes 05x or 07x.
964 */ 993 */
965 if ((i.JType.op & 050) != 050) 994 if ((i.JType.op & 050) != 050)
966 return false; 995 return false;
967 996
968 /* 997 /*
969 * Except these two opcodes are not stores. 998 * Except these two opcodes are not stores.
970 */ 999 */
971 return i.JType.op != OP_RSVD073 && i.JType.op != OP_CACHE; 1000 return i.JType.op != OP_RSVD073 && i.JType.op != OP_CACHE;
972} 1001}
973 1002
974/* 1003/*
975 * Return the next pc if the given branch is taken. 1004 * Return the next pc if the given branch is taken.
976 * mips_emul_branch() runs analysis for branch delay slot. 1005 * mips_emul_branch() runs analysis for branch delay slot.
977 */ 1006 */
978db_addr_t 1007db_addr_t
979branch_taken(int inst, db_addr_t pc, db_regs_t *regs) 1008branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
980{ 1009{
981 struct pcb * const pcb = lwp_getpcb(curlwp); 1010 struct pcb * const pcb = lwp_getpcb(curlwp);
982 const uint32_t fpucsr = PCB_FSR(pcb); 1011 const uint32_t fpucsr = PCB_FSR(pcb);
983 vaddr_t ra; 1012 vaddr_t ra;
984 1013
985 ra = mips_emul_branch((struct trapframe *)regs, pc, fpucsr, false); 1014 ra = mips_emul_branch((struct trapframe *)regs, pc, fpucsr, false);
986 return ra; 1015 return ra;
987} 1016}
988 1017
989/* 1018/*
990 * Return the next pc of an arbitrary instruction. 1019 * Return the next pc of an arbitrary instruction.
991 */ 1020 */
992db_addr_t 1021db_addr_t
993next_instr_address(db_addr_t pc, bool bd) 1022next_instr_address(db_addr_t pc, bool bd)
994{ 1023{
995 uint32_t ins; 1024 uint32_t ins;
996 1025
997 if (bd == false) 1026 if (bd == false)
998 return (pc + 4); 1027 return (pc + 4);
999 1028
1000 if (pc < MIPS_KSEG0_START) 1029 if (pc < MIPS_KSEG0_START)
1001 ins = mips_ufetch32((void *)pc); 1030 ins = mips_ufetch32((void *)pc);
1002 else 1031 else
1003 ins = *(uint32_t *)pc; 1032 ins = *(uint32_t *)pc;
1004 1033
1005 if (inst_branch(ins) || inst_call(ins) || inst_return(ins)) 1034 if (inst_branch(ins) || inst_call(ins) || inst_return(ins))
1006 return (pc + 4); 1035 return (pc + 4);
1007 1036
1008 return (pc); 1037 return (pc);
1009} 1038}
1010 1039
1011#ifdef MULTIPROCESSOR 1040#ifdef MULTIPROCESSOR
1012 1041
1013bool 1042bool
1014ddb_running_on_this_cpu_p(void) 1043ddb_running_on_this_cpu_p(void)
1015{ 1044{
1016 return ddb_cpu == cpu_number(); 1045 return ddb_cpu == cpu_number();
1017} 1046}
1018 1047
1019bool 1048bool
1020ddb_running_on_any_cpu_p(void) 1049ddb_running_on_any_cpu_p(void)
1021{ 1050{
1022 return ddb_cpu != NOCPU; 1051 return ddb_cpu != NOCPU;
1023} 1052}
1024 1053
1025void 1054void
1026db_resume_others(void) 1055db_resume_others(void)
1027{ 1056{
1028 u_int cpu_me = cpu_number(); 1057 u_int cpu_me = cpu_number();
1029 1058
1030 if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me) 1059 if (atomic_cas_uint(&ddb_cpu, cpu_me, NOCPU) == cpu_me)
1031 cpu_resume_others(); 1060 cpu_resume_others();
1032} 1061}
1033 1062
1034static void 1063static void
1035db_mach_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) 1064db_mach_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif)
1036{ 1065{
1037 CPU_INFO_ITERATOR cii; 1066 CPU_INFO_ITERATOR cii;
1038 struct cpu_info *ci; 1067 struct cpu_info *ci;
1039 1068
1040 if (!have_addr) { 1069 if (!have_addr) {
1041 cpu_debug_dump(); 1070 cpu_debug_dump();
1042 return; 1071 return;
1043 } 1072 }
1044 for (CPU_INFO_FOREACH(cii, ci)) { 1073 for (CPU_INFO_FOREACH(cii, ci)) {
1045 if (cpu_index(ci) == addr) 1074 if (cpu_index(ci) == addr)
1046 break; 1075 break;
1047 } 1076 }
1048 if (ci == NULL) { 1077 if (ci == NULL) {
1049 db_printf("CPU %ld not configured\n", (long)addr); 1078 db_printf("CPU %ld not configured\n", (long)addr);
1050 return; 1079 return;
1051 } 1080 }
1052 if (ci != curcpu()) { 1081 if (ci != curcpu()) {
1053 if (!cpu_is_paused(cpu_index(ci))) { 1082 if (!cpu_is_paused(cpu_index(ci))) {
1054 db_printf("CPU %ld not paused\n", (long)addr); 1083 db_printf("CPU %ld not paused\n", (long)addr);
1055 return; 1084 return;
1056 } 1085 }
1057 (void)atomic_cas_uint(&ddb_cpu, cpu_number(), cpu_index(ci)); 1086 (void)atomic_cas_uint(&ddb_cpu, cpu_number(), cpu_index(ci));
1058 db_continue_cmd(0, false, 0, ""); 1087 db_continue_cmd(0, false, 0, "");
1059 } 1088 }
1060} 1089}
1061#endif /* MULTIPROCESSOR */ 1090#endif /* MULTIPROCESSOR */
1062 1091
1063#endif /* _KERNEL */ 1092#endif /* _KERNEL */

cvs diff -r1.7 -r1.8 src/sys/arch/riscv/riscv/db_disasm.c (switch to unified diff)

--- src/sys/arch/riscv/riscv/db_disasm.c 2021/05/01 06:48:51 1.7
+++ src/sys/arch/riscv/riscv/db_disasm.c 2021/05/23 23:22:55 1.8
@@ -1,1503 +1,1497 @@ @@ -1,1503 +1,1497 @@
1/* $NetBSD: db_disasm.c,v 1.7 2021/05/01 06:48:51 skrll Exp $ */ 1/* $NetBSD: db_disasm.c,v 1.8 2021/05/23 23:22:55 dholland Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 4 * Copyright (c) 2014 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas of 3am Software Foundry. 8 * by Matt Thomas of 3am Software Foundry.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33 33
34__RCSID("$NetBSD: db_disasm.c,v 1.7 2021/05/01 06:48:51 skrll Exp $"); 34__RCSID("$NetBSD: db_disasm.c,v 1.8 2021/05/23 23:22:55 dholland Exp $");
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/systm.h> 37#include <sys/systm.h>
38 38
39#include <riscv/db_machdep.h> 39#include <riscv/db_machdep.h>
40#include <riscv/insn.h> 40#include <riscv/insn.h>
41 41
 42#include <ddb/db_access.h>
42#include <ddb/db_user.h> 43#include <ddb/db_user.h>
43#include <ddb/db_interface.h> 44#include <ddb/db_interface.h>
44#include <ddb/db_output.h> 45#include <ddb/db_output.h>
45#include <ddb/db_extern.h> 46#include <ddb/db_extern.h>
46#include <ddb/db_sym.h> 47#include <ddb/db_sym.h>
47 48
48//////////////////////////////////////////////////////////// 49////////////////////////////////////////////////////////////
49// registers 50// registers
50 51
51static const char *riscv_registers[32] = { 52static const char *riscv_registers[32] = {
52 "zero", "ra", "sp", "gp", "tp", 53 "zero", "ra", "sp", "gp", "tp",
53 "t0", "t1", "t2", 54 "t0", "t1", "t2",
54 "s0", "s1", 55 "s0", "s1",
55 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", 56 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
56 "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", 57 "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
57 "t3", "t4", "t5", "t6" 58 "t3", "t4", "t5", "t6"
58}; 59};
59 60
60/* XXX this should be in MI ddb */ 61/* XXX this should be in MI ddb */
61static void 62static void
62db_print_addr(db_addr_t loc) 63db_print_addr(db_addr_t loc)
63{ 64{
64 db_expr_t diff; 65 db_expr_t diff;
65 db_sym_t sym; 66 db_sym_t sym;
66 const char *symname; 67 const char *symname;
67 68
68/* hack for testing since the test program is ASLR'd */ 69/* hack for testing since the test program is ASLR'd */
69#ifndef _KERNEL 70#ifndef _KERNEL
70 loc &= 0xfff; 71 loc &= 0xfff;
71#endif 72#endif
72 73
73 diff = INT_MAX; 74 diff = INT_MAX;
74 symname = NULL; 75 symname = NULL;
75 sym = db_search_symbol(loc, DB_STGY_ANY, &diff); 76 sym = db_search_symbol(loc, DB_STGY_ANY, &diff);
76 db_symbol_values(sym, &symname, 0); 77 db_symbol_values(sym, &symname, 0);
77 78
78 if (symname) { 79 if (symname) {
79 if (diff == 0) 80 if (diff == 0)
80 db_printf("%s", symname); 81 db_printf("%s", symname);
81 else 82 else
82 db_printf("<%s+%"DDB_EXPR_FMT"x>", symname, diff); 83 db_printf("<%s+%"DDB_EXPR_FMT"x>", symname, diff);
83 db_printf("\t[addr:%#"PRIxVADDR"]", loc); 84 db_printf("\t[addr:%#"PRIxVADDR"]", loc);
84 } else { 85 } else {
85 db_printf("%#"PRIxVADDR, loc); 86 db_printf("%#"PRIxVADDR, loc);
86 } 87 }
87} 88}
88 89
89//////////////////////////////////////////////////////////// 90////////////////////////////////////////////////////////////
90// 16-bit instructions 91// 16-bit instructions
91 92
92/* 93/*
93 * This is too tightly wedged in to make it worth trying to make it 94 * This is too tightly wedged in to make it worth trying to make it
94 * table-driven. But I'm going to hack it up to use a 1-level switch. 95 * table-driven. But I'm going to hack it up to use a 1-level switch.
95 * 96 *
96 * Note that quite a few instructions depend on the architecture word 97 * Note that quite a few instructions depend on the architecture word
97 * size. I've used the #defines for that to conditionalize it, on the 98 * size. I've used the #defines for that to conditionalize it, on the
98 * grounds that ddb is disassembling itself so the build machine 99 * grounds that ddb is disassembling itself so the build machine
99 * version is the target machine version. This is not true for crash 100 * version is the target machine version. This is not true for crash
100 * necessarily but I don't think 101 * necessarily but I don't think
101 */ 102 */
102 103
103#define COMBINE(op, q) (((op) << 2) | (q)) 104#define COMBINE(op, q) (((op) << 2) | (q))
104 105
105#define IN_Q0(op) COMBINE(op, OPCODE16_Q0) 106#define IN_Q0(op) COMBINE(op, OPCODE16_Q0)
106#define IN_Q1(op) COMBINE(op, OPCODE16_Q1) 107#define IN_Q1(op) COMBINE(op, OPCODE16_Q1)
107#define IN_Q2(op) COMBINE(op, OPCODE16_Q2) 108#define IN_Q2(op) COMBINE(op, OPCODE16_Q2)
108 109
109/* 110/*
110 * All the 16-bit immediate bit-wrangling is done in uint32_t, which 111 * All the 16-bit immediate bit-wrangling is done in uint32_t, which
111 * is sufficient, but on RV64 the resulting values should be printed 112 * is sufficient, but on RV64 the resulting values should be printed
112 * as 64-bit. Continuing the assumption that we're disassembling for 113 * as 64-bit. Continuing the assumption that we're disassembling for
113 * the size we're built on, do nothing for RV32 and sign-extend from 114 * the size we're built on, do nothing for RV32 and sign-extend from
114 * 32 to 64 for RV64. (And bail on RV128 since it's not clear what 115 * 32 to 64 for RV64. (And bail on RV128 since it's not clear what
115 * the C type sizes are going to be there anyway...) 116 * the C type sizes are going to be there anyway...)
116 */ 117 */
117static unsigned long 118static unsigned long
118maybe_signext64(uint32_t x) 119maybe_signext64(uint32_t x)
119{ 120{
120#if __riscv_xlen == 32 121#if __riscv_xlen == 32
121 return x; 122 return x;
122#elif __riscv_xlen == 64 123#elif __riscv_xlen == 64
123 uint64_t xx; 124 uint64_t xx;
124 125
125 xx = ((x & 0x80000000) ? 0xffffffff00000000 : 0) | x; 126 xx = ((x & 0x80000000) ? 0xffffffff00000000 : 0) | x;
126 return xx; 127 return xx;
127#else 128#else
128#error Oops. 129#error Oops.
129#endif 130#endif
130} 131}
131 132
132static int 133static int
133db_disasm_16(db_addr_t loc, uint32_t insn, bool altfmt) 134db_disasm_16(db_addr_t loc, uint32_t insn, bool altfmt)
134{ 135{
135 /* note: insn needs to be uint32_t for immediate computations */ 136 /* note: insn needs to be uint32_t for immediate computations */
136 137
137 uint32_t imm; 138 uint32_t imm;
138 unsigned rd, rs1, rs2; 139 unsigned rd, rs1, rs2;
139 140
140 //warnx("toot 0x%x", insn); 141 //warnx("toot 0x%x", insn);
141 switch (COMBINE(INSN16_FUNCT3(insn), INSN16_QUADRANT(insn))) { 142 switch (COMBINE(INSN16_FUNCT3(insn), INSN16_QUADRANT(insn))) {
142 case IN_Q0(Q0_ADDI4SPN): 143 case IN_Q0(Q0_ADDI4SPN):
143 rd = INSN16_RS2x(insn); 144 rd = INSN16_RS2x(insn);
144 imm = INSN16_IMM_CIW(insn); 145 imm = INSN16_IMM_CIW(insn);
145 if (imm == 0) { 146 if (imm == 0) {
146 /* reserved (all bits 0 -> invalid) */ 147 /* reserved (all bits 0 -> invalid) */
147 return EINVAL; 148 return EINVAL;
148 } 149 }
149 db_printf("c.addi4spn %s, 0x%x\n", riscv_registers[rd], imm); 150 db_printf("c.addi4spn %s, 0x%x\n", riscv_registers[rd], imm);
150 break; 151 break;
151 case IN_Q0(Q0_FLD_LQ): 152 case IN_Q0(Q0_FLD_LQ):
152 rs1 = INSN16_RS1x(insn); 153 rs1 = INSN16_RS1x(insn);
153 rd = INSN16_RS2x(insn); 154 rd = INSN16_RS2x(insn);
154#if __riscv_xlen < 128 155#if __riscv_xlen < 128
155 imm = INSN16_IMM_CL_D(insn); 156 imm = INSN16_IMM_CL_D(insn);
156 db_printf("c.fld f%d, %d(%s)\n", rd, (int32_t)imm, 157 db_printf("c.fld f%d, %d(%s)\n", rd, (int32_t)imm,
157 riscv_registers[rs1]); 158 riscv_registers[rs1]);
158#else 159#else
159 imm = INSN16_IMM_CL_Q(insn); 160 imm = INSN16_IMM_CL_Q(insn);
160 db_printf("c.lq %s, %d(%s)\n", riscv_registers[rd], 161 db_printf("c.lq %s, %d(%s)\n", riscv_registers[rd],
161 (int32_t)imm, riscv_registers[rs1]); 162 (int32_t)imm, riscv_registers[rs1]);
162#endif 163#endif
163 break; 164 break;
164 case IN_Q0(Q0_LW): 165 case IN_Q0(Q0_LW):
165 rs1 = INSN16_RS1x(insn); 166 rs1 = INSN16_RS1x(insn);
166 rd = INSN16_RS2x(insn); 167 rd = INSN16_RS2x(insn);
167 imm = INSN16_IMM_CL_W(insn); 168 imm = INSN16_IMM_CL_W(insn);
168 db_printf("c.lw %s, %d(%s)\n", riscv_registers[rd], 169 db_printf("c.lw %s, %d(%s)\n", riscv_registers[rd],
169 (int32_t)imm, riscv_registers[rs1]); 170 (int32_t)imm, riscv_registers[rs1]);
170 break; 171 break;
171 case IN_Q0(Q0_FLW_LD): 172 case IN_Q0(Q0_FLW_LD):
172 rs1 = INSN16_RS1x(insn); 173 rs1 = INSN16_RS1x(insn);
173 rd = INSN16_RS2x(insn); 174 rd = INSN16_RS2x(insn);
174#if __riscv_xlen == 32 175#if __riscv_xlen == 32
175 imm = INSN16_IMM_CL_W(insn); 176 imm = INSN16_IMM_CL_W(insn);
176 db_printf("c.flw f%d, %d(%s)\n", rd, (int32_t)imm, 177 db_printf("c.flw f%d, %d(%s)\n", rd, (int32_t)imm,
177 riscv_registers[rs1]); 178 riscv_registers[rs1]);
178#else 179#else
179 imm = INSN16_IMM_CL_D(insn); 180 imm = INSN16_IMM_CL_D(insn);
180 db_printf("c.ld %s, %d(%s)\n", riscv_registers[rd], 181 db_printf("c.ld %s, %d(%s)\n", riscv_registers[rd],
181 (int32_t)imm, riscv_registers[rs1]); 182 (int32_t)imm, riscv_registers[rs1]);
182#endif 183#endif
183 break; 184 break;
184 case IN_Q0(Q0_FSD_SQ): 185 case IN_Q0(Q0_FSD_SQ):
185 rs1 = INSN16_RS1x(insn); 186 rs1 = INSN16_RS1x(insn);
186 rs2 = INSN16_RS2x(insn); 187 rs2 = INSN16_RS2x(insn);
187#if __riscv_xlen < 128 188#if __riscv_xlen < 128
188 imm = INSN16_IMM_CS_D(insn); 189 imm = INSN16_IMM_CS_D(insn);
189 db_printf("c.fsd f%d, %d(%s)\n", rs2, (int32_t)imm, 190 db_printf("c.fsd f%d, %d(%s)\n", rs2, (int32_t)imm,
190 riscv_registers[rs1]); 191 riscv_registers[rs1]);
191#else 192#else
192 imm = INSN16_IMM_CS_Q(insn); 193 imm = INSN16_IMM_CS_Q(insn);
193 db_printf("c.sq %s, %d(%s)\n", riscv_registers[rs2], 194 db_printf("c.sq %s, %d(%s)\n", riscv_registers[rs2],
194 (int32_t)imm, riscv_registers[rs1]); 195 (int32_t)imm, riscv_registers[rs1]);
195#endif 196#endif
196 break; 197 break;
197 case IN_Q0(Q0_SW): 198 case IN_Q0(Q0_SW):
198 rs1 = INSN16_RS1x(insn); 199 rs1 = INSN16_RS1x(insn);
199 rs2 = INSN16_RS2x(insn); 200 rs2 = INSN16_RS2x(insn);
200 imm = INSN16_IMM_CS_W(insn); 201 imm = INSN16_IMM_CS_W(insn);
201 db_printf("c.sw %s, %d(%s)\n", riscv_registers[rs2], 202 db_printf("c.sw %s, %d(%s)\n", riscv_registers[rs2],
202 (int32_t)imm, riscv_registers[rs1]); 203 (int32_t)imm, riscv_registers[rs1]);
203 break; 204 break;
204 case IN_Q0(Q0_FSW_SD): 205 case IN_Q0(Q0_FSW_SD):
205 rs1 = INSN16_RS1x(insn); 206 rs1 = INSN16_RS1x(insn);
206 rs2 = INSN16_RS2x(insn); 207 rs2 = INSN16_RS2x(insn);
207#if __riscv_xlen == 32 208#if __riscv_xlen == 32
208 imm = INSN16_IMM_CS_W(insn); 209 imm = INSN16_IMM_CS_W(insn);
209 db_printf("c.fsw f%d, %d(%s)\n", rs2, (int32_t)imm, 210 db_printf("c.fsw f%d, %d(%s)\n", rs2, (int32_t)imm,
210 riscv_registers[rs1]); 211 riscv_registers[rs1]);
211#else 212#else
212 imm = INSN16_IMM_CS_D(insn); 213 imm = INSN16_IMM_CS_D(insn);
213 db_printf("c.sd %s, %d(%s)\n", riscv_registers[rs2], 214 db_printf("c.sd %s, %d(%s)\n", riscv_registers[rs2],
214 (int32_t)imm, riscv_registers[rs1]); 215 (int32_t)imm, riscv_registers[rs1]);
215#endif 216#endif
216 break; 217 break;
217 case IN_Q1(Q1_NOP_ADDI): 218 case IN_Q1(Q1_NOP_ADDI):
218 rd = INSN16_RS1(insn); 219 rd = INSN16_RS1(insn);
219 imm = INSN16_IMM_CI_K(insn); 220 imm = INSN16_IMM_CI_K(insn);
220 if (rd == 0 && imm == 0) { 221 if (rd == 0 && imm == 0) {
221 db_printf("c.nop\n"); 222 db_printf("c.nop\n");
222 } else if (rd == 0 && imm != 0) { 223 } else if (rd == 0 && imm != 0) {
223 /* undefined hint */ 224 /* undefined hint */
224 return EINVAL; 225 return EINVAL;
225 } else if (rd != 0 && imm == 0) { 226 } else if (rd != 0 && imm == 0) {
226 /* undefined hint */ 227 /* undefined hint */
227 return EINVAL; 228 return EINVAL;
228 } else { 229 } else {
229 db_printf("c.addi %s, %s, 0x%lx\n", 230 db_printf("c.addi %s, %s, 0x%lx\n",
230 riscv_registers[rd], 231 riscv_registers[rd],
231 riscv_registers[rd], 232 riscv_registers[rd],
232 maybe_signext64(imm)); 233 maybe_signext64(imm));
233 } 234 }
234 break; 235 break;
235 case IN_Q1(Q1_JAL_ADDIW): 236 case IN_Q1(Q1_JAL_ADDIW):
236#if __riscv_xlen == 32 237#if __riscv_xlen == 32
237 imm = INSN16_IMM_CJ(insn); 238 imm = INSN16_IMM_CJ(insn);
238 db_printf("c.jal "); 239 db_printf("c.jal ");
239 db_print_addr(loc + (int32_t)imm); 240 db_print_addr(loc + (int32_t)imm);
240 db_printf("\n"); 241 db_printf("\n");
241#else 242#else
242 rd = INSN16_RS1(insn); 243 rd = INSN16_RS1(insn);
243 imm = INSN16_IMM_CI_K(insn); 244 imm = INSN16_IMM_CI_K(insn);
244 db_printf("c.addiw %s, %s, 0x%lx\n", riscv_registers[rd], 245 db_printf("c.addiw %s, %s, 0x%lx\n", riscv_registers[rd],
245 riscv_registers[rd], maybe_signext64(imm)); 246 riscv_registers[rd], maybe_signext64(imm));
246#endif 247#endif
247 break; 248 break;
248 case IN_Q1(Q1_LI): 249 case IN_Q1(Q1_LI):
249 rd = INSN16_RS1(insn); 250 rd = INSN16_RS1(insn);
250 imm = INSN16_IMM_CI_K(insn); 251 imm = INSN16_IMM_CI_K(insn);
251 db_printf("c.li %s, 0x%lx\n", riscv_registers[rd], 252 db_printf("c.li %s, 0x%lx\n", riscv_registers[rd],
252 maybe_signext64(imm)); 253 maybe_signext64(imm));
253 break; 254 break;
254 case IN_Q1(Q1_ADDI16SP_LUI): 255 case IN_Q1(Q1_ADDI16SP_LUI):
255 rd = INSN16_RS1(insn); 256 rd = INSN16_RS1(insn);
256 if (rd == 2/*sp*/) { 257 if (rd == 2/*sp*/) {
257 imm = INSN16_IMM_CI_K4(insn); 258 imm = INSN16_IMM_CI_K4(insn);
258 db_printf("c.add16sp sp, 0x%lx\n", 259 db_printf("c.add16sp sp, 0x%lx\n",
259 maybe_signext64(imm)); 260 maybe_signext64(imm));
260 } 261 }
261 else { 262 else {
262 imm = INSN16_IMM_CI_K12(insn); 263 imm = INSN16_IMM_CI_K12(insn);
263 db_printf("c.lui %s, 0x%lx\n", riscv_registers[rd], 264 db_printf("c.lui %s, 0x%lx\n", riscv_registers[rd],
264 maybe_signext64(imm)); 265 maybe_signext64(imm));
265 } 266 }
266 break; 267 break;
267 case IN_Q1(Q1_MISC): 268 case IN_Q1(Q1_MISC):
268 imm = INSN16_IMM_CI_K(insn); 269 imm = INSN16_IMM_CI_K(insn);
269 rd = INSN16_RS1x(insn); 270 rd = INSN16_RS1x(insn);
270 switch (INSN16_FUNCT2a(insn)) { 271 switch (INSN16_FUNCT2a(insn)) {
271 case Q1MISC_SRLI: 272 case Q1MISC_SRLI:
272 case Q1MISC_SRAI: 273 case Q1MISC_SRAI:
273#if __riscv_xlen == 32 274#if __riscv_xlen == 32
274 if (imm > 31) { 275 if (imm > 31) {
275 /* reserved */ 276 /* reserved */
276 return EINVAL; 277 return EINVAL;
277 } 278 }
278#elif __riscv_xlen == 64 279#elif __riscv_xlen == 64
279 /* drop the sign-extension */ 280 /* drop the sign-extension */
280 imm &= 63; 281 imm &= 63;
281#elif __riscv_xlen == 128 282#elif __riscv_xlen == 128
282 if (imm == 0) { 283 if (imm == 0) {
283 imm = 64; 284 imm = 64;
284 } 285 }
285 else { 286 else {
286 imm &= 127; 287 imm &= 127;
287 } 288 }
288#endif 289#endif
289 db_printf("c.%s %s, %d\n", 290 db_printf("c.%s %s, %d\n",
290 INSN16_FUNCT2a(insn) == Q1MISC_SRLI ? 291 INSN16_FUNCT2a(insn) == Q1MISC_SRLI ?
291 "srli" : "srai", 292 "srli" : "srai",
292 riscv_registers[rd], imm); 293 riscv_registers[rd], imm);
293 break; 294 break;
294 case Q1MISC_ANDI: 295 case Q1MISC_ANDI:
295 db_printf("c.andi %s, 0x%lx\n", riscv_registers[rd], 296 db_printf("c.andi %s, 0x%lx\n", riscv_registers[rd],
296 maybe_signext64(imm)); 297 maybe_signext64(imm));
297 break; 298 break;
298 case Q1MISC_MORE: 299 case Q1MISC_MORE:
299 rs2 = INSN16_RS2x(insn); 300 rs2 = INSN16_RS2x(insn);
300 switch (INSN16_FUNCT3c(insn)) { 301 switch (INSN16_FUNCT3c(insn)) {
301 case Q1MORE_SUB: 302 case Q1MORE_SUB:
302 db_printf("c.sub"); 303 db_printf("c.sub");
303 break; 304 break;
304 case Q1MORE_XOR: 305 case Q1MORE_XOR:
305 db_printf("c.xor"); 306 db_printf("c.xor");
306 break; 307 break;
307 case Q1MORE_OR: 308 case Q1MORE_OR:
308 db_printf("c.or"); 309 db_printf("c.or");
309 break; 310 break;
310 case Q1MORE_AND: 311 case Q1MORE_AND:
311 db_printf("c.and"); 312 db_printf("c.and");
312 break; 313 break;
313 case Q1MORE_SUBW: 314 case Q1MORE_SUBW:
314 db_printf("c.subw"); 315 db_printf("c.subw");
315 break; 316 break;
316 case Q1MORE_ADDW: 317 case Q1MORE_ADDW:
317 db_printf("c.addw"); 318 db_printf("c.addw");
318 break; 319 break;
319 default: 320 default:
320 return EINVAL; 321 return EINVAL;
321 } 322 }
322 db_printf(" %s, %s, %s\n", riscv_registers[rd], 323 db_printf(" %s, %s, %s\n", riscv_registers[rd],
323 riscv_registers[rd], riscv_registers[rs2]); 324 riscv_registers[rd], riscv_registers[rs2]);
324 break; 325 break;
325 } 326 }
326 break; 327 break;
327 case IN_Q1(Q1_J): 328 case IN_Q1(Q1_J):
328 imm = INSN16_IMM_CJ(insn); 329 imm = INSN16_IMM_CJ(insn);
329 db_printf("c.j "); 330 db_printf("c.j ");
330 db_print_addr(loc + (int32_t)imm); 331 db_print_addr(loc + (int32_t)imm);
331 db_printf("\n"); 332 db_printf("\n");
332 break; 333 break;
333 case IN_Q1(Q1_BEQZ): 334 case IN_Q1(Q1_BEQZ):
334 rs1 = INSN16_RS1x(insn); 335 rs1 = INSN16_RS1x(insn);
335 imm = INSN16_IMM_CB(insn); 336 imm = INSN16_IMM_CB(insn);
336 db_printf("c.beqz %s, ", riscv_registers[rs1]); 337 db_printf("c.beqz %s, ", riscv_registers[rs1]);
337 db_print_addr(loc + (int32_t)imm); 338 db_print_addr(loc + (int32_t)imm);
338 db_printf("\n"); 339 db_printf("\n");
339 break; 340 break;
340 case IN_Q1(Q1_BNEZ): 341 case IN_Q1(Q1_BNEZ):
341 rs1 = INSN16_RS1x(insn); 342 rs1 = INSN16_RS1x(insn);
342 imm = INSN16_IMM_CB(insn); 343 imm = INSN16_IMM_CB(insn);
343 db_printf("c.bnez %s, ", riscv_registers[rs1]); 344 db_printf("c.bnez %s, ", riscv_registers[rs1]);
344 db_print_addr(loc + (int32_t)imm); 345 db_print_addr(loc + (int32_t)imm);
345 db_printf("\n"); 346 db_printf("\n");
346 break; 347 break;
347 case IN_Q2(Q2_SLLI): 348 case IN_Q2(Q2_SLLI):
348 rd = INSN16_RS1(insn); 349 rd = INSN16_RS1(insn);
349 imm = INSN16_IMM_CI_K(insn); 350 imm = INSN16_IMM_CI_K(insn);
350#if __riscv_xlen == 32 351#if __riscv_xlen == 32
351 if (imm > 31) { 352 if (imm > 31) {
352 /* reserved */ 353 /* reserved */
353 return EINVAL; 354 return EINVAL;
354 } 355 }
355#elif __riscv_xlen == 64 356#elif __riscv_xlen == 64
356 /* drop the sign-extension */ 357 /* drop the sign-extension */
357 imm &= 63; 358 imm &= 63;
358#elif __riscv_xlen == 128 359#elif __riscv_xlen == 128
359 if (imm == 0) { 360 if (imm == 0) {
360 imm = 64; 361 imm = 64;
361 } 362 }
362 else { 363 else {
363 /* 364 /*
364 * XXX the manual is not clear on 365 * XXX the manual is not clear on
365 * whether this is like c.srli/c.srai 366 * whether this is like c.srli/c.srai
366 * or truncates to 6 bits. I'm assuming 367 * or truncates to 6 bits. I'm assuming
367 * the former. 368 * the former.
368 */ 369 */
369 imm &= 127; 370 imm &= 127;
370 } 371 }
371#endif 372#endif
372 db_printf("c.slli %s, %d\n", riscv_registers[rd], imm); 373 db_printf("c.slli %s, %d\n", riscv_registers[rd], imm);
373 break; 374 break;
374 case IN_Q2(Q2_FLDSP_LQSP): 375 case IN_Q2(Q2_FLDSP_LQSP):
375 rd = INSN16_RS1(insn); 376 rd = INSN16_RS1(insn);
376#if __riscv_xlen < 128 377#if __riscv_xlen < 128
377 imm = INSN16_IMM_CI_D(insn); 378 imm = INSN16_IMM_CI_D(insn);
378 db_printf("c.fldsp f%d, %d(sp)\n", rd, imm); 379 db_printf("c.fldsp f%d, %d(sp)\n", rd, imm);
379#else 380#else
380 if (rd == 0) { 381 if (rd == 0) {
381 /* reserved */ 382 /* reserved */
382 return EINVAL; 383 return EINVAL;
383 } 384 }
384 imm = INSN16_IMM_CI_Q(insn); 385 imm = INSN16_IMM_CI_Q(insn);
385 db_printf("c.lqsp %s, %d(sp)\n", riscv_registers[rd], imm); 386 db_printf("c.lqsp %s, %d(sp)\n", riscv_registers[rd], imm);
386#endif 387#endif
387 break; 388 break;
388 case IN_Q2(Q2_LWSP): 389 case IN_Q2(Q2_LWSP):
389 rd = INSN16_RS1(insn); 390 rd = INSN16_RS1(insn);
390 if (rd == 0) { 391 if (rd == 0) {
391 /* reserved */ 392 /* reserved */
392 return EINVAL; 393 return EINVAL;
393 } 394 }
394 imm = INSN16_IMM_CI_W(insn); 395 imm = INSN16_IMM_CI_W(insn);
395 db_printf("c.lwsp %s, %d(sp)\n", riscv_registers[rd], imm); 396 db_printf("c.lwsp %s, %d(sp)\n", riscv_registers[rd], imm);
396 break; 397 break;
397 case IN_Q2(Q2_FLWSP_LDSP): 398 case IN_Q2(Q2_FLWSP_LDSP):
398 rd = INSN16_RS1(insn); 399 rd = INSN16_RS1(insn);
399#if __riscv_xlen == 32 400#if __riscv_xlen == 32
400 imm = INSN16_IMM_CI_W(insn); 401 imm = INSN16_IMM_CI_W(insn);
401 db_printf("c.flwsp f%d, %d(sp)\n", rd, imm); 402 db_printf("c.flwsp f%d, %d(sp)\n", rd, imm);
402#else 403#else
403 if (rd == 0) { 404 if (rd == 0) {
404 /* reserved */ 405 /* reserved */
405 return EINVAL; 406 return EINVAL;
406 } 407 }
407 imm = INSN16_IMM_CI_D(insn); 408 imm = INSN16_IMM_CI_D(insn);
408 db_printf("c.ldsp %s, %d(sp)\n", riscv_registers[rd], imm); 409 db_printf("c.ldsp %s, %d(sp)\n", riscv_registers[rd], imm);
409#endif 410#endif
410 break; 411 break;
411 case IN_Q2(Q2_MISC): 412 case IN_Q2(Q2_MISC):
412 rs1 = INSN16_RS1(insn); 413 rs1 = INSN16_RS1(insn);
413 rs2 = INSN16_RS2(insn); 414 rs2 = INSN16_RS2(insn);
414 switch (INSN16_FUNCT1b(insn)) { 415 switch (INSN16_FUNCT1b(insn)) {
415 case Q2MISC_JR_MV: 416 case Q2MISC_JR_MV:
416 if (rs1 == 0) { 417 if (rs1 == 0) {
417 return EINVAL; 418 return EINVAL;
418 } else if (rs2 == 0) { 419 } else if (rs2 == 0) {
419 db_printf("c.jr %s\n", riscv_registers[rs1]); 420 db_printf("c.jr %s\n", riscv_registers[rs1]);
420 } else { 421 } else {
421 db_printf("c.mv %s, %s\n", 422 db_printf("c.mv %s, %s\n",
422 riscv_registers[rs1], 423 riscv_registers[rs1],
423 riscv_registers[rs2]); 424 riscv_registers[rs2]);
424 } 425 }
425 break; 426 break;
426 case Q2MISC_EBREAK_JALR_ADD: 427 case Q2MISC_EBREAK_JALR_ADD:
427 if (rs1 == 0 && rs2 == 0) { 428 if (rs1 == 0 && rs2 == 0) {
428 db_printf("c.ebreak\n"); 429 db_printf("c.ebreak\n");
429 } else if (rs2 == 0) { 430 } else if (rs2 == 0) {
430 db_printf("c.jalr %s\n", riscv_registers[rs1]); 431 db_printf("c.jalr %s\n", riscv_registers[rs1]);
431 } else if (rs1 == 0) { 432 } else if (rs1 == 0) {
432 return EINVAL; 433 return EINVAL;
433 } else { 434 } else {
434 db_printf("c.add %s, %s, %s\n", 435 db_printf("c.add %s, %s, %s\n",
435 riscv_registers[rs1], 436 riscv_registers[rs1],
436 riscv_registers[rs1], 437 riscv_registers[rs1],
437 riscv_registers[rs2]); 438 riscv_registers[rs2]);
438 } 439 }
439 break; 440 break;
440 } 441 }
441 break; 442 break;
442 case IN_Q2(Q2_FSDSP_SQSP): 443 case IN_Q2(Q2_FSDSP_SQSP):
443 rs2 = INSN16_RS2(insn); 444 rs2 = INSN16_RS2(insn);
444#if __riscv_xlen < 128 445#if __riscv_xlen < 128
445 imm = INSN16_IMM_CSS_D(insn); 446 imm = INSN16_IMM_CSS_D(insn);
446 db_printf("c.fsdsp f%d, %d(sp)\n", rs2, imm); 447 db_printf("c.fsdsp f%d, %d(sp)\n", rs2, imm);
447#else 448#else
448 imm = INSN16_IMM_CSS_Q(insn); 449 imm = INSN16_IMM_CSS_Q(insn);
449 db_printf("c.sqsp %s, %d(sp)\n", riscv_registers[rs2], imm); 450 db_printf("c.sqsp %s, %d(sp)\n", riscv_registers[rs2], imm);
450#endif 451#endif
451 break; 452 break;
452 case IN_Q2(Q2_SWSP): 453 case IN_Q2(Q2_SWSP):
453 rs2 = INSN16_RS2(insn); 454 rs2 = INSN16_RS2(insn);
454 imm = INSN16_IMM_CSS_W(insn); 455 imm = INSN16_IMM_CSS_W(insn);
455 db_printf("c.swsp %s, %d(sp)\n", riscv_registers[rs2], imm); 456 db_printf("c.swsp %s, %d(sp)\n", riscv_registers[rs2], imm);
456 break; 457 break;
457 case IN_Q2(Q2_FSWSP_SDSP): 458 case IN_Q2(Q2_FSWSP_SDSP):
458 rs2 = INSN16_RS2(insn); 459 rs2 = INSN16_RS2(insn);
459#if __riscv_xlen == 32 460#if __riscv_xlen == 32
460 imm = INSN16_IMM_CSS_W(insn); 461 imm = INSN16_IMM_CSS_W(insn);
461 db_printf("c.fswsp f%d, %d(sp)\n", rs2, imm); 462 db_printf("c.fswsp f%d, %d(sp)\n", rs2, imm);
462#else 463#else
463 imm = INSN16_IMM_CSS_D(insn); 464 imm = INSN16_IMM_CSS_D(insn);
464 db_printf("c.sdsp %s, %d(sp)\n", riscv_registers[rs2], imm); 465 db_printf("c.sdsp %s, %d(sp)\n", riscv_registers[rs2], imm);
465#endif 466#endif
466 break; 467 break;
467 default: 468 default:
468 /* 0b11 marks 32-bit instructions and shouldn't come here */ 469 /* 0b11 marks 32-bit instructions and shouldn't come here */
469 KASSERT(INSN16_QUADRANT(insn) != 0b11); 470 KASSERT(INSN16_QUADRANT(insn) != 0b11);
470 return EINVAL; 471 return EINVAL;
471 } 472 }
472 return 0; 473 return 0;
473} 474}
474 475
475//////////////////////////////////////////////////////////// 476////////////////////////////////////////////////////////////
476// 32-bit instructions 477// 32-bit instructions
477 478
478/* match flags */ 479/* match flags */
479#define CHECK_F3 0x0001 /* check funct3 field */ 480#define CHECK_F3 0x0001 /* check funct3 field */
480#define CHECK_F7 0x0002 /* check funct7 field */ 481#define CHECK_F7 0x0002 /* check funct7 field */
481#define CHECK_F5 0x0004 /* check tpo of funct7 field only */ 482#define CHECK_F5 0x0004 /* check tpo of funct7 field only */
482#define CHECK_RS2 0x0008 /* check rs2 as quaternary opcode */ 483#define CHECK_RS2 0x0008 /* check rs2 as quaternary opcode */
483#define SHIFT32 0x0010 /* 32-bit immediate shift */ 484#define SHIFT32 0x0010 /* 32-bit immediate shift */
484#define SHIFT64 0x0020 /* 64-bit immediate shift */ 485#define SHIFT64 0x0020 /* 64-bit immediate shift */
485#define RD_0 0x0040 /* rd field should be 0 */ 486#define RD_0 0x0040 /* rd field should be 0 */
486#define RS1_0 0x0080 /* rs1 field should be 0 */ 487#define RS1_0 0x0080 /* rs1 field should be 0 */
487#define RS2_0 0x0100 /* rs2 field should be 0 */ 488#define RS2_0 0x0100 /* rs2 field should be 0 */
488#define IMM_0 0x0200 /* immediate value should be 0 */ 489#define IMM_0 0x0200 /* immediate value should be 0 */
489#define F3AMO 0x0400 /* expect amo size in funct3 */ 490#define F3AMO 0x0400 /* expect amo size in funct3 */
490#define F3ROUND 0x0800 /* expect fp rounding mode in funct3 */ 491#define F3ROUND 0x0800 /* expect fp rounding mode in funct3 */
491#define F7SIZE 0x1000 /* expect fp size in funct7:0-1 */ 492#define F7SIZE 0x1000 /* expect fp size in funct7:0-1 */
492#define RS2_FSIZE 0x2000 /* expect fp size in rs2 */ 493#define RS2_FSIZE 0x2000 /* expect fp size in rs2 */
493#define RS2_FSIZE_INT 0x4000 /* expect fp size in rs2 */ 494#define RS2_FSIZE_INT 0x4000 /* expect fp size in rs2 */
494#define FENCEFM 0x8000 /* fence mode in top 4 bits of imm */ 495#define FENCEFM 0x8000 /* fence mode in top 4 bits of imm */
495/* do not add more without increasing the field size below */ 496/* do not add more without increasing the field size below */
496 497
497#ifdef _LP64 /* disassembling ourself so can use our build flags... */ 498#ifdef _LP64 /* disassembling ourself so can use our build flags... */
498#define SHIFTNATIVE SHIFT64 499#define SHIFTNATIVE SHIFT64
499#else 500#else
500#define SHIFTNATIVE SHIFT32 501#define SHIFTNATIVE SHIFT32
501#endif 502#endif
502 503
503/* print flags */ 504/* print flags */
504#define MEMORYIMM 0x001 /* print immediate as 0(reg) */ 505#define MEMORYIMM 0x001 /* print immediate as 0(reg) */
505#define FENCEIMM 0x002 /* print fence instruction codes */ 506#define FENCEIMM 0x002 /* print fence instruction codes */
506#define DECIMM 0x004 /* print immediate in decimal */ 507#define DECIMM 0x004 /* print immediate in decimal */
507#define BRANCHIMM 0x008 /* print immediate as branch target */ 508#define BRANCHIMM 0x008 /* print immediate as branch target */
508#define CSRIMM 0x010 /* immediate is csr number */ 509#define CSRIMM 0x010 /* immediate is csr number */
509#define CSRIIMM 0x020 /* ... also an immediate in rs1 */ 510#define CSRIIMM 0x020 /* ... also an immediate in rs1 */
510#define AMOAQRL 0x040 /* print acquire/release bits of amo */ 511#define AMOAQRL 0x040 /* print acquire/release bits of amo */
511#define RS2SIZE_FIRST 0x080 /* print rs2 size before funct7 size */ 512#define RS2SIZE_FIRST 0x080 /* print rs2 size before funct7 size */
512#define RD_FREG 0x100 /* rd is a fpu reg */ 513#define RD_FREG 0x100 /* rd is a fpu reg */
513#define RS1_FREG 0x200 /* rs1 is a fpu reg */ 514#define RS1_FREG 0x200 /* rs1 is a fpu reg */
514#define RS2_FREG 0x400 /* rs2 is a fpu reg */ 515#define RS2_FREG 0x400 /* rs2 is a fpu reg */
515#define ISCVT 0x800 /* is an fpu conversion op */ 516#define ISCVT 0x800 /* is an fpu conversion op */
516/* do not add more without increasing the field size below */ 517/* do not add more without increasing the field size below */
517 518
518#define ALL_FREG (RD_FREG | RS1_FREG | RS2_FREG) 519#define ALL_FREG (RD_FREG | RS1_FREG | RS2_FREG)
519#define RS12_FREG (RS1_FREG | RS2_FREG) 520#define RS12_FREG (RS1_FREG | RS2_FREG)
520 521
521/* entries for matching within a major opcode */ 522/* entries for matching within a major opcode */
522struct riscv_disasm_insn { 523struct riscv_disasm_insn {
523 const char *name; 524 const char *name;
524 unsigned int matchflags: 16, 525 unsigned int matchflags: 16,
525 funct3: 3, 526 funct3: 3,
526 funct7: 7, 527 funct7: 7,
527 rs2: 5; 528 rs2: 5;
528 unsigned int printflags: 12; 529 unsigned int printflags: 12;
529}; 530};
530 531
531/* format codes */ 532/* format codes */
532#define FMT_R 0 533#define FMT_R 0
533#define FMT_R4 1 534#define FMT_R4 1
534#define FMT_I 2 535#define FMT_I 2
535#define FMT_In 3 536#define FMT_In 3
536#define FMT_S 4 537#define FMT_S 4
537#define FMT_B 5 538#define FMT_B 5
538#define FMT_U 6 539#define FMT_U 6
539#define FMT_J 7 540#define FMT_J 7
540#define FMT_UNKNOWN 8 541#define FMT_UNKNOWN 8
541#define FMT_ASSERT 9 542#define FMT_ASSERT 9
542 543
543/* top-level opcode dispatch */ 544/* top-level opcode dispatch */
544struct riscv_disasm32_entry { 545struct riscv_disasm32_entry {
545 uint8_t fmt; 546 uint8_t fmt;
546 union { 547 union {
547 // R4, In, U, J 548 // R4, In, U, J
548 const char *name; 549 const char *name;
549 // R, I, S, B 550 // R, I, S, B
550 struct { 551 struct {
551 const struct riscv_disasm_insn *v; 552 const struct riscv_disasm_insn *v;
552 unsigned n; 553 unsigned n;
553 } entries; 554 } entries;
554 } u; 555 } u;
555}; 556};
556 557
557#define INSN_F3(n, f3, moretests, pflags) \ 558#define INSN_F3(n, f3, moretests, pflags) \
558 { \ 559 { \
559 .name = n, \ 560 .name = n, \
560 .matchflags = CHECK_F3 | moretests, \ 561 .matchflags = CHECK_F3 | moretests, \
561 .funct3 = f3, .funct7 = 0, .rs2 = 0, \ 562 .funct3 = f3, .funct7 = 0, .rs2 = 0, \
562 .printflags = pflags, \ 563 .printflags = pflags, \
563 } 564 }
564 565
565#define INSN_F5(n, f5, moretests, pflags) \ 566#define INSN_F5(n, f5, moretests, pflags) \
566 { \ 567 { \
567 .name = n, \ 568 .name = n, \
568 .matchflags = CHECK_F7 | CHECK_F5 | moretests, \ 569 .matchflags = CHECK_F7 | CHECK_F5 | moretests, \
569 .funct3 = 0, .funct7 = f5 << 2, .rs2 = 0, \ 570 .funct3 = 0, .funct7 = f5 << 2, .rs2 = 0, \
570 .printflags = pflags, \ 571 .printflags = pflags, \
571 } 572 }
572 573
573#define INSN_F53(n, f5, f3, moretests, pflags) \ 574#define INSN_F53(n, f5, f3, moretests, pflags) \
574 { \ 575 { \
575 .name = n, \ 576 .name = n, \
576 .matchflags = CHECK_F7 | CHECK_F5 | CHECK_F3 | moretests, \ 577 .matchflags = CHECK_F7 | CHECK_F5 | CHECK_F3 | moretests, \
577 .funct3 = f3, .funct7 = f5 << 2, .rs2 = 0, \ 578 .funct3 = f3, .funct7 = f5 << 2, .rs2 = 0, \
578 .printflags = pflags, \ 579 .printflags = pflags, \
579 } 580 }
580 581
581#define INSN_F7(n, f7, moretests, pflags) \ 582#define INSN_F7(n, f7, moretests, pflags) \
582 { \ 583 { \
583 .name = n, \ 584 .name = n, \
584 .matchflags = CHECK_F7 | moretests, \ 585 .matchflags = CHECK_F7 | moretests, \
585 .funct3 = 0, .funct7 = f7, .rs2 = 0, \ 586 .funct3 = 0, .funct7 = f7, .rs2 = 0, \
586 .printflags = pflags, \ 587 .printflags = pflags, \
587 } 588 }
588 589
589#define INSN_F73(n, f7, f3, moretests, pflags) \ 590#define INSN_F73(n, f7, f3, moretests, pflags) \
590 { \ 591 { \
591 .name = n, \ 592 .name = n, \
592 .matchflags = CHECK_F7 | CHECK_F3 | moretests, \ 593 .matchflags = CHECK_F7 | CHECK_F3 | moretests, \
593 .funct3 = f3, .funct7 = f7, .rs2 = 0, \ 594 .funct3 = f3, .funct7 = f7, .rs2 = 0, \
594 .printflags = pflags, \ 595 .printflags = pflags, \
595 } 596 }
596 597
597#define INSN_F37(n, f3, f7, moretests, pflags) \ 598#define INSN_F37(n, f3, f7, moretests, pflags) \
598 INSN_F73(n, f7, f3, moretests, pflags) 599 INSN_F73(n, f7, f3, moretests, pflags)
599 600
600#define INSN_USER(n, rs2val, moretests, pflags) \ 601#define INSN_USER(n, rs2val, moretests, pflags) \
601 { \ 602 { \
602 .name = n, \ 603 .name = n, \
603 .matchflags = CHECK_F7 | CHECK_F3 | CHECK_RS2 | moretests, \ 604 .matchflags = CHECK_F7 | CHECK_F3 | CHECK_RS2 | moretests, \
604 .funct3 = SYSTEM_PRIV, .funct7 = PRIV_USER, \ 605 .funct3 = SYSTEM_PRIV, .funct7 = PRIV_USER, \
605 .rs2 = rs2val, \ 606 .rs2 = rs2val, \
606 .printflags = pflags, \ 607 .printflags = pflags, \
607 } 608 }
608 609
609#define INSN_SYSTEM(n, rs2val, moretests, pflags) \ 610#define INSN_SYSTEM(n, rs2val, moretests, pflags) \
610 { \ 611 { \
611 .name = n, \ 612 .name = n, \
612 .matchflags = CHECK_F7 | CHECK_F3 | CHECK_RS2 | moretests, \ 613 .matchflags = CHECK_F7 | CHECK_F3 | CHECK_RS2 | moretests, \
613 .funct3 = SYSTEM_PRIV, .funct7 = PRIV_SYSTEM, \ 614 .funct3 = SYSTEM_PRIV, .funct7 = PRIV_SYSTEM, \
614 .rs2 = rs2val, \ 615 .rs2 = rs2val, \
615 .printflags = pflags, \ 616 .printflags = pflags, \
616 } 617 }
617 618
618#define INSN_MACHINE(n, rs2val, moretests, pflags) \ 619#define INSN_MACHINE(n, rs2val, moretests, pflags) \
619 { \ 620 { \
620 .name = n, \ 621 .name = n, \
621 .matchflags = CHECK_F7 | CHECK_F3 | CHECK_RS2 | moretests, \ 622 .matchflags = CHECK_F7 | CHECK_F3 | CHECK_RS2 | moretests, \
622 .funct3 = SYSTEM_PRIV, .funct7 = PRIV_MACHINE, \ 623 .funct3 = SYSTEM_PRIV, .funct7 = PRIV_MACHINE, \
623 .rs2 = rs2val, \ 624 .rs2 = rs2val, \
624 .printflags = pflags, \ 625 .printflags = pflags, \
625 } 626 }
626 627
627static const struct riscv_disasm_insn riscv_disasm_miscmem[] = { 628static const struct riscv_disasm_insn riscv_disasm_miscmem[] = {
628 INSN_F3("fence", MISCMEM_FENCE, RD_0 | RS1_0 | FENCEFM, FENCEIMM), 629 INSN_F3("fence", MISCMEM_FENCE, RD_0 | RS1_0 | FENCEFM, FENCEIMM),
629 INSN_F3("fence.i", MISCMEM_FENCEI, RD_0 | RS1_0 | IMM_0, 0), 630 INSN_F3("fence.i", MISCMEM_FENCEI, RD_0 | RS1_0 | IMM_0, 0),
630}; 631};
631 632
632static const struct riscv_disasm_insn riscv_disasm_load[] = { 633static const struct riscv_disasm_insn riscv_disasm_load[] = {
633 INSN_F3("lb", LOAD_LB, 0, MEMORYIMM), 634 INSN_F3("lb", LOAD_LB, 0, MEMORYIMM),
634 INSN_F3("lh", LOAD_LH, 0, MEMORYIMM), 635 INSN_F3("lh", LOAD_LH, 0, MEMORYIMM),
635 INSN_F3("lw", LOAD_LW, 0, MEMORYIMM), 636 INSN_F3("lw", LOAD_LW, 0, MEMORYIMM),
636 INSN_F3("ld", LOAD_LD, 0, MEMORYIMM), 637 INSN_F3("ld", LOAD_LD, 0, MEMORYIMM),
637 INSN_F3("lbu", LOAD_LBU, 0, MEMORYIMM), 638 INSN_F3("lbu", LOAD_LBU, 0, MEMORYIMM),
638 INSN_F3("lhu", LOAD_LHU, 0, MEMORYIMM), 639 INSN_F3("lhu", LOAD_LHU, 0, MEMORYIMM),
639 INSN_F3("lwu", LOAD_LWU, 0, MEMORYIMM), 640 INSN_F3("lwu", LOAD_LWU, 0, MEMORYIMM),
640}; 641};
641 642
642static const struct riscv_disasm_insn riscv_disasm_loadfp[] = { 643static const struct riscv_disasm_insn riscv_disasm_loadfp[] = {
643 INSN_F3("flw", LOADFP_FLW, 0, MEMORYIMM | RD_FREG), 644 INSN_F3("flw", LOADFP_FLW, 0, MEMORYIMM | RD_FREG),
644 INSN_F3("fld", LOADFP_FLD, 0, MEMORYIMM | RD_FREG), 645 INSN_F3("fld", LOADFP_FLD, 0, MEMORYIMM | RD_FREG),
645 INSN_F3("flq", LOADFP_FLQ, 0, MEMORYIMM | RD_FREG), 646 INSN_F3("flq", LOADFP_FLQ, 0, MEMORYIMM | RD_FREG),
646}; 647};
647 648
648static const struct riscv_disasm_insn riscv_disasm_opimm[] = { 649static const struct riscv_disasm_insn riscv_disasm_opimm[] = {
649 INSN_F3("nop", OP_ADDSUB, RD_0 | RS1_0 | IMM_0, 0), 650 INSN_F3("nop", OP_ADDSUB, RD_0 | RS1_0 | IMM_0, 0),
650 INSN_F3("addi", OP_ADDSUB, 0, 0), 651 INSN_F3("addi", OP_ADDSUB, 0, 0),
651 INSN_F3("slti", OP_SLT, 0, 0), 652 INSN_F3("slti", OP_SLT, 0, 0),
652 INSN_F3("sltiu", OP_SLTU, 0, 0), 653 INSN_F3("sltiu", OP_SLTU, 0, 0),
653 INSN_F3("xori", OP_XOR, 0, 0), 654 INSN_F3("xori", OP_XOR, 0, 0),
654 INSN_F3("ori", OP_OR, 0, 0), 655 INSN_F3("ori", OP_OR, 0, 0),
655 INSN_F3("andi", OP_AND, 0, 0), 656 INSN_F3("andi", OP_AND, 0, 0),
656 INSN_F37("slli", OP_SLL, OP_ARITH, SHIFTNATIVE, DECIMM), 657 INSN_F37("slli", OP_SLL, OP_ARITH, SHIFTNATIVE, DECIMM),
657 INSN_F37("srli", OP_SRX, OP_ARITH, SHIFTNATIVE, DECIMM), 658 INSN_F37("srli", OP_SRX, OP_ARITH, SHIFTNATIVE, DECIMM),
658 INSN_F37("srai", OP_SRX, OP_NARITH, SHIFTNATIVE, DECIMM), 659 INSN_F37("srai", OP_SRX, OP_NARITH, SHIFTNATIVE, DECIMM),
659}; 660};
660 661
661static const struct riscv_disasm_insn riscv_disasm_opimm32[] = { 662static const struct riscv_disasm_insn riscv_disasm_opimm32[] = {
662 INSN_F3("addiw", OP_ADDSUB, 0, 0), 663 INSN_F3("addiw", OP_ADDSUB, 0, 0),
663 INSN_F37("slliw", OP_SLL, OP_ARITH, SHIFT32, DECIMM), 664 INSN_F37("slliw", OP_SLL, OP_ARITH, SHIFT32, DECIMM),
664 INSN_F37("srliw", OP_SRX, OP_ARITH, SHIFT32, DECIMM), 665 INSN_F37("srliw", OP_SRX, OP_ARITH, SHIFT32, DECIMM),
665 INSN_F37("sraiw", OP_SRX, OP_NARITH, SHIFT32, DECIMM), 666 INSN_F37("sraiw", OP_SRX, OP_NARITH, SHIFT32, DECIMM),
666}; 667};
667 668
668static const struct riscv_disasm_insn riscv_disasm_store[] = { 669static const struct riscv_disasm_insn riscv_disasm_store[] = {
669 INSN_F3("sb", STORE_SB, 0, MEMORYIMM), 670 INSN_F3("sb", STORE_SB, 0, MEMORYIMM),
670 INSN_F3("sh", STORE_SH, 0, MEMORYIMM), 671 INSN_F3("sh", STORE_SH, 0, MEMORYIMM),
671 INSN_F3("sw", STORE_SW, 0, MEMORYIMM), 672 INSN_F3("sw", STORE_SW, 0, MEMORYIMM),
672 INSN_F3("sd", STORE_SD, 0, MEMORYIMM), 673 INSN_F3("sd", STORE_SD, 0, MEMORYIMM),
673}; 674};
674 675
675static const struct riscv_disasm_insn riscv_disasm_storefp[] = { 676static const struct riscv_disasm_insn riscv_disasm_storefp[] = {
676 INSN_F3("fsw", STOREFP_FSW, 0, MEMORYIMM | RS2_FREG), 677 INSN_F3("fsw", STOREFP_FSW, 0, MEMORYIMM | RS2_FREG),
677 INSN_F3("fsd", STOREFP_FSD, 0, MEMORYIMM | RS2_FREG), 678 INSN_F3("fsd", STOREFP_FSD, 0, MEMORYIMM | RS2_FREG),
678 INSN_F3("fsq", STOREFP_FSQ, 0, MEMORYIMM | RS2_FREG), 679 INSN_F3("fsq", STOREFP_FSQ, 0, MEMORYIMM | RS2_FREG),
679}; 680};
680 681
681static const struct riscv_disasm_insn riscv_disasm_branch[] = { 682static const struct riscv_disasm_insn riscv_disasm_branch[] = {
682 INSN_F3("beq", BRANCH_BEQ, 0, BRANCHIMM), 683 INSN_F3("beq", BRANCH_BEQ, 0, BRANCHIMM),
683 INSN_F3("bne", BRANCH_BNE, 0, BRANCHIMM), 684 INSN_F3("bne", BRANCH_BNE, 0, BRANCHIMM),
684 INSN_F3("blt", BRANCH_BLT, 0, BRANCHIMM), 685 INSN_F3("blt", BRANCH_BLT, 0, BRANCHIMM),
685 INSN_F3("bge", BRANCH_BGE, 0, BRANCHIMM), 686 INSN_F3("bge", BRANCH_BGE, 0, BRANCHIMM),
686 INSN_F3("bltu", BRANCH_BLTU, 0, BRANCHIMM), 687 INSN_F3("bltu", BRANCH_BLTU, 0, BRANCHIMM),
687 INSN_F3("bgeu", BRANCH_BGEU, 0, BRANCHIMM), 688 INSN_F3("bgeu", BRANCH_BGEU, 0, BRANCHIMM),
688}; 689};
689 690
690static const struct riscv_disasm_insn riscv_disasm_system[] = { 691static const struct riscv_disasm_insn riscv_disasm_system[] = {
691 INSN_F3("csrw", SYSTEM_CSRRW, RD_0, CSRIMM), 692 INSN_F3("csrw", SYSTEM_CSRRW, RD_0, CSRIMM),
692 INSN_F3("csrrw", SYSTEM_CSRRW, 0, CSRIMM), 693 INSN_F3("csrrw", SYSTEM_CSRRW, 0, CSRIMM),
693 INSN_F3("csrr", SYSTEM_CSRRS, RS1_0, CSRIMM), 694 INSN_F3("csrr", SYSTEM_CSRRS, RS1_0, CSRIMM),
694 INSN_F3("csrrs", SYSTEM_CSRRS, 0, CSRIMM), 695 INSN_F3("csrrs", SYSTEM_CSRRS, 0, CSRIMM),
695 INSN_F3("csrrc", SYSTEM_CSRRC, 0, CSRIMM), 696 INSN_F3("csrrc", SYSTEM_CSRRC, 0, CSRIMM),
696 INSN_F3("csrwi", SYSTEM_CSRRWI, RD_0, CSRIIMM), 697 INSN_F3("csrwi", SYSTEM_CSRRWI, RD_0, CSRIIMM),
697 INSN_F3("csrrwi", SYSTEM_CSRRWI, 0, CSRIIMM), 698 INSN_F3("csrrwi", SYSTEM_CSRRWI, 0, CSRIIMM),
698 INSN_F3("csrrsi", SYSTEM_CSRRSI, 0, CSRIIMM), 699 INSN_F3("csrrsi", SYSTEM_CSRRSI, 0, CSRIIMM),
699 INSN_F3("csrrci", SYSTEM_CSRRCI, 0, CSRIIMM), 700 INSN_F3("csrrci", SYSTEM_CSRRCI, 0, CSRIIMM),
700 INSN_F37("sfence.vma", SYSTEM_PRIV, PRIV_SFENCE_VMA, RD_0, 0), 701 INSN_F37("sfence.vma", SYSTEM_PRIV, PRIV_SFENCE_VMA, RD_0, 0),
701 INSN_F37("hfence.bvma", SYSTEM_PRIV, PRIV_HFENCE_BVMA, 0, 0), 702 INSN_F37("hfence.bvma", SYSTEM_PRIV, PRIV_HFENCE_BVMA, 0, 0),
702 INSN_F37("hfence.gvma", SYSTEM_PRIV, PRIV_HFENCE_GVMA, 0, 0), 703 INSN_F37("hfence.gvma", SYSTEM_PRIV, PRIV_HFENCE_GVMA, 0, 0),
703 INSN_USER("ecall", USER_ECALL, RD_0 | RS1_0, 0), 704 INSN_USER("ecall", USER_ECALL, RD_0 | RS1_0, 0),
704 INSN_USER("ebreak", USER_EBREAK, RD_0 | RS1_0, 0), 705 INSN_USER("ebreak", USER_EBREAK, RD_0 | RS1_0, 0),
705 INSN_USER("uret", USER_URET, RD_0 | RS1_0, 0), 706 INSN_USER("uret", USER_URET, RD_0 | RS1_0, 0),
706 INSN_SYSTEM("sret", SYSTEM_SRET, RD_0 | RS1_0, 0), 707 INSN_SYSTEM("sret", SYSTEM_SRET, RD_0 | RS1_0, 0),
707 INSN_SYSTEM("wfi", SYSTEM_WFI, RD_0 | RS1_0, 0), 708 INSN_SYSTEM("wfi", SYSTEM_WFI, RD_0 | RS1_0, 0),
708 INSN_MACHINE("mret", MACHINE_MRET, RD_0 | RS1_0, 0), 709 INSN_MACHINE("mret", MACHINE_MRET, RD_0 | RS1_0, 0),
709}; 710};
710 711
711static const struct riscv_disasm_insn riscv_disasm_amo[] = { 712static const struct riscv_disasm_insn riscv_disasm_amo[] = {
712 INSN_F5("amoadd", AMO_ADD, F3AMO, AMOAQRL), 713 INSN_F5("amoadd", AMO_ADD, F3AMO, AMOAQRL),
713 INSN_F5("amoswap", AMO_SWAP, F3AMO, AMOAQRL), 714 INSN_F5("amoswap", AMO_SWAP, F3AMO, AMOAQRL),
714 INSN_F5("lr", AMO_LR, F3AMO | RS2_0, AMOAQRL), 715 INSN_F5("lr", AMO_LR, F3AMO | RS2_0, AMOAQRL),
715 INSN_F5("sc", AMO_SC, F3AMO, AMOAQRL), 716 INSN_F5("sc", AMO_SC, F3AMO, AMOAQRL),
716 INSN_F5("amoxor", AMO_XOR, F3AMO, AMOAQRL), 717 INSN_F5("amoxor", AMO_XOR, F3AMO, AMOAQRL),
717 INSN_F5("amoor", AMO_OR, F3AMO, AMOAQRL), 718 INSN_F5("amoor", AMO_OR, F3AMO, AMOAQRL),
718 INSN_F5("amoand", AMO_AND, F3AMO, AMOAQRL), 719 INSN_F5("amoand", AMO_AND, F3AMO, AMOAQRL),
719 INSN_F5("amomin", AMO_MIN, F3AMO, AMOAQRL), 720 INSN_F5("amomin", AMO_MIN, F3AMO, AMOAQRL),
720 INSN_F5("amomax", AMO_MAX, F3AMO, AMOAQRL), 721 INSN_F5("amomax", AMO_MAX, F3AMO, AMOAQRL),
721 INSN_F5("amominu", AMO_MINU, F3AMO, AMOAQRL), 722 INSN_F5("amominu", AMO_MINU, F3AMO, AMOAQRL),
722 INSN_F5("amomaxu", AMO_MAXU, F3AMO, AMOAQRL), 723 INSN_F5("amomaxu", AMO_MAXU, F3AMO, AMOAQRL),
723}; 724};
724 725
725static const struct riscv_disasm_insn riscv_disasm_op[] = { 726static const struct riscv_disasm_insn riscv_disasm_op[] = {
726 INSN_F37("add", OP_ADDSUB, OP_ARITH, 0, 0), 727 INSN_F37("add", OP_ADDSUB, OP_ARITH, 0, 0),
727 INSN_F37("sub", OP_ADDSUB, OP_NARITH, 0, 0), 728 INSN_F37("sub", OP_ADDSUB, OP_NARITH, 0, 0),
728 INSN_F37("sll", OP_SLL, OP_ARITH, 0, 0), 729 INSN_F37("sll", OP_SLL, OP_ARITH, 0, 0),
729 INSN_F37("slt", OP_SLT, OP_ARITH, 0, 0), 730 INSN_F37("slt", OP_SLT, OP_ARITH, 0, 0),
730 INSN_F37("sltu", OP_SLTU, OP_ARITH, 0, 0), 731 INSN_F37("sltu", OP_SLTU, OP_ARITH, 0, 0),
731 INSN_F37("xor", OP_XOR, OP_ARITH, 0, 0), 732 INSN_F37("xor", OP_XOR, OP_ARITH, 0, 0),
732 INSN_F37("srl", OP_SRX, OP_ARITH, 0, 0), 733 INSN_F37("srl", OP_SRX, OP_ARITH, 0, 0),
733 INSN_F37("sra", OP_SRX, OP_NARITH, 0, 0), 734 INSN_F37("sra", OP_SRX, OP_NARITH, 0, 0),
734 INSN_F37("or", OP_OR, OP_ARITH, 0, 0), 735 INSN_F37("or", OP_OR, OP_ARITH, 0, 0),
735 INSN_F37("and", OP_AND, OP_ARITH, 0, 0), 736 INSN_F37("and", OP_AND, OP_ARITH, 0, 0),
736 INSN_F37("mul", OP_MUL, OP_MULDIV, 0, 0), 737 INSN_F37("mul", OP_MUL, OP_MULDIV, 0, 0),
737 INSN_F37("mulh", OP_MULH, OP_MULDIV, 0, 0), 738 INSN_F37("mulh", OP_MULH, OP_MULDIV, 0, 0),
738 INSN_F37("mulhsu", OP_MULHSU, OP_MULDIV, 0, 0), 739 INSN_F37("mulhsu", OP_MULHSU, OP_MULDIV, 0, 0),
739 INSN_F37("mulhu", OP_MULHU, OP_MULDIV, 0, 0), 740 INSN_F37("mulhu", OP_MULHU, OP_MULDIV, 0, 0),
740 INSN_F37("div", OP_DIV, OP_MULDIV, 0, 0), 741 INSN_F37("div", OP_DIV, OP_MULDIV, 0, 0),
741 INSN_F37("divu", OP_DIVU, OP_MULDIV, 0, 0), 742 INSN_F37("divu", OP_DIVU, OP_MULDIV, 0, 0),
742 INSN_F37("rem", OP_REM, OP_MULDIV, 0, 0), 743 INSN_F37("rem", OP_REM, OP_MULDIV, 0, 0),
743 INSN_F37("remu", OP_REMU, OP_MULDIV, 0, 0), 744 INSN_F37("remu", OP_REMU, OP_MULDIV, 0, 0),
744}; 745};
745 746
746static const struct riscv_disasm_insn riscv_disasm_op32[] = { 747static const struct riscv_disasm_insn riscv_disasm_op32[] = {
747 INSN_F37("addw", OP_ADDSUB, OP_ARITH, 0, 0), 748 INSN_F37("addw", OP_ADDSUB, OP_ARITH, 0, 0),
748 INSN_F37("subw", OP_ADDSUB, OP_NARITH, 0, 0), 749 INSN_F37("subw", OP_ADDSUB, OP_NARITH, 0, 0),
749 INSN_F37("sllw", OP_SLL, OP_ARITH, 0, 0), 750 INSN_F37("sllw", OP_SLL, OP_ARITH, 0, 0),
750 INSN_F37("srlw", OP_SRX, OP_ARITH, 0, 0), 751 INSN_F37("srlw", OP_SRX, OP_ARITH, 0, 0),
751 INSN_F37("sraw", OP_SRX, OP_NARITH, 0, 0), 752 INSN_F37("sraw", OP_SRX, OP_NARITH, 0, 0),
752 INSN_F37("mulw", OP_MUL, OP_MULDIV, 0, 0), 753 INSN_F37("mulw", OP_MUL, OP_MULDIV, 0, 0),
753 INSN_F37("divw", OP_DIV, OP_MULDIV, 0, 0), 754 INSN_F37("divw", OP_DIV, OP_MULDIV, 0, 0),
754 INSN_F37("divuw", OP_DIVU, OP_MULDIV, 0, 0), 755 INSN_F37("divuw", OP_DIVU, OP_MULDIV, 0, 0),
755 INSN_F37("remw", OP_REM, OP_MULDIV, 0, 0), 756 INSN_F37("remw", OP_REM, OP_MULDIV, 0, 0),
756 INSN_F37("remuw", OP_REMU, OP_MULDIV, 0, 0), 757 INSN_F37("remuw", OP_REMU, OP_MULDIV, 0, 0),
757}; 758};
758 759
759static const struct riscv_disasm_insn riscv_disasm_opfp[] = { 760static const struct riscv_disasm_insn riscv_disasm_opfp[] = {
760 INSN_F5("fadd", OPFP_ADD, F7SIZE|F3ROUND, ALL_FREG), 761 INSN_F5("fadd", OPFP_ADD, F7SIZE|F3ROUND, ALL_FREG),
761 INSN_F5("fsub", OPFP_SUB, F7SIZE|F3ROUND, ALL_FREG), 762 INSN_F5("fsub", OPFP_SUB, F7SIZE|F3ROUND, ALL_FREG),
762 INSN_F5("fmul", OPFP_MUL, F7SIZE|F3ROUND, ALL_FREG), 763 INSN_F5("fmul", OPFP_MUL, F7SIZE|F3ROUND, ALL_FREG),
763 INSN_F5("fdiv", OPFP_DIV, F7SIZE|F3ROUND, ALL_FREG), 764 INSN_F5("fdiv", OPFP_DIV, F7SIZE|F3ROUND, ALL_FREG),
764 INSN_F53("fsgnj", OPFP_SGNJ, SGN_SGNJ, F7SIZE, ALL_FREG), 765 INSN_F53("fsgnj", OPFP_SGNJ, SGN_SGNJ, F7SIZE, ALL_FREG),
765 INSN_F53("fsgnjn", OPFP_SGNJ, SGN_SGNJN, F7SIZE, ALL_FREG), 766 INSN_F53("fsgnjn", OPFP_SGNJ, SGN_SGNJN, F7SIZE, ALL_FREG),
766 INSN_F53("fsgnjx", OPFP_SGNJ, SGN_SGNJX, F7SIZE, ALL_FREG), 767 INSN_F53("fsgnjx", OPFP_SGNJ, SGN_SGNJX, F7SIZE, ALL_FREG),
767 INSN_F53("fmin", OPFP_MINMAX, MINMAX_MIN, F7SIZE, ALL_FREG), 768 INSN_F53("fmin", OPFP_MINMAX, MINMAX_MIN, F7SIZE, ALL_FREG),
768 INSN_F53("fmax", OPFP_MINMAX, MINMAX_MAX, F7SIZE, ALL_FREG), 769 INSN_F53("fmax", OPFP_MINMAX, MINMAX_MAX, F7SIZE, ALL_FREG),
769 INSN_F5("fcvt", OPFP_CVTFF, F7SIZE|F3ROUND|RS2_FSIZE, 770 INSN_F5("fcvt", OPFP_CVTFF, F7SIZE|F3ROUND|RS2_FSIZE,
770 ISCVT | ALL_FREG), 771 ISCVT | ALL_FREG),
771 INSN_F5("fsqrt", OPFP_SQRT, F7SIZE|F3ROUND|RS2_0, ALL_FREG), 772 INSN_F5("fsqrt", OPFP_SQRT, F7SIZE|F3ROUND|RS2_0, ALL_FREG),
772 INSN_F53("fle", OPFP_CMP, CMP_LE, F7SIZE, RS12_FREG), 773 INSN_F53("fle", OPFP_CMP, CMP_LE, F7SIZE, RS12_FREG),
773 INSN_F53("flt", OPFP_CMP, CMP_LT, F7SIZE, RS12_FREG), 774 INSN_F53("flt", OPFP_CMP, CMP_LT, F7SIZE, RS12_FREG),
774 INSN_F53("feq", OPFP_CMP, CMP_EQ, F7SIZE, RS12_FREG), 775 INSN_F53("feq", OPFP_CMP, CMP_EQ, F7SIZE, RS12_FREG),
775 INSN_F5("fcvt", OPFP_CVTIF, F7SIZE|F3ROUND|RS2_FSIZE|RS2_FSIZE_INT, 776 INSN_F5("fcvt", OPFP_CVTIF, F7SIZE|F3ROUND|RS2_FSIZE|RS2_FSIZE_INT,
776 ISCVT | RS2SIZE_FIRST | RS1_FREG), 777 ISCVT | RS2SIZE_FIRST | RS1_FREG),
777 INSN_F5("fcvt", OPFP_CVTFI, F7SIZE|F3ROUND|RS2_FSIZE|RS2_FSIZE_INT, 778 INSN_F5("fcvt", OPFP_CVTFI, F7SIZE|F3ROUND|RS2_FSIZE|RS2_FSIZE_INT,
778 ISCVT | RD_FREG), 779 ISCVT | RD_FREG),
779 INSN_F53("fclass", OPFP_MVFI_CLASS, MVFI_CLASS_CLASS, F7SIZE|RS2_0, 780 INSN_F53("fclass", OPFP_MVFI_CLASS, MVFI_CLASS_CLASS, F7SIZE|RS2_0,
780 RS1_FREG), 781 RS1_FREG),
781 INSN_F73("fmv.x.w", (OPFP_MVFI_CLASS << 2) | OPFP_S, MVFI_CLASS_MVFI, 782 INSN_F73("fmv.x.w", (OPFP_MVFI_CLASS << 2) | OPFP_S, MVFI_CLASS_MVFI,
782 RS2_0, RS1_FREG), 783 RS2_0, RS1_FREG),
783 INSN_F73("fmv.w.x", (OPFP_MVIF << 2) | OPFP_S, 0, 784 INSN_F73("fmv.w.x", (OPFP_MVIF << 2) | OPFP_S, 0,
784 RS2_0, RD_FREG), 785 RS2_0, RD_FREG),
785 INSN_F73("fmv.x.d", (OPFP_MVFI_CLASS << 2) | OPFP_D, MVFI_CLASS_MVFI, 786 INSN_F73("fmv.x.d", (OPFP_MVFI_CLASS << 2) | OPFP_D, MVFI_CLASS_MVFI,
786 RS2_0, RS1_FREG), 787 RS2_0, RS1_FREG),
787 INSN_F73("fmv.d.x", (OPFP_MVIF << 2) | OPFP_D, 0, 788 INSN_F73("fmv.d.x", (OPFP_MVIF << 2) | OPFP_D, 0,
788 RS2_0, RD_FREG), 789 RS2_0, RD_FREG),
789}; 790};
790 791
791#define TABLE(table) \ 792#define TABLE(table) \
792 .u.entries.v = table, .u.entries.n = __arraycount(table) 793 .u.entries.v = table, .u.entries.n = __arraycount(table)
793 794
794static const struct riscv_disasm32_entry riscv_disasm32[32] = { 795static const struct riscv_disasm32_entry riscv_disasm32[32] = {
795 [OPCODE_AUIPC] = { .fmt = FMT_U, .u.name = "auipc" }, 796 [OPCODE_AUIPC] = { .fmt = FMT_U, .u.name = "auipc" },
796 [OPCODE_LUI] = { .fmt = FMT_U, .u.name = "lui" }, 797 [OPCODE_LUI] = { .fmt = FMT_U, .u.name = "lui" },
797 [OPCODE_JAL] = { .fmt = FMT_J, .u.name = "jal" }, 798 [OPCODE_JAL] = { .fmt = FMT_J, .u.name = "jal" },
798 [OPCODE_JALR] = { .fmt = FMT_In, .u.name = "jalr" }, 799 [OPCODE_JALR] = { .fmt = FMT_In, .u.name = "jalr" },
799 [OPCODE_MISCMEM] = { .fmt = FMT_I, TABLE(riscv_disasm_miscmem) }, 800 [OPCODE_MISCMEM] = { .fmt = FMT_I, TABLE(riscv_disasm_miscmem) },
800 [OPCODE_LOAD] = { .fmt = FMT_I, TABLE(riscv_disasm_load) }, 801 [OPCODE_LOAD] = { .fmt = FMT_I, TABLE(riscv_disasm_load) },
801 [OPCODE_LOADFP] = { .fmt = FMT_I, TABLE(riscv_disasm_loadfp) }, 802 [OPCODE_LOADFP] = { .fmt = FMT_I, TABLE(riscv_disasm_loadfp) },
802 [OPCODE_OPIMM] = { .fmt = FMT_I, TABLE(riscv_disasm_opimm) }, 803 [OPCODE_OPIMM] = { .fmt = FMT_I, TABLE(riscv_disasm_opimm) },
803 [OPCODE_OPIMM32] = { .fmt = FMT_I, TABLE(riscv_disasm_opimm32) }, 804 [OPCODE_OPIMM32] = { .fmt = FMT_I, TABLE(riscv_disasm_opimm32) },
804 [OPCODE_STORE] = { .fmt = FMT_S, TABLE(riscv_disasm_store) }, 805 [OPCODE_STORE] = { .fmt = FMT_S, TABLE(riscv_disasm_store) },
805 [OPCODE_STOREFP] = { .fmt = FMT_S, TABLE(riscv_disasm_storefp) }, 806 [OPCODE_STOREFP] = { .fmt = FMT_S, TABLE(riscv_disasm_storefp) },
806 [OPCODE_BRANCH] = { .fmt = FMT_B, TABLE(riscv_disasm_branch) }, 807 [OPCODE_BRANCH] = { .fmt = FMT_B, TABLE(riscv_disasm_branch) },
807 [OPCODE_SYSTEM] = { .fmt = FMT_R, TABLE(riscv_disasm_system) }, 808 [OPCODE_SYSTEM] = { .fmt = FMT_R, TABLE(riscv_disasm_system) },
808 [OPCODE_AMO] = { .fmt = FMT_R, TABLE(riscv_disasm_amo) }, 809 [OPCODE_AMO] = { .fmt = FMT_R, TABLE(riscv_disasm_amo) },
809 [OPCODE_OP] = { .fmt = FMT_R, TABLE(riscv_disasm_op) }, 810 [OPCODE_OP] = { .fmt = FMT_R, TABLE(riscv_disasm_op) },
810 [OPCODE_OP32] = { .fmt = FMT_R, TABLE(riscv_disasm_op32) }, 811 [OPCODE_OP32] = { .fmt = FMT_R, TABLE(riscv_disasm_op32) },
811 [OPCODE_OPFP] = { .fmt = FMT_R, TABLE(riscv_disasm_opfp) }, 812 [OPCODE_OPFP] = { .fmt = FMT_R, TABLE(riscv_disasm_opfp) },
812 [OPCODE_MADD] = { .fmt = FMT_R4, .u.name = "fmadd" }, 813 [OPCODE_MADD] = { .fmt = FMT_R4, .u.name = "fmadd" },
813 [OPCODE_MSUB] = { .fmt = FMT_R4, .u.name = "fmsub" }, 814 [OPCODE_MSUB] = { .fmt = FMT_R4, .u.name = "fmsub" },
814 [OPCODE_NMADD] = { .fmt = FMT_R4, .u.name = "fnmadd" }, 815 [OPCODE_NMADD] = { .fmt = FMT_R4, .u.name = "fnmadd" },
815 [OPCODE_NMSUB] = { .fmt = FMT_R4, .u.name = "fnmsub" }, 816 [OPCODE_NMSUB] = { .fmt = FMT_R4, .u.name = "fnmsub" },
816 [OPCODE_CUSTOM0] = { .fmt = FMT_UNKNOWN }, 817 [OPCODE_CUSTOM0] = { .fmt = FMT_UNKNOWN },
817 [OPCODE_CUSTOM1] = { .fmt = FMT_UNKNOWN }, 818 [OPCODE_CUSTOM1] = { .fmt = FMT_UNKNOWN },
818 [OPCODE_CUSTOM2] = { .fmt = FMT_UNKNOWN }, 819 [OPCODE_CUSTOM2] = { .fmt = FMT_UNKNOWN },
819 [OPCODE_CUSTOM3] = { .fmt = FMT_UNKNOWN }, 820 [OPCODE_CUSTOM3] = { .fmt = FMT_UNKNOWN },
820 [OPCODE_rsvd21] = { .fmt = FMT_UNKNOWN }, 821 [OPCODE_rsvd21] = { .fmt = FMT_UNKNOWN },
821 [OPCODE_rsvd26] = { .fmt = FMT_UNKNOWN }, 822 [OPCODE_rsvd26] = { .fmt = FMT_UNKNOWN },
822 [OPCODE_rsvd29] = { .fmt = FMT_UNKNOWN }, 823 [OPCODE_rsvd29] = { .fmt = FMT_UNKNOWN },
823 [OPCODE_X48a] = { .fmt = FMT_ASSERT }, 824 [OPCODE_X48a] = { .fmt = FMT_ASSERT },
824 [OPCODE_X48b] = { .fmt = FMT_ASSERT }, 825 [OPCODE_X48b] = { .fmt = FMT_ASSERT },
825 [OPCODE_X64] = { .fmt = FMT_ASSERT }, 826 [OPCODE_X64] = { .fmt = FMT_ASSERT },
826 [OPCODE_X80] = { .fmt = FMT_ASSERT }, 827 [OPCODE_X80] = { .fmt = FMT_ASSERT },
827}; 828};
828 829
829static const struct riscv_disasm_insn * 830static const struct riscv_disasm_insn *
830riscv_disasm_match(const struct riscv_disasm_insn *table, unsigned num, 831riscv_disasm_match(const struct riscv_disasm_insn *table, unsigned num,
831 uint32_t insn, uint32_t imm) 832 uint32_t insn, uint32_t imm)
832{ 833{
833 unsigned i, f3, f7, testf7; 834 unsigned i, f3, f7, testf7;
834 const struct riscv_disasm_insn *info; 835 const struct riscv_disasm_insn *info;
835 836
836 f3 = INSN_FUNCT3(insn); 837 f3 = INSN_FUNCT3(insn);
837 f7 = INSN_FUNCT7(insn); 838 f7 = INSN_FUNCT7(insn);
838 for (i=0; i<num; i++) { 839 for (i=0; i<num; i++) {
839 info = &table[i]; 840 info = &table[i];
840 841
841 /* always check funct3 first */ 842 /* always check funct3 first */
842 if (info->matchflags & CHECK_F3) { 843 if (info->matchflags & CHECK_F3) {
843 if (info->funct3 != f3) { 844 if (info->funct3 != f3) {
844 continue; 845 continue;
845 } 846 }
846 } 847 }
847 848
848 /* now funct7 */ 849 /* now funct7 */
849 testf7 = f7; 850 testf7 = f7;
850 if (info->matchflags & SHIFT64) { 851 if (info->matchflags & SHIFT64) {
851 /* shift count leaks into the bottom bit of funct7 */ 852 /* shift count leaks into the bottom bit of funct7 */
852 testf7 &= 0b1111110; 853 testf7 &= 0b1111110;
853 } 854 }
854 if (info->matchflags & CHECK_F5) { 855 if (info->matchflags & CHECK_F5) {
855 /* other stuff in the bottom two bits, don't look */ 856 /* other stuff in the bottom two bits, don't look */
856 testf7 &= 0b1111100; 857 testf7 &= 0b1111100;
857 } 858 }
858 if (info->matchflags & CHECK_F7) { 859 if (info->matchflags & CHECK_F7) {
859 if (info->funct7 != testf7) { 860 if (info->funct7 != testf7) {
860 continue; 861 continue;
861 } 862 }
862 } 863 }
863 864
864 /* finally rs2 as the 4th opcode field */ 865 /* finally rs2 as the 4th opcode field */
865 if (info->matchflags & CHECK_RS2) { 866 if (info->matchflags & CHECK_RS2) {
866 if (info->rs2 != INSN_RS2(insn)) { 867 if (info->rs2 != INSN_RS2(insn)) {
867 continue; 868 continue;
868 } 869 }
869 } 870 }
870 871
871 /* check fields that are supposed to be 0 */ 872 /* check fields that are supposed to be 0 */
872 if (info->matchflags & RD_0) { 873 if (info->matchflags & RD_0) {
873 if (INSN_RD(insn) != 0) { 874 if (INSN_RD(insn) != 0) {
874 continue; 875 continue;
875 } 876 }
876 } 877 }
877 if (info->matchflags & RS1_0) { 878 if (info->matchflags & RS1_0) {
878 if (INSN_RS1(insn) != 0) { 879 if (INSN_RS1(insn) != 0) {
879 continue; 880 continue;
880 } 881 }
881 } 882 }
882 if (info->matchflags & RS2_0) { 883 if (info->matchflags & RS2_0) {
883 /* this could be folded into CHECK_RS2 */ 884 /* this could be folded into CHECK_RS2 */
884 /* (but would make the initializations uglier) */ 885 /* (but would make the initializations uglier) */
885 if (INSN_RS2(insn) != 0) { 886 if (INSN_RS2(insn) != 0) {
886 continue; 887 continue;
887 } 888 }
888 } 889 }
889 if (info->matchflags & IMM_0) { 890 if (info->matchflags & IMM_0) {
890 if (imm != 0) { 891 if (imm != 0) {
891 continue; 892 continue;
892 } 893 }
893 } 894 }
894 895
895 /* other checks */ 896 /* other checks */
896 if (info->matchflags & F3AMO) { 897 if (info->matchflags & F3AMO) {
897 if (f3 != AMO_W && f3 != AMO_D) { 898 if (f3 != AMO_W && f3 != AMO_D) {
898 continue; 899 continue;
899 } 900 }
900 } 901 }
901 if (info->matchflags & F3ROUND) { 902 if (info->matchflags & F3ROUND) {
902 switch (f3) { 903 switch (f3) {
903 case ROUND_RNE: 904 case ROUND_RNE:
904 case ROUND_RTZ: 905 case ROUND_RTZ:
905 case ROUND_RDN: 906 case ROUND_RDN:
906 case ROUND_RUP: 907 case ROUND_RUP:
907 case ROUND_RMM: 908 case ROUND_RMM:
908 case ROUND_DYN: 909 case ROUND_DYN:
909 break; 910 break;
910 default: 911 default:
911 continue; 912 continue;
912 } 913 }
913 } 914 }
914 if (info->matchflags & F7SIZE) { 915 if (info->matchflags & F7SIZE) {
915 /* fpu size bits at bottom of funct7 */ 916 /* fpu size bits at bottom of funct7 */
916 /* always floating sizes */ 917 /* always floating sizes */
917 switch (f7 & 3) { 918 switch (f7 & 3) {
918 case OPFP_S: 919 case OPFP_S:
919 case OPFP_D: 920 case OPFP_D:
920 case OPFP_Q: 921 case OPFP_Q:
921 break; 922 break;
922 default: 923 default:
923 continue; 924 continue;
924 } 925 }
925 } 926 }
926 if (info->matchflags & RS2_FSIZE) { 927 if (info->matchflags & RS2_FSIZE) {
927 /* fpu size bits in rs2 field */ 928 /* fpu size bits in rs2 field */
928 if (info->matchflags & RS2_FSIZE_INT) { 929 if (info->matchflags & RS2_FSIZE_INT) {
929 /* integer sizes */ 930 /* integer sizes */
930 switch (INSN_RS2(insn)) { 931 switch (INSN_RS2(insn)) {
931 case OPFP_W: 932 case OPFP_W:
932 case OPFP_WU: 933 case OPFP_WU:
933 case OPFP_L: 934 case OPFP_L:
934 case OPFP_LU: 935 case OPFP_LU:
935 break; 936 break;
936 default: 937 default:
937 continue; 938 continue;
938 } 939 }
939 } 940 }
940 else { 941 else {
941 /* floating sizes */ 942 /* floating sizes */
942 switch (INSN_RS2(insn)) { 943 switch (INSN_RS2(insn)) {
943 case OPFP_S: 944 case OPFP_S:
944 case OPFP_D: 945 case OPFP_D:
945 case OPFP_Q: 946 case OPFP_Q:
946 break; 947 break;
947 default: 948 default:
948 continue; 949 continue;
949 } 950 }
950 } 951 }
951 } 952 }
952 if (info->matchflags & FENCEFM) { 953 if (info->matchflags & FENCEFM) {
953 /* imm is 12 bits, upper 4 are a fence mode */ 954 /* imm is 12 bits, upper 4 are a fence mode */
954 switch (imm >> 8) { 955 switch (imm >> 8) {
955 case FENCE_FM_NORMAL: 956 case FENCE_FM_NORMAL:
956 case FENCE_FM_TSO: 957 case FENCE_FM_TSO:
957 break; 958 break;
958 default: 959 default:
959 continue; 960 continue;
960 } 961 }
961 } 962 }
962 963
963 /* passed all tests */ 964 /* passed all tests */
964 return info; 965 return info;
965 } 966 }
966 /* no match */ 967 /* no match */
967 return NULL; 968 return NULL;
968} 969}
969 970
970static void 971static void
971db_print_riscv_fencebits(unsigned bits) 972db_print_riscv_fencebits(unsigned bits)
972{ 973{
973 if (bits == 0) { 974 if (bits == 0) {
974 db_printf("0"); 975 db_printf("0");
975 } 976 }
976 else { 977 else {
977 db_printf("%s%s%s%s", 978 db_printf("%s%s%s%s",
978 (bits & FENCE_INPUT) ? "i" : "", 979 (bits & FENCE_INPUT) ? "i" : "",
979 (bits & FENCE_OUTPUT) ? "o" : "", 980 (bits & FENCE_OUTPUT) ? "o" : "",
980 (bits & FENCE_READ) ? "r" : "", 981 (bits & FENCE_READ) ? "r" : "",
981 (bits & FENCE_WRITE) ? "w" : ""); 982 (bits & FENCE_WRITE) ? "w" : "");
982 } 983 }
983} 984}
984 985
985static void 986static void
986db_print_riscv_reg(unsigned reg, bool isfreg) 987db_print_riscv_reg(unsigned reg, bool isfreg)
987{ 988{
988 if (isfreg) { 989 if (isfreg) {
989 db_printf("f%d", reg); 990 db_printf("f%d", reg);
990 } 991 }
991 else { 992 else {
992 db_printf("%s", riscv_registers[reg]); 993 db_printf("%s", riscv_registers[reg]);
993 } 994 }
994} 995}
995 996
996static const char * 997static const char *
997riscv_int_size(unsigned fpsize) 998riscv_int_size(unsigned fpsize)
998{ 999{
999 switch (fpsize) { 1000 switch (fpsize) {
1000 case OPFP_W: return ".w"; 1001 case OPFP_W: return ".w";
1001 case OPFP_WU: return ".wu"; 1002 case OPFP_WU: return ".wu";
1002 case OPFP_L: return ".l"; 1003 case OPFP_L: return ".l";
1003 case OPFP_LU: return ".lu"; 1004 case OPFP_LU: return ".lu";
1004 default: 1005 default:
1005 /* matching should prevent it coming here */ 1006 /* matching should prevent it coming here */
1006 KASSERT(0); 1007 KASSERT(0);
1007 return ".?"; 1008 return ".?";
1008 } 1009 }
1009} 1010}
1010 1011
1011static const char * 1012static const char *
1012riscv_fp_size(unsigned fpsize) 1013riscv_fp_size(unsigned fpsize)
1013{ 1014{
1014 switch (fpsize) { 1015 switch (fpsize) {
1015 case OPFP_S: return ".s"; 1016 case OPFP_S: return ".s";
1016 case OPFP_D: return ".d"; 1017 case OPFP_D: return ".d";
1017 case OPFP_Q: return ".q"; 1018 case OPFP_Q: return ".q";
1018 default: 1019 default:
1019 /* matching should prevent it coming here */ 1020 /* matching should prevent it coming here */
1020 KASSERT(0); 1021 KASSERT(0);
1021 return ".?"; 1022 return ".?";
1022 } 1023 }
1023} 1024}
1024 1025
1025static bool 1026static bool
1026larger_f_i(unsigned sz1, unsigned sz2) 1027larger_f_i(unsigned sz1, unsigned sz2)
1027{ 1028{
1028 switch (sz1) { 1029 switch (sz1) {
1029 case OPFP_S: 1030 case OPFP_S:
1030 break; 1031 break;
1031 case OPFP_D: 1032 case OPFP_D:
1032 switch (sz2) { 1033 switch (sz2) {
1033 case OPFP_W: 1034 case OPFP_W:
1034 case OPFP_WU: 1035 case OPFP_WU:
1035 return true; 1036 return true;
1036 default: 1037 default:
1037 break; 1038 break;
1038 } 1039 }
1039 break; 1040 break;
1040 case OPFP_Q: 1041 case OPFP_Q:
1041 switch (sz2) { 1042 switch (sz2) {
1042 case OPFP_W: 1043 case OPFP_W:
1043 case OPFP_WU: 1044 case OPFP_WU:
1044 case OPFP_L: 1045 case OPFP_L:
1045 case OPFP_LU: 1046 case OPFP_LU:
1046 return true; 1047 return true;
1047 default: 1048 default:
1048 break; 1049 break;
1049 } 1050 }
1050 break; 1051 break;
1051 default: 1052 default:
1052 /* matching should keep it from coming here */ 1053 /* matching should keep it from coming here */
1053 KASSERT(0); 1054 KASSERT(0);
1054 break; 1055 break;
1055 } 1056 }
1056 return false; 1057 return false;
1057} 1058}
1058 1059
1059static bool 1060static bool
1060larger_f_f(unsigned sz1, unsigned sz2) 1061larger_f_f(unsigned sz1, unsigned sz2)
1061{ 1062{
1062 switch (sz1) { 1063 switch (sz1) {
1063 case OPFP_S: 1064 case OPFP_S:
1064 break; 1065 break;
1065 case OPFP_D: 1066 case OPFP_D:
1066 switch (sz2) { 1067 switch (sz2) {
1067 case OPFP_S: 1068 case OPFP_S:
1068 return true; 1069 return true;
1069 default: 1070 default:
1070 break; 1071 break;
1071 } 1072 }
1072 break; 1073 break;
1073 case OPFP_Q: 1074 case OPFP_Q:
1074 switch (sz2) { 1075 switch (sz2) {
1075 case OPFP_S: 1076 case OPFP_S:
1076 case OPFP_D: 1077 case OPFP_D:
1077 return true; 1078 return true;
1078 default: 1079 default:
1079 break; 1080 break;
1080 } 1081 }
1081 break; 1082 break;
1082 default: 1083 default:
1083 /* matching should keep it from coming here */ 1084 /* matching should keep it from coming here */
1084 KASSERT(0); 1085 KASSERT(0);
1085 break; 1086 break;
1086 } 1087 }
1087 return false; 1088 return false;
1088} 1089}
1089 1090
1090static void 1091static void
1091db_print_riscv_fpround(const char *sep, unsigned round) 1092db_print_riscv_fpround(const char *sep, unsigned round)
1092{ 1093{
1093 switch (round) { 1094 switch (round) {
1094 case ROUND_RNE: db_printf("%srne", sep); break; 1095 case ROUND_RNE: db_printf("%srne", sep); break;
1095 case ROUND_RTZ: db_printf("%srtz", sep); break; 1096 case ROUND_RTZ: db_printf("%srtz", sep); break;
1096 case ROUND_RDN: db_printf("%srdn", sep); break; 1097 case ROUND_RDN: db_printf("%srdn", sep); break;
1097 case ROUND_RUP: db_printf("%srup", sep); break; 1098 case ROUND_RUP: db_printf("%srup", sep); break;
1098 case ROUND_RMM: db_printf("%srmm", sep); break; 1099 case ROUND_RMM: db_printf("%srmm", sep); break;
1099 case ROUND_DYN: break; 1100 case ROUND_DYN: break;
1100 default: 1101 default:
1101 /* matching should prevent it coming here */ 1102 /* matching should prevent it coming here */
1102 KASSERT(0); 1103 KASSERT(0);
1103 db_printf("%s<unknown-rounding-mode>", sep); 1104 db_printf("%s<unknown-rounding-mode>", sep);
1104 break; 1105 break;
1105 } 1106 }
1106} 1107}
1107 1108
1108 1109
1109static void 1110static void
1110db_print_riscv_insnname(uint32_t insn, const struct riscv_disasm_insn *info) 1111db_print_riscv_insnname(uint32_t insn, const struct riscv_disasm_insn *info)
1111{ 1112{
1112 db_printf("%s", info->name); 1113 db_printf("%s", info->name);
1113 1114
1114 /* accumulated mode cruft on the name */ 1115 /* accumulated mode cruft on the name */
1115 if (info->matchflags & F3AMO) { 1116 if (info->matchflags & F3AMO) {
1116 db_printf("%s", INSN_FUNCT3(insn) == AMO_W ? ".w" : ".d"); 1117 db_printf("%s", INSN_FUNCT3(insn) == AMO_W ? ".w" : ".d");
1117 } 1118 }
1118 if ((info->matchflags & RS2_FSIZE) && 1119 if ((info->matchflags & RS2_FSIZE) &&
1119 (info->printflags & RS2SIZE_FIRST)) { 1120 (info->printflags & RS2SIZE_FIRST)) {
1120 if (info->matchflags & RS2_FSIZE_INT) { 1121 if (info->matchflags & RS2_FSIZE_INT) {
1121 db_printf("%s", riscv_int_size(INSN_RS2(insn))); 1122 db_printf("%s", riscv_int_size(INSN_RS2(insn)));
1122 } 1123 }
1123 else { 1124 else {
1124 db_printf("%s", riscv_fp_size(INSN_RS2(insn))); 1125 db_printf("%s", riscv_fp_size(INSN_RS2(insn)));
1125 } 1126 }
1126 } 1127 }
1127 if (info->matchflags & F7SIZE) { 1128 if (info->matchflags & F7SIZE) {
1128 db_printf("%s", riscv_fp_size(INSN_FUNCT7(insn) & 3)); 1129 db_printf("%s", riscv_fp_size(INSN_FUNCT7(insn) & 3));
1129 } 1130 }
1130 if ((info->matchflags & RS2_FSIZE) && 1131 if ((info->matchflags & RS2_FSIZE) &&
1131 (info->printflags & RS2SIZE_FIRST) == 0) { 1132 (info->printflags & RS2SIZE_FIRST) == 0) {
1132 if (info->matchflags & RS2_FSIZE_INT) { 1133 if (info->matchflags & RS2_FSIZE_INT) {
1133 db_printf("%s", riscv_int_size(INSN_RS2(insn))); 1134 db_printf("%s", riscv_int_size(INSN_RS2(insn)));
1134 } 1135 }
1135 else { 1136 else {
1136 db_printf("%s", riscv_fp_size(INSN_RS2(insn))); 1137 db_printf("%s", riscv_fp_size(INSN_RS2(insn)));
1137 } 1138 }
1138 } 1139 }
1139 if (info->matchflags & FENCEFM) { 1140 if (info->matchflags & FENCEFM) {
1140 /* 1141 /*
1141 * The fence mode is the top 4 bits of the instruction, 1142 * The fence mode is the top 4 bits of the instruction,
1142 * which is the top 4 bits of funct7, so get it from 1143 * which is the top 4 bits of funct7, so get it from
1143 * there. Elsewhere in this file it's defined in terms 1144 * there. Elsewhere in this file it's defined in terms
1144 * of the immediate though. XXX tidy up 1145 * of the immediate though. XXX tidy up
1145 */ 1146 */
1146 if ((INSN_FUNCT7(insn) >> 3) == FENCE_FM_TSO) { 1147 if ((INSN_FUNCT7(insn) >> 3) == FENCE_FM_TSO) {
1147 db_printf(".tso"); 1148 db_printf(".tso");
1148 } 1149 }
1149 } 1150 }
1150 if (info->printflags & AMOAQRL) { 1151 if (info->printflags & AMOAQRL) {
1151 db_printf("%s%s", 1152 db_printf("%s%s",
1152 INSN_FUNCT7(insn) & AMO_AQ ? ".aq" : "", 1153 INSN_FUNCT7(insn) & AMO_AQ ? ".aq" : "",
1153 INSN_FUNCT7(insn) & AMO_RL ? ".rl" : ""); 1154 INSN_FUNCT7(insn) & AMO_RL ? ".rl" : "");
1154 } 1155 }
1155} 1156}
1156 1157
1157static int 1158static int
1158db_disasm_32(db_addr_t loc, uint32_t insn, bool altfmt) 1159db_disasm_32(db_addr_t loc, uint32_t insn, bool altfmt)
1159{ 1160{
1160 unsigned opcode; 1161 unsigned opcode;
1161 const struct riscv_disasm32_entry *d; 1162 const struct riscv_disasm32_entry *d;
1162 unsigned numtable; 1163 unsigned numtable;
1163 const struct riscv_disasm_insn *table, *info; 1164 const struct riscv_disasm_insn *table, *info;
1164 const char *sep = " "; 1165 const char *sep = " ";
1165 uint32_t imm; 1166 uint32_t imm;
1166 1167
1167 opcode = INSN_OPCODE32(insn); 1168 opcode = INSN_OPCODE32(insn);
1168 d = &riscv_disasm32[opcode]; 1169 d = &riscv_disasm32[opcode];
1169 switch (d->fmt) { 1170 switch (d->fmt) {
1170 case FMT_R: 1171 case FMT_R:
1171 /* register ops */ 1172 /* register ops */
1172 table = d->u.entries.v; 1173 table = d->u.entries.v;
1173 numtable = d->u.entries.n; 1174 numtable = d->u.entries.n;
1174 info = riscv_disasm_match(table, numtable, insn, 0); 1175 info = riscv_disasm_match(table, numtable, insn, 0);
1175 if (info == NULL) { 1176 if (info == NULL) {
1176 return EINVAL; 1177 return EINVAL;
1177 } 1178 }
1178 1179
1179 /* name */ 1180 /* name */
1180 db_print_riscv_insnname(insn, info); 1181 db_print_riscv_insnname(insn, info);
1181 1182
1182 /* rd */ 1183 /* rd */
1183 if ((info->matchflags & RD_0) == 0) { 1184 if ((info->matchflags & RD_0) == 0) {
1184 db_printf("%s", sep); 1185 db_printf("%s", sep);
1185 db_print_riscv_reg(INSN_RD(insn), 1186 db_print_riscv_reg(INSN_RD(insn),
1186 info->printflags & RD_FREG); 1187 info->printflags & RD_FREG);
1187 sep = ", "; 1188 sep = ", ";
1188 } 1189 }
1189 1190
1190 if (info->printflags & CSRIMM) { 1191 if (info->printflags & CSRIMM) {
1191 /* 1192 /*
1192 * CSR instruction; these appear under a major 1193 * CSR instruction; these appear under a major
1193 * opcode with register format, but they 1194 * opcode with register format, but they
1194 * actually use the I format. Sigh. The 1195 * actually use the I format. Sigh. The
1195 * immediate field contains the CSR number and 1196 * immediate field contains the CSR number and
1196 * prints _before_ rs1. 1197 * prints _before_ rs1.
1197 */ 1198 */
1198 imm = INSN_IMM_I(insn); 1199 imm = INSN_IMM_I(insn);
1199 db_printf("%s0x%x, ", sep, (int32_t)imm); 1200 db_printf("%s0x%x, ", sep, (int32_t)imm);
1200 db_print_riscv_reg(INSN_RS1(insn), 1201 db_print_riscv_reg(INSN_RS1(insn),
1201 info->printflags & RS1_FREG); 1202 info->printflags & RS1_FREG);
1202 } else if (info->printflags & CSRIIMM) { 1203 } else if (info->printflags & CSRIIMM) {
1203 /* 1204 /*
1204 * CSR instruction with immediate; the CSR 1205 * CSR instruction with immediate; the CSR
1205 * number is in the immediate fiel and the RS1 1206 * number is in the immediate fiel and the RS1
1206 * field contains the immediate. Bleck. 1207 * field contains the immediate. Bleck.
1207 */ 1208 */
1208 imm = INSN_IMM_I(insn); 1209 imm = INSN_IMM_I(insn);
1209 db_printf("%s0x%x, %d", sep, (int32_t)imm, 1210 db_printf("%s0x%x, %d", sep, (int32_t)imm,
1210 INSN_RS1(insn)); 1211 INSN_RS1(insn));
1211 } 1212 }
1212 else { 1213 else {
1213 /* rs1 */ 1214 /* rs1 */
1214 if ((info->matchflags & RS1_0) == 0) { 1215 if ((info->matchflags & RS1_0) == 0) {
1215 db_printf("%s", sep); 1216 db_printf("%s", sep);
1216 db_print_riscv_reg(INSN_RS1(insn), 1217 db_print_riscv_reg(INSN_RS1(insn),
1217 info->printflags & RS1_FREG); 1218 info->printflags & RS1_FREG);
1218 sep = ", "; 1219 sep = ", ";
1219 } 1220 }
1220 1221
1221 /* rs2 */ 1222 /* rs2 */
1222 if ((info->matchflags & RS2_0) == 0 && 1223 if ((info->matchflags & RS2_0) == 0 &&
1223 (info->matchflags & CHECK_RS2) == 0 && 1224 (info->matchflags & CHECK_RS2) == 0 &&
1224 (info->matchflags & RS2_FSIZE) == 0) { 1225 (info->matchflags & RS2_FSIZE) == 0) {
1225 db_printf("%s", sep); 1226 db_printf("%s", sep);
1226 db_print_riscv_reg(INSN_RS2(insn), 1227 db_print_riscv_reg(INSN_RS2(insn),
1227 info->printflags & RS2_FREG); 1228 info->printflags & RS2_FREG);
1228 } 1229 }
1229 } 1230 }
1230 1231
1231 if (info->matchflags & F3ROUND) { 1232 if (info->matchflags & F3ROUND) {
1232 /* 1233 /*
1233 * Suppress rounding mode print for insns that 1234 * Suppress rounding mode print for insns that
1234 * never round, because gas encodes it as 0 1235 * never round, because gas encodes it as 0
1235 * ("rup") rather than the normal default 1236 * ("rup") rather than the normal default
1236 * ("dyn"). 1237 * ("dyn").
1237 * 1238 *
1238 * These are: convert float to larger float, 1239 * These are: convert float to larger float,
1239 * convert int to float larger than the float. 1240 * convert int to float larger than the float.
1240 */ 1241 */
1241 bool suppress; 1242 bool suppress;
1242 1243
1243 if (info->printflags & ISCVT) { 1244 if (info->printflags & ISCVT) {
1244 KASSERT(info->matchflags & F7SIZE); 1245 KASSERT(info->matchflags & F7SIZE);
1245 KASSERT(info->matchflags & RS2_FSIZE); 1246 KASSERT(info->matchflags & RS2_FSIZE);
1246 if (info->matchflags & RS2SIZE_FIRST) { 1247 if (info->matchflags & RS2SIZE_FIRST) {
1247 /* convert to int */ 1248 /* convert to int */
1248 suppress = false; 1249 suppress = false;
1249 } 1250 }
1250 else if (info->matchflags & RS2_FSIZE_INT) { 1251 else if (info->matchflags & RS2_FSIZE_INT) {
1251 /* convert from int */ 1252 /* convert from int */
1252 suppress = larger_f_i( 1253 suppress = larger_f_i(
1253 INSN_FUNCT7(insn) & 3, 1254 INSN_FUNCT7(insn) & 3,
1254 INSN_RS2(insn)); 1255 INSN_RS2(insn));
1255 } 1256 }
1256 else { 1257 else {
1257 /* convert from float */ 1258 /* convert from float */
1258 suppress = larger_f_f( 1259 suppress = larger_f_f(
1259 INSN_FUNCT7(insn) & 3, 1260 INSN_FUNCT7(insn) & 3,
1260 INSN_RS2(insn)); 1261 INSN_RS2(insn));
1261 } 1262 }
1262 } 1263 }
1263 else { 1264 else {
1264 suppress = false; 1265 suppress = false;
1265 } 1266 }
1266 1267
1267 if (!suppress) { 1268 if (!suppress) {
1268 db_print_riscv_fpround(sep, INSN_FUNCT3(insn)); 1269 db_print_riscv_fpround(sep, INSN_FUNCT3(insn));
1269 } 1270 }
1270 } 1271 }
1271 1272
1272 db_printf("\n"); 1273 db_printf("\n");
1273 break; 1274 break;
1274 case FMT_R4: 1275 case FMT_R4:
1275 db_printf("%s%s f%d, f%d, f%d, f%d", d->u.name, 1276 db_printf("%s%s f%d, f%d, f%d, f%d", d->u.name,
1276 riscv_fp_size(INSN_FUNCT7(insn) & 3), 1277 riscv_fp_size(INSN_FUNCT7(insn) & 3),
1277 INSN_RD(insn), 1278 INSN_RD(insn),
1278 INSN_RS1(insn), 1279 INSN_RS1(insn),
1279 INSN_RS2(insn), 1280 INSN_RS2(insn),
1280 INSN_FUNCT7(insn) >> 2); 1281 INSN_FUNCT7(insn) >> 2);
1281 db_print_riscv_fpround(", ", INSN_FUNCT3(insn)); 1282 db_print_riscv_fpround(", ", INSN_FUNCT3(insn));
1282 db_printf("\n"); 1283 db_printf("\n");
1283 break; 1284 break;
1284 case FMT_I: 1285 case FMT_I:
1285 /* immediates */ 1286 /* immediates */
1286 imm = INSN_IMM_I(insn); 1287 imm = INSN_IMM_I(insn);
1287 1288
1288 table = d->u.entries.v; 1289 table = d->u.entries.v;
1289 numtable = d->u.entries.n; 1290 numtable = d->u.entries.n;
1290 info = riscv_disasm_match(table, numtable, insn, imm); 1291 info = riscv_disasm_match(table, numtable, insn, imm);
1291 if (info == NULL) { 1292 if (info == NULL) {
1292 return EINVAL; 1293 return EINVAL;
1293 } 1294 }
1294 1295
1295 if (info->matchflags & SHIFT32) { 1296 if (info->matchflags & SHIFT32) {
1296 imm &= 31; 1297 imm &= 31;
1297 } else if (info->matchflags & SHIFT64) { 1298 } else if (info->matchflags & SHIFT64) {
1298 imm &= 63; 1299 imm &= 63;
1299 } 1300 }
1300 1301
1301 /* name */ 1302 /* name */
1302 db_print_riscv_insnname(insn, info); 1303 db_print_riscv_insnname(insn, info);
1303 1304
1304 /* rd */ 1305 /* rd */
1305 if ((info->matchflags & RD_0) == 0) { 1306 if ((info->matchflags & RD_0) == 0) {
1306 db_printf("%s", sep); 1307 db_printf("%s", sep);
1307 db_print_riscv_reg(INSN_RD(insn), 1308 db_print_riscv_reg(INSN_RD(insn),
1308 info->printflags & RD_FREG); 1309 info->printflags & RD_FREG);
1309 sep = ", "; 1310 sep = ", ";
1310 } 1311 }
1311 1312
1312 if (info->printflags & MEMORYIMM) { 1313 if (info->printflags & MEMORYIMM) {
1313 db_printf("%s", sep); 1314 db_printf("%s", sep);
1314 db_printf("%d(", (int32_t)imm); 1315 db_printf("%d(", (int32_t)imm);
1315 db_print_riscv_reg(INSN_RS1(insn), 1316 db_print_riscv_reg(INSN_RS1(insn),
1316 info->printflags & RS1_FREG); 1317 info->printflags & RS1_FREG);
1317 db_printf(")"); 1318 db_printf(")");
1318 } 1319 }
1319 else { 1320 else {
1320 /* rs1 */ 1321 /* rs1 */
1321 if ((info->matchflags & RS1_0) == 0) { 1322 if ((info->matchflags & RS1_0) == 0) {
1322 db_printf("%s", sep); 1323 db_printf("%s", sep);
1323 db_print_riscv_reg(INSN_RS1(insn), 1324 db_print_riscv_reg(INSN_RS1(insn),
1324 info->printflags & RS1_FREG); 1325 info->printflags & RS1_FREG);
1325 sep = ", "; 1326 sep = ", ";
1326 } 1327 }
1327 1328
1328 /* imm */ 1329 /* imm */
1329 if (info->matchflags & IMM_0) { 1330 if (info->matchflags & IMM_0) {
1330 /* nothing */ 1331 /* nothing */
1331 } else if (info->printflags & FENCEIMM) { 1332 } else if (info->printflags & FENCEIMM) {
1332 unsigned pred, succ; 1333 unsigned pred, succ;
1333 1334
1334 /* fm is part of the name, doesn't go here */ 1335 /* fm is part of the name, doesn't go here */
1335 pred = (imm >> 4) & 0xf; 1336 pred = (imm >> 4) & 0xf;
1336 succ = imm & 0xf; 1337 succ = imm & 0xf;
1337 db_printf("%s", sep); 1338 db_printf("%s", sep);
1338 db_print_riscv_fencebits(pred); 1339 db_print_riscv_fencebits(pred);
1339 db_printf(", "); 1340 db_printf(", ");
1340 db_print_riscv_fencebits(succ); 1341 db_print_riscv_fencebits(succ);
1341 } else if (info->printflags & BRANCHIMM) { 1342 } else if (info->printflags & BRANCHIMM) {
1342 /* should be B format and not come here */ 1343 /* should be B format and not come here */
1343 KASSERT(0); 1344 KASSERT(0);
1344 } else if (info->printflags & DECIMM) { 1345 } else if (info->printflags & DECIMM) {
1345 db_printf("%s%d", sep, (int32_t)imm); 1346 db_printf("%s%d", sep, (int32_t)imm);
1346 } else { 1347 } else {
1347 db_printf("%s0x%x", sep, imm); 1348 db_printf("%s0x%x", sep, imm);
1348 } 1349 }
1349 } 1350 }
1350 db_printf("\n"); 1351 db_printf("\n");
1351 break; 1352 break;
1352 case FMT_In: 1353 case FMT_In:
1353 /* same as I but funct3 should be 0 so just one case */ 1354 /* same as I but funct3 should be 0 so just one case */
1354 if (INSN_FUNCT3(insn) != 0) { 1355 if (INSN_FUNCT3(insn) != 0) {
1355 return EINVAL; 1356 return EINVAL;
1356 } 1357 }
1357 db_printf("%s %s, %s, 0x%x\n", 1358 db_printf("%s %s, %s, 0x%x\n",
1358 d->u.name, 1359 d->u.name,
1359 riscv_registers[INSN_RD(insn)], 1360 riscv_registers[INSN_RD(insn)],
1360 riscv_registers[INSN_RS1(insn)], 1361 riscv_registers[INSN_RS1(insn)],
1361 INSN_IMM_I(insn)); 1362 INSN_IMM_I(insn));
1362 break; 1363 break;
1363 case FMT_S: 1364 case FMT_S:
1364 /* stores */ 1365 /* stores */
1365 imm = INSN_IMM_S(insn); 1366 imm = INSN_IMM_S(insn);
1366 1367
1367 table = d->u.entries.v; 1368 table = d->u.entries.v;
1368 numtable = d->u.entries.n; 1369 numtable = d->u.entries.n;
1369 info = riscv_disasm_match(table, numtable, insn, imm); 1370 info = riscv_disasm_match(table, numtable, insn, imm);
1370 if (info == NULL) { 1371 if (info == NULL) {
1371 return EINVAL; 1372 return EINVAL;
1372 } 1373 }
1373 1374
1374 KASSERT((info->matchflags & (RS1_0 | RS2_0 | CHECK_RS2)) == 0); 1375 KASSERT((info->matchflags & (RS1_0 | RS2_0 | CHECK_RS2)) == 0);
1375 KASSERT(info->printflags & MEMORYIMM); 1376 KASSERT(info->printflags & MEMORYIMM);
1376 1377
1377 /* name */ 1378 /* name */
1378 db_print_riscv_insnname(insn, info); 1379 db_print_riscv_insnname(insn, info);
1379 db_printf(" "); 1380 db_printf(" ");
1380 1381
1381 db_print_riscv_reg(INSN_RS2(insn), 1382 db_print_riscv_reg(INSN_RS2(insn),
1382 info->printflags & RS2_FREG); 1383 info->printflags & RS2_FREG);
1383 db_printf("%s", sep); 1384 db_printf("%s", sep);
1384 1385
1385 db_printf("%d(", (int32_t)imm); 1386 db_printf("%d(", (int32_t)imm);
1386 db_print_riscv_reg(INSN_RS1(insn), 1387 db_print_riscv_reg(INSN_RS1(insn),
1387 info->printflags & RS1_FREG); 1388 info->printflags & RS1_FREG);
1388 db_printf(")\n"); 1389 db_printf(")\n");
1389 break; 1390 break;
1390 case FMT_B: 1391 case FMT_B:
1391 /* branches */ 1392 /* branches */
1392 imm = INSN_IMM_B(insn); 1393 imm = INSN_IMM_B(insn);
1393 1394
1394 table = d->u.entries.v; 1395 table = d->u.entries.v;
1395 numtable = d->u.entries.n; 1396 numtable = d->u.entries.n;
1396 info = riscv_disasm_match(table, numtable, insn, imm); 1397 info = riscv_disasm_match(table, numtable, insn, imm);
1397 if (info == NULL) { 1398 if (info == NULL) {
1398 return EINVAL; 1399 return EINVAL;
1399 } 1400 }
1400 1401
1401 KASSERT((info->matchflags & (RS1_0 | RS2_0 | CHECK_RS2)) == 0); 1402 KASSERT((info->matchflags & (RS1_0 | RS2_0 | CHECK_RS2)) == 0);
1402 KASSERT(info->printflags & BRANCHIMM); 1403 KASSERT(info->printflags & BRANCHIMM);
1403 1404
1404 /* name */ 1405 /* name */
1405 db_print_riscv_insnname(insn, info); 1406 db_print_riscv_insnname(insn, info);
1406 db_printf(" "); 1407 db_printf(" ");
1407 1408
1408 db_print_riscv_reg(INSN_RS1(insn), 1409 db_print_riscv_reg(INSN_RS1(insn),
1409 info->printflags & RS1_FREG); 1410 info->printflags & RS1_FREG);
1410 db_printf(", "); 1411 db_printf(", ");
1411 1412
1412 db_print_riscv_reg(INSN_RS2(insn), 1413 db_print_riscv_reg(INSN_RS2(insn),
1413 info->printflags & RS2_FREG); 1414 info->printflags & RS2_FREG);
1414 db_printf(", "); 1415 db_printf(", ");
1415 db_print_addr(loc + (int32_t)imm); 1416 db_print_addr(loc + (int32_t)imm);
1416 db_printf("\n"); 1417 db_printf("\n");
1417 break; 1418 break;
1418 case FMT_U: 1419 case FMT_U:
1419 /* large immediates */ 1420 /* large immediates */
1420 db_printf("%s %s, 0x%x\n", 1421 db_printf("%s %s, 0x%x\n",
1421 d->u.name, 1422 d->u.name,
1422 riscv_registers[INSN_RD(insn)], 1423 riscv_registers[INSN_RD(insn)],
1423 INSN_IMM_U(insn)); 1424 INSN_IMM_U(insn));
1424 break; 1425 break;
1425 case FMT_J: 1426 case FMT_J:
1426 /* jal */ 1427 /* jal */
1427 db_printf("%s %s, ", 1428 db_printf("%s %s, ",
1428 d->u.name, 1429 d->u.name,
1429 riscv_registers[INSN_RD(insn)]); 1430 riscv_registers[INSN_RD(insn)]);
1430 db_print_addr(loc + (int32_t)INSN_IMM_J(insn)); 1431 db_print_addr(loc + (int32_t)INSN_IMM_J(insn));
1431 db_printf("\n"); 1432 db_printf("\n");
1432 break; 1433 break;
1433 case FMT_UNKNOWN: 1434 case FMT_UNKNOWN:
1434 /* reserved, custom, etc. */ 1435 /* reserved, custom, etc. */
1435 return EINVAL; 1436 return EINVAL;
1436 case FMT_ASSERT: 1437 case FMT_ASSERT:
1437 /* shouldn't have come here */ 1438 /* shouldn't have come here */
1438 KASSERTMSG(false, "db_disasm_32: non-32-bit instruction"); 1439 KASSERTMSG(false, "db_disasm_32: non-32-bit instruction");
1439 return EINVAL; 1440 return EINVAL;
1440 } 1441 }
1441 return 0; 1442 return 0;
1442} 1443}
1443 1444
1444//////////////////////////////////////////////////////////// 1445////////////////////////////////////////////////////////////
1445 1446
1446static void 1447static void
1447db_disasm_unknown(const uint16_t *insn, unsigned n) 1448db_disasm_unknown(const uint16_t *insn, unsigned n)
1448{ 1449{
1449 unsigned i; 1450 unsigned i;
1450 1451
1451 db_printf(".insn%u 0x", n*16); 1452 db_printf(".insn%u 0x", n*16);
1452 for (i=n; i-- > 0; ) { 1453 for (i=n; i-- > 0; ) {
1453 db_printf("%02x", insn[i]); 1454 db_printf("%02x", insn[i]);
1454 } 1455 }
1455 db_printf("\n"); 1456 db_printf("\n");
1456} 1457}
1457 1458
1458db_addr_t 1459db_addr_t
1459db_disasm(db_addr_t loc, bool altfmt) 1460db_disasm(db_addr_t loc, bool altfmt)
1460{ 1461{
1461 /* instructions are up to 5 halfwords */ 1462 /* instructions are up to 5 halfwords */
1462 uint16_t insn[5]; 1463 uint16_t insn[5];
1463 unsigned n, i; 1464 unsigned n, i;
1464 uint32_t insn32; 1465 uint32_t insn32;
1465 1466
1466#ifdef _KERNEL 
1467 if ((intptr_t) loc >= 0) { 
1468 db_printf("%s: %#"PRIxVADDR" is not a kernel address\n", 
1469 __func__, loc); 
1470 return loc; 
1471 } 
1472#endif 
1473 
1474 /* 1467 /*
1475 * Fetch the instruction. The first halfword tells us how many 1468 * Fetch the instruction. The first halfword tells us how many
1476 * more there are, and they're always in little-endian order. 1469 * more there are, and they're always in little-endian order.
1477 */ 1470 */
1478 insn[0] = ((const uint16_t *)loc)[0]; 1471 db_read_bytes(loc, sizeof(insn[0]), (void *)&insn[0]);
1479 n = INSN_HALFWORDS(insn[0]); 1472 n = INSN_HALFWORDS(insn[0]);
1480 KASSERT(n > 0 && n <= 5); 1473 KASSERT(n > 0 && n <= 5);
1481 for (i = 1; i < n; i++) { 1474 for (i = 1; i < n; i++) {
1482 insn[i] = ((const uint16_t *)loc)[i]; 1475 db_read_bytes(loc + i * sizeof(insn[i]), sizeof(insn[i]),
 1476 (void *)&insn[i]);
1483 } 1477 }
1484 1478
1485 switch (n) { 1479 switch (n) {
1486 case 1: 1480 case 1:
1487 if (db_disasm_16(loc, insn[0], altfmt) != 0) { 1481 if (db_disasm_16(loc, insn[0], altfmt) != 0) {
1488 db_disasm_unknown(insn, n); 1482 db_disasm_unknown(insn, n);
1489 } 1483 }
1490 break; 1484 break;
1491 case 2: 1485 case 2:
1492 insn32 = ((uint32_t)insn[1] << 16) | insn[0]; 1486 insn32 = ((uint32_t)insn[1] << 16) | insn[0];
1493 if (db_disasm_32(loc, insn32, altfmt) != 0) { 1487 if (db_disasm_32(loc, insn32, altfmt) != 0) {
1494 db_disasm_unknown(insn, n); 1488 db_disasm_unknown(insn, n);
1495 } 1489 }
1496 break; 1490 break;
1497 default: 1491 default:
1498 /* no standard instructions of size 3+ */ 1492 /* no standard instructions of size 3+ */
1499 db_disasm_unknown(insn, n); 1493 db_disasm_unknown(insn, n);
1500 break; 1494 break;
1501 } 1495 }
1502 return loc + n * sizeof(uint16_t); 1496 return loc + n * sizeof(uint16_t);
1503} 1497}

cvs diff -r1.7 -r1.8 src/sys/arch/riscv/riscv/db_machdep.c (switch to unified diff)

--- src/sys/arch/riscv/riscv/db_machdep.c 2021/04/14 06:32:20 1.7
+++ src/sys/arch/riscv/riscv/db_machdep.c 2021/05/23 23:22:55 1.8
@@ -1,253 +1,281 @@ @@ -1,253 +1,281 @@
1/* $NetBSD: db_machdep.c,v 1.7 2021/04/14 06:32:20 dholland Exp $ */ 1/* $NetBSD: db_machdep.c,v 1.8 2021/05/23 23:22:55 dholland Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 The NetBSD Foundation, Inc. 4 * Copyright (c) 2014 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas of 3am Software Foundry. 8 * by Matt Thomas of 3am Software Foundry.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33 33
34__RCSID("$NetBSD: db_machdep.c,v 1.7 2021/04/14 06:32:20 dholland Exp $"); 34__RCSID("$NetBSD: db_machdep.c,v 1.8 2021/05/23 23:22:55 dholland Exp $");
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37 37
38#include <riscv/insn.h> 38#include <riscv/insn.h>
39#include <riscv/db_machdep.h> 39#include <riscv/db_machdep.h>
40 40
41#include <ddb/db_access.h> 41#include <ddb/db_access.h>
42#include <ddb/db_interface.h> 42#include <ddb/db_interface.h>
43#include <ddb/db_extern.h> 43#include <ddb/db_extern.h>
44#include <ddb/db_variables.h> 44#include <ddb/db_variables.h>
 45#include <ddb/db_output.h>
45 46
46int db_active = 0; 47int db_active = 0;
47 48
48static int db_rw_ddbreg(const struct db_variable *, db_expr_t *, int); 49static int db_rw_ddbreg(const struct db_variable *, db_expr_t *, int);
49 50
50const struct db_variable db_regs[] = { 51const struct db_variable db_regs[] = {
51 { "ra", (void *)offsetof(struct trapframe, tf_ra), db_rw_ddbreg, NULL }, 52 { "ra", (void *)offsetof(struct trapframe, tf_ra), db_rw_ddbreg, NULL },
52 { "sp", (void *)offsetof(struct trapframe, tf_sp), db_rw_ddbreg, NULL }, 53 { "sp", (void *)offsetof(struct trapframe, tf_sp), db_rw_ddbreg, NULL },
53 { "gp", (void *)offsetof(struct trapframe, tf_gp), db_rw_ddbreg, NULL }, 54 { "gp", (void *)offsetof(struct trapframe, tf_gp), db_rw_ddbreg, NULL },
54 { "tp", (void *)offsetof(struct trapframe, tf_tp), db_rw_ddbreg, NULL }, 55 { "tp", (void *)offsetof(struct trapframe, tf_tp), db_rw_ddbreg, NULL },
55 { "s0", (void *)offsetof(struct trapframe, tf_s0), db_rw_ddbreg, NULL }, 56 { "s0", (void *)offsetof(struct trapframe, tf_s0), db_rw_ddbreg, NULL },
56 { "s1", (void *)offsetof(struct trapframe, tf_s1), db_rw_ddbreg, NULL }, 57 { "s1", (void *)offsetof(struct trapframe, tf_s1), db_rw_ddbreg, NULL },
57 { "s2", (void *)offsetof(struct trapframe, tf_s2), db_rw_ddbreg, NULL }, 58 { "s2", (void *)offsetof(struct trapframe, tf_s2), db_rw_ddbreg, NULL },
58 { "s3", (void *)offsetof(struct trapframe, tf_s3), db_rw_ddbreg, NULL }, 59 { "s3", (void *)offsetof(struct trapframe, tf_s3), db_rw_ddbreg, NULL },
59 { "s4", (void *)offsetof(struct trapframe, tf_s4), db_rw_ddbreg, NULL }, 60 { "s4", (void *)offsetof(struct trapframe, tf_s4), db_rw_ddbreg, NULL },
60 { "s5", (void *)offsetof(struct trapframe, tf_s5), db_rw_ddbreg, NULL }, 61 { "s5", (void *)offsetof(struct trapframe, tf_s5), db_rw_ddbreg, NULL },
61 { "s6", (void *)offsetof(struct trapframe, tf_s6), db_rw_ddbreg, NULL }, 62 { "s6", (void *)offsetof(struct trapframe, tf_s6), db_rw_ddbreg, NULL },
62 { "s7", (void *)offsetof(struct trapframe, tf_s7), db_rw_ddbreg, NULL }, 63 { "s7", (void *)offsetof(struct trapframe, tf_s7), db_rw_ddbreg, NULL },
63 { "s8", (void *)offsetof(struct trapframe, tf_s8), db_rw_ddbreg, NULL }, 64 { "s8", (void *)offsetof(struct trapframe, tf_s8), db_rw_ddbreg, NULL },
64 { "s9", (void *)offsetof(struct trapframe, tf_s9), db_rw_ddbreg, NULL }, 65 { "s9", (void *)offsetof(struct trapframe, tf_s9), db_rw_ddbreg, NULL },
65 { "s10", (void *)offsetof(struct trapframe, tf_s10), db_rw_ddbreg, NULL }, 66 { "s10", (void *)offsetof(struct trapframe, tf_s10), db_rw_ddbreg, NULL },
66 { "s11", (void *)offsetof(struct trapframe, tf_s11), db_rw_ddbreg, NULL }, 67 { "s11", (void *)offsetof(struct trapframe, tf_s11), db_rw_ddbreg, NULL },
67 { "a0", (void *)offsetof(struct trapframe, tf_a0), db_rw_ddbreg, NULL }, 68 { "a0", (void *)offsetof(struct trapframe, tf_a0), db_rw_ddbreg, NULL },
68 { "a1", (void *)offsetof(struct trapframe, tf_a1), db_rw_ddbreg, NULL }, 69 { "a1", (void *)offsetof(struct trapframe, tf_a1), db_rw_ddbreg, NULL },
69 { "a2", (void *)offsetof(struct trapframe, tf_a2), db_rw_ddbreg, NULL }, 70 { "a2", (void *)offsetof(struct trapframe, tf_a2), db_rw_ddbreg, NULL },
70 { "a3", (void *)offsetof(struct trapframe, tf_a3), db_rw_ddbreg, NULL }, 71 { "a3", (void *)offsetof(struct trapframe, tf_a3), db_rw_ddbreg, NULL },
71 { "a4", (void *)offsetof(struct trapframe, tf_a4), db_rw_ddbreg, NULL }, 72 { "a4", (void *)offsetof(struct trapframe, tf_a4), db_rw_ddbreg, NULL },
72 { "a5", (void *)offsetof(struct trapframe, tf_a5), db_rw_ddbreg, NULL }, 73 { "a5", (void *)offsetof(struct trapframe, tf_a5), db_rw_ddbreg, NULL },
73 { "a6", (void *)offsetof(struct trapframe, tf_a6), db_rw_ddbreg, NULL }, 74 { "a6", (void *)offsetof(struct trapframe, tf_a6), db_rw_ddbreg, NULL },
74 { "a7", (void *)offsetof(struct trapframe, tf_a7), db_rw_ddbreg, NULL }, 75 { "a7", (void *)offsetof(struct trapframe, tf_a7), db_rw_ddbreg, NULL },
75 { "t0", (void *)offsetof(struct trapframe, tf_t0), db_rw_ddbreg, NULL }, 76 { "t0", (void *)offsetof(struct trapframe, tf_t0), db_rw_ddbreg, NULL },
76 { "t1", (void *)offsetof(struct trapframe, tf_t1), db_rw_ddbreg, NULL }, 77 { "t1", (void *)offsetof(struct trapframe, tf_t1), db_rw_ddbreg, NULL },
77 { "t2", (void *)offsetof(struct trapframe, tf_t2), db_rw_ddbreg, NULL }, 78 { "t2", (void *)offsetof(struct trapframe, tf_t2), db_rw_ddbreg, NULL },
78 { "t3", (void *)offsetof(struct trapframe, tf_t3), db_rw_ddbreg, NULL }, 79 { "t3", (void *)offsetof(struct trapframe, tf_t3), db_rw_ddbreg, NULL },
79 { "t4", (void *)offsetof(struct trapframe, tf_t4), db_rw_ddbreg, NULL }, 80 { "t4", (void *)offsetof(struct trapframe, tf_t4), db_rw_ddbreg, NULL },
80 { "t5", (void *)offsetof(struct trapframe, tf_t5), db_rw_ddbreg, NULL }, 81 { "t5", (void *)offsetof(struct trapframe, tf_t5), db_rw_ddbreg, NULL },
81 { "t6", (void *)offsetof(struct trapframe, tf_t6), db_rw_ddbreg, NULL }, 82 { "t6", (void *)offsetof(struct trapframe, tf_t6), db_rw_ddbreg, NULL },
82 { "pc", (void *)offsetof(struct trapframe, tf_pc), db_rw_ddbreg, NULL }, 83 { "pc", (void *)offsetof(struct trapframe, tf_pc), db_rw_ddbreg, NULL },
83 { "status", (void *)offsetof(struct trapframe, tf_sr), db_rw_ddbreg, "i" }, 84 { "status", (void *)offsetof(struct trapframe, tf_sr), db_rw_ddbreg, "i" },
84 { "cause", (void *)offsetof(struct trapframe, tf_cause), db_rw_ddbreg, "i" }, 85 { "cause", (void *)offsetof(struct trapframe, tf_cause), db_rw_ddbreg, "i" },
85 { "tval", (void *)offsetof(struct trapframe, tf_tval), db_rw_ddbreg, NULL }, 86 { "tval", (void *)offsetof(struct trapframe, tf_tval), db_rw_ddbreg, NULL },
86}; 87};
87const struct db_variable * const db_eregs = db_regs + __arraycount(db_regs); 88const struct db_variable * const db_eregs = db_regs + __arraycount(db_regs);
88 89
89int 90int
90db_rw_ddbreg(const struct db_variable *vp, db_expr_t *valp, int rw) 91db_rw_ddbreg(const struct db_variable *vp, db_expr_t *valp, int rw)
91{ 92{
92 struct trapframe * const tf = curcpu()->ci_ddb_regs; 93 struct trapframe * const tf = curcpu()->ci_ddb_regs;
93 KASSERT(db_regs <= vp && vp < db_regs + __arraycount(db_regs)); 94 KASSERT(db_regs <= vp && vp < db_regs + __arraycount(db_regs));
94 const uintptr_t addr = (uintptr_t)tf + (uintptr_t)vp->valuep; 95 const uintptr_t addr = (uintptr_t)tf + (uintptr_t)vp->valuep;
95 if (vp->modif != NULL && vp->modif[0] == 'i') { 96 if (vp->modif != NULL && vp->modif[0] == 'i') {
96 if (rw == DB_VAR_GET) { 97 if (rw == DB_VAR_GET) {
97 *valp = *(const uint32_t *)addr; 98 *valp = *(const uint32_t *)addr;
98 } else { 99 } else {
99 *(uint32_t *)addr = *valp; 100 *(uint32_t *)addr = *valp;
100 } 101 }
101 } else { 102 } else {
102 if (rw == DB_VAR_GET) { 103 if (rw == DB_VAR_GET) {
103 *valp = *(const register_t *)addr; 104 *valp = *(const register_t *)addr;
104 } else { 105 } else {
105 *(register_t *)addr = *valp; 106 *(register_t *)addr = *valp;
106 } 107 }
107 } 108 }
108 return 0; 109 return 0;
109} 110}
110 111
111// These are for the software implementation of single-stepping. 112// These are for the software implementation of single-stepping.
112// 113//
113// XXX none of this checks for 16-bit instructions; it should all be 114// XXX none of this checks for 16-bit instructions; it should all be
114// converted to the newer decoding macros. Also, XXX it does not look 115// converted to the newer decoding macros. Also, XXX it does not look
115// like the MI parts in ddb is going to work in the presence of 16-bit 116// like the MI parts in ddb is going to work in the presence of 16-bit
116// instructions anyway. 117// instructions anyway.
117// 118//
118// returns true is the instruction might branch 119// returns true is the instruction might branch
119bool 120bool
120inst_branch(uint32_t insn) 121inst_branch(uint32_t insn)
121{ 122{
122 return OPCODE_P(insn, BRANCH); 123 return OPCODE_P(insn, BRANCH);
123} 124}
124 125
125// returns true is the instruction might branch 126// returns true is the instruction might branch
126bool 127bool
127inst_call(uint32_t insn) 128inst_call(uint32_t insn)
128{ 129{
129 const union riscv_insn ri = { .val = insn }; 130 const union riscv_insn ri = { .val = insn };
130 return (OPCODE_P(insn, JAL) && ri.type_u.u_rd == 1) 131 return (OPCODE_P(insn, JAL) && ri.type_u.u_rd == 1)
131 || (OPCODE_P(insn, JALR) && ri.type_i.i_rd == 1); 132 || (OPCODE_P(insn, JALR) && ri.type_i.i_rd == 1);
132} 133}
133 134
134// return true if the instructon is an uncondition branch/jump. 135// return true if the instructon is an uncondition branch/jump.
135bool 136bool
136inst_unconditional_flow_transfer(uint32_t insn) 137inst_unconditional_flow_transfer(uint32_t insn)
137{ 138{
138 // we should check for beq xN,xN but why use that instead of jal x0,... 139 // we should check for beq xN,xN but why use that instead of jal x0,...
139 return OPCODE_P(insn, JAL) || OPCODE_P(insn, JALR); 140 return OPCODE_P(insn, JAL) || OPCODE_P(insn, JALR);
140} 141}
141 142
142bool 143bool
143inst_return(uint32_t insn) 144inst_return(uint32_t insn)
144{ 145{
145 const union riscv_insn ri = { .val = insn }; 146 const union riscv_insn ri = { .val = insn };
146 return OPCODE_P(insn, JALR) && ri.type_i.i_rs1 == 1; 147 return OPCODE_P(insn, JALR) && ri.type_i.i_rs1 == 1;
147} 148}
148 149
149bool 150bool
150inst_load(uint32_t insn) 151inst_load(uint32_t insn)
151{ 152{
152 return OPCODE_P(insn, LOAD) || OPCODE_P(insn, LOADFP); 153 return OPCODE_P(insn, LOAD) || OPCODE_P(insn, LOADFP);
153} 154}
154 155
155bool 156bool
156inst_store(uint32_t insn) 157inst_store(uint32_t insn)
157{ 158{
158 return OPCODE_P(insn, STORE) || OPCODE_P(insn, STOREFP); 159 return OPCODE_P(insn, STORE) || OPCODE_P(insn, STOREFP);
159} 160}
160 161
161static inline register_t 162static inline register_t
162get_reg_value(const db_regs_t *tf, u_int regno) 163get_reg_value(const db_regs_t *tf, u_int regno)
163{ 164{
164 return (regno == 0 ? 0 : tf->tf_reg[regno - 1]); 165 return (regno == 0 ? 0 : tf->tf_reg[regno - 1]);
165} 166}
166 167
167db_addr_t 168db_addr_t
168branch_taken(uint32_t insn, db_addr_t pc, db_regs_t *tf) 169branch_taken(uint32_t insn, db_addr_t pc, db_regs_t *tf)
169{ 170{
170 const union riscv_insn i = { .val = insn }; 171 const union riscv_insn i = { .val = insn };
171 intptr_t displacement; 172 intptr_t displacement;
172 173
173 if (OPCODE_P(insn, JALR)) { 174 if (OPCODE_P(insn, JALR)) {
174 return i.type_i.i_imm11to0 + get_reg_value(tf, i.type_i.i_rs1); 175 return i.type_i.i_imm11to0 + get_reg_value(tf, i.type_i.i_rs1);
175 } 176 }
176 if (OPCODE_P(insn, JAL)) { 177 if (OPCODE_P(insn, JAL)) {
177 displacement = i.type_j.j_imm20 << 20; 178 displacement = i.type_j.j_imm20 << 20;
178 displacement |= i.type_j.j_imm19to12 << 12; 179 displacement |= i.type_j.j_imm19to12 << 12;
179 displacement |= i.type_j.j_imm11 << 11; 180 displacement |= i.type_j.j_imm11 << 11;
180 displacement |= i.type_j.j_imm10to1 << 1; 181 displacement |= i.type_j.j_imm10to1 << 1;
181 } else { 182 } else {
182 KASSERT(OPCODE_P(insn, BRANCH)); 183 KASSERT(OPCODE_P(insn, BRANCH));
183 register_t rs1 = get_reg_value(tf, i.type_b.b_rs1); 184 register_t rs1 = get_reg_value(tf, i.type_b.b_rs1);
184 register_t rs2 = get_reg_value(tf, i.type_b.b_rs2); 185 register_t rs2 = get_reg_value(tf, i.type_b.b_rs2);
185 bool branch_p; // = false; 186 bool branch_p; // = false;
186 switch (i.type_b.b_funct3 & 0b110U) { 187 switch (i.type_b.b_funct3 & 0b110U) {
187 case 0b000U: 188 case 0b000U:
188 branch_p = (rs1 == rs2); 189 branch_p = (rs1 == rs2);
189 break; 190 break;
190 case 0b010U: 191 case 0b010U:
191 branch_p = ((rs1 & (1 << (i.type_b.b_rs2))) != 0); 192 branch_p = ((rs1 & (1 << (i.type_b.b_rs2))) != 0);
192 break; 193 break;
193 case 0b100U: 194 case 0b100U:
194 branch_p = (rs1 < rs2); 195 branch_p = (rs1 < rs2);
195 break; 196 break;
196 default: // stupid gcc 197 default: // stupid gcc
197 case 0b110U: 198 case 0b110U:
198 branch_p = ((uregister_t)rs1 < (uregister_t)rs2); 199 branch_p = ((uregister_t)rs1 < (uregister_t)rs2);
199 break; 200 break;
200 } 201 }
201 202
202 if (i.type_b.b_funct3 & 1) 203 if (i.type_b.b_funct3 & 1)
203 branch_p = !branch_p; 204 branch_p = !branch_p;
204 205
205 if (!branch_p) { 206 if (!branch_p) {
206 displacement = 4; 207 displacement = 4;
207 } else { 208 } else {
208 displacement = i.type_b.b_imm12 << 12; 209 displacement = i.type_b.b_imm12 << 12;
209 displacement |= i.type_b.b_imm11 << 11; 210 displacement |= i.type_b.b_imm11 << 11;
210 displacement |= i.type_b.b_imm10to5 << 5; 211 displacement |= i.type_b.b_imm10to5 << 5;
211 displacement |= i.type_b.b_imm4to1 << 1; 212 displacement |= i.type_b.b_imm4to1 << 1;
212 } 213 }
213 } 214 }
214 215
215 return pc + displacement; 216 return pc + displacement;
216} 217}
217 218
218db_addr_t 219db_addr_t
219next_instr_address(db_addr_t pc, bool bdslot_p) 220next_instr_address(db_addr_t pc, bool bdslot_p)
220{ 221{
221 return pc + (bdslot_p ? 0 : 4); 222 return pc + (bdslot_p ? 0 : 4);
222} 223}
223 224
224void 225void
225db_read_bytes(db_addr_t addr, size_t len, char *data) 226db_read_bytes(db_addr_t addr, size_t len, char *data)
226{ 227{
227 const char *src = (char *)addr; 228 const char *src = (char *)addr;
 229 int err;
 230
 231 /* If asked to fetch from userspace, do it safely */
 232 if ((intptr_t)addr >= 0) {
 233 err = copyin(src, data, len);
 234 if (err) {
 235#ifdef DDB
 236 db_printf("address %p is invalid\n", src);
 237#endif
 238 memset(data, 0, len);
 239 }
 240 return;
 241 }
228 242
229 while (len--) { 243 while (len--) {
230 *data++ = *src++; 244 *data++ = *src++;
231 } 245 }
232} 246}
233 247
234/* 248/*
235 * Write bytes to kernel address space for debugger. 249 * Write bytes to kernel address space for debugger.
236 */ 250 */
237void 251void
238db_write_bytes(vaddr_t addr, size_t len, const char *data) 252db_write_bytes(vaddr_t addr, size_t len, const char *data)
239{ 253{
 254 int err;
 255
 256 /* If asked to fetch from userspace, do it safely */
 257 if ((intptr_t)addr >= 0) {
 258 err = copyout(data, (char *)addr, len);
 259 if (err) {
 260#ifdef DDB
 261 db_printf("address %p is invalid\n", (char *)addr);
 262#endif
 263 }
 264 return;
 265 }
 266
240 if (len == 8) { 267 if (len == 8) {
241 *(uint64_t *)addr = *(const uint64_t *) data; 268 *(uint64_t *)addr = *(const uint64_t *) data;
242 } else if (len == 4) { 269 } else if (len == 4) {
243 *(uint32_t *)addr = *(const uint32_t *) data; 270 *(uint32_t *)addr = *(const uint32_t *) data;
244 } else if (len == 2) { 271 } else if (len == 2) {
245 *(uint16_t *)addr = *(const uint16_t *) data; 272 *(uint16_t *)addr = *(const uint16_t *) data;
246 } else { 273 } else {
 274 KASSERT(len == 1);
247 *(uint8_t *)addr = *(const uint8_t *) data; 275 *(uint8_t *)addr = *(const uint8_t *) data;
248 } 276 }
249 __asm("fence rw,rw; fence.i"); 277 __asm("fence rw,rw; fence.i");
250} 278}
251 279
252 280
253 281