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