1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Disassemble SuperH instructions. |
4 | * |
5 | * Copyright (C) 1999 kaz Kojima |
6 | * Copyright (C) 2008 Paul Mundt |
7 | */ |
8 | #include <linux/kernel.h> |
9 | #include <linux/string.h> |
10 | #include <linux/uaccess.h> |
11 | |
12 | #include <asm/ptrace.h> |
13 | |
14 | /* |
15 | * Format of an instruction in memory. |
16 | */ |
17 | typedef enum { |
18 | HEX_0, HEX_1, HEX_2, HEX_3, HEX_4, HEX_5, HEX_6, HEX_7, |
19 | HEX_8, HEX_9, HEX_A, HEX_B, HEX_C, HEX_D, HEX_E, HEX_F, |
20 | REG_N, REG_M, REG_NM, REG_B, |
21 | BRANCH_12, BRANCH_8, |
22 | DISP_8, DISP_4, |
23 | IMM_4, IMM_4BY2, IMM_4BY4, PCRELIMM_8BY2, PCRELIMM_8BY4, |
24 | IMM_8, IMM_8BY2, IMM_8BY4, |
25 | } sh_nibble_type; |
26 | |
27 | typedef enum { |
28 | A_END, A_BDISP12, A_BDISP8, |
29 | A_DEC_M, A_DEC_N, |
30 | A_DISP_GBR, A_DISP_PC, A_DISP_REG_M, A_DISP_REG_N, |
31 | A_GBR, |
32 | A_IMM, |
33 | A_INC_M, A_INC_N, |
34 | A_IND_M, A_IND_N, A_IND_R0_REG_M, A_IND_R0_REG_N, |
35 | A_MACH, A_MACL, |
36 | A_PR, A_R0, A_R0_GBR, A_REG_M, A_REG_N, A_REG_B, |
37 | A_SR, A_VBR, A_SSR, A_SPC, A_SGR, A_DBR, |
38 | F_REG_N, F_REG_M, D_REG_N, D_REG_M, |
39 | X_REG_N, /* Only used for argument parsing */ |
40 | X_REG_M, /* Only used for argument parsing */ |
41 | DX_REG_N, DX_REG_M, V_REG_N, V_REG_M, |
42 | FD_REG_N, |
43 | XMTRX_M4, |
44 | F_FR0, |
45 | FPUL_N, FPUL_M, FPSCR_N, FPSCR_M, |
46 | } sh_arg_type; |
47 | |
48 | static struct sh_opcode_info { |
49 | char *name; |
50 | sh_arg_type arg[7]; |
51 | sh_nibble_type nibbles[4]; |
52 | } sh_table[] = { |
53 | {"add" ,{A_IMM,A_REG_N},{HEX_7,REG_N,IMM_8}}, |
54 | {"add" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}}, |
55 | {"addc" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}}, |
56 | {"addv" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_F}}, |
57 | {"and" ,{A_IMM,A_R0},{HEX_C,HEX_9,IMM_8}}, |
58 | {"and" ,{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_9}}, |
59 | {"and.b" ,{A_IMM,A_R0_GBR},{HEX_C,HEX_D,IMM_8}}, |
60 | {"bra" ,{A_BDISP12},{HEX_A,BRANCH_12}}, |
61 | {"bsr" ,{A_BDISP12},{HEX_B,BRANCH_12}}, |
62 | {"bt" ,{A_BDISP8},{HEX_8,HEX_9,BRANCH_8}}, |
63 | {"bf" ,{A_BDISP8},{HEX_8,HEX_B,BRANCH_8}}, |
64 | {"bt.s" ,{A_BDISP8},{HEX_8,HEX_D,BRANCH_8}}, |
65 | {"bt/s" ,{A_BDISP8},{HEX_8,HEX_D,BRANCH_8}}, |
66 | {"bf.s" ,{A_BDISP8},{HEX_8,HEX_F,BRANCH_8}}, |
67 | {"bf/s" ,{A_BDISP8},{HEX_8,HEX_F,BRANCH_8}}, |
68 | {"clrmac" ,{0},{HEX_0,HEX_0,HEX_2,HEX_8}}, |
69 | {"clrs" ,{0},{HEX_0,HEX_0,HEX_4,HEX_8}}, |
70 | {"clrt" ,{0},{HEX_0,HEX_0,HEX_0,HEX_8}}, |
71 | {"cmp/eq" ,{A_IMM,A_R0},{HEX_8,HEX_8,IMM_8}}, |
72 | {"cmp/eq" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_0}}, |
73 | {"cmp/ge" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_3}}, |
74 | {"cmp/gt" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_7}}, |
75 | {"cmp/hi" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_6}}, |
76 | {"cmp/hs" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_2}}, |
77 | {"cmp/pl" ,{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_5}}, |
78 | {"cmp/pz" ,{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_1}}, |
79 | {"cmp/str" ,{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_C}}, |
80 | {"div0s" ,{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_7}}, |
81 | {"div0u" ,{0},{HEX_0,HEX_0,HEX_1,HEX_9}}, |
82 | {"div1" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_4}}, |
83 | {"exts.b" ,{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_E}}, |
84 | {"exts.w" ,{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_F}}, |
85 | {"extu.b" ,{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_C}}, |
86 | {"extu.w" ,{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_D}}, |
87 | {"jmp" ,{A_IND_N},{HEX_4,REG_N,HEX_2,HEX_B}}, |
88 | {"jsr" ,{A_IND_N},{HEX_4,REG_N,HEX_0,HEX_B}}, |
89 | {"ldc" ,{A_REG_N,A_SR},{HEX_4,REG_N,HEX_0,HEX_E}}, |
90 | {"ldc" ,{A_REG_N,A_GBR},{HEX_4,REG_N,HEX_1,HEX_E}}, |
91 | {"ldc" ,{A_REG_N,A_VBR},{HEX_4,REG_N,HEX_2,HEX_E}}, |
92 | {"ldc" ,{A_REG_N,A_SSR},{HEX_4,REG_N,HEX_3,HEX_E}}, |
93 | {"ldc" ,{A_REG_N,A_SPC},{HEX_4,REG_N,HEX_4,HEX_E}}, |
94 | {"ldc" ,{A_REG_N,A_DBR},{HEX_4,REG_N,HEX_7,HEX_E}}, |
95 | {"ldc" ,{A_REG_N,A_REG_B},{HEX_4,REG_N,REG_B,HEX_E}}, |
96 | {"ldc.l" ,{A_INC_N,A_SR},{HEX_4,REG_N,HEX_0,HEX_7}}, |
97 | {"ldc.l" ,{A_INC_N,A_GBR},{HEX_4,REG_N,HEX_1,HEX_7}}, |
98 | {"ldc.l" ,{A_INC_N,A_VBR},{HEX_4,REG_N,HEX_2,HEX_7}}, |
99 | {"ldc.l" ,{A_INC_N,A_SSR},{HEX_4,REG_N,HEX_3,HEX_7}}, |
100 | {"ldc.l" ,{A_INC_N,A_SPC},{HEX_4,REG_N,HEX_4,HEX_7}}, |
101 | {"ldc.l" ,{A_INC_N,A_DBR},{HEX_4,REG_N,HEX_7,HEX_7}}, |
102 | {"ldc.l" ,{A_INC_N,A_REG_B},{HEX_4,REG_N,REG_B,HEX_7}}, |
103 | {"lds" ,{A_REG_N,A_MACH},{HEX_4,REG_N,HEX_0,HEX_A}}, |
104 | {"lds" ,{A_REG_N,A_MACL},{HEX_4,REG_N,HEX_1,HEX_A}}, |
105 | {"lds" ,{A_REG_N,A_PR},{HEX_4,REG_N,HEX_2,HEX_A}}, |
106 | {"lds" ,{A_REG_M,FPUL_N},{HEX_4,REG_M,HEX_5,HEX_A}}, |
107 | {"lds" ,{A_REG_M,FPSCR_N},{HEX_4,REG_M,HEX_6,HEX_A}}, |
108 | {"lds.l" ,{A_INC_N,A_MACH},{HEX_4,REG_N,HEX_0,HEX_6}}, |
109 | {"lds.l" ,{A_INC_N,A_MACL},{HEX_4,REG_N,HEX_1,HEX_6}}, |
110 | {"lds.l" ,{A_INC_N,A_PR},{HEX_4,REG_N,HEX_2,HEX_6}}, |
111 | {"lds.l" ,{A_INC_M,FPUL_N},{HEX_4,REG_M,HEX_5,HEX_6}}, |
112 | {"lds.l" ,{A_INC_M,FPSCR_N},{HEX_4,REG_M,HEX_6,HEX_6}}, |
113 | {"ldtlb" ,{0},{HEX_0,HEX_0,HEX_3,HEX_8}}, |
114 | {"mac.w" ,{A_INC_M,A_INC_N},{HEX_4,REG_N,REG_M,HEX_F}}, |
115 | {"mov" ,{A_IMM,A_REG_N},{HEX_E,REG_N,IMM_8}}, |
116 | {"mov" ,{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_3}}, |
117 | {"mov.b" ,{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_4}}, |
118 | {"mov.b" ,{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_4}}, |
119 | {"mov.b" ,{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_0}}, |
120 | {"mov.b" ,{A_DISP_REG_M,A_R0},{HEX_8,HEX_4,REG_M,IMM_4}}, |
121 | {"mov.b" ,{A_DISP_GBR,A_R0},{HEX_C,HEX_4,IMM_8}}, |
122 | {"mov.b" ,{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_C}}, |
123 | {"mov.b" ,{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_4}}, |
124 | {"mov.b" ,{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_0}}, |
125 | {"mov.b" ,{A_R0,A_DISP_REG_M},{HEX_8,HEX_0,REG_M,IMM_4}}, |
126 | {"mov.b" ,{A_R0,A_DISP_GBR},{HEX_C,HEX_0,IMM_8}}, |
127 | {"mov.l" ,{ A_REG_M,A_DISP_REG_N},{HEX_1,REG_N,REG_M,IMM_4BY4}}, |
128 | {"mov.l" ,{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_6}}, |
129 | {"mov.l" ,{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_6}}, |
130 | {"mov.l" ,{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_2}}, |
131 | {"mov.l" ,{A_DISP_REG_M,A_REG_N},{HEX_5,REG_N,REG_M,IMM_4BY4}}, |
132 | {"mov.l" ,{A_DISP_GBR,A_R0},{HEX_C,HEX_6,IMM_8BY4}}, |
133 | {"mov.l" ,{A_DISP_PC,A_REG_N},{HEX_D,REG_N,PCRELIMM_8BY4}}, |
134 | {"mov.l" ,{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_E}}, |
135 | {"mov.l" ,{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_6}}, |
136 | {"mov.l" ,{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_2}}, |
137 | {"mov.l" ,{A_R0,A_DISP_GBR},{HEX_C,HEX_2,IMM_8BY4}}, |
138 | {"mov.w" ,{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_5}}, |
139 | {"mov.w" ,{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_5}}, |
140 | {"mov.w" ,{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_1}}, |
141 | {"mov.w" ,{A_DISP_REG_M,A_R0},{HEX_8,HEX_5,REG_M,IMM_4BY2}}, |
142 | {"mov.w" ,{A_DISP_GBR,A_R0},{HEX_C,HEX_5,IMM_8BY2}}, |
143 | {"mov.w" ,{A_DISP_PC,A_REG_N},{HEX_9,REG_N,PCRELIMM_8BY2}}, |
144 | {"mov.w" ,{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_D}}, |
145 | {"mov.w" ,{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_5}}, |
146 | {"mov.w" ,{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_1}}, |
147 | {"mov.w" ,{A_R0,A_DISP_REG_M},{HEX_8,HEX_1,REG_M,IMM_4BY2}}, |
148 | {"mov.w" ,{A_R0,A_DISP_GBR},{HEX_C,HEX_1,IMM_8BY2}}, |
149 | {"mova" ,{A_DISP_PC,A_R0},{HEX_C,HEX_7,PCRELIMM_8BY4}}, |
150 | {"movca.l" ,{A_R0,A_IND_N},{HEX_0,REG_N,HEX_C,HEX_3}}, |
151 | {"movt" ,{A_REG_N},{HEX_0,REG_N,HEX_2,HEX_9}}, |
152 | {"muls" ,{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_F}}, |
153 | {"mul.l" ,{ A_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_7}}, |
154 | {"mulu" ,{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_E}}, |
155 | {"neg" ,{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_B}}, |
156 | {"negc" ,{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_A}}, |
157 | {"nop" ,{0},{HEX_0,HEX_0,HEX_0,HEX_9}}, |
158 | {"not" ,{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_7}}, |
159 | {"ocbi" ,{A_IND_N},{HEX_0,REG_N,HEX_9,HEX_3}}, |
160 | {"ocbp" ,{A_IND_N},{HEX_0,REG_N,HEX_A,HEX_3}}, |
161 | {"ocbwb" ,{A_IND_N},{HEX_0,REG_N,HEX_B,HEX_3}}, |
162 | {"or" ,{A_IMM,A_R0},{HEX_C,HEX_B,IMM_8}}, |
163 | {"or" ,{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_B}}, |
164 | {"or.b" ,{A_IMM,A_R0_GBR},{HEX_C,HEX_F,IMM_8}}, |
165 | {"pref" ,{A_IND_N},{HEX_0,REG_N,HEX_8,HEX_3}}, |
166 | {"rotcl" ,{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_4}}, |
167 | {"rotcr" ,{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_5}}, |
168 | {"rotl" ,{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_4}}, |
169 | {"rotr" ,{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_5}}, |
170 | {"rte" ,{0},{HEX_0,HEX_0,HEX_2,HEX_B}}, |
171 | {"rts" ,{0},{HEX_0,HEX_0,HEX_0,HEX_B}}, |
172 | {"sets" ,{0},{HEX_0,HEX_0,HEX_5,HEX_8}}, |
173 | {"sett" ,{0},{HEX_0,HEX_0,HEX_1,HEX_8}}, |
174 | {"shad" ,{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}}, |
175 | {"shld" ,{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}}, |
176 | {"shal" ,{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}}, |
177 | {"shar" ,{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}}, |
178 | {"shll" ,{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}}, |
179 | {"shll16" ,{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_8}}, |
180 | {"shll2" ,{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_8}}, |
181 | {"shll8" ,{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_8}}, |
182 | {"shlr" ,{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_1}}, |
183 | {"shlr16" ,{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_9}}, |
184 | {"shlr2" ,{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_9}}, |
185 | {"shlr8" ,{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_9}}, |
186 | {"sleep" ,{0},{HEX_0,HEX_0,HEX_1,HEX_B}}, |
187 | {"stc" ,{A_SR,A_REG_N},{HEX_0,REG_N,HEX_0,HEX_2}}, |
188 | {"stc" ,{A_GBR,A_REG_N},{HEX_0,REG_N,HEX_1,HEX_2}}, |
189 | {"stc" ,{A_VBR,A_REG_N},{HEX_0,REG_N,HEX_2,HEX_2}}, |
190 | {"stc" ,{A_SSR,A_REG_N},{HEX_0,REG_N,HEX_3,HEX_2}}, |
191 | {"stc" ,{A_SPC,A_REG_N},{HEX_0,REG_N,HEX_4,HEX_2}}, |
192 | {"stc" ,{A_SGR,A_REG_N},{HEX_0,REG_N,HEX_6,HEX_2}}, |
193 | {"stc" ,{A_DBR,A_REG_N},{HEX_0,REG_N,HEX_7,HEX_2}}, |
194 | {"stc" ,{A_REG_B,A_REG_N},{HEX_0,REG_N,REG_B,HEX_2}}, |
195 | {"stc.l" ,{A_SR,A_DEC_N},{HEX_4,REG_N,HEX_0,HEX_3}}, |
196 | {"stc.l" ,{A_GBR,A_DEC_N},{HEX_4,REG_N,HEX_1,HEX_3}}, |
197 | {"stc.l" ,{A_VBR,A_DEC_N},{HEX_4,REG_N,HEX_2,HEX_3}}, |
198 | {"stc.l" ,{A_SSR,A_DEC_N},{HEX_4,REG_N,HEX_3,HEX_3}}, |
199 | {"stc.l" ,{A_SPC,A_DEC_N},{HEX_4,REG_N,HEX_4,HEX_3}}, |
200 | {"stc.l" ,{A_SGR,A_DEC_N},{HEX_4,REG_N,HEX_6,HEX_3}}, |
201 | {"stc.l" ,{A_DBR,A_DEC_N},{HEX_4,REG_N,HEX_7,HEX_3}}, |
202 | {"stc.l" ,{A_REG_B,A_DEC_N},{HEX_4,REG_N,REG_B,HEX_3}}, |
203 | {"sts" ,{A_MACH,A_REG_N},{HEX_0,REG_N,HEX_0,HEX_A}}, |
204 | {"sts" ,{A_MACL,A_REG_N},{HEX_0,REG_N,HEX_1,HEX_A}}, |
205 | {"sts" ,{A_PR,A_REG_N},{HEX_0,REG_N,HEX_2,HEX_A}}, |
206 | {"sts" ,{FPUL_M,A_REG_N},{HEX_0,REG_N,HEX_5,HEX_A}}, |
207 | {"sts" ,{FPSCR_M,A_REG_N},{HEX_0,REG_N,HEX_6,HEX_A}}, |
208 | {"sts.l" ,{A_MACH,A_DEC_N},{HEX_4,REG_N,HEX_0,HEX_2}}, |
209 | {"sts.l" ,{A_MACL,A_DEC_N},{HEX_4,REG_N,HEX_1,HEX_2}}, |
210 | {"sts.l" ,{A_PR,A_DEC_N},{HEX_4,REG_N,HEX_2,HEX_2}}, |
211 | {"sts.l" ,{FPUL_M,A_DEC_N},{HEX_4,REG_N,HEX_5,HEX_2}}, |
212 | {"sts.l" ,{FPSCR_M,A_DEC_N},{HEX_4,REG_N,HEX_6,HEX_2}}, |
213 | {"sub" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_8}}, |
214 | {"subc" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_A}}, |
215 | {"subv" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_B}}, |
216 | {"swap.b" ,{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_8}}, |
217 | {"swap.w" ,{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_9}}, |
218 | {"tas.b" ,{A_IND_N},{HEX_4,REG_N,HEX_1,HEX_B}}, |
219 | {"trapa" ,{A_IMM},{HEX_C,HEX_3,IMM_8}}, |
220 | {"tst" ,{A_IMM,A_R0},{HEX_C,HEX_8,IMM_8}}, |
221 | {"tst" ,{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_8}}, |
222 | {"tst.b" ,{A_IMM,A_R0_GBR},{HEX_C,HEX_C,IMM_8}}, |
223 | {"xor" ,{A_IMM,A_R0},{HEX_C,HEX_A,IMM_8}}, |
224 | {"xor" ,{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_A}}, |
225 | {"xor.b" ,{A_IMM,A_R0_GBR},{HEX_C,HEX_E,IMM_8}}, |
226 | {"xtrct" ,{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_D}}, |
227 | {"mul.l" ,{ A_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_7}}, |
228 | {"dt" ,{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_0}}, |
229 | {"dmuls.l" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_D}}, |
230 | {"dmulu.l" ,{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_5}}, |
231 | {"mac.l" ,{A_INC_M,A_INC_N},{HEX_0,REG_N,REG_M,HEX_F}}, |
232 | {"braf" ,{A_REG_N},{HEX_0,REG_N,HEX_2,HEX_3}}, |
233 | {"bsrf" ,{A_REG_N},{HEX_0,REG_N,HEX_0,HEX_3}}, |
234 | {"fabs" ,{FD_REG_N},{HEX_F,REG_N,HEX_5,HEX_D}}, |
235 | {"fadd" ,{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_0}}, |
236 | {"fadd" ,{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_0}}, |
237 | {"fcmp/eq" ,{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_4}}, |
238 | {"fcmp/eq" ,{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_4}}, |
239 | {"fcmp/gt" ,{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_5}}, |
240 | {"fcmp/gt" ,{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_5}}, |
241 | {"fcnvds" ,{D_REG_N,FPUL_M},{HEX_F,REG_N,HEX_B,HEX_D}}, |
242 | {"fcnvsd" ,{FPUL_M,D_REG_N},{HEX_F,REG_N,HEX_A,HEX_D}}, |
243 | {"fdiv" ,{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_3}}, |
244 | {"fdiv" ,{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_3}}, |
245 | {"fipr" ,{V_REG_M,V_REG_N},{HEX_F,REG_NM,HEX_E,HEX_D}}, |
246 | {"fldi0" ,{F_REG_N},{HEX_F,REG_N,HEX_8,HEX_D}}, |
247 | {"fldi1" ,{F_REG_N},{HEX_F,REG_N,HEX_9,HEX_D}}, |
248 | {"flds" ,{F_REG_N,FPUL_M},{HEX_F,REG_N,HEX_1,HEX_D}}, |
249 | {"float" ,{FPUL_M,FD_REG_N},{HEX_F,REG_N,HEX_2,HEX_D}}, |
250 | {"fmac" ,{F_FR0,F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_E}}, |
251 | {"fmov" ,{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_C}}, |
252 | {"fmov" ,{DX_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_C}}, |
253 | {"fmov" ,{A_IND_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, |
254 | {"fmov" ,{A_IND_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, |
255 | {"fmov" ,{F_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, |
256 | {"fmov" ,{DX_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, |
257 | {"fmov" ,{A_INC_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, |
258 | {"fmov" ,{A_INC_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, |
259 | {"fmov" ,{F_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, |
260 | {"fmov" ,{DX_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, |
261 | {"fmov" ,{A_IND_R0_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, |
262 | {"fmov" ,{A_IND_R0_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, |
263 | {"fmov" ,{F_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, |
264 | {"fmov" ,{DX_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, |
265 | {"fmov.d" ,{A_IND_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, |
266 | {"fmov.d" ,{DX_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, |
267 | {"fmov.d" ,{A_INC_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, |
268 | {"fmov.d" ,{DX_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, |
269 | {"fmov.d" ,{A_IND_R0_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, |
270 | {"fmov.d" ,{DX_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, |
271 | {"fmov.s" ,{A_IND_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, |
272 | {"fmov.s" ,{F_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, |
273 | {"fmov.s" ,{A_INC_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, |
274 | {"fmov.s" ,{F_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, |
275 | {"fmov.s" ,{A_IND_R0_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, |
276 | {"fmov.s" ,{F_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, |
277 | {"fmul" ,{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_2}}, |
278 | {"fmul" ,{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_2}}, |
279 | {"fneg" ,{FD_REG_N},{HEX_F,REG_N,HEX_4,HEX_D}}, |
280 | {"frchg" ,{0},{HEX_F,HEX_B,HEX_F,HEX_D}}, |
281 | {"fschg" ,{0},{HEX_F,HEX_3,HEX_F,HEX_D}}, |
282 | {"fsqrt" ,{FD_REG_N},{HEX_F,REG_N,HEX_6,HEX_D}}, |
283 | {"fsts" ,{FPUL_M,F_REG_N},{HEX_F,REG_N,HEX_0,HEX_D}}, |
284 | {"fsub" ,{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_1}}, |
285 | {"fsub" ,{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_1}}, |
286 | {"ftrc" ,{FD_REG_N,FPUL_M},{HEX_F,REG_N,HEX_3,HEX_D}}, |
287 | {"ftrv" ,{XMTRX_M4,V_REG_N},{HEX_F,REG_NM,HEX_F,HEX_D}}, |
288 | { 0 }, |
289 | }; |
290 | |
291 | static void print_sh_insn(u32 memaddr, u16 insn) |
292 | { |
293 | int relmask = ~0; |
294 | int nibs[4] = { (insn >> 12) & 0xf, (insn >> 8) & 0xf, (insn >> 4) & 0xf, insn & 0xf}; |
295 | int lastsp; |
296 | struct sh_opcode_info *op = sh_table; |
297 | |
298 | for (; op->name; op++) { |
299 | int n; |
300 | int imm = 0; |
301 | int rn = 0; |
302 | int rm = 0; |
303 | int rb = 0; |
304 | int disp_pc; |
305 | int disp_pc_addr = 0; |
306 | |
307 | for (n = 0; n < 4; n++) { |
308 | int i = op->nibbles[n]; |
309 | |
310 | if (i < 16) { |
311 | if (nibs[n] == i) |
312 | continue; |
313 | goto fail; |
314 | } |
315 | switch (i) { |
316 | case BRANCH_8: |
317 | imm = (nibs[2] << 4) | (nibs[3]); |
318 | if (imm & 0x80) |
319 | imm |= ~0xff; |
320 | imm = ((char)imm) * 2 + 4 ; |
321 | goto ok; |
322 | case BRANCH_12: |
323 | imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]); |
324 | if (imm & 0x800) |
325 | imm |= ~0xfff; |
326 | imm = imm * 2 + 4; |
327 | goto ok; |
328 | case IMM_4: |
329 | imm = nibs[3]; |
330 | goto ok; |
331 | case IMM_4BY2: |
332 | imm = nibs[3] <<1; |
333 | goto ok; |
334 | case IMM_4BY4: |
335 | imm = nibs[3] <<2; |
336 | goto ok; |
337 | case IMM_8: |
338 | imm = (nibs[2] << 4) | nibs[3]; |
339 | goto ok; |
340 | case PCRELIMM_8BY2: |
341 | imm = ((nibs[2] << 4) | nibs[3]) <<1; |
342 | relmask = ~1; |
343 | goto ok; |
344 | case PCRELIMM_8BY4: |
345 | imm = ((nibs[2] << 4) | nibs[3]) <<2; |
346 | relmask = ~3; |
347 | goto ok; |
348 | case IMM_8BY2: |
349 | imm = ((nibs[2] << 4) | nibs[3]) <<1; |
350 | goto ok; |
351 | case IMM_8BY4: |
352 | imm = ((nibs[2] << 4) | nibs[3]) <<2; |
353 | goto ok; |
354 | case DISP_8: |
355 | imm = (nibs[2] << 4) | (nibs[3]); |
356 | goto ok; |
357 | case DISP_4: |
358 | imm = nibs[3]; |
359 | goto ok; |
360 | case REG_N: |
361 | rn = nibs[n]; |
362 | break; |
363 | case REG_M: |
364 | rm = nibs[n]; |
365 | break; |
366 | case REG_NM: |
367 | rn = (nibs[n] & 0xc) >> 2; |
368 | rm = (nibs[n] & 0x3); |
369 | break; |
370 | case REG_B: |
371 | rb = nibs[n] & 0x07; |
372 | break; |
373 | default: |
374 | return; |
375 | } |
376 | } |
377 | |
378 | ok: |
379 | pr_cont("%-8s " , op->name); |
380 | lastsp = (op->arg[0] == A_END); |
381 | disp_pc = 0; |
382 | for (n = 0; n < 6 && op->arg[n] != A_END; n++) { |
383 | if (n && op->arg[1] != A_END) |
384 | pr_cont(", " ); |
385 | switch (op->arg[n]) { |
386 | case A_IMM: |
387 | pr_cont("#%d" , (char)(imm)); |
388 | break; |
389 | case A_R0: |
390 | pr_cont("r0" ); |
391 | break; |
392 | case A_REG_N: |
393 | pr_cont("r%d" , rn); |
394 | break; |
395 | case A_INC_N: |
396 | pr_cont("@r%d+" , rn); |
397 | break; |
398 | case A_DEC_N: |
399 | pr_cont("@-r%d" , rn); |
400 | break; |
401 | case A_IND_N: |
402 | pr_cont("@r%d" , rn); |
403 | break; |
404 | case A_DISP_REG_N: |
405 | pr_cont("@(%d,r%d)" , imm, rn); |
406 | break; |
407 | case A_REG_M: |
408 | pr_cont("r%d" , rm); |
409 | break; |
410 | case A_INC_M: |
411 | pr_cont("@r%d+" , rm); |
412 | break; |
413 | case A_DEC_M: |
414 | pr_cont("@-r%d" , rm); |
415 | break; |
416 | case A_IND_M: |
417 | pr_cont("@r%d" , rm); |
418 | break; |
419 | case A_DISP_REG_M: |
420 | pr_cont("@(%d,r%d)" , imm, rm); |
421 | break; |
422 | case A_REG_B: |
423 | pr_cont("r%d_bank" , rb); |
424 | break; |
425 | case A_DISP_PC: |
426 | disp_pc = 1; |
427 | disp_pc_addr = imm + 4 + (memaddr & relmask); |
428 | pr_cont("%08x <%pS>" , disp_pc_addr, |
429 | (void *)disp_pc_addr); |
430 | break; |
431 | case A_IND_R0_REG_N: |
432 | pr_cont("@(r0,r%d)" , rn); |
433 | break; |
434 | case A_IND_R0_REG_M: |
435 | pr_cont("@(r0,r%d)" , rm); |
436 | break; |
437 | case A_DISP_GBR: |
438 | pr_cont("@(%d,gbr)" , imm); |
439 | break; |
440 | case A_R0_GBR: |
441 | pr_cont("@(r0,gbr)" ); |
442 | break; |
443 | case A_BDISP12: |
444 | case A_BDISP8: |
445 | pr_cont("%08x" , imm + memaddr); |
446 | break; |
447 | case A_SR: |
448 | pr_cont("sr" ); |
449 | break; |
450 | case A_GBR: |
451 | pr_cont("gbr" ); |
452 | break; |
453 | case A_VBR: |
454 | pr_cont("vbr" ); |
455 | break; |
456 | case A_SSR: |
457 | pr_cont("ssr" ); |
458 | break; |
459 | case A_SPC: |
460 | pr_cont("spc" ); |
461 | break; |
462 | case A_MACH: |
463 | pr_cont("mach" ); |
464 | break; |
465 | case A_MACL: |
466 | pr_cont("macl" ); |
467 | break; |
468 | case A_PR: |
469 | pr_cont("pr" ); |
470 | break; |
471 | case A_SGR: |
472 | pr_cont("sgr" ); |
473 | break; |
474 | case A_DBR: |
475 | pr_cont("dbr" ); |
476 | break; |
477 | case FD_REG_N: |
478 | case F_REG_N: |
479 | pr_cont("fr%d" , rn); |
480 | break; |
481 | case F_REG_M: |
482 | pr_cont("fr%d" , rm); |
483 | break; |
484 | case DX_REG_N: |
485 | if (rn & 1) { |
486 | pr_cont("xd%d" , rn & ~1); |
487 | break; |
488 | } |
489 | fallthrough; |
490 | case D_REG_N: |
491 | pr_cont("dr%d" , rn); |
492 | break; |
493 | case DX_REG_M: |
494 | if (rm & 1) { |
495 | pr_cont("xd%d" , rm & ~1); |
496 | break; |
497 | } |
498 | fallthrough; |
499 | case D_REG_M: |
500 | pr_cont("dr%d" , rm); |
501 | break; |
502 | case FPSCR_M: |
503 | case FPSCR_N: |
504 | pr_cont("fpscr" ); |
505 | break; |
506 | case FPUL_M: |
507 | case FPUL_N: |
508 | pr_cont("fpul" ); |
509 | break; |
510 | case F_FR0: |
511 | pr_cont("fr0" ); |
512 | break; |
513 | case V_REG_N: |
514 | pr_cont("fv%d" , rn*4); |
515 | break; |
516 | case V_REG_M: |
517 | pr_cont("fv%d" , rm*4); |
518 | break; |
519 | case XMTRX_M4: |
520 | pr_cont("xmtrx" ); |
521 | break; |
522 | default: |
523 | return; |
524 | } |
525 | } |
526 | |
527 | if (disp_pc && strcmp(op->name, "mova" ) != 0) { |
528 | u32 val; |
529 | |
530 | if (relmask == ~1) |
531 | __get_user(val, (u16 *)disp_pc_addr); |
532 | else |
533 | __get_user(val, (u32 *)disp_pc_addr); |
534 | |
535 | pr_cont(" ! %08x <%pS>" , val, (void *)val); |
536 | } |
537 | |
538 | return; |
539 | fail: |
540 | ; |
541 | |
542 | } |
543 | |
544 | pr_info(".word 0x%x%x%x%x" , nibs[0], nibs[1], nibs[2], nibs[3]); |
545 | } |
546 | |
547 | void show_code(struct pt_regs *regs) |
548 | { |
549 | unsigned short *pc = (unsigned short *)regs->pc; |
550 | long i; |
551 | |
552 | if (regs->pc & 0x1) |
553 | return; |
554 | |
555 | pr_info("Code:\n" ); |
556 | |
557 | for (i = -3 ; i < 6 ; i++) { |
558 | unsigned short insn; |
559 | |
560 | if (__get_user(insn, pc + i)) { |
561 | pr_err(" (Bad address in pc)\n" ); |
562 | break; |
563 | } |
564 | |
565 | pr_info("%s%08lx: " , (i ? " " : "->" ), |
566 | (unsigned long)(pc + i)); |
567 | print_sh_insn(memaddr: (unsigned long)(pc + i), insn); |
568 | pr_cont("\n" ); |
569 | } |
570 | |
571 | pr_info("\n" ); |
572 | } |
573 | |