mips-dis.c revision 1.12 1 1.1 skrll /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 1.12 christos Copyright (C) 1989-2025 Free Software Foundation, Inc.
3 1.1 skrll Contributed by Nobuyuki Hikichi(hikichi (at) sra.co.jp).
4 1.1 skrll
5 1.1 skrll This file is part of the GNU opcodes library.
6 1.1 skrll
7 1.1 skrll This library is free software; you can redistribute it and/or modify
8 1.1 skrll it under the terms of the GNU General Public License as published by
9 1.1 skrll the Free Software Foundation; either version 3, or (at your option)
10 1.1 skrll any later version.
11 1.1 skrll
12 1.1 skrll It is distributed in the hope that it will be useful, but WITHOUT
13 1.1 skrll ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 skrll or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 1.1 skrll License for more details.
16 1.1 skrll
17 1.1 skrll You should have received a copy of the GNU General Public License
18 1.1 skrll along with this program; if not, write to the Free Software
19 1.1 skrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 1.1 skrll MA 02110-1301, USA. */
21 1.1 skrll
22 1.1 skrll #include "sysdep.h"
23 1.7 christos #include "disassemble.h"
24 1.1 skrll #include "libiberty.h"
25 1.1 skrll #include "opcode/mips.h"
26 1.1 skrll #include "opintl.h"
27 1.9 christos #include "elf-bfd.h"
28 1.9 christos #include "elf/mips.h"
29 1.9 christos #include "elfxx-mips.h"
30 1.1 skrll
31 1.1 skrll /* FIXME: These are needed to figure out if the code is mips16 or
32 1.1 skrll not. The low bit of the address is often a good indicator. No
33 1.1 skrll symbol table is available when this code runs out in an embedded
34 1.1 skrll system as when it is used for disassembler support in a monitor. */
35 1.1 skrll
36 1.1 skrll #if !defined(EMBEDDED_ENV)
37 1.1 skrll #define SYMTAB_AVAILABLE 1
38 1.1 skrll #endif
39 1.1 skrll
40 1.1 skrll /* Mips instructions are at maximum this many bytes long. */
41 1.1 skrll #define INSNLEN 4
42 1.1 skrll
43 1.1 skrll
44 1.1 skrll /* FIXME: These should be shared with gdb somehow. */
46 1.1 skrll
47 1.1 skrll struct mips_cp0sel_name
48 1.1 skrll {
49 1.1 skrll unsigned int cp0reg;
50 1.1 skrll unsigned int sel;
51 1.1 skrll const char * const name;
52 1.1 skrll };
53 1.1 skrll
54 1.1 skrll static const char * const mips_gpr_names_numeric[32] =
55 1.1 skrll {
56 1.1 skrll "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
57 1.1 skrll "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
58 1.1 skrll "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
59 1.1 skrll "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
60 1.1 skrll };
61 1.1 skrll
62 1.1 skrll static const char * const mips_gpr_names_oldabi[32] =
63 1.1 skrll {
64 1.1 skrll "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
65 1.1 skrll "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
66 1.1 skrll "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
67 1.1 skrll "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
68 1.1 skrll };
69 1.1 skrll
70 1.1 skrll static const char * const mips_gpr_names_newabi[32] =
71 1.1 skrll {
72 1.1 skrll "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
73 1.1 skrll "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
74 1.1 skrll "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
75 1.1 skrll "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
76 1.1 skrll };
77 1.1 skrll
78 1.1 skrll static const char * const mips_fpr_names_numeric[32] =
79 1.1 skrll {
80 1.1 skrll "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
81 1.1 skrll "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
82 1.1 skrll "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
83 1.1 skrll "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
84 1.1 skrll };
85 1.1 skrll
86 1.1 skrll static const char * const mips_fpr_names_32[32] =
87 1.1 skrll {
88 1.1 skrll "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
89 1.1 skrll "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
90 1.1 skrll "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f",
91 1.1 skrll "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f"
92 1.1 skrll };
93 1.12 christos
94 1.12 christos static const char * const mips_fpr_names_o64[32] =
95 1.12 christos {
96 1.12 christos "fv0", "fv1", "ft0", "ft1", "ft2", "ft3", "ft4", "ft5",
97 1.12 christos "ft6", "ft7", "ft8", "ft9", "fa0", "fa1", "ft10", "ft11",
98 1.12 christos "ft12", "ft13", "ft14", "ft15", "fs0", "fs1", "fs2", "fs3",
99 1.12 christos "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", "fs10", "fs11",
100 1.12 christos };
101 1.1 skrll
102 1.1 skrll static const char * const mips_fpr_names_n32[32] =
103 1.1 skrll {
104 1.1 skrll "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3",
105 1.1 skrll "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
106 1.1 skrll "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9",
107 1.1 skrll "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13"
108 1.1 skrll };
109 1.1 skrll
110 1.1 skrll static const char * const mips_fpr_names_64[32] =
111 1.1 skrll {
112 1.1 skrll "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
113 1.1 skrll "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
114 1.1 skrll "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
115 1.1 skrll "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
116 1.1 skrll };
117 1.12 christos
118 1.12 christos static const char * const mips_fpr_names_eabi32[32] =
119 1.12 christos {
120 1.12 christos "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
121 1.12 christos "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
122 1.12 christos "fa2", "fa2f", "fa3", "fa3f", "fs0", "fs0f", "fs1", "fs1f",
123 1.12 christos "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f",
124 1.12 christos };
125 1.12 christos
126 1.12 christos static const char * const mips_fpr_names_eabi64[32] =
127 1.12 christos {
128 1.12 christos "fv0", "fv1", "ft0", "ft1", "ft2", "ft3", "ft4", "ft5",
129 1.12 christos "ft6", "ft7", "ft8", "ft9", "fa0", "fa1", "fa2", "fa3",
130 1.12 christos "fa4", "fa5", "fa6", "fa7", "fs0", "fs1", "fs2", "fs3",
131 1.12 christos "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", "fs10", "fs11",
132 1.12 christos };
133 1.1 skrll
134 1.1 skrll static const char * const mips_cp0_names_numeric[32] =
135 1.1 skrll {
136 1.1 skrll "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
137 1.1 skrll "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
138 1.1 skrll "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
139 1.1 skrll "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
140 1.1 skrll };
141 1.5 christos
142 1.5 christos static const char * const mips_cp1_names_numeric[32] =
143 1.5 christos {
144 1.5 christos "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
145 1.5 christos "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
146 1.5 christos "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
147 1.5 christos "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
148 1.5 christos };
149 1.10 christos
150 1.10 christos static const char * const mips_cp0_names_r3900[32] =
151 1.10 christos {
152 1.10 christos "$0", "$1", "$2", "c0_config",
153 1.10 christos "$4", "$5", "$6", "c0_cache",
154 1.10 christos "c0_badvaddr", "$9", "$10", "$11",
155 1.10 christos "c0_sr", "c0_cause", "c0_epc", "c0_prid",
156 1.10 christos "c0_debug", "c0_depc", "$18", "$19",
157 1.10 christos "$20", "$21", "$22", "$23",
158 1.10 christos "$24", "$25", "$26", "$27",
159 1.10 christos "$28", "$29", "$30", "$31",
160 1.10 christos };
161 1.1 skrll
162 1.1 skrll static const char * const mips_cp0_names_r3000[32] =
163 1.1 skrll {
164 1.1 skrll "c0_index", "c0_random", "c0_entrylo", "$3",
165 1.1 skrll "c0_context", "$5", "$6", "$7",
166 1.1 skrll "c0_badvaddr", "$9", "c0_entryhi", "$11",
167 1.1 skrll "c0_sr", "c0_cause", "c0_epc", "c0_prid",
168 1.1 skrll "$16", "$17", "$18", "$19",
169 1.1 skrll "$20", "$21", "$22", "$23",
170 1.1 skrll "$24", "$25", "$26", "$27",
171 1.1 skrll "$28", "$29", "$30", "$31",
172 1.1 skrll };
173 1.1 skrll
174 1.1 skrll static const char * const mips_cp0_names_r4000[32] =
175 1.1 skrll {
176 1.1 skrll "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
177 1.1 skrll "c0_context", "c0_pagemask", "c0_wired", "$7",
178 1.1 skrll "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
179 1.1 skrll "c0_sr", "c0_cause", "c0_epc", "c0_prid",
180 1.1 skrll "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
181 1.1 skrll "c0_xcontext", "$21", "$22", "$23",
182 1.1 skrll "$24", "$25", "c0_ecc", "c0_cacheerr",
183 1.1 skrll "c0_taglo", "c0_taghi", "c0_errorepc", "$31",
184 1.1 skrll };
185 1.5 christos
186 1.5 christos static const char * const mips_cp0_names_r5900[32] =
187 1.5 christos {
188 1.5 christos "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
189 1.5 christos "c0_context", "c0_pagemask", "c0_wired", "$7",
190 1.5 christos "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
191 1.5 christos "c0_sr", "c0_cause", "c0_epc", "c0_prid",
192 1.5 christos "c0_config", "$17", "$18", "$19",
193 1.5 christos "$20", "$21", "$22", "c0_badpaddr",
194 1.5 christos "c0_depc", "c0_perfcnt", "$26", "$27",
195 1.5 christos "c0_taglo", "c0_taghi", "c0_errorepc", "$31"
196 1.5 christos };
197 1.1 skrll
198 1.1 skrll static const char * const mips_cp0_names_mips3264[32] =
199 1.1 skrll {
200 1.1 skrll "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
201 1.1 skrll "c0_context", "c0_pagemask", "c0_wired", "$7",
202 1.1 skrll "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
203 1.1 skrll "c0_status", "c0_cause", "c0_epc", "c0_prid",
204 1.1 skrll "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
205 1.1 skrll "c0_xcontext", "$21", "$22", "c0_debug",
206 1.1 skrll "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
207 1.1 skrll "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
208 1.1 skrll };
209 1.10 christos
210 1.10 christos static const char * const mips_cp1_names_mips[32] =
211 1.10 christos {
212 1.10 christos "c1_fir", "$1", "$2", "$3",
213 1.10 christos "$4", "$5", "$6", "$7",
214 1.10 christos "$8", "$9", "$10", "$11",
215 1.10 christos "$12", "$13", "$14", "$15",
216 1.10 christos "$16", "$17", "$18", "$19",
217 1.10 christos "$20", "$21", "$22", "$23",
218 1.10 christos "$24", "$25", "$26", "$27",
219 1.10 christos "$28", "$29", "$30", "c1_fcsr"
220 1.10 christos };
221 1.5 christos
222 1.5 christos static const char * const mips_cp1_names_mips3264[32] =
223 1.5 christos {
224 1.5 christos "c1_fir", "c1_ufr", "$2", "$3",
225 1.5 christos "c1_unfr", "$5", "$6", "$7",
226 1.5 christos "$8", "$9", "$10", "$11",
227 1.5 christos "$12", "$13", "$14", "$15",
228 1.5 christos "$16", "$17", "$18", "$19",
229 1.5 christos "$20", "$21", "$22", "$23",
230 1.5 christos "$24", "c1_fccr", "c1_fexr", "$27",
231 1.5 christos "c1_fenr", "$29", "$30", "c1_fcsr"
232 1.5 christos };
233 1.1 skrll
234 1.1 skrll static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] =
235 1.1 skrll {
236 1.1 skrll { 16, 1, "c0_config1" },
237 1.1 skrll { 16, 2, "c0_config2" },
238 1.1 skrll { 16, 3, "c0_config3" },
239 1.1 skrll { 18, 1, "c0_watchlo,1" },
240 1.1 skrll { 18, 2, "c0_watchlo,2" },
241 1.1 skrll { 18, 3, "c0_watchlo,3" },
242 1.1 skrll { 18, 4, "c0_watchlo,4" },
243 1.1 skrll { 18, 5, "c0_watchlo,5" },
244 1.1 skrll { 18, 6, "c0_watchlo,6" },
245 1.1 skrll { 18, 7, "c0_watchlo,7" },
246 1.1 skrll { 19, 1, "c0_watchhi,1" },
247 1.1 skrll { 19, 2, "c0_watchhi,2" },
248 1.1 skrll { 19, 3, "c0_watchhi,3" },
249 1.1 skrll { 19, 4, "c0_watchhi,4" },
250 1.1 skrll { 19, 5, "c0_watchhi,5" },
251 1.1 skrll { 19, 6, "c0_watchhi,6" },
252 1.1 skrll { 19, 7, "c0_watchhi,7" },
253 1.1 skrll { 25, 1, "c0_perfcnt,1" },
254 1.1 skrll { 25, 2, "c0_perfcnt,2" },
255 1.1 skrll { 25, 3, "c0_perfcnt,3" },
256 1.1 skrll { 25, 4, "c0_perfcnt,4" },
257 1.1 skrll { 25, 5, "c0_perfcnt,5" },
258 1.1 skrll { 25, 6, "c0_perfcnt,6" },
259 1.1 skrll { 25, 7, "c0_perfcnt,7" },
260 1.1 skrll { 27, 1, "c0_cacheerr,1" },
261 1.1 skrll { 27, 2, "c0_cacheerr,2" },
262 1.1 skrll { 27, 3, "c0_cacheerr,3" },
263 1.1 skrll { 28, 1, "c0_datalo" },
264 1.1 skrll { 29, 1, "c0_datahi" }
265 1.1 skrll };
266 1.1 skrll
267 1.1 skrll static const char * const mips_cp0_names_mips3264r2[32] =
268 1.1 skrll {
269 1.1 skrll "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
270 1.1 skrll "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
271 1.1 skrll "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
272 1.1 skrll "c0_status", "c0_cause", "c0_epc", "c0_prid",
273 1.1 skrll "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
274 1.1 skrll "c0_xcontext", "$21", "$22", "c0_debug",
275 1.1 skrll "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
276 1.1 skrll "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
277 1.1 skrll };
278 1.1 skrll
279 1.1 skrll static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] =
280 1.1 skrll {
281 1.1 skrll { 4, 1, "c0_contextconfig" },
282 1.1 skrll { 0, 1, "c0_mvpcontrol" },
283 1.1 skrll { 0, 2, "c0_mvpconf0" },
284 1.1 skrll { 0, 3, "c0_mvpconf1" },
285 1.1 skrll { 1, 1, "c0_vpecontrol" },
286 1.1 skrll { 1, 2, "c0_vpeconf0" },
287 1.1 skrll { 1, 3, "c0_vpeconf1" },
288 1.1 skrll { 1, 4, "c0_yqmask" },
289 1.1 skrll { 1, 5, "c0_vpeschedule" },
290 1.1 skrll { 1, 6, "c0_vpeschefback" },
291 1.1 skrll { 2, 1, "c0_tcstatus" },
292 1.1 skrll { 2, 2, "c0_tcbind" },
293 1.1 skrll { 2, 3, "c0_tcrestart" },
294 1.1 skrll { 2, 4, "c0_tchalt" },
295 1.1 skrll { 2, 5, "c0_tccontext" },
296 1.1 skrll { 2, 6, "c0_tcschedule" },
297 1.1 skrll { 2, 7, "c0_tcschefback" },
298 1.1 skrll { 5, 1, "c0_pagegrain" },
299 1.1 skrll { 6, 1, "c0_srsconf0" },
300 1.1 skrll { 6, 2, "c0_srsconf1" },
301 1.1 skrll { 6, 3, "c0_srsconf2" },
302 1.1 skrll { 6, 4, "c0_srsconf3" },
303 1.1 skrll { 6, 5, "c0_srsconf4" },
304 1.1 skrll { 12, 1, "c0_intctl" },
305 1.1 skrll { 12, 2, "c0_srsctl" },
306 1.1 skrll { 12, 3, "c0_srsmap" },
307 1.1 skrll { 15, 1, "c0_ebase" },
308 1.1 skrll { 16, 1, "c0_config1" },
309 1.1 skrll { 16, 2, "c0_config2" },
310 1.1 skrll { 16, 3, "c0_config3" },
311 1.1 skrll { 18, 1, "c0_watchlo,1" },
312 1.1 skrll { 18, 2, "c0_watchlo,2" },
313 1.1 skrll { 18, 3, "c0_watchlo,3" },
314 1.1 skrll { 18, 4, "c0_watchlo,4" },
315 1.1 skrll { 18, 5, "c0_watchlo,5" },
316 1.1 skrll { 18, 6, "c0_watchlo,6" },
317 1.1 skrll { 18, 7, "c0_watchlo,7" },
318 1.1 skrll { 19, 1, "c0_watchhi,1" },
319 1.1 skrll { 19, 2, "c0_watchhi,2" },
320 1.1 skrll { 19, 3, "c0_watchhi,3" },
321 1.1 skrll { 19, 4, "c0_watchhi,4" },
322 1.1 skrll { 19, 5, "c0_watchhi,5" },
323 1.1 skrll { 19, 6, "c0_watchhi,6" },
324 1.1 skrll { 19, 7, "c0_watchhi,7" },
325 1.1 skrll { 23, 1, "c0_tracecontrol" },
326 1.1 skrll { 23, 2, "c0_tracecontrol2" },
327 1.1 skrll { 23, 3, "c0_usertracedata" },
328 1.1 skrll { 23, 4, "c0_tracebpc" },
329 1.1 skrll { 25, 1, "c0_perfcnt,1" },
330 1.1 skrll { 25, 2, "c0_perfcnt,2" },
331 1.1 skrll { 25, 3, "c0_perfcnt,3" },
332 1.1 skrll { 25, 4, "c0_perfcnt,4" },
333 1.1 skrll { 25, 5, "c0_perfcnt,5" },
334 1.1 skrll { 25, 6, "c0_perfcnt,6" },
335 1.1 skrll { 25, 7, "c0_perfcnt,7" },
336 1.1 skrll { 27, 1, "c0_cacheerr,1" },
337 1.1 skrll { 27, 2, "c0_cacheerr,2" },
338 1.1 skrll { 27, 3, "c0_cacheerr,3" },
339 1.1 skrll { 28, 1, "c0_datalo" },
340 1.1 skrll { 28, 2, "c0_taglo1" },
341 1.1 skrll { 28, 3, "c0_datalo1" },
342 1.1 skrll { 28, 4, "c0_taglo2" },
343 1.1 skrll { 28, 5, "c0_datalo2" },
344 1.1 skrll { 28, 6, "c0_taglo3" },
345 1.1 skrll { 28, 7, "c0_datalo3" },
346 1.1 skrll { 29, 1, "c0_datahi" },
347 1.1 skrll { 29, 2, "c0_taghi1" },
348 1.1 skrll { 29, 3, "c0_datahi1" },
349 1.1 skrll { 29, 4, "c0_taghi2" },
350 1.1 skrll { 29, 5, "c0_datahi2" },
351 1.1 skrll { 29, 6, "c0_taghi3" },
352 1.1 skrll { 29, 7, "c0_datahi3" },
353 1.1 skrll };
354 1.1 skrll
355 1.1 skrll /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
356 1.1 skrll static const char * const mips_cp0_names_sb1[32] =
357 1.1 skrll {
358 1.1 skrll "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
359 1.1 skrll "c0_context", "c0_pagemask", "c0_wired", "$7",
360 1.1 skrll "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
361 1.1 skrll "c0_status", "c0_cause", "c0_epc", "c0_prid",
362 1.1 skrll "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
363 1.1 skrll "c0_xcontext", "$21", "$22", "c0_debug",
364 1.1 skrll "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
365 1.1 skrll "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
366 1.1 skrll };
367 1.1 skrll
368 1.1 skrll static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] =
369 1.1 skrll {
370 1.1 skrll { 16, 1, "c0_config1" },
371 1.1 skrll { 18, 1, "c0_watchlo,1" },
372 1.1 skrll { 19, 1, "c0_watchhi,1" },
373 1.1 skrll { 22, 0, "c0_perftrace" },
374 1.1 skrll { 23, 3, "c0_edebug" },
375 1.1 skrll { 25, 1, "c0_perfcnt,1" },
376 1.1 skrll { 25, 2, "c0_perfcnt,2" },
377 1.1 skrll { 25, 3, "c0_perfcnt,3" },
378 1.1 skrll { 25, 4, "c0_perfcnt,4" },
379 1.1 skrll { 25, 5, "c0_perfcnt,5" },
380 1.1 skrll { 25, 6, "c0_perfcnt,6" },
381 1.1 skrll { 25, 7, "c0_perfcnt,7" },
382 1.1 skrll { 26, 1, "c0_buserr_pa" },
383 1.1 skrll { 27, 1, "c0_cacheerr_d" },
384 1.1 skrll { 27, 3, "c0_cacheerr_d_pa" },
385 1.1 skrll { 28, 1, "c0_datalo_i" },
386 1.1 skrll { 28, 2, "c0_taglo_d" },
387 1.1 skrll { 28, 3, "c0_datalo_d" },
388 1.1 skrll { 29, 1, "c0_datahi_i" },
389 1.1 skrll { 29, 2, "c0_taghi_d" },
390 1.1 skrll { 29, 3, "c0_datahi_d" },
391 1.1 skrll };
392 1.2 matt
393 1.2 matt /* Xlr cop0 register names. */
394 1.2 matt static const char * const mips_cp0_names_xlr[32] = {
395 1.3 christos "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
396 1.2 matt "c0_context", "c0_pagemask", "c0_wired", "$7",
397 1.2 matt "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
398 1.2 matt "c0_status", "c0_cause", "c0_epc", "c0_prid",
399 1.3 christos "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
400 1.2 matt "c0_xcontext", "$21", "$22", "c0_debug",
401 1.2 matt "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
402 1.2 matt "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
403 1.2 matt };
404 1.2 matt
405 1.2 matt /* XLR's CP0 Select Registers. */
406 1.2 matt
407 1.2 matt static const struct mips_cp0sel_name mips_cp0sel_names_xlr[] = {
408 1.2 matt { 9, 6, "c0_extintreq" },
409 1.2 matt { 9, 7, "c0_extintmask" },
410 1.2 matt { 15, 1, "c0_ebase" },
411 1.2 matt { 16, 1, "c0_config1" },
412 1.2 matt { 16, 2, "c0_config2" },
413 1.2 matt { 16, 3, "c0_config3" },
414 1.2 matt { 16, 7, "c0_procid2" },
415 1.2 matt { 18, 1, "c0_watchlo,1" },
416 1.2 matt { 18, 2, "c0_watchlo,2" },
417 1.2 matt { 18, 3, "c0_watchlo,3" },
418 1.2 matt { 18, 4, "c0_watchlo,4" },
419 1.2 matt { 18, 5, "c0_watchlo,5" },
420 1.2 matt { 18, 6, "c0_watchlo,6" },
421 1.2 matt { 18, 7, "c0_watchlo,7" },
422 1.2 matt { 19, 1, "c0_watchhi,1" },
423 1.2 matt { 19, 2, "c0_watchhi,2" },
424 1.2 matt { 19, 3, "c0_watchhi,3" },
425 1.2 matt { 19, 4, "c0_watchhi,4" },
426 1.2 matt { 19, 5, "c0_watchhi,5" },
427 1.2 matt { 19, 6, "c0_watchhi,6" },
428 1.2 matt { 19, 7, "c0_watchhi,7" },
429 1.2 matt { 25, 1, "c0_perfcnt,1" },
430 1.2 matt { 25, 2, "c0_perfcnt,2" },
431 1.2 matt { 25, 3, "c0_perfcnt,3" },
432 1.2 matt { 25, 4, "c0_perfcnt,4" },
433 1.2 matt { 25, 5, "c0_perfcnt,5" },
434 1.2 matt { 25, 6, "c0_perfcnt,6" },
435 1.2 matt { 25, 7, "c0_perfcnt,7" },
436 1.2 matt { 27, 1, "c0_cacheerr,1" },
437 1.2 matt { 27, 2, "c0_cacheerr,2" },
438 1.2 matt { 27, 3, "c0_cacheerr,3" },
439 1.2 matt { 28, 1, "c0_datalo" },
440 1.2 matt { 29, 1, "c0_datahi" }
441 1.2 matt };
442 1.1 skrll
443 1.1 skrll static const char * const mips_hwr_names_numeric[32] =
444 1.1 skrll {
445 1.1 skrll "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
446 1.1 skrll "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
447 1.1 skrll "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
448 1.1 skrll "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
449 1.1 skrll };
450 1.1 skrll
451 1.1 skrll static const char * const mips_hwr_names_mips3264r2[32] =
452 1.1 skrll {
453 1.1 skrll "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
454 1.1 skrll "$4", "$5", "$6", "$7",
455 1.1 skrll "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
456 1.1 skrll "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
457 1.1 skrll "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
458 1.1 skrll };
459 1.5 christos
460 1.5 christos static const char * const msa_control_names[32] =
461 1.5 christos {
462 1.5 christos "msa_ir", "msa_csr", "msa_access", "msa_save",
463 1.5 christos "msa_modify", "msa_request", "msa_map", "msa_unmap",
464 1.5 christos "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
465 1.5 christos "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
466 1.5 christos "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
467 1.5 christos };
468 1.1 skrll
469 1.1 skrll struct mips_abi_choice
470 1.1 skrll {
471 1.1 skrll const char * name;
472 1.1 skrll const char * const *gpr_names;
473 1.1 skrll const char * const *fpr_names;
474 1.1 skrll };
475 1.1 skrll
476 1.1 skrll struct mips_abi_choice mips_abi_choices[] =
477 1.1 skrll {
478 1.1 skrll { "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric },
479 1.12 christos { "32", mips_gpr_names_oldabi, mips_fpr_names_32 },
480 1.1 skrll { "o64", mips_gpr_names_oldabi, mips_fpr_names_o64 },
481 1.1 skrll { "n32", mips_gpr_names_newabi, mips_fpr_names_n32 },
482 1.12 christos { "64", mips_gpr_names_newabi, mips_fpr_names_64 },
483 1.12 christos { "eabi32", mips_gpr_names_newabi, mips_fpr_names_eabi32 },
484 1.1 skrll { "eabi64", mips_gpr_names_newabi, mips_fpr_names_eabi64 },
485 1.1 skrll };
486 1.1 skrll
487 1.1 skrll struct mips_arch_choice
488 1.1 skrll {
489 1.1 skrll const char *name;
490 1.1 skrll int bfd_mach_valid;
491 1.1 skrll unsigned long bfd_mach;
492 1.1 skrll int processor;
493 1.5 christos int isa;
494 1.1 skrll int ase;
495 1.1 skrll const char * const *cp0_names;
496 1.1 skrll const struct mips_cp0sel_name *cp0sel_names;
497 1.5 christos unsigned int cp0sel_names_len;
498 1.1 skrll const char * const *cp1_names;
499 1.1 skrll const char * const *hwr_names;
500 1.1 skrll };
501 1.1 skrll
502 1.1 skrll const struct mips_arch_choice mips_arch_choices[] =
503 1.5 christos {
504 1.5 christos { "numeric", 0, 0, 0, 0, 0,
505 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
506 1.1 skrll mips_hwr_names_numeric },
507 1.5 christos
508 1.10 christos { "r3000", 1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1, 0,
509 1.5 christos mips_cp0_names_r3000, NULL, 0, mips_cp1_names_mips,
510 1.5 christos mips_hwr_names_numeric },
511 1.10 christos { "r3900", 1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1, 0,
512 1.5 christos mips_cp0_names_r3900, NULL, 0, mips_cp1_names_numeric,
513 1.5 christos mips_hwr_names_numeric },
514 1.10 christos { "r4000", 1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3, 0,
515 1.5 christos mips_cp0_names_r4000, NULL, 0, mips_cp1_names_mips,
516 1.5 christos mips_hwr_names_numeric },
517 1.10 christos { "r4010", 1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2, 0,
518 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
519 1.11 christos mips_hwr_names_numeric },
520 1.11 christos { "allegrex", 1, bfd_mach_mips_allegrex, CPU_ALLEGREX, ISA_MIPS2, 0,
521 1.11 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
522 1.5 christos mips_hwr_names_numeric },
523 1.10 christos { "vr4100", 1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3, 0,
524 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
525 1.5 christos mips_hwr_names_numeric },
526 1.10 christos { "vr4111", 1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3, 0,
527 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
528 1.5 christos mips_hwr_names_numeric },
529 1.10 christos { "vr4120", 1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3, 0,
530 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
531 1.5 christos mips_hwr_names_numeric },
532 1.10 christos { "r4300", 1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3, 0,
533 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
534 1.5 christos mips_hwr_names_numeric },
535 1.10 christos { "r4400", 1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3, 0,
536 1.5 christos mips_cp0_names_r4000, NULL, 0, mips_cp1_names_mips,
537 1.5 christos mips_hwr_names_numeric },
538 1.10 christos { "r4600", 1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3, 0,
539 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
540 1.5 christos mips_hwr_names_numeric },
541 1.10 christos { "r4650", 1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3, 0,
542 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
543 1.5 christos mips_hwr_names_numeric },
544 1.10 christos { "r5000", 1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4, 0,
545 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
546 1.5 christos mips_hwr_names_numeric },
547 1.10 christos { "vr5400", 1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4, 0,
548 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
549 1.5 christos mips_hwr_names_numeric },
550 1.10 christos { "vr5500", 1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4, 0,
551 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
552 1.5 christos mips_hwr_names_numeric },
553 1.10 christos { "r5900", 1, bfd_mach_mips5900, CPU_R5900, ISA_MIPS3, 0,
554 1.5 christos mips_cp0_names_r5900, NULL, 0, mips_cp1_names_mips,
555 1.5 christos mips_hwr_names_numeric },
556 1.10 christos { "r6000", 1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2, 0,
557 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
558 1.5 christos mips_hwr_names_numeric },
559 1.10 christos { "rm7000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
560 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
561 1.5 christos mips_hwr_names_numeric },
562 1.10 christos { "rm9000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
563 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
564 1.5 christos mips_hwr_names_numeric },
565 1.10 christos { "r8000", 1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4, 0,
566 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
567 1.5 christos mips_hwr_names_numeric },
568 1.10 christos { "r10000", 1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4, 0,
569 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
570 1.5 christos mips_hwr_names_numeric },
571 1.10 christos { "r12000", 1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4, 0,
572 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
573 1.5 christos mips_hwr_names_numeric },
574 1.10 christos { "r14000", 1, bfd_mach_mips14000, CPU_R14000, ISA_MIPS4, 0,
575 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
576 1.5 christos mips_hwr_names_numeric },
577 1.10 christos { "r16000", 1, bfd_mach_mips16000, CPU_R16000, ISA_MIPS4, 0,
578 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
579 1.5 christos mips_hwr_names_numeric },
580 1.10 christos { "mips5", 1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5, 0,
581 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
582 1.1 skrll mips_hwr_names_numeric },
583 1.1 skrll
584 1.1 skrll /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
585 1.1 skrll Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
586 1.1 skrll _MIPS32 Architecture For Programmers Volume I: Introduction to the
587 1.1 skrll MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
588 1.1 skrll page 1. */
589 1.5 christos { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32,
590 1.1 skrll ISA_MIPS32, ASE_SMARTMIPS,
591 1.1 skrll mips_cp0_names_mips3264,
592 1.5 christos mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
593 1.1 skrll mips_cp1_names_mips3264, mips_hwr_names_numeric },
594 1.1 skrll
595 1.5 christos { "mips32r2", 1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
596 1.5 christos ISA_MIPS32R2,
597 1.5 christos (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
598 1.5 christos | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
599 1.5 christos mips_cp0_names_mips3264r2,
600 1.5 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
601 1.5 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
602 1.5 christos
603 1.5 christos { "mips32r3", 1, bfd_mach_mipsisa32r3, CPU_MIPS32R3,
604 1.5 christos ISA_MIPS32R3,
605 1.5 christos (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
606 1.5 christos | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
607 1.5 christos mips_cp0_names_mips3264r2,
608 1.5 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
609 1.5 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
610 1.5 christos
611 1.5 christos { "mips32r5", 1, bfd_mach_mipsisa32r5, CPU_MIPS32R5,
612 1.5 christos ISA_MIPS32R5,
613 1.5 christos (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
614 1.5 christos | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
615 1.5 christos mips_cp0_names_mips3264r2,
616 1.5 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
617 1.5 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
618 1.5 christos
619 1.5 christos { "mips32r6", 1, bfd_mach_mipsisa32r6, CPU_MIPS32R6,
620 1.5 christos ISA_MIPS32R6,
621 1.8 christos (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_XPA | ASE_MCU | ASE_MT | ASE_DSP
622 1.1 skrll | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC | ASE_GINV),
623 1.1 skrll mips_cp0_names_mips3264r2,
624 1.5 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
625 1.1 skrll mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
626 1.1 skrll
627 1.1 skrll /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
628 1.5 christos { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64,
629 1.1 skrll ISA_MIPS64, ASE_MIPS3D | ASE_MDMX,
630 1.1 skrll mips_cp0_names_mips3264,
631 1.5 christos mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
632 1.1 skrll mips_cp1_names_mips3264, mips_hwr_names_numeric },
633 1.1 skrll
634 1.5 christos { "mips64r2", 1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
635 1.5 christos ISA_MIPS64R2,
636 1.5 christos (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
637 1.5 christos | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
638 1.5 christos mips_cp0_names_mips3264r2,
639 1.5 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
640 1.5 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
641 1.5 christos
642 1.5 christos { "mips64r3", 1, bfd_mach_mipsisa64r3, CPU_MIPS64R3,
643 1.5 christos ISA_MIPS64R3,
644 1.5 christos (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
645 1.5 christos | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
646 1.5 christos mips_cp0_names_mips3264r2,
647 1.5 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
648 1.5 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
649 1.5 christos
650 1.5 christos { "mips64r5", 1, bfd_mach_mipsisa64r5, CPU_MIPS64R5,
651 1.5 christos ISA_MIPS64R5,
652 1.5 christos (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
653 1.5 christos | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
654 1.5 christos mips_cp0_names_mips3264r2,
655 1.5 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
656 1.5 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
657 1.5 christos
658 1.5 christos { "mips64r6", 1, bfd_mach_mipsisa64r6, CPU_MIPS64R6,
659 1.5 christos ISA_MIPS64R6,
660 1.8 christos (ASE_EVA | ASE_MSA | ASE_MSA64 | ASE_XPA | ASE_VIRT | ASE_VIRT64
661 1.8 christos | ASE_MCU | ASE_MT | ASE_DSP | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC
662 1.1 skrll | ASE_CRC64 | ASE_GINV),
663 1.1 skrll mips_cp0_names_mips3264r2,
664 1.5 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
665 1.1 skrll mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
666 1.7 christos
667 1.7 christos { "interaptiv-mr2", 1, bfd_mach_mips_interaptiv_mr2, CPU_INTERAPTIV_MR2,
668 1.7 christos ISA_MIPS32R3,
669 1.7 christos ASE_MT | ASE_EVA | ASE_DSP | ASE_DSPR2 | ASE_MIPS16E2 | ASE_MIPS16E2_MT,
670 1.7 christos mips_cp0_names_mips3264r2,
671 1.7 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
672 1.7 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
673 1.1 skrll
674 1.5 christos { "sb1", 1, bfd_mach_mips_sb1, CPU_SB1,
675 1.1 skrll ISA_MIPS64 | INSN_SB1, ASE_MIPS3D,
676 1.1 skrll mips_cp0_names_sb1,
677 1.5 christos mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
678 1.1 skrll mips_cp1_names_mips3264, mips_hwr_names_numeric },
679 1.1 skrll
680 1.5 christos { "loongson2e", 1, bfd_mach_mips_loongson_2e, CPU_LOONGSON_2E,
681 1.10 christos ISA_MIPS3 | INSN_LOONGSON_2E, 0, mips_cp0_names_numeric,
682 1.1 skrll NULL, 0, mips_cp1_names_mips, mips_hwr_names_numeric },
683 1.1 skrll
684 1.9 christos { "loongson2f", 1, bfd_mach_mips_loongson_2f, CPU_LOONGSON_2F,
685 1.10 christos ISA_MIPS3 | INSN_LOONGSON_2F, ASE_LOONGSON_MMI, mips_cp0_names_numeric,
686 1.1 skrll NULL, 0, mips_cp1_names_mips, mips_hwr_names_numeric },
687 1.9 christos
688 1.9 christos /* The loongson3a is an alias of gs464 for compatibility */
689 1.9 christos { "loongson3a", 1, bfd_mach_mips_gs464, CPU_GS464,
690 1.9 christos ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
691 1.9 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
692 1.9 christos mips_hwr_names_numeric },
693 1.9 christos
694 1.9 christos { "gs464", 1, bfd_mach_mips_gs464, CPU_GS464,
695 1.9 christos ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
696 1.9 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
697 1.9 christos mips_hwr_names_numeric },
698 1.9 christos
699 1.9 christos { "gs464e", 1, bfd_mach_mips_gs464e, CPU_GS464E,
700 1.9 christos ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
701 1.9 christos | ASE_LOONGSON_EXT2, mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
702 1.9 christos mips_hwr_names_numeric },
703 1.10 christos
704 1.9 christos { "gs264e", 1, bfd_mach_mips_gs264e, CPU_GS264E,
705 1.9 christos ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
706 1.9 christos | ASE_LOONGSON_EXT2 | ASE_MSA | ASE_MSA64, mips_cp0_names_numeric, NULL,
707 1.4 christos 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
708 1.1 skrll
709 1.5 christos { "octeon", 1, bfd_mach_mips_octeon, CPU_OCTEON,
710 1.5 christos ISA_MIPS64R2 | INSN_OCTEON, 0, mips_cp0_names_numeric, NULL, 0,
711 1.1 skrll mips_cp1_names_mips3264, mips_hwr_names_numeric },
712 1.4 christos
713 1.5 christos { "octeon+", 1, bfd_mach_mips_octeonp, CPU_OCTEONP,
714 1.5 christos ISA_MIPS64R2 | INSN_OCTEONP, 0, mips_cp0_names_numeric,
715 1.4 christos NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
716 1.4 christos
717 1.5 christos { "octeon2", 1, bfd_mach_mips_octeon2, CPU_OCTEON2,
718 1.5 christos ISA_MIPS64R2 | INSN_OCTEON2, 0, mips_cp0_names_numeric,
719 1.5 christos NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
720 1.5 christos
721 1.5 christos { "octeon3", 1, bfd_mach_mips_octeon3, CPU_OCTEON3,
722 1.5 christos ISA_MIPS64R5 | INSN_OCTEON3, ASE_VIRT | ASE_VIRT64,
723 1.5 christos mips_cp0_names_numeric,
724 1.4 christos NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
725 1.2 matt
726 1.5 christos { "xlr", 1, bfd_mach_mips_xlr, CPU_XLR,
727 1.2 matt ISA_MIPS64 | INSN_XLR, 0,
728 1.2 matt mips_cp0_names_xlr,
729 1.5 christos mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
730 1.2 matt mips_cp1_names_mips3264, mips_hwr_names_numeric },
731 1.4 christos
732 1.4 christos /* XLP is mostly like XLR, with the prominent exception it is being
733 1.4 christos MIPS64R2. */
734 1.5 christos { "xlp", 1, bfd_mach_mips_xlr, CPU_XLR,
735 1.4 christos ISA_MIPS64R2 | INSN_XLR, 0,
736 1.4 christos mips_cp0_names_xlr,
737 1.5 christos mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
738 1.4 christos mips_cp1_names_mips3264, mips_hwr_names_numeric },
739 1.1 skrll
740 1.1 skrll /* This entry, mips16, is here only for ISA/processor selection; do
741 1.7 christos not print its name. */
742 1.7 christos { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS64,
743 1.5 christos ASE_MIPS16E2 | ASE_MIPS16E2_MT,
744 1.5 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
745 1.1 skrll mips_hwr_names_numeric },
746 1.1 skrll };
747 1.1 skrll
748 1.1 skrll /* ISA and processor type to disassemble for, and register names to use.
749 1.1 skrll set_default_mips_dis_options and parse_mips_dis_options fill in these
750 1.1 skrll values. */
751 1.1 skrll static int mips_processor;
752 1.5 christos static int mips_isa;
753 1.4 christos static int mips_ase;
754 1.1 skrll static int micromips_ase;
755 1.1 skrll static const char * const *mips_gpr_names;
756 1.1 skrll static const char * const *mips_fpr_names;
757 1.1 skrll static const char * const *mips_cp0_names;
758 1.1 skrll static const struct mips_cp0sel_name *mips_cp0sel_names;
759 1.5 christos static int mips_cp0sel_names_len;
760 1.1 skrll static const char * const *mips_cp1_names;
761 1.1 skrll static const char * const *mips_hwr_names;
762 1.1 skrll
763 1.1 skrll /* Other options */
764 1.1 skrll static int no_aliases; /* If set disassemble as most general inst. */
765 1.1 skrll
766 1.1 skrll static const struct mips_abi_choice *
768 1.1 skrll choose_abi_by_name (const char *name, unsigned int namelen)
769 1.1 skrll {
770 1.1 skrll const struct mips_abi_choice *c;
771 1.1 skrll unsigned int i;
772 1.1 skrll
773 1.1 skrll for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++)
774 1.1 skrll if (strncmp (mips_abi_choices[i].name, name, namelen) == 0
775 1.1 skrll && strlen (mips_abi_choices[i].name) == namelen)
776 1.1 skrll c = &mips_abi_choices[i];
777 1.1 skrll
778 1.1 skrll return c;
779 1.1 skrll }
780 1.1 skrll
781 1.1 skrll static const struct mips_arch_choice *
782 1.1 skrll choose_arch_by_name (const char *name, unsigned int namelen)
783 1.1 skrll {
784 1.1 skrll const struct mips_arch_choice *c = NULL;
785 1.1 skrll unsigned int i;
786 1.1 skrll
787 1.1 skrll for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
788 1.1 skrll if (strncmp (mips_arch_choices[i].name, name, namelen) == 0
789 1.1 skrll && strlen (mips_arch_choices[i].name) == namelen)
790 1.1 skrll c = &mips_arch_choices[i];
791 1.1 skrll
792 1.1 skrll return c;
793 1.1 skrll }
794 1.1 skrll
795 1.1 skrll static const struct mips_arch_choice *
796 1.1 skrll choose_arch_by_number (unsigned long mach)
797 1.1 skrll {
798 1.1 skrll static unsigned long hint_bfd_mach;
799 1.1 skrll static const struct mips_arch_choice *hint_arch_choice;
800 1.1 skrll const struct mips_arch_choice *c;
801 1.1 skrll unsigned int i;
802 1.1 skrll
803 1.1 skrll /* We optimize this because even if the user specifies no
804 1.1 skrll flags, this will be done for every instruction! */
805 1.1 skrll if (hint_bfd_mach == mach
806 1.1 skrll && hint_arch_choice != NULL
807 1.1 skrll && hint_arch_choice->bfd_mach == hint_bfd_mach)
808 1.1 skrll return hint_arch_choice;
809 1.1 skrll
810 1.1 skrll for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
811 1.1 skrll {
812 1.1 skrll if (mips_arch_choices[i].bfd_mach_valid
813 1.1 skrll && mips_arch_choices[i].bfd_mach == mach)
814 1.1 skrll {
815 1.1 skrll c = &mips_arch_choices[i];
816 1.1 skrll hint_bfd_mach = mach;
817 1.1 skrll hint_arch_choice = c;
818 1.1 skrll }
819 1.1 skrll }
820 1.1 skrll return c;
821 1.1 skrll }
822 1.1 skrll
823 1.1 skrll /* Check if the object uses NewABI conventions. */
824 1.1 skrll
825 1.1 skrll static int
826 1.1 skrll is_newabi (Elf_Internal_Ehdr *header)
827 1.1 skrll {
828 1.1 skrll /* There are no old-style ABIs which use 64-bit ELF. */
829 1.1 skrll if (header->e_ident[EI_CLASS] == ELFCLASS64)
830 1.1 skrll return 1;
831 1.1 skrll
832 1.1 skrll /* If a 32-bit ELF file, n32 is a new-style ABI. */
833 1.1 skrll if ((header->e_flags & EF_MIPS_ABI2) != 0)
834 1.1 skrll return 1;
835 1.1 skrll
836 1.1 skrll return 0;
837 1.4 christos }
838 1.4 christos
839 1.4 christos /* Check if the object has microMIPS ASE code. */
840 1.4 christos
841 1.4 christos static int
842 1.4 christos is_micromips (Elf_Internal_Ehdr *header)
843 1.4 christos {
844 1.4 christos if ((header->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0)
845 1.4 christos return 1;
846 1.4 christos
847 1.4 christos return 0;
848 1.7 christos }
849 1.7 christos
850 1.7 christos /* Convert ASE flags from .MIPS.abiflags to internal values. */
851 1.7 christos
852 1.7 christos static unsigned long
853 1.7 christos mips_convert_abiflags_ases (unsigned long afl_ases)
854 1.7 christos {
855 1.7 christos unsigned long opcode_ases = 0;
856 1.7 christos
857 1.7 christos if (afl_ases & AFL_ASE_DSP)
858 1.7 christos opcode_ases |= ASE_DSP;
859 1.7 christos if (afl_ases & AFL_ASE_DSPR2)
860 1.7 christos opcode_ases |= ASE_DSPR2;
861 1.7 christos if (afl_ases & AFL_ASE_EVA)
862 1.7 christos opcode_ases |= ASE_EVA;
863 1.7 christos if (afl_ases & AFL_ASE_MCU)
864 1.7 christos opcode_ases |= ASE_MCU;
865 1.7 christos if (afl_ases & AFL_ASE_MDMX)
866 1.7 christos opcode_ases |= ASE_MDMX;
867 1.7 christos if (afl_ases & AFL_ASE_MIPS3D)
868 1.7 christos opcode_ases |= ASE_MIPS3D;
869 1.7 christos if (afl_ases & AFL_ASE_MT)
870 1.7 christos opcode_ases |= ASE_MT;
871 1.7 christos if (afl_ases & AFL_ASE_SMARTMIPS)
872 1.7 christos opcode_ases |= ASE_SMARTMIPS;
873 1.7 christos if (afl_ases & AFL_ASE_VIRT)
874 1.7 christos opcode_ases |= ASE_VIRT;
875 1.7 christos if (afl_ases & AFL_ASE_MSA)
876 1.7 christos opcode_ases |= ASE_MSA;
877 1.7 christos if (afl_ases & AFL_ASE_XPA)
878 1.7 christos opcode_ases |= ASE_XPA;
879 1.7 christos if (afl_ases & AFL_ASE_DSPR3)
880 1.7 christos opcode_ases |= ASE_DSPR3;
881 1.7 christos if (afl_ases & AFL_ASE_MIPS16E2)
882 1.7 christos opcode_ases |= ASE_MIPS16E2;
883 1.7 christos return opcode_ases;
884 1.7 christos }
885 1.7 christos
886 1.7 christos /* Calculate combination ASE flags from regular ASE flags. */
887 1.9 christos
888 1.7 christos static unsigned long
889 1.7 christos mips_calculate_combination_ases (int opcode_isa, unsigned long opcode_ases)
890 1.7 christos {
891 1.7 christos unsigned long combination_ases = 0;
892 1.7 christos
893 1.7 christos if ((opcode_ases & (ASE_XPA | ASE_VIRT)) == (ASE_XPA | ASE_VIRT))
894 1.7 christos combination_ases |= ASE_XPA_VIRT;
895 1.9 christos if ((opcode_ases & (ASE_MIPS16E2 | ASE_MT)) == (ASE_MIPS16E2 | ASE_MT))
896 1.9 christos combination_ases |= ASE_MIPS16E2_MT;
897 1.9 christos if ((opcode_ases & ASE_EVA)
898 1.9 christos && ((opcode_isa & INSN_ISA_MASK) == ISA_MIPS64R6
899 1.7 christos || (opcode_isa & INSN_ISA_MASK) == ISA_MIPS32R6))
900 1.7 christos combination_ases |= ASE_EVA_R6;
901 1.7 christos return combination_ases;
902 1.1 skrll }
903 1.1 skrll
904 1.1 skrll static void
905 1.1 skrll set_default_mips_dis_options (struct disassemble_info *info)
906 1.1 skrll {
907 1.4 christos const struct mips_arch_choice *chosen_arch;
908 1.4 christos
909 1.4 christos /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
910 1.1 skrll is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
911 1.4 christos CP0 register, and HWR names. */
912 1.4 christos mips_isa = ISA_MIPS3;
913 1.5 christos mips_processor = CPU_R3000;
914 1.1 skrll micromips_ase = 0;
915 1.1 skrll mips_ase = 0;
916 1.1 skrll mips_gpr_names = mips_gpr_names_oldabi;
917 1.1 skrll mips_fpr_names = mips_fpr_names_numeric;
918 1.1 skrll mips_cp0_names = mips_cp0_names_numeric;
919 1.5 christos mips_cp0sel_names = NULL;
920 1.1 skrll mips_cp0sel_names_len = 0;
921 1.1 skrll mips_cp1_names = mips_cp1_names_numeric;
922 1.1 skrll mips_hwr_names = mips_hwr_names_numeric;
923 1.1 skrll no_aliases = 0;
924 1.1 skrll
925 1.1 skrll /* Set ISA, architecture, and cp0 register names as best we can. */
926 1.1 skrll #if ! SYMTAB_AVAILABLE
927 1.1 skrll /* This is running out on a target machine, not in a host tool.
928 1.1 skrll FIXME: Where does mips_target_info come from? */
929 1.5 christos target_processor = mips_target_info.processor;
930 1.1 skrll mips_isa = mips_target_info.isa;
931 1.1 skrll mips_ase = mips_target_info.ase;
932 1.1 skrll #else
933 1.1 skrll chosen_arch = choose_arch_by_number (info->mach);
934 1.1 skrll if (chosen_arch != NULL)
935 1.1 skrll {
936 1.5 christos mips_processor = chosen_arch->processor;
937 1.1 skrll mips_isa = chosen_arch->isa;
938 1.1 skrll mips_ase = chosen_arch->ase;
939 1.1 skrll mips_cp0_names = chosen_arch->cp0_names;
940 1.5 christos mips_cp0sel_names = chosen_arch->cp0sel_names;
941 1.1 skrll mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
942 1.1 skrll mips_cp1_names = chosen_arch->cp1_names;
943 1.7 christos mips_hwr_names = chosen_arch->hwr_names;
944 1.7 christos }
945 1.7 christos
946 1.7 christos /* Update settings according to the ELF file header flags. */
947 1.7 christos if (info->flavour == bfd_target_elf_flavour && info->section != NULL)
948 1.7 christos {
949 1.7 christos struct bfd *abfd = info->section->owner;
950 1.7 christos Elf_Internal_Ehdr *header = elf_elfheader (abfd);
951 1.7 christos Elf_Internal_ABIFlags_v0 *abiflags = NULL;
952 1.7 christos
953 1.7 christos /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
954 1.7 christos because we won't then have a MIPS/ELF BFD, however we need
955 1.7 christos to guard against a link error in a `--enable-targets=...'
956 1.7 christos configuration with a 32-bit host where the MIPS target is
957 1.7 christos a secondary, or with MIPS/ECOFF configurations. */
958 1.1 skrll #ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
959 1.7 christos abiflags = bfd_mips_elf_get_abiflags (abfd);
960 1.7 christos #endif
961 1.7 christos /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
962 1.7 christos if (is_newabi (header))
963 1.7 christos mips_gpr_names = mips_gpr_names_newabi;
964 1.7 christos /* If a microMIPS binary, then don't use MIPS16 bindings. */
965 1.7 christos micromips_ase = is_micromips (header);
966 1.7 christos /* OR in any extra ASE flags set in ELF file structures. */
967 1.7 christos if (abiflags)
968 1.7 christos mips_ase |= mips_convert_abiflags_ases (abiflags->ases);
969 1.7 christos else if (header->e_flags & EF_MIPS_ARCH_ASE_MDMX)
970 1.7 christos mips_ase |= ASE_MDMX;
971 1.9 christos }
972 1.1 skrll #endif
973 1.1 skrll mips_ase |= mips_calculate_combination_ases (mips_isa, mips_ase);
974 1.7 christos }
975 1.7 christos
976 1.7 christos /* Parse an ASE disassembler option and set the corresponding global
977 1.10 christos ASE flag(s). Return TRUE if successful, FALSE otherwise. */
978 1.7 christos
979 1.1 skrll static bool
980 1.10 christos parse_mips_ase_option (const char *option)
981 1.5 christos {
982 1.5 christos if (startswith (option, "msa"))
983 1.5 christos {
984 1.5 christos mips_ase |= ASE_MSA;
985 1.5 christos if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R2
986 1.5 christos || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R3
987 1.5 christos || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R5
988 1.10 christos || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6)
989 1.5 christos mips_ase |= ASE_MSA64;
990 1.5 christos return true;
991 1.10 christos }
992 1.5 christos
993 1.5 christos if (startswith (option, "virt"))
994 1.5 christos {
995 1.5 christos mips_ase |= ASE_VIRT;
996 1.5 christos if (mips_isa & ISA_MIPS64R2
997 1.5 christos || mips_isa & ISA_MIPS64R3
998 1.5 christos || mips_isa & ISA_MIPS64R5
999 1.10 christos || mips_isa & ISA_MIPS64R6)
1000 1.5 christos mips_ase |= ASE_VIRT64;
1001 1.5 christos return true;
1002 1.10 christos }
1003 1.5 christos
1004 1.5 christos if (startswith (option, "xpa"))
1005 1.10 christos {
1006 1.7 christos mips_ase |= ASE_XPA;
1007 1.7 christos return true;
1008 1.10 christos }
1009 1.8 christos
1010 1.8 christos if (startswith (option, "ginv"))
1011 1.10 christos {
1012 1.8 christos mips_ase |= ASE_GINV;
1013 1.8 christos return true;
1014 1.10 christos }
1015 1.9 christos
1016 1.9 christos if (startswith (option, "loongson-mmi"))
1017 1.10 christos {
1018 1.9 christos mips_ase |= ASE_LOONGSON_MMI;
1019 1.9 christos return true;
1020 1.10 christos }
1021 1.9 christos
1022 1.9 christos if (startswith (option, "loongson-cam"))
1023 1.10 christos {
1024 1.9 christos mips_ase |= ASE_LOONGSON_CAM;
1025 1.9 christos return true;
1026 1.9 christos }
1027 1.10 christos
1028 1.9 christos /* Put here for match ext2 frist */
1029 1.9 christos if (startswith (option, "loongson-ext2"))
1030 1.10 christos {
1031 1.9 christos mips_ase |= ASE_LOONGSON_EXT2;
1032 1.9 christos return true;
1033 1.10 christos }
1034 1.9 christos
1035 1.9 christos if (startswith (option, "loongson-ext"))
1036 1.10 christos {
1037 1.9 christos mips_ase |= ASE_LOONGSON_EXT;
1038 1.9 christos return true;
1039 1.10 christos }
1040 1.7 christos
1041 1.7 christos return false;
1042 1.7 christos }
1043 1.7 christos
1044 1.7 christos static void
1045 1.7 christos parse_mips_dis_option (const char *option, unsigned int len)
1046 1.7 christos {
1047 1.7 christos unsigned int i, optionlen, vallen;
1048 1.7 christos const char *val;
1049 1.7 christos const struct mips_abi_choice *chosen_abi;
1050 1.7 christos const struct mips_arch_choice *chosen_arch;
1051 1.10 christos
1052 1.7 christos /* Try to match options that are simple flags */
1053 1.7 christos if (startswith (option, "no-aliases"))
1054 1.5 christos {
1055 1.5 christos no_aliases = 1;
1056 1.5 christos return;
1057 1.7 christos }
1058 1.7 christos
1059 1.9 christos if (parse_mips_ase_option (option))
1060 1.7 christos {
1061 1.7 christos mips_ase |= mips_calculate_combination_ases (mips_isa, mips_ase);
1062 1.5 christos return;
1063 1.1 skrll }
1064 1.1 skrll
1065 1.1 skrll /* Look for the = that delimits the end of the option name. */
1066 1.1 skrll for (i = 0; i < len; i++)
1067 1.1 skrll if (option[i] == '=')
1068 1.1 skrll break;
1069 1.1 skrll
1070 1.1 skrll if (i == 0) /* Invalid option: no name before '='. */
1071 1.1 skrll return;
1072 1.1 skrll if (i == len) /* Invalid option: no '='. */
1073 1.1 skrll return;
1074 1.1 skrll if (i == (len - 1)) /* Invalid option: no value after '='. */
1075 1.1 skrll return;
1076 1.1 skrll
1077 1.1 skrll optionlen = i;
1078 1.1 skrll val = option + (optionlen + 1);
1079 1.1 skrll vallen = len - (optionlen + 1);
1080 1.1 skrll
1081 1.1 skrll if (strncmp ("gpr-names", option, optionlen) == 0
1082 1.1 skrll && strlen ("gpr-names") == optionlen)
1083 1.1 skrll {
1084 1.1 skrll chosen_abi = choose_abi_by_name (val, vallen);
1085 1.1 skrll if (chosen_abi != NULL)
1086 1.1 skrll mips_gpr_names = chosen_abi->gpr_names;
1087 1.1 skrll return;
1088 1.1 skrll }
1089 1.1 skrll
1090 1.1 skrll if (strncmp ("fpr-names", option, optionlen) == 0
1091 1.1 skrll && strlen ("fpr-names") == optionlen)
1092 1.1 skrll {
1093 1.1 skrll chosen_abi = choose_abi_by_name (val, vallen);
1094 1.1 skrll if (chosen_abi != NULL)
1095 1.1 skrll mips_fpr_names = chosen_abi->fpr_names;
1096 1.1 skrll return;
1097 1.1 skrll }
1098 1.1 skrll
1099 1.1 skrll if (strncmp ("cp0-names", option, optionlen) == 0
1100 1.1 skrll && strlen ("cp0-names") == optionlen)
1101 1.1 skrll {
1102 1.1 skrll chosen_arch = choose_arch_by_name (val, vallen);
1103 1.1 skrll if (chosen_arch != NULL)
1104 1.1 skrll {
1105 1.1 skrll mips_cp0_names = chosen_arch->cp0_names;
1106 1.1 skrll mips_cp0sel_names = chosen_arch->cp0sel_names;
1107 1.1 skrll mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
1108 1.1 skrll }
1109 1.1 skrll return;
1110 1.5 christos }
1111 1.5 christos
1112 1.5 christos if (strncmp ("cp1-names", option, optionlen) == 0
1113 1.5 christos && strlen ("cp1-names") == optionlen)
1114 1.5 christos {
1115 1.5 christos chosen_arch = choose_arch_by_name (val, vallen);
1116 1.5 christos if (chosen_arch != NULL)
1117 1.5 christos mips_cp1_names = chosen_arch->cp1_names;
1118 1.5 christos return;
1119 1.1 skrll }
1120 1.1 skrll
1121 1.1 skrll if (strncmp ("hwr-names", option, optionlen) == 0
1122 1.1 skrll && strlen ("hwr-names") == optionlen)
1123 1.1 skrll {
1124 1.1 skrll chosen_arch = choose_arch_by_name (val, vallen);
1125 1.1 skrll if (chosen_arch != NULL)
1126 1.1 skrll mips_hwr_names = chosen_arch->hwr_names;
1127 1.1 skrll return;
1128 1.1 skrll }
1129 1.1 skrll
1130 1.1 skrll if (strncmp ("reg-names", option, optionlen) == 0
1131 1.1 skrll && strlen ("reg-names") == optionlen)
1132 1.1 skrll {
1133 1.1 skrll /* We check both ABI and ARCH here unconditionally, so
1134 1.1 skrll that "numeric" will do the desirable thing: select
1135 1.1 skrll numeric register names for all registers. Other than
1136 1.1 skrll that, a given name probably won't match both. */
1137 1.1 skrll chosen_abi = choose_abi_by_name (val, vallen);
1138 1.1 skrll if (chosen_abi != NULL)
1139 1.1 skrll {
1140 1.1 skrll mips_gpr_names = chosen_abi->gpr_names;
1141 1.1 skrll mips_fpr_names = chosen_abi->fpr_names;
1142 1.1 skrll }
1143 1.1 skrll chosen_arch = choose_arch_by_name (val, vallen);
1144 1.1 skrll if (chosen_arch != NULL)
1145 1.1 skrll {
1146 1.1 skrll mips_cp0_names = chosen_arch->cp0_names;
1147 1.5 christos mips_cp0sel_names = chosen_arch->cp0sel_names;
1148 1.1 skrll mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
1149 1.1 skrll mips_cp1_names = chosen_arch->cp1_names;
1150 1.1 skrll mips_hwr_names = chosen_arch->hwr_names;
1151 1.1 skrll }
1152 1.1 skrll return;
1153 1.1 skrll }
1154 1.1 skrll
1155 1.1 skrll /* Invalid option. */
1156 1.1 skrll }
1157 1.1 skrll
1158 1.1 skrll static void
1159 1.1 skrll parse_mips_dis_options (const char *options)
1160 1.1 skrll {
1161 1.1 skrll const char *option_end;
1162 1.1 skrll
1163 1.1 skrll if (options == NULL)
1164 1.1 skrll return;
1165 1.1 skrll
1166 1.1 skrll while (*options != '\0')
1167 1.1 skrll {
1168 1.1 skrll /* Skip empty options. */
1169 1.1 skrll if (*options == ',')
1170 1.1 skrll {
1171 1.1 skrll options++;
1172 1.1 skrll continue;
1173 1.1 skrll }
1174 1.1 skrll
1175 1.1 skrll /* We know that *options is neither NUL or a comma. */
1176 1.1 skrll option_end = options + 1;
1177 1.1 skrll while (*option_end != ',' && *option_end != '\0')
1178 1.1 skrll option_end++;
1179 1.1 skrll
1180 1.1 skrll parse_mips_dis_option (options, option_end - options);
1181 1.1 skrll
1182 1.1 skrll /* Go on to the next one. If option_end points to a comma, it
1183 1.1 skrll will be skipped above. */
1184 1.1 skrll options = option_end;
1185 1.1 skrll }
1186 1.1 skrll }
1187 1.1 skrll
1188 1.1 skrll static const struct mips_cp0sel_name *
1189 1.1 skrll lookup_mips_cp0sel_name (const struct mips_cp0sel_name *names,
1190 1.1 skrll unsigned int len,
1191 1.1 skrll unsigned int cp0reg,
1192 1.1 skrll unsigned int sel)
1193 1.1 skrll {
1194 1.1 skrll unsigned int i;
1195 1.1 skrll
1196 1.1 skrll for (i = 0; i < len; i++)
1197 1.1 skrll if (names[i].cp0reg == cp0reg && names[i].sel == sel)
1198 1.1 skrll return &names[i];
1199 1.5 christos return NULL;
1200 1.5 christos }
1201 1.1 skrll
1202 1.1 skrll /* Print register REGNO, of type TYPE, for instruction OPCODE. */
1203 1.5 christos
1204 1.5 christos static void
1205 1.1 skrll print_reg (struct disassemble_info *info, const struct mips_opcode *opcode,
1206 1.11 christos enum mips_reg_operand_type type, int regno)
1207 1.11 christos {
1208 1.5 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1209 1.5 christos
1210 1.5 christos switch (type)
1211 1.11 christos {
1212 1.11 christos case OP_REG_GP:
1213 1.5 christos infprintf (info->stream, dis_style_register, "%s",
1214 1.5 christos mips_gpr_names[regno]);
1215 1.5 christos break;
1216 1.11 christos
1217 1.11 christos case OP_REG_FP:
1218 1.5 christos infprintf (info->stream, dis_style_register, "%s",
1219 1.5 christos mips_fpr_names[regno]);
1220 1.5 christos break;
1221 1.5 christos
1222 1.11 christos case OP_REG_CCC:
1223 1.5 christos if (opcode->pinfo & (FP_D | FP_S))
1224 1.11 christos infprintf (info->stream, dis_style_register, "$fcc%d", regno);
1225 1.5 christos else
1226 1.1 skrll infprintf (info->stream, dis_style_register, "$cc%d", regno);
1227 1.5 christos break;
1228 1.5 christos
1229 1.11 christos case OP_REG_VEC:
1230 1.5 christos if (opcode->membership & INSN_5400)
1231 1.11 christos infprintf (info->stream, dis_style_register, "$f%d", regno);
1232 1.5 christos else
1233 1.1 skrll infprintf (info->stream, dis_style_register, "$v%d", regno);
1234 1.5 christos break;
1235 1.11 christos
1236 1.5 christos case OP_REG_ACC:
1237 1.1 skrll infprintf (info->stream, dis_style_register, "$ac%d", regno);
1238 1.5 christos break;
1239 1.5 christos
1240 1.11 christos case OP_REG_COPRO:
1241 1.10 christos if (opcode->name[strlen (opcode->name) - 1] == '0')
1242 1.11 christos infprintf (info->stream, dis_style_register, "%s", mips_cp0_names[regno]);
1243 1.10 christos else
1244 1.10 christos infprintf (info->stream, dis_style_register, "$%d", regno);
1245 1.10 christos break;
1246 1.10 christos
1247 1.11 christos case OP_REG_CONTROL:
1248 1.5 christos if (opcode->name[strlen (opcode->name) - 1] == '1')
1249 1.11 christos infprintf (info->stream, dis_style_register, "%s", mips_cp1_names[regno]);
1250 1.5 christos else
1251 1.1 skrll infprintf (info->stream, dis_style_register, "$%d", regno);
1252 1.5 christos break;
1253 1.11 christos
1254 1.5 christos case OP_REG_HW:
1255 1.1 skrll infprintf (info->stream, dis_style_register, "%s", mips_hwr_names[regno]);
1256 1.5 christos break;
1257 1.11 christos
1258 1.5 christos case OP_REG_VF:
1259 1.1 skrll infprintf (info->stream, dis_style_register, "$vf%d", regno);
1260 1.5 christos break;
1261 1.11 christos
1262 1.5 christos case OP_REG_VI:
1263 1.1 skrll infprintf (info->stream, dis_style_register, "$vi%d", regno);
1264 1.5 christos break;
1265 1.11 christos
1266 1.5 christos case OP_REG_R5900_I:
1267 1.1 skrll infprintf (info->stream, dis_style_register, "$I");
1268 1.5 christos break;
1269 1.11 christos
1270 1.5 christos case OP_REG_R5900_Q:
1271 1.1 skrll infprintf (info->stream, dis_style_register, "$Q");
1272 1.5 christos break;
1273 1.11 christos
1274 1.5 christos case OP_REG_R5900_R:
1275 1.1 skrll infprintf (info->stream, dis_style_register, "$R");
1276 1.5 christos break;
1277 1.11 christos
1278 1.5 christos case OP_REG_R5900_ACC:
1279 1.1 skrll infprintf (info->stream, dis_style_register, "$ACC");
1280 1.5 christos break;
1281 1.11 christos
1282 1.5 christos case OP_REG_MSA:
1283 1.1 skrll infprintf (info->stream, dis_style_register, "$w%d", regno);
1284 1.5 christos break;
1285 1.11 christos
1286 1.11 christos case OP_REG_MSA_CTRL:
1287 1.5 christos infprintf (info->stream, dis_style_register, "%s",
1288 1.1 skrll msa_control_names[regno]);
1289 1.5 christos break;
1290 1.5 christos
1291 1.5 christos }
1292 1.5 christos }
1293 1.5 christos
1294 1.5 christos /* Used to track the state carried over from previous operands in
1296 1.5 christos an instruction. */
1297 1.5 christos struct mips_print_arg_state {
1298 1.5 christos /* The value of the last OP_INT seen. We only use this for OP_MSB,
1299 1.5 christos where the value is known to be unsigned and small. */
1300 1.5 christos unsigned int last_int;
1301 1.5 christos
1302 1.5 christos /* The type and number of the last OP_REG seen. We only use this for
1303 1.5 christos OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1304 1.5 christos enum mips_reg_operand_type last_reg_type;
1305 1.5 christos unsigned int last_regno;
1306 1.1 skrll unsigned int dest_regno;
1307 1.5 christos unsigned int seen_dest;
1308 1.1 skrll };
1309 1.5 christos
1310 1.5 christos /* Initialize STATE for the start of an instruction. */
1311 1.5 christos
1312 1.5 christos static inline void
1313 1.5 christos init_print_arg_state (struct mips_print_arg_state *state)
1314 1.1 skrll {
1315 1.5 christos memset (state, 0, sizeof (*state));
1316 1.5 christos }
1317 1.1 skrll
1318 1.5 christos /* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1319 1.5 christos whose value is given by UVAL. */
1320 1.11 christos
1321 1.11 christos static void
1322 1.5 christos print_vu0_channel (struct disassemble_info *info,
1323 1.11 christos const struct mips_operand *operand, unsigned int uval,
1324 1.11 christos enum disassembler_style style)
1325 1.5 christos {
1326 1.11 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1327 1.5 christos
1328 1.5 christos if (operand->size == 4)
1329 1.5 christos infprintf (info->stream, style, "%s%s%s%s",
1330 1.5 christos uval & 8 ? "x" : "",
1331 1.5 christos uval & 4 ? "y" : "",
1332 1.11 christos uval & 2 ? "z" : "",
1333 1.5 christos uval & 1 ? "w" : "");
1334 1.5 christos else if (operand->size == 2)
1335 1.5 christos infprintf (info->stream, style, "%c", "xyzw"[uval]);
1336 1.1 skrll else
1337 1.5 christos abort ();
1338 1.1 skrll }
1339 1.5 christos
1340 1.5 christos /* Record information about a register operand. */
1341 1.5 christos
1342 1.5 christos static void
1343 1.5 christos mips_seen_register (struct mips_print_arg_state *state,
1344 1.5 christos unsigned int regno,
1345 1.5 christos enum mips_reg_operand_type reg_type)
1346 1.1 skrll {
1347 1.5 christos state->last_reg_type = reg_type;
1348 1.5 christos state->last_regno = regno;
1349 1.5 christos
1350 1.5 christos if (!state->seen_dest)
1351 1.5 christos {
1352 1.5 christos state->seen_dest = 1;
1353 1.1 skrll state->dest_regno = regno;
1354 1.7 christos }
1355 1.7 christos }
1356 1.7 christos
1357 1.7 christos /* Print SAVE/RESTORE instruction operands according to the argument
1358 1.7 christos register mask AMASK, the number of static registers saved NSREG,
1359 1.7 christos the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1360 1.7 christos and the frame size FRAME_SIZE. */
1361 1.7 christos
1362 1.7 christos static void
1363 1.7 christos mips_print_save_restore (struct disassemble_info *info, unsigned int amask,
1364 1.7 christos unsigned int nsreg, unsigned int ra,
1365 1.11 christos unsigned int s0, unsigned int s1,
1366 1.7 christos unsigned int frame_size)
1367 1.7 christos {
1368 1.7 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1369 1.7 christos unsigned int nargs, nstatics, smask, i, j;
1370 1.7 christos void *is = info->stream;
1371 1.7 christos const char *sep;
1372 1.7 christos
1373 1.7 christos if (amask == MIPS_SVRS_ALL_ARGS)
1374 1.7 christos {
1375 1.7 christos nargs = 4;
1376 1.7 christos nstatics = 0;
1377 1.7 christos }
1378 1.7 christos else if (amask == MIPS_SVRS_ALL_STATICS)
1379 1.7 christos {
1380 1.7 christos nargs = 0;
1381 1.7 christos nstatics = 4;
1382 1.7 christos }
1383 1.7 christos else
1384 1.7 christos {
1385 1.7 christos nargs = amask >> 2;
1386 1.7 christos nstatics = amask & 3;
1387 1.7 christos }
1388 1.7 christos
1389 1.11 christos sep = "";
1390 1.7 christos if (nargs > 0)
1391 1.11 christos {
1392 1.7 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[4]);
1393 1.7 christos if (nargs > 1)
1394 1.7 christos infprintf (is, dis_style_register, "-%s", mips_gpr_names[4 + nargs - 1]);
1395 1.11 christos sep = ",";
1396 1.11 christos }
1397 1.7 christos
1398 1.7 christos infprintf (is, dis_style_text, "%s", sep);
1399 1.11 christos infprintf (is, dis_style_immediate, "%d", frame_size);
1400 1.11 christos
1401 1.11 christos if (ra) /* $ra */
1402 1.11 christos {
1403 1.7 christos infprintf (is, dis_style_text, ",");
1404 1.7 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[31]);
1405 1.7 christos }
1406 1.7 christos
1407 1.7 christos smask = 0;
1408 1.7 christos if (s0) /* $s0 */
1409 1.7 christos smask |= 1 << 0;
1410 1.7 christos if (s1) /* $s1 */
1411 1.7 christos smask |= 1 << 1;
1412 1.7 christos if (nsreg > 0) /* $s2-$s8 */
1413 1.7 christos smask |= ((1 << nsreg) - 1) << 2;
1414 1.7 christos
1415 1.11 christos for (i = 0; i < 9; i++)
1416 1.11 christos if (smask & (1 << i))
1417 1.11 christos {
1418 1.7 christos infprintf (is, dis_style_text, ",");
1419 1.7 christos infprintf (is, dis_style_register, "%s",
1420 1.7 christos mips_gpr_names[i == 8 ? 30 : (16 + i)]);
1421 1.7 christos /* Skip over string of set bits. */
1422 1.11 christos for (j = i; smask & (2 << j); j++)
1423 1.11 christos continue;
1424 1.11 christos if (j > i)
1425 1.11 christos {
1426 1.11 christos infprintf (is, dis_style_text, "-");
1427 1.7 christos infprintf (is, dis_style_register, "%s",
1428 1.7 christos mips_gpr_names[j == 8 ? 30 : (16 + j)]);
1429 1.7 christos }
1430 1.7 christos i = j + 1;
1431 1.11 christos }
1432 1.11 christos /* Statics $ax - $a3. */
1433 1.11 christos if (nstatics == 1)
1434 1.11 christos {
1435 1.7 christos infprintf (is, dis_style_text, ",");
1436 1.11 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[7]);
1437 1.11 christos }
1438 1.11 christos else if (nstatics > 0)
1439 1.11 christos {
1440 1.11 christos infprintf (is, dis_style_text, ",");
1441 1.11 christos infprintf (is, dis_style_register, "%s",
1442 1.11 christos mips_gpr_names[7 - nstatics + 1]);
1443 1.7 christos infprintf (is, dis_style_text, "-");
1444 1.7 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[7]);
1445 1.7 christos }
1446 1.5 christos }
1447 1.5 christos
1448 1.5 christos
1449 1.1 skrll /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1450 1.5 christos UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1451 1.5 christos the base address for OP_PCREL operands. */
1452 1.5 christos
1453 1.5 christos static void
1454 1.5 christos print_insn_arg (struct disassemble_info *info,
1455 1.5 christos struct mips_print_arg_state *state,
1456 1.5 christos const struct mips_opcode *opcode,
1457 1.5 christos const struct mips_operand *operand,
1458 1.11 christos bfd_vma base_pc,
1459 1.5 christos unsigned int uval)
1460 1.1 skrll {
1461 1.5 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1462 1.5 christos void *is = info->stream;
1463 1.5 christos
1464 1.5 christos switch (operand->type)
1465 1.5 christos {
1466 1.4 christos case OP_INT:
1467 1.5 christos {
1468 1.5 christos const struct mips_int_operand *int_op;
1469 1.5 christos
1470 1.5 christos int_op = (const struct mips_int_operand *) operand;
1471 1.11 christos uval = mips_decode_int_operand (int_op, uval);
1472 1.5 christos state->last_int = uval;
1473 1.11 christos if (int_op->print_hex)
1474 1.5 christos infprintf (is, dis_style_immediate, "0x%x", uval);
1475 1.5 christos else
1476 1.4 christos infprintf (is, dis_style_immediate, "%d", uval);
1477 1.5 christos }
1478 1.5 christos break;
1479 1.5 christos
1480 1.1 skrll case OP_MAPPED_INT:
1481 1.5 christos {
1482 1.5 christos const struct mips_mapped_int_operand *mint_op;
1483 1.5 christos
1484 1.5 christos mint_op = (const struct mips_mapped_int_operand *) operand;
1485 1.11 christos uval = mint_op->int_map[uval];
1486 1.5 christos state->last_int = uval;
1487 1.11 christos if (mint_op->print_hex)
1488 1.5 christos infprintf (is, dis_style_immediate, "0x%x", uval);
1489 1.5 christos else
1490 1.1 skrll infprintf (is, dis_style_immediate, "%d", uval);
1491 1.5 christos }
1492 1.5 christos break;
1493 1.5 christos
1494 1.1 skrll case OP_MSB:
1495 1.5 christos {
1496 1.5 christos const struct mips_msb_operand *msb_op;
1497 1.5 christos
1498 1.5 christos msb_op = (const struct mips_msb_operand *) operand;
1499 1.11 christos uval += msb_op->bias;
1500 1.5 christos if (msb_op->add_lsb)
1501 1.5 christos uval -= state->last_int;
1502 1.1 skrll infprintf (is, dis_style_immediate, "0x%x", uval);
1503 1.5 christos }
1504 1.5 christos break;
1505 1.5 christos
1506 1.5 christos case OP_REG:
1507 1.1 skrll case OP_OPTIONAL_REG:
1508 1.5 christos {
1509 1.5 christos const struct mips_reg_operand *reg_op;
1510 1.5 christos
1511 1.1 skrll reg_op = (const struct mips_reg_operand *) operand;
1512 1.5 christos uval = mips_decode_reg_operand (reg_op, uval);
1513 1.5 christos print_reg (info, opcode, reg_op->reg_type, uval);
1514 1.5 christos
1515 1.1 skrll mips_seen_register (state, uval, reg_op->reg_type);
1516 1.5 christos }
1517 1.5 christos break;
1518 1.5 christos
1519 1.1 skrll case OP_REG_PAIR:
1520 1.5 christos {
1521 1.5 christos const struct mips_reg_pair_operand *pair_op;
1522 1.5 christos
1523 1.11 christos pair_op = (const struct mips_reg_pair_operand *) operand;
1524 1.5 christos print_reg (info, opcode, pair_op->reg_type,
1525 1.5 christos pair_op->reg1_map[uval]);
1526 1.5 christos infprintf (is, dis_style_text, ",");
1527 1.5 christos print_reg (info, opcode, pair_op->reg_type,
1528 1.1 skrll pair_op->reg2_map[uval]);
1529 1.5 christos }
1530 1.5 christos break;
1531 1.5 christos
1532 1.1 skrll case OP_PCREL:
1533 1.5 christos {
1534 1.5 christos const struct mips_pcrel_operand *pcrel_op;
1535 1.1 skrll
1536 1.7 christos pcrel_op = (const struct mips_pcrel_operand *) operand;
1537 1.7 christos info->target = mips_decode_pcrel_operand (pcrel_op, base_pc, uval);
1538 1.7 christos
1539 1.7 christos /* For jumps and branches clear the ISA bit except for
1540 1.5 christos the GDB disassembler. */
1541 1.1 skrll if (pcrel_op->include_isa_bit
1542 1.5 christos && info->flavour != bfd_target_unknown_flavour)
1543 1.5 christos info->target &= -2;
1544 1.5 christos
1545 1.1 skrll (*info->print_address_func) (info->target, info);
1546 1.5 christos }
1547 1.11 christos break;
1548 1.5 christos
1549 1.1 skrll case OP_PERF_REG:
1550 1.5 christos infprintf (is, dis_style_register, "%d", uval);
1551 1.5 christos break;
1552 1.5 christos
1553 1.1 skrll case OP_ADDIUSP_INT:
1554 1.5 christos {
1555 1.5 christos int sval;
1556 1.5 christos
1557 1.11 christos sval = mips_signed_operand (operand, uval) * 4;
1558 1.5 christos if (sval >= -8 && sval < 8)
1559 1.5 christos sval ^= 0x400;
1560 1.1 skrll infprintf (is, dis_style_immediate, "%d", sval);
1561 1.5 christos break;
1562 1.5 christos }
1563 1.5 christos
1564 1.1 skrll case OP_CLO_CLZ_DEST:
1565 1.5 christos {
1566 1.5 christos unsigned int reg1, reg2;
1567 1.5 christos
1568 1.5 christos reg1 = uval & 31;
1569 1.11 christos reg2 = uval >> 5;
1570 1.5 christos /* If one is zero use the other. */
1571 1.11 christos if (reg1 == reg2 || reg2 == 0)
1572 1.5 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[reg1]);
1573 1.11 christos else if (reg1 == 0)
1574 1.11 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[reg2]);
1575 1.11 christos else
1576 1.11 christos {
1577 1.11 christos /* Bogus, result depends on processor. */
1578 1.11 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[reg1]);
1579 1.5 christos infprintf (is, dis_style_text, " or ");
1580 1.5 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[reg2]);
1581 1.5 christos }
1582 1.5 christos }
1583 1.5 christos break;
1584 1.5 christos
1585 1.5 christos case OP_SAME_RS_RT:
1586 1.5 christos case OP_CHECK_PREV:
1587 1.5 christos case OP_NON_ZERO_REG:
1588 1.5 christos {
1589 1.5 christos print_reg (info, opcode, OP_REG_GP, uval & 31);
1590 1.5 christos mips_seen_register (state, uval, OP_REG_GP);
1591 1.5 christos }
1592 1.5 christos break;
1593 1.5 christos
1594 1.5 christos case OP_LWM_SWM_LIST:
1595 1.11 christos if (operand->size == 2)
1596 1.11 christos {
1597 1.11 christos if (uval == 0)
1598 1.11 christos {
1599 1.11 christos infprintf (is, dis_style_register, "%s",
1600 1.11 christos mips_gpr_names[16]);
1601 1.11 christos infprintf (is, dis_style_text, ",");
1602 1.5 christos infprintf (is, dis_style_register, "%s",
1603 1.11 christos mips_gpr_names[31]);
1604 1.11 christos }
1605 1.11 christos else
1606 1.11 christos {
1607 1.11 christos infprintf (is, dis_style_register, "%s",
1608 1.11 christos mips_gpr_names[16]);
1609 1.11 christos infprintf (is, dis_style_text, "-");
1610 1.11 christos infprintf (is, dis_style_register, "%s",
1611 1.11 christos mips_gpr_names[16 + uval]);
1612 1.11 christos infprintf (is, dis_style_text, ",");
1613 1.5 christos infprintf (is, dis_style_register, "%s",
1614 1.5 christos mips_gpr_names[31]);
1615 1.5 christos }
1616 1.5 christos }
1617 1.5 christos else
1618 1.5 christos {
1619 1.5 christos int s_reg_encode;
1620 1.5 christos
1621 1.5 christos s_reg_encode = uval & 0xf;
1622 1.11 christos if (s_reg_encode != 0)
1623 1.5 christos {
1624 1.11 christos if (s_reg_encode == 1)
1625 1.11 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[16]);
1626 1.11 christos else if (s_reg_encode < 9)
1627 1.11 christos {
1628 1.11 christos infprintf (is, dis_style_register, "%s",
1629 1.11 christos mips_gpr_names[16]);
1630 1.11 christos infprintf (is, dis_style_text, "-");
1631 1.5 christos infprintf (is, dis_style_register, "%s",
1632 1.11 christos mips_gpr_names[15 + s_reg_encode]);
1633 1.11 christos }
1634 1.11 christos else if (s_reg_encode == 9)
1635 1.11 christos {
1636 1.11 christos infprintf (is, dis_style_register, "%s",
1637 1.11 christos mips_gpr_names[16]);
1638 1.11 christos infprintf (is, dis_style_text, "-");
1639 1.11 christos infprintf (is, dis_style_register, "%s",
1640 1.11 christos mips_gpr_names[23]);
1641 1.11 christos infprintf (is, dis_style_text, ",");
1642 1.5 christos infprintf (is, dis_style_register, "%s",
1643 1.11 christos mips_gpr_names[30]);
1644 1.5 christos }
1645 1.5 christos else
1646 1.5 christos infprintf (is, dis_style_text, "UNKNOWN");
1647 1.5 christos }
1648 1.5 christos
1649 1.11 christos if (uval & 0x10) /* For ra. */
1650 1.5 christos {
1651 1.11 christos if (s_reg_encode == 0)
1652 1.11 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[31]);
1653 1.11 christos else
1654 1.11 christos {
1655 1.11 christos infprintf (is, dis_style_text, ",");
1656 1.5 christos infprintf (is, dis_style_register, "%s",
1657 1.5 christos mips_gpr_names[31]);
1658 1.5 christos }
1659 1.5 christos }
1660 1.5 christos }
1661 1.5 christos break;
1662 1.5 christos
1663 1.5 christos case OP_ENTRY_EXIT_LIST:
1664 1.5 christos {
1665 1.5 christos const char *sep;
1666 1.5 christos unsigned int amask, smask;
1667 1.5 christos
1668 1.1 skrll sep = "";
1669 1.11 christos amask = (uval >> 3) & 7;
1670 1.5 christos if (amask > 0 && amask < 5)
1671 1.11 christos {
1672 1.11 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[4]);
1673 1.11 christos if (amask > 1)
1674 1.11 christos {
1675 1.11 christos infprintf (is, dis_style_text, "-");
1676 1.5 christos infprintf (is, dis_style_register, "%s",
1677 1.5 christos mips_gpr_names[amask + 3]);
1678 1.5 christos }
1679 1.5 christos sep = ",";
1680 1.5 christos }
1681 1.5 christos
1682 1.11 christos smask = (uval >> 1) & 3;
1683 1.5 christos if (smask == 3)
1684 1.5 christos {
1685 1.5 christos infprintf (is, dis_style_text, "%s??", sep);
1686 1.5 christos sep = ",";
1687 1.11 christos }
1688 1.11 christos else if (smask > 0)
1689 1.5 christos {
1690 1.11 christos infprintf (is, dis_style_text, "%s", sep);
1691 1.11 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[16]);
1692 1.11 christos if (smask > 1)
1693 1.11 christos {
1694 1.11 christos infprintf (is, dis_style_text, "-");
1695 1.5 christos infprintf (is, dis_style_register, "%s",
1696 1.5 christos mips_gpr_names[smask + 15]);
1697 1.5 christos }
1698 1.5 christos sep = ",";
1699 1.5 christos }
1700 1.11 christos
1701 1.11 christos if (uval & 1)
1702 1.5 christos {
1703 1.5 christos infprintf (is, dis_style_text, "%s", sep);
1704 1.5 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[31]);
1705 1.5 christos sep = ",";
1706 1.5 christos }
1707 1.11 christos
1708 1.11 christos if (amask == 5 || amask == 6)
1709 1.5 christos {
1710 1.11 christos infprintf (is, dis_style_text, "%s", sep);
1711 1.11 christos infprintf (is, dis_style_register, "%s", mips_fpr_names[0]);
1712 1.11 christos if (amask == 6)
1713 1.11 christos {
1714 1.5 christos infprintf (is, dis_style_text, "-");
1715 1.5 christos infprintf (is, dis_style_register, "%s", mips_fpr_names[1]);
1716 1.5 christos }
1717 1.5 christos }
1718 1.5 christos }
1719 1.7 christos break;
1720 1.5 christos
1721 1.5 christos case OP_SAVE_RESTORE_LIST:
1722 1.5 christos /* Should be handled by the caller due to complex behavior. */
1723 1.5 christos abort ();
1724 1.5 christos
1725 1.5 christos case OP_MDMX_IMM_REG:
1726 1.5 christos {
1727 1.5 christos unsigned int vsel;
1728 1.5 christos
1729 1.5 christos vsel = uval >> 5;
1730 1.5 christos uval &= 31;
1731 1.5 christos if ((vsel & 0x10) == 0)
1732 1.5 christos {
1733 1.5 christos int fmt;
1734 1.5 christos
1735 1.5 christos vsel &= 0x0f;
1736 1.5 christos for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
1737 1.11 christos if ((vsel & 1) == 0)
1738 1.11 christos break;
1739 1.11 christos print_reg (info, opcode, OP_REG_VEC, uval);
1740 1.1 skrll infprintf (is, dis_style_text, "[");
1741 1.5 christos infprintf (is, dis_style_immediate, "%d", vsel >> 1);
1742 1.5 christos infprintf (is, dis_style_text, "]");
1743 1.5 christos }
1744 1.11 christos else if ((vsel & 0x08) == 0)
1745 1.5 christos print_reg (info, opcode, OP_REG_VEC, uval);
1746 1.5 christos else
1747 1.1 skrll infprintf (is, dis_style_immediate, "0x%x", uval);
1748 1.5 christos }
1749 1.5 christos break;
1750 1.5 christos
1751 1.1 skrll case OP_REPEAT_PREV_REG:
1752 1.5 christos print_reg (info, opcode, state->last_reg_type, state->last_regno);
1753 1.5 christos break;
1754 1.5 christos
1755 1.1 skrll case OP_REPEAT_DEST_REG:
1756 1.5 christos print_reg (info, opcode, state->last_reg_type, state->dest_regno);
1757 1.11 christos break;
1758 1.5 christos
1759 1.1 skrll case OP_PC:
1760 1.7 christos infprintf (is, dis_style_register, "$pc");
1761 1.7 christos break;
1762 1.7 christos
1763 1.7 christos case OP_REG28:
1764 1.5 christos print_reg (info, opcode, OP_REG_GP, 28);
1765 1.5 christos break;
1766 1.11 christos
1767 1.5 christos case OP_VU0_SUFFIX:
1768 1.1 skrll case OP_VU0_MATCH_SUFFIX:
1769 1.5 christos print_vu0_channel (info, operand, uval, dis_style_register);
1770 1.11 christos break;
1771 1.11 christos
1772 1.11 christos case OP_IMM_INDEX:
1773 1.5 christos infprintf (is, dis_style_text, "[");
1774 1.1 skrll infprintf (is, dis_style_immediate, "%d", uval);
1775 1.5 christos infprintf (is, dis_style_text, "]");
1776 1.11 christos break;
1777 1.5 christos
1778 1.11 christos case OP_REG_INDEX:
1779 1.5 christos infprintf (is, dis_style_text, "[");
1780 1.5 christos print_reg (info, opcode, OP_REG_GP, uval);
1781 1.5 christos infprintf (is, dis_style_text, "]");
1782 1.1 skrll break;
1783 1.5 christos }
1784 1.5 christos }
1785 1.1 skrll
1786 1.10 christos /* Validate the arguments for INSN, which is described by OPCODE.
1787 1.5 christos Use DECODE_OPERAND to get the encoding of each operand. */
1788 1.5 christos
1789 1.5 christos static bool
1790 1.5 christos validate_insn_args (const struct mips_opcode *opcode,
1791 1.5 christos const struct mips_operand *(*decode_operand) (const char *),
1792 1.5 christos unsigned int insn)
1793 1.5 christos {
1794 1.5 christos struct mips_print_arg_state state;
1795 1.1 skrll const struct mips_operand *operand;
1796 1.5 christos const char *s;
1797 1.5 christos unsigned int uval;
1798 1.5 christos
1799 1.5 christos init_print_arg_state (&state);
1800 1.5 christos for (s = opcode->args; *s; ++s)
1801 1.5 christos {
1802 1.5 christos switch (*s)
1803 1.5 christos {
1804 1.1 skrll case ',':
1805 1.1 skrll case '(':
1806 1.5 christos case ')':
1807 1.5 christos break;
1808 1.1 skrll
1809 1.1 skrll case '#':
1810 1.5 christos ++s;
1811 1.5 christos break;
1812 1.1 skrll
1813 1.5 christos default:
1814 1.5 christos operand = decode_operand (s);
1815 1.5 christos
1816 1.5 christos if (operand)
1817 1.5 christos {
1818 1.5 christos uval = mips_extract_operand (operand, insn);
1819 1.5 christos switch (operand->type)
1820 1.5 christos {
1821 1.5 christos case OP_REG:
1822 1.1 skrll case OP_OPTIONAL_REG:
1823 1.5 christos {
1824 1.5 christos const struct mips_reg_operand *reg_op;
1825 1.5 christos
1826 1.5 christos reg_op = (const struct mips_reg_operand *) operand;
1827 1.5 christos uval = mips_decode_reg_operand (reg_op, uval);
1828 1.1 skrll mips_seen_register (&state, uval, reg_op->reg_type);
1829 1.5 christos }
1830 1.5 christos break;
1831 1.5 christos
1832 1.1 skrll case OP_SAME_RS_RT:
1833 1.5 christos {
1834 1.5 christos unsigned int reg1, reg2;
1835 1.1 skrll
1836 1.5 christos reg1 = uval & 31;
1837 1.10 christos reg2 = uval >> 5;
1838 1.5 christos
1839 1.5 christos if (reg1 != reg2 || reg1 == 0)
1840 1.1 skrll return false;
1841 1.5 christos }
1842 1.5 christos break;
1843 1.5 christos
1844 1.1 skrll case OP_CHECK_PREV:
1845 1.5 christos {
1846 1.1 skrll const struct mips_check_prev_operand *prev_op;
1847 1.5 christos
1848 1.10 christos prev_op = (const struct mips_check_prev_operand *) operand;
1849 1.1 skrll
1850 1.5 christos if (!prev_op->zero_ok && uval == 0)
1851 1.5 christos return false;
1852 1.5 christos
1853 1.5 christos if (((prev_op->less_than_ok && uval < state.last_regno)
1854 1.1 skrll || (prev_op->greater_than_ok && uval > state.last_regno)
1855 1.10 christos || (prev_op->equal_ok && uval == state.last_regno)))
1856 1.5 christos break;
1857 1.1 skrll
1858 1.5 christos return false;
1859 1.5 christos }
1860 1.5 christos
1861 1.10 christos case OP_NON_ZERO_REG:
1862 1.5 christos {
1863 1.5 christos if (uval == 0)
1864 1.1 skrll return false;
1865 1.5 christos }
1866 1.5 christos break;
1867 1.5 christos
1868 1.5 christos case OP_INT:
1869 1.5 christos case OP_MAPPED_INT:
1870 1.5 christos case OP_MSB:
1871 1.5 christos case OP_REG_PAIR:
1872 1.5 christos case OP_PCREL:
1873 1.5 christos case OP_PERF_REG:
1874 1.5 christos case OP_ADDIUSP_INT:
1875 1.5 christos case OP_CLO_CLZ_DEST:
1876 1.5 christos case OP_LWM_SWM_LIST:
1877 1.5 christos case OP_ENTRY_EXIT_LIST:
1878 1.5 christos case OP_MDMX_IMM_REG:
1879 1.7 christos case OP_REPEAT_PREV_REG:
1880 1.5 christos case OP_REPEAT_DEST_REG:
1881 1.5 christos case OP_PC:
1882 1.5 christos case OP_REG28:
1883 1.5 christos case OP_VU0_SUFFIX:
1884 1.7 christos case OP_VU0_MATCH_SUFFIX:
1885 1.5 christos case OP_IMM_INDEX:
1886 1.5 christos case OP_REG_INDEX:
1887 1.5 christos case OP_SAVE_RESTORE_LIST:
1888 1.5 christos break;
1889 1.5 christos }
1890 1.5 christos }
1891 1.5 christos if (*s == 'm' || *s == '+' || *s == '-')
1892 1.10 christos ++s;
1893 1.5 christos }
1894 1.1 skrll }
1895 1.5 christos return true;
1896 1.5 christos }
1897 1.5 christos
1898 1.5 christos /* Print the arguments for INSN, which is described by OPCODE.
1899 1.1 skrll Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
1900 1.5 christos as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1901 1.5 christos operand is for a branch or jump. */
1902 1.5 christos
1903 1.5 christos static void
1904 1.5 christos print_insn_args (struct disassemble_info *info,
1905 1.5 christos const struct mips_opcode *opcode,
1906 1.11 christos const struct mips_operand *(*decode_operand) (const char *),
1907 1.5 christos unsigned int insn, bfd_vma insn_pc, unsigned int length)
1908 1.5 christos {
1909 1.5 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1910 1.5 christos void *is = info->stream;
1911 1.1 skrll struct mips_print_arg_state state;
1912 1.5 christos const struct mips_operand *operand;
1913 1.5 christos const char *s;
1914 1.5 christos
1915 1.5 christos init_print_arg_state (&state);
1916 1.5 christos for (s = opcode->args; *s; ++s)
1917 1.5 christos {
1918 1.5 christos switch (*s)
1919 1.5 christos {
1920 1.11 christos case ',':
1921 1.1 skrll case '(':
1922 1.1 skrll case ')':
1923 1.5 christos infprintf (is, dis_style_text, "%c", *s);
1924 1.5 christos break;
1925 1.11 christos
1926 1.1 skrll case '#':
1927 1.1 skrll ++s;
1928 1.1 skrll infprintf (is, dis_style_text, "%c%c", *s, *s);
1929 1.5 christos break;
1930 1.5 christos
1931 1.5 christos default:
1932 1.5 christos operand = decode_operand (s);
1933 1.11 christos if (!operand)
1934 1.5 christos {
1935 1.5 christos /* xgettext:c-format */
1936 1.5 christos infprintf (is, dis_style_text,
1937 1.5 christos _("# internal error, undefined operand in `%s %s'"),
1938 1.7 christos opcode->name, opcode->args);
1939 1.7 christos return;
1940 1.7 christos }
1941 1.7 christos
1942 1.7 christos if (operand->type == OP_SAVE_RESTORE_LIST)
1943 1.7 christos {
1944 1.7 christos /* Handle this case here because of the complex behavior. */
1945 1.7 christos unsigned int amask = (insn >> 15) & 0xf;
1946 1.7 christos unsigned int nsreg = (insn >> 23) & 0x7;
1947 1.7 christos unsigned int ra = insn & 0x1000; /* $ra */
1948 1.7 christos unsigned int s0 = insn & 0x800; /* $s0 */
1949 1.7 christos unsigned int s1 = insn & 0x400; /* $s1 */
1950 1.7 christos unsigned int frame_size = (((insn >> 15) & 0xf0)
1951 1.7 christos | ((insn >> 6) & 0x0f)) * 8;
1952 1.7 christos mips_print_save_restore (info, amask, nsreg, ra, s0, s1,
1953 1.7 christos frame_size);
1954 1.12 christos }
1955 1.7 christos else if (operand->type == OP_REG
1956 1.5 christos && s[1] == ','
1957 1.7 christos && (s[2] == 'H' || s[2] == 'J')
1958 1.5 christos && opcode->name[strlen (opcode->name) - 1] == '0')
1959 1.5 christos {
1960 1.5 christos /* Coprocessor register 0 with sel field. */
1961 1.5 christos const struct mips_cp0sel_name *n;
1962 1.5 christos unsigned int reg, sel;
1963 1.5 christos
1964 1.5 christos reg = mips_extract_operand (operand, insn);
1965 1.5 christos s += 2;
1966 1.5 christos operand = decode_operand (s);
1967 1.5 christos sel = mips_extract_operand (operand, insn);
1968 1.5 christos
1969 1.5 christos /* CP0 register including 'sel' code for mftc0, to be
1970 1.5 christos printed textually if known. If not known, print both
1971 1.5 christos CP0 register name and sel numerically since CP0 register
1972 1.5 christos with sel 0 may have a name unrelated to register being
1973 1.5 christos printed. */
1974 1.5 christos n = lookup_mips_cp0sel_name (mips_cp0sel_names,
1975 1.11 christos mips_cp0sel_names_len,
1976 1.5 christos reg, sel);
1977 1.11 christos if (n != NULL)
1978 1.11 christos infprintf (is, dis_style_register, "%s", n->name);
1979 1.11 christos else
1980 1.11 christos {
1981 1.11 christos infprintf (is, dis_style_register, "$%d", reg);
1982 1.5 christos infprintf (is, dis_style_text, ",");
1983 1.5 christos infprintf (is, dis_style_immediate, "%d", sel);
1984 1.5 christos }
1985 1.5 christos }
1986 1.5 christos else
1987 1.5 christos {
1988 1.5 christos bfd_vma base_pc = insn_pc;
1989 1.5 christos
1990 1.5 christos /* Adjust the PC relative base so that branch/jump insns use
1991 1.5 christos the following PC as the base but genuinely PC relative
1992 1.5 christos operands use the current PC. */
1993 1.5 christos if (operand->type == OP_PCREL)
1994 1.5 christos {
1995 1.5 christos const struct mips_pcrel_operand *pcrel_op;
1996 1.5 christos
1997 1.5 christos pcrel_op = (const struct mips_pcrel_operand *) operand;
1998 1.5 christos /* The include_isa_bit flag is sufficient to distinguish
1999 1.5 christos branch/jump from other PC relative operands. */
2000 1.5 christos if (pcrel_op->include_isa_bit)
2001 1.5 christos base_pc += length;
2002 1.5 christos }
2003 1.5 christos
2004 1.5 christos print_insn_arg (info, &state, opcode, operand, base_pc,
2005 1.5 christos mips_extract_operand (operand, insn));
2006 1.5 christos }
2007 1.1 skrll if (*s == 'm' || *s == '+' || *s == '-')
2008 1.1 skrll ++s;
2009 1.1 skrll break;
2010 1.1 skrll }
2011 1.1 skrll }
2012 1.1 skrll }
2013 1.1 skrll
2014 1.1 skrll /* Print the mips instruction at address MEMADDR in debugged memory,
2016 1.1 skrll on using INFO. Returns length of the instruction, in bytes, which is
2017 1.1 skrll always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
2018 1.4 christos this is little-endian code. */
2019 1.1 skrll
2020 1.1 skrll static int
2021 1.5 christos print_insn_mips (bfd_vma memaddr,
2022 1.5 christos int word,
2023 1.4 christos struct disassemble_info *info)
2024 1.11 christos {
2025 1.1 skrll #define GET_OP(insn, field) \
2026 1.10 christos (((insn) >> OP_SH_##field) & OP_MASK_##field)
2027 1.4 christos static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
2028 1.1 skrll const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
2029 1.1 skrll const struct mips_opcode *op;
2030 1.1 skrll static bool init = 0;
2031 1.1 skrll void *is = info->stream;
2032 1.1 skrll
2033 1.1 skrll /* Build a hash table to shorten the search time. */
2034 1.1 skrll if (! init)
2035 1.1 skrll {
2036 1.1 skrll unsigned int i;
2037 1.1 skrll
2038 1.1 skrll for (i = 0; i <= OP_MASK_OP; i++)
2039 1.1 skrll {
2040 1.1 skrll for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
2041 1.4 christos {
2042 1.1 skrll if (op->pinfo == INSN_MACRO
2043 1.1 skrll || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
2044 1.1 skrll continue;
2045 1.1 skrll if (i == GET_OP (op->match, OP))
2046 1.1 skrll {
2047 1.1 skrll mips_hash[i] = op;
2048 1.1 skrll break;
2049 1.1 skrll }
2050 1.1 skrll }
2051 1.1 skrll }
2052 1.1 skrll
2053 1.1 skrll init = 1;
2054 1.1 skrll }
2055 1.1 skrll
2056 1.1 skrll info->bytes_per_chunk = INSNLEN;
2057 1.1 skrll info->display_endian = info->endian;
2058 1.1 skrll info->insn_info_valid = 1;
2059 1.1 skrll info->branch_delay_insns = 0;
2060 1.1 skrll info->data_size = 0;
2061 1.4 christos info->insn_type = dis_nonbranch;
2062 1.1 skrll info->target = 0;
2063 1.1 skrll info->target2 = 0;
2064 1.1 skrll
2065 1.1 skrll op = mips_hash[GET_OP (word, OP)];
2066 1.5 christos if (op != NULL)
2067 1.1 skrll {
2068 1.1 skrll for (; op < &mips_opcodes[NUMOPCODES]; op++)
2069 1.1 skrll {
2070 1.5 christos if (op->pinfo != INSN_MACRO
2071 1.5 christos && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
2072 1.5 christos && (word & op->mask) == op->match)
2073 1.5 christos {
2074 1.5 christos /* We always disassemble the jalx instruction, except for MIPS r6. */
2075 1.1 skrll if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
2076 1.1 skrll && (strcmp (op->name, "jalx")
2077 1.1 skrll || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6
2078 1.1 skrll || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6))
2079 1.1 skrll continue;
2080 1.5 christos
2081 1.1 skrll /* Figure out instruction type and branch delay information. */
2082 1.1 skrll if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
2083 1.1 skrll {
2084 1.1 skrll if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
2085 1.1 skrll info->insn_type = dis_jsr;
2086 1.1 skrll else
2087 1.1 skrll info->insn_type = dis_branch;
2088 1.1 skrll info->branch_delay_insns = 1;
2089 1.3 christos }
2090 1.1 skrll else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
2091 1.1 skrll | INSN_COND_BRANCH_LIKELY)) != 0)
2092 1.1 skrll {
2093 1.1 skrll if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2094 1.1 skrll info->insn_type = dis_condjsr;
2095 1.1 skrll else
2096 1.5 christos info->insn_type = dis_condbranch;
2097 1.1 skrll info->branch_delay_insns = 1;
2098 1.1 skrll }
2099 1.5 christos else if ((op->pinfo & (INSN_STORE_MEMORY
2100 1.5 christos | INSN_LOAD_MEMORY)) != 0)
2101 1.5 christos info->insn_type = dis_dref;
2102 1.11 christos
2103 1.5 christos if (!validate_insn_args (op, decode_mips_operand, word))
2104 1.5 christos continue;
2105 1.5 christos
2106 1.5 christos infprintf (is, dis_style_mnemonic, "%s", op->name);
2107 1.11 christos if (op->pinfo2 & INSN2_VU0_CHANNEL_SUFFIX)
2108 1.5 christos {
2109 1.11 christos unsigned int uval;
2110 1.11 christos
2111 1.5 christos infprintf (is, dis_style_mnemonic, ".");
2112 1.1 skrll uval = mips_extract_operand (&mips_vu0_channel_mask, word);
2113 1.5 christos print_vu0_channel (info, &mips_vu0_channel_mask, uval,
2114 1.1 skrll dis_style_mnemonic);
2115 1.11 christos }
2116 1.5 christos
2117 1.5 christos if (op->args[0])
2118 1.1 skrll {
2119 1.1 skrll infprintf (is, dis_style_text, "\t");
2120 1.1 skrll print_insn_args (info, op, decode_mips_operand, word,
2121 1.1 skrll memaddr, 4);
2122 1.1 skrll }
2123 1.1 skrll
2124 1.4 christos return INSNLEN;
2125 1.1 skrll }
2126 1.1 skrll }
2127 1.1 skrll }
2128 1.11 christos #undef GET_OP
2129 1.11 christos
2130 1.11 christos /* Handle undefined instructions. */
2131 1.1 skrll info->insn_type = dis_noninsn;
2132 1.1 skrll infprintf (is, dis_style_assembler_directive, ".word");
2133 1.1 skrll infprintf (is, dis_style_text, "\t");
2134 1.1 skrll infprintf (is, dis_style_immediate, "0x%x", word);
2135 1.1 skrll return INSNLEN;
2136 1.1 skrll }
2137 1.5 christos
2138 1.5 christos /* Disassemble an operand for a mips16 instruction. */
2140 1.5 christos
2141 1.10 christos static void
2142 1.10 christos print_mips16_insn_arg (struct disassemble_info *info,
2143 1.1 skrll struct mips_print_arg_state *state,
2144 1.11 christos const struct mips_opcode *opcode,
2145 1.4 christos char type, bfd_vma memaddr,
2146 1.5 christos unsigned insn, bool use_extend,
2147 1.7 christos unsigned extend, bool is_offset)
2148 1.5 christos {
2149 1.5 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
2150 1.5 christos void *is = info->stream;
2151 1.5 christos const struct mips_operand *operand, *ext_operand;
2152 1.5 christos unsigned short ext_size;
2153 1.4 christos unsigned int uval;
2154 1.1 skrll bfd_vma baseaddr;
2155 1.1 skrll
2156 1.1 skrll if (!use_extend)
2157 1.1 skrll extend = 0;
2158 1.1 skrll
2159 1.11 christos switch (type)
2160 1.1 skrll {
2161 1.1 skrll case ',':
2162 1.5 christos case '(':
2163 1.10 christos case ')':
2164 1.5 christos infprintf (is, dis_style_text, "%c", type);
2165 1.5 christos break;
2166 1.5 christos
2167 1.11 christos default:
2168 1.5 christos operand = decode_mips16_operand (type, false);
2169 1.5 christos if (!operand)
2170 1.5 christos {
2171 1.1 skrll /* xgettext:c-format */
2172 1.5 christos infprintf (is, dis_style_text, _("# internal error, undefined operand in `%s %s'"),
2173 1.5 christos opcode->name, opcode->args);
2174 1.7 christos return;
2175 1.5 christos }
2176 1.7 christos
2177 1.7 christos if (operand->type == OP_SAVE_RESTORE_LIST)
2178 1.7 christos {
2179 1.7 christos /* Handle this case here because of the complex interaction
2180 1.7 christos with the EXTEND opcode. */
2181 1.7 christos unsigned int amask = extend & 0xf;
2182 1.5 christos unsigned int nsreg = (extend >> 8) & 0x7;
2183 1.5 christos unsigned int ra = insn & 0x40; /* $ra */
2184 1.7 christos unsigned int s0 = insn & 0x20; /* $s0 */
2185 1.5 christos unsigned int s1 = insn & 0x10; /* $s1 */
2186 1.5 christos unsigned int frame_size = ((extend & 0xf0) | (insn & 0x0f)) * 8;
2187 1.1 skrll if (frame_size == 0 && !use_extend)
2188 1.5 christos frame_size = 128;
2189 1.5 christos mips_print_save_restore (info, amask, nsreg, ra, s0, s1, frame_size);
2190 1.5 christos break;
2191 1.1 skrll }
2192 1.5 christos
2193 1.5 christos if (is_offset && operand->type == OP_INT)
2194 1.5 christos {
2195 1.5 christos const struct mips_int_operand *int_op;
2196 1.1 skrll
2197 1.7 christos int_op = (const struct mips_int_operand *) operand;
2198 1.7 christos info->insn_type = dis_dref;
2199 1.5 christos info->data_size = 1 << int_op->shift;
2200 1.10 christos }
2201 1.7 christos
2202 1.7 christos ext_size = 0;
2203 1.7 christos if (use_extend)
2204 1.5 christos {
2205 1.7 christos ext_operand = decode_mips16_operand (type, true);
2206 1.7 christos if (ext_operand != operand
2207 1.5 christos || (operand->type == OP_INT && operand->lsb == 0
2208 1.5 christos && mips_opcode_32bit_p (opcode)))
2209 1.7 christos {
2210 1.7 christos ext_size = ext_operand->size;
2211 1.7 christos operand = ext_operand;
2212 1.7 christos }
2213 1.7 christos }
2214 1.7 christos if (operand->size == 26)
2215 1.7 christos uval = ((extend & 0x1f) << 21) | ((extend & 0x3e0) << 11) | insn;
2216 1.7 christos else if (ext_size == 16 || ext_size == 9)
2217 1.7 christos uval = ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
2218 1.7 christos else if (ext_size == 15)
2219 1.7 christos uval = ((extend & 0xf) << 11) | (extend & 0x7f0) | (insn & 0xf);
2220 1.7 christos else if (ext_size == 6)
2221 1.1 skrll uval = ((extend >> 6) & 0x1f) | (extend & 0x20);
2222 1.5 christos else
2223 1.5 christos uval = mips_extract_operand (operand, (extend << 16) | insn);
2224 1.5 christos if (ext_size == 9)
2225 1.5 christos uval &= (1U << ext_size) - 1;
2226 1.1 skrll
2227 1.5 christos baseaddr = memaddr + 2;
2228 1.5 christos if (operand->type == OP_PCREL)
2229 1.5 christos {
2230 1.5 christos const struct mips_pcrel_operand *pcrel_op;
2231 1.7 christos
2232 1.7 christos pcrel_op = (const struct mips_pcrel_operand *) operand;
2233 1.5 christos if (!pcrel_op->include_isa_bit && use_extend)
2234 1.7 christos baseaddr = memaddr - 2;
2235 1.7 christos else if (!pcrel_op->include_isa_bit)
2236 1.7 christos {
2237 1.7 christos bfd_byte buffer[2];
2238 1.7 christos
2239 1.7 christos /* If this instruction is in the delay slot of a JAL/JALX
2240 1.7 christos instruction, the base address is the address of the
2241 1.7 christos JAL/JALX instruction. If it is in the delay slot of
2242 1.7 christos a JR/JALR instruction, the base address is the address
2243 1.7 christos of the JR/JALR instruction. This test is unreliable:
2244 1.7 christos we have no way of knowing whether the previous word is
2245 1.7 christos instruction or data. */
2246 1.7 christos if (info->read_memory_func (memaddr - 4, buffer, 2, info) == 0
2247 1.7 christos && (((info->endian == BFD_ENDIAN_BIG
2248 1.7 christos ? bfd_getb16 (buffer)
2249 1.7 christos : bfd_getl16 (buffer))
2250 1.7 christos & 0xf800) == 0x1800))
2251 1.7 christos baseaddr = memaddr - 4;
2252 1.7 christos else if (info->read_memory_func (memaddr - 2, buffer, 2,
2253 1.7 christos info) == 0
2254 1.7 christos && (((info->endian == BFD_ENDIAN_BIG
2255 1.7 christos ? bfd_getb16 (buffer)
2256 1.7 christos : bfd_getl16 (buffer))
2257 1.7 christos & 0xf89f) == 0xe800)
2258 1.7 christos && (((info->endian == BFD_ENDIAN_BIG
2259 1.7 christos ? bfd_getb16 (buffer)
2260 1.7 christos : bfd_getl16 (buffer))
2261 1.5 christos & 0x0060) != 0x0060))
2262 1.1 skrll baseaddr = memaddr - 2;
2263 1.5 christos else
2264 1.1 skrll baseaddr = memaddr;
2265 1.5 christos }
2266 1.5 christos }
2267 1.1 skrll
2268 1.1 skrll print_insn_arg (info, state, opcode, operand, baseaddr + 1, uval);
2269 1.5 christos break;
2270 1.5 christos }
2271 1.5 christos }
2272 1.5 christos
2273 1.10 christos
2274 1.5 christos /* Check if the given address is the last word of a MIPS16 PLT entry.
2275 1.5 christos This word is data and depending on the value it may interfere with
2276 1.5 christos disassembly of further PLT entries. We make use of the fact PLT
2277 1.5 christos symbols are marked BSF_SYNTHETIC. */
2278 1.5 christos static bool
2279 1.5 christos is_mips16_plt_tail (struct disassemble_info *info, bfd_vma addr)
2280 1.10 christos {
2281 1.1 skrll if (info->symbols
2282 1.10 christos && info->symbols[0]
2283 1.1 skrll && (info->symbols[0]->flags & BSF_SYNTHETIC)
2284 1.1 skrll && addr == bfd_asymbol_value (info->symbols[0]) + 12)
2285 1.7 christos return true;
2286 1.7 christos
2287 1.7 christos return false;
2288 1.7 christos }
2289 1.7 christos
2290 1.7 christos /* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2291 1.7 christos
2292 1.7 christos enum match_kind
2293 1.7 christos {
2294 1.1 skrll MATCH_NONE,
2295 1.1 skrll MATCH_FULL,
2296 1.1 skrll MATCH_SHORT
2297 1.1 skrll };
2298 1.1 skrll
2299 1.11 christos /* Disassemble mips16 instructions. */
2300 1.1 skrll
2301 1.5 christos static int
2302 1.1 skrll print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
2303 1.5 christos {
2304 1.4 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
2305 1.10 christos int status;
2306 1.10 christos bfd_byte buffer[4];
2307 1.7 christos const struct mips_opcode *op, *opend;
2308 1.7 christos struct mips_print_arg_state state;
2309 1.7 christos void *is = info->stream;
2310 1.1 skrll bool have_second;
2311 1.1 skrll bool extend_only;
2312 1.1 skrll unsigned int second;
2313 1.1 skrll unsigned int first;
2314 1.1 skrll unsigned int full;
2315 1.1 skrll
2316 1.1 skrll info->bytes_per_chunk = 2;
2317 1.1 skrll info->display_endian = info->endian;
2318 1.1 skrll info->insn_info_valid = 1;
2319 1.5 christos info->branch_delay_insns = 0;
2320 1.5 christos info->data_size = 0;
2321 1.5 christos info->target = 0;
2322 1.5 christos info->target2 = 0;
2323 1.5 christos
2324 1.5 christos #define GET_OP(insn, field) \
2325 1.5 christos (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
2326 1.5 christos /* Decode PLT entry's GOT slot address word. */
2327 1.5 christos if (is_mips16_plt_tail (info, memaddr))
2328 1.5 christos {
2329 1.5 christos info->insn_type = dis_noninsn;
2330 1.5 christos status = (*info->read_memory_func) (memaddr, buffer, 4, info);
2331 1.5 christos if (status == 0)
2332 1.5 christos {
2333 1.5 christos unsigned int gotslot;
2334 1.11 christos
2335 1.11 christos if (info->endian == BFD_ENDIAN_BIG)
2336 1.11 christos gotslot = bfd_getb32 (buffer);
2337 1.5 christos else
2338 1.5 christos gotslot = bfd_getl32 (buffer);
2339 1.5 christos infprintf (is, dis_style_assembler_directive, ".word");
2340 1.5 christos infprintf (is, dis_style_text, "\t");
2341 1.5 christos infprintf (is, dis_style_immediate, "0x%x", gotslot);
2342 1.5 christos
2343 1.5 christos return 4;
2344 1.5 christos }
2345 1.5 christos }
2346 1.1 skrll else
2347 1.1 skrll {
2348 1.1 skrll info->insn_type = dis_nonbranch;
2349 1.1 skrll status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2350 1.1 skrll }
2351 1.1 skrll if (status != 0)
2352 1.10 christos {
2353 1.1 skrll (*info->memory_error_func) (status, memaddr, info);
2354 1.1 skrll return -1;
2355 1.7 christos }
2356 1.1 skrll
2357 1.7 christos extend_only = false;
2358 1.1 skrll
2359 1.7 christos if (info->endian == BFD_ENDIAN_BIG)
2360 1.7 christos first = bfd_getb16 (buffer);
2361 1.1 skrll else
2362 1.10 christos first = bfd_getl16 (buffer);
2363 1.1 skrll
2364 1.7 christos status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2365 1.1 skrll if (status == 0)
2366 1.7 christos {
2367 1.7 christos have_second = true;
2368 1.7 christos if (info->endian == BFD_ENDIAN_BIG)
2369 1.7 christos second = bfd_getb16 (buffer);
2370 1.7 christos else
2371 1.10 christos second = bfd_getl16 (buffer);
2372 1.7 christos full = (first << 16) | second;
2373 1.7 christos }
2374 1.1 skrll else
2375 1.1 skrll {
2376 1.1 skrll have_second = false;
2377 1.1 skrll second = 0;
2378 1.1 skrll full = first;
2379 1.1 skrll }
2380 1.1 skrll
2381 1.7 christos /* FIXME: Should probably use a hash table on the major opcode here. */
2382 1.7 christos
2383 1.7 christos opend = mips16_opcodes + bfd_mips16_num_opcodes;
2384 1.7 christos for (op = mips16_opcodes; op < opend; op++)
2385 1.7 christos {
2386 1.7 christos enum match_kind match;
2387 1.7 christos
2388 1.7 christos if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor))
2389 1.7 christos continue;
2390 1.7 christos
2391 1.7 christos if (op->pinfo == INSN_MACRO
2392 1.7 christos || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
2393 1.7 christos match = MATCH_NONE;
2394 1.7 christos else if (mips_opcode_32bit_p (op))
2395 1.7 christos {
2396 1.7 christos if (have_second
2397 1.7 christos && (full & op->mask) == op->match)
2398 1.7 christos match = MATCH_FULL;
2399 1.7 christos else
2400 1.7 christos match = MATCH_NONE;
2401 1.7 christos }
2402 1.7 christos else if ((first & op->mask) == op->match)
2403 1.7 christos {
2404 1.7 christos match = MATCH_SHORT;
2405 1.7 christos second = 0;
2406 1.7 christos full = first;
2407 1.1 skrll }
2408 1.7 christos else if ((first & 0xf800) == 0xf000
2409 1.1 skrll && have_second
2410 1.7 christos && !extend_only
2411 1.10 christos && (second & op->mask) == op->match)
2412 1.7 christos {
2413 1.7 christos if (op->pinfo2 & INSN2_SHORT_ONLY)
2414 1.7 christos {
2415 1.7 christos match = MATCH_NONE;
2416 1.7 christos extend_only = true;
2417 1.7 christos }
2418 1.1 skrll else
2419 1.7 christos match = MATCH_FULL;
2420 1.7 christos }
2421 1.7 christos else
2422 1.1 skrll match = MATCH_NONE;
2423 1.11 christos
2424 1.1 skrll if (match != MATCH_NONE)
2425 1.11 christos {
2426 1.1 skrll const char *s;
2427 1.5 christos
2428 1.1 skrll infprintf (is, dis_style_mnemonic, "%s", op->name);
2429 1.1 skrll if (op->args[0] != '\0')
2430 1.1 skrll infprintf (is, dis_style_text, "\t");
2431 1.1 skrll
2432 1.7 christos init_print_arg_state (&state);
2433 1.1 skrll for (s = op->args; *s != '\0'; s++)
2434 1.1 skrll {
2435 1.1 skrll if (*s == ','
2436 1.1 skrll && s[1] == 'w'
2437 1.1 skrll && GET_OP (full, RX) == GET_OP (full, RY))
2438 1.1 skrll {
2439 1.1 skrll /* Skip the register and the comma. */
2440 1.7 christos ++s;
2441 1.1 skrll continue;
2442 1.1 skrll }
2443 1.1 skrll if (*s == ','
2444 1.1 skrll && s[1] == 'v'
2445 1.1 skrll && GET_OP (full, RZ) == GET_OP (full, RX))
2446 1.7 christos {
2447 1.7 christos /* Skip the register and the comma. */
2448 1.7 christos ++s;
2449 1.7 christos continue;
2450 1.7 christos }
2451 1.7 christos if (s[0] == 'N'
2452 1.7 christos && s[1] == ','
2453 1.7 christos && s[2] == 'O'
2454 1.7 christos && op->name[strlen (op->name) - 1] == '0')
2455 1.7 christos {
2456 1.10 christos /* Coprocessor register 0 with sel field. */
2457 1.7 christos const struct mips_cp0sel_name *n;
2458 1.7 christos const struct mips_operand *operand;
2459 1.10 christos unsigned int reg, sel;
2460 1.7 christos
2461 1.7 christos operand = decode_mips16_operand (*s, true);
2462 1.7 christos reg = mips_extract_operand (operand, (first << 16) | second);
2463 1.7 christos s += 2;
2464 1.7 christos operand = decode_mips16_operand (*s, true);
2465 1.7 christos sel = mips_extract_operand (operand, (first << 16) | second);
2466 1.7 christos
2467 1.7 christos /* CP0 register including 'sel' code for mftc0, to be
2468 1.7 christos printed textually if known. If not known, print both
2469 1.7 christos CP0 register name and sel numerically since CP0 register
2470 1.7 christos with sel 0 may have a name unrelated to register being
2471 1.11 christos printed. */
2472 1.7 christos n = lookup_mips_cp0sel_name (mips_cp0sel_names,
2473 1.11 christos mips_cp0sel_names_len,
2474 1.11 christos reg, sel);
2475 1.11 christos if (n != NULL)
2476 1.11 christos infprintf (is, dis_style_register, "%s", n->name);
2477 1.11 christos else
2478 1.7 christos {
2479 1.7 christos infprintf (is, dis_style_register, "$%d", reg);
2480 1.7 christos infprintf (is, dis_style_text, ",");
2481 1.7 christos infprintf (is, dis_style_immediate, "%d", sel);
2482 1.7 christos }
2483 1.7 christos }
2484 1.10 christos else
2485 1.7 christos switch (match)
2486 1.7 christos {
2487 1.7 christos case MATCH_FULL:
2488 1.10 christos print_mips16_insn_arg (info, &state, op, *s, memaddr + 2,
2489 1.7 christos second, true, first, s[1] == '(');
2490 1.7 christos break;
2491 1.7 christos case MATCH_SHORT:
2492 1.7 christos print_mips16_insn_arg (info, &state, op, *s, memaddr,
2493 1.1 skrll first, false, 0, s[1] == '(');
2494 1.1 skrll break;
2495 1.3 christos case MATCH_NONE: /* Stop the compiler complaining. */
2496 1.1 skrll break;
2497 1.3 christos }
2498 1.5 christos }
2499 1.5 christos
2500 1.1 skrll /* Figure out branch instruction type and delay slot information. */
2501 1.3 christos if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
2502 1.3 christos info->branch_delay_insns = 1;
2503 1.3 christos if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0
2504 1.1 skrll || (op->pinfo2 & INSN2_UNCOND_BRANCH) != 0)
2505 1.1 skrll {
2506 1.5 christos if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2507 1.3 christos info->insn_type = dis_jsr;
2508 1.1 skrll else
2509 1.7 christos info->insn_type = dis_branch;
2510 1.1 skrll }
2511 1.1 skrll else if ((op->pinfo2 & INSN2_COND_BRANCH) != 0)
2512 1.4 christos info->insn_type = dis_condbranch;
2513 1.1 skrll
2514 1.11 christos return match == MATCH_FULL ? 4 : 2;
2515 1.11 christos }
2516 1.11 christos }
2517 1.4 christos #undef GET_OP
2518 1.4 christos
2519 1.7 christos infprintf (is, dis_style_assembler_directive, ".short");
2520 1.4 christos infprintf (is, dis_style_text, "\t");
2521 1.4 christos infprintf (is, dis_style_immediate, "0x%x", first);
2522 1.4 christos info->insn_type = dis_noninsn;
2523 1.4 christos
2524 1.4 christos return 2;
2525 1.4 christos }
2526 1.4 christos
2527 1.11 christos /* Disassemble microMIPS instructions. */
2528 1.4 christos
2529 1.4 christos static int
2530 1.4 christos print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
2531 1.5 christos {
2532 1.5 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
2533 1.4 christos const struct mips_opcode *op, *opend;
2534 1.5 christos void *is = info->stream;
2535 1.4 christos bfd_byte buffer[2];
2536 1.4 christos unsigned int higher;
2537 1.4 christos unsigned int length;
2538 1.4 christos int status;
2539 1.4 christos unsigned int insn;
2540 1.4 christos
2541 1.4 christos info->bytes_per_chunk = 2;
2542 1.4 christos info->display_endian = info->endian;
2543 1.4 christos info->insn_info_valid = 1;
2544 1.4 christos info->branch_delay_insns = 0;
2545 1.4 christos info->data_size = 0;
2546 1.4 christos info->insn_type = dis_nonbranch;
2547 1.4 christos info->target = 0;
2548 1.4 christos info->target2 = 0;
2549 1.4 christos
2550 1.4 christos status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2551 1.4 christos if (status != 0)
2552 1.4 christos {
2553 1.4 christos (*info->memory_error_func) (status, memaddr, info);
2554 1.4 christos return -1;
2555 1.4 christos }
2556 1.4 christos
2557 1.4 christos length = 2;
2558 1.4 christos
2559 1.6 christos if (info->endian == BFD_ENDIAN_BIG)
2560 1.4 christos insn = bfd_getb16 (buffer);
2561 1.4 christos else
2562 1.4 christos insn = bfd_getl16 (buffer);
2563 1.4 christos
2564 1.4 christos if ((insn & 0x1c00) == 0x0000 || (insn & 0x1000) == 0x1000)
2565 1.4 christos {
2566 1.4 christos /* This is a 32-bit microMIPS instruction. */
2567 1.11 christos higher = insn;
2568 1.4 christos
2569 1.4 christos status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2570 1.4 christos if (status != 0)
2571 1.4 christos {
2572 1.4 christos infprintf (is, dis_style_text, "micromips 0x%x", higher);
2573 1.4 christos (*info->memory_error_func) (status, memaddr + 2, info);
2574 1.4 christos return -1;
2575 1.4 christos }
2576 1.4 christos
2577 1.4 christos if (info->endian == BFD_ENDIAN_BIG)
2578 1.4 christos insn = bfd_getb16 (buffer);
2579 1.4 christos else
2580 1.4 christos insn = bfd_getl16 (buffer);
2581 1.4 christos
2582 1.4 christos insn = insn | (higher << 16);
2583 1.4 christos
2584 1.4 christos length += 2;
2585 1.4 christos }
2586 1.4 christos
2587 1.4 christos /* FIXME: Should probably use a hash table on the major opcode here. */
2588 1.4 christos
2589 1.4 christos opend = micromips_opcodes + bfd_micromips_num_opcodes;
2590 1.4 christos for (op = micromips_opcodes; op < opend; op++)
2591 1.4 christos {
2592 1.4 christos if (op->pinfo != INSN_MACRO
2593 1.5 christos && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
2594 1.5 christos && (insn & op->mask) == op->match
2595 1.4 christos && ((length == 2 && (op->mask & 0xffff0000) == 0)
2596 1.11 christos || (length == 4 && (op->mask & 0xffff0000) != 0)))
2597 1.4 christos {
2598 1.5 christos if (!validate_insn_args (op, decode_micromips_operand, insn))
2599 1.4 christos continue;
2600 1.11 christos
2601 1.5 christos infprintf (is, dis_style_mnemonic, "%s", op->name);
2602 1.5 christos
2603 1.4 christos if (op->args[0])
2604 1.4 christos {
2605 1.4 christos infprintf (is, dis_style_text, "\t");
2606 1.4 christos print_insn_args (info, op, decode_micromips_operand, insn,
2607 1.4 christos memaddr + 1, length);
2608 1.4 christos }
2609 1.4 christos
2610 1.4 christos /* Figure out instruction type and branch delay information. */
2611 1.4 christos if ((op->pinfo
2612 1.5 christos & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY)) != 0)
2613 1.4 christos info->branch_delay_insns = 1;
2614 1.4 christos if (((op->pinfo & INSN_UNCOND_BRANCH_DELAY)
2615 1.4 christos | (op->pinfo2 & INSN2_UNCOND_BRANCH)) != 0)
2616 1.4 christos {
2617 1.4 christos if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
2618 1.4 christos info->insn_type = dis_jsr;
2619 1.4 christos else
2620 1.4 christos info->insn_type = dis_branch;
2621 1.4 christos }
2622 1.4 christos else if (((op->pinfo & INSN_COND_BRANCH_DELAY)
2623 1.4 christos | (op->pinfo2 & INSN2_COND_BRANCH)) != 0)
2624 1.4 christos {
2625 1.4 christos if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2626 1.5 christos info->insn_type = dis_condjsr;
2627 1.4 christos else
2628 1.4 christos info->insn_type = dis_condbranch;
2629 1.4 christos }
2630 1.4 christos else if ((op->pinfo
2631 1.4 christos & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY)) != 0)
2632 1.4 christos info->insn_type = dis_dref;
2633 1.11 christos
2634 1.11 christos return length;
2635 1.11 christos }
2636 1.11 christos }
2637 1.11 christos
2638 1.11 christos infprintf (is, dis_style_assembler_directive, ".short");
2639 1.11 christos infprintf (is, dis_style_text, "\t");
2640 1.11 christos if (length != 2)
2641 1.11 christos {
2642 1.1 skrll infprintf (is, dis_style_immediate, "0x%x", (insn >> 16) & 0xffff);
2643 1.1 skrll infprintf (is, dis_style_text, ", ");
2644 1.1 skrll }
2645 1.1 skrll infprintf (is, dis_style_immediate, "0x%x", (insn & 0xffff));
2646 1.1 skrll
2647 1.4 christos info->insn_type = dis_noninsn;
2648 1.6 christos
2649 1.6 christos return length;
2650 1.6 christos }
2651 1.6 christos
2652 1.6 christos /* Return 1 if a symbol associated with the location being disassembled
2653 1.6 christos indicates a compressed mode, either MIPS16 or microMIPS, according to
2654 1.4 christos MICROMIPS_P. We iterate over all the symbols at the address being
2655 1.10 christos considered assuming if at least one of them indicates code compression,
2656 1.10 christos then such code has been genuinely produced here (other symbols could
2657 1.4 christos have been derived from function symbols defined elsewhere or could
2658 1.4 christos define data). Otherwise, return 0. */
2659 1.5 christos
2660 1.4 christos static bool
2661 1.5 christos is_compressed_mode_p (struct disassemble_info *info, bool micromips_p)
2662 1.5 christos {
2663 1.6 christos int i;
2664 1.5 christos int l;
2665 1.6 christos
2666 1.5 christos for (i = info->symtab_pos, l = i + info->num_symbols; i < l; i++)
2667 1.5 christos if (((info->symtab[i])->flags & BSF_SYNTHETIC) != 0
2668 1.5 christos && ((!micromips_p
2669 1.5 christos && ELF_ST_IS_MIPS16 ((*info->symbols)->udata.i))
2670 1.5 christos || (micromips_p
2671 1.5 christos && ELF_ST_IS_MICROMIPS ((*info->symbols)->udata.i))))
2672 1.6 christos return 1;
2673 1.5 christos else if (bfd_asymbol_flavour (info->symtab[i]) == bfd_target_elf_flavour
2674 1.6 christos && info->symtab[i]->section == info->section)
2675 1.5 christos {
2676 1.5 christos elf_symbol_type *symbol = (elf_symbol_type *) info->symtab[i];
2677 1.5 christos if ((!micromips_p
2678 1.4 christos && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
2679 1.4 christos || (micromips_p
2680 1.4 christos && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
2681 1.4 christos return 1;
2682 1.1 skrll }
2683 1.1 skrll
2684 1.1 skrll return 0;
2685 1.1 skrll }
2686 1.1 skrll
2687 1.1 skrll /* In an environment where we do not know the symbol type of the
2688 1.1 skrll instruction we are forced to assume that the low order bit of the
2689 1.1 skrll instructions' address may mark it as a mips16 instruction. If we
2690 1.1 skrll are single stepping, or the pc is within the disassembled function,
2691 1.1 skrll this works. Otherwise, we need a clue. Sometimes. */
2692 1.1 skrll
2693 1.1 skrll static int
2694 1.1 skrll _print_insn_mips (bfd_vma memaddr,
2695 1.1 skrll struct disassemble_info *info,
2696 1.1 skrll enum bfd_endian endianness)
2697 1.1 skrll {
2698 1.1 skrll bfd_byte buffer[INSNLEN];
2699 1.4 christos int status;
2700 1.4 christos
2701 1.4 christos set_default_mips_dis_options (info);
2702 1.4 christos parse_mips_dis_options (info->disassembler_options);
2703 1.4 christos
2704 1.1 skrll if (info->mach == bfd_mach_mips16)
2705 1.4 christos return print_insn_mips16 (memaddr, info);
2706 1.1 skrll if (info->mach == bfd_mach_mips_micromips)
2707 1.1 skrll return print_insn_micromips (memaddr, info);
2708 1.6 christos
2709 1.6 christos #if 1
2710 1.6 christos /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
2711 1.6 christos /* Only a few tools will work this way. */
2712 1.6 christos if (memaddr & 0x01)
2713 1.6 christos {
2714 1.1 skrll if (micromips_ase)
2715 1.1 skrll return print_insn_micromips (memaddr, info);
2716 1.1 skrll else
2717 1.10 christos return print_insn_mips16 (memaddr, info);
2718 1.6 christos }
2719 1.10 christos #endif
2720 1.6 christos
2721 1.1 skrll #if SYMTAB_AVAILABLE
2722 1.1 skrll if (is_compressed_mode_p (info, true))
2723 1.1 skrll return print_insn_micromips (memaddr, info);
2724 1.1 skrll if (is_compressed_mode_p (info, false))
2725 1.1 skrll return print_insn_mips16 (memaddr, info);
2726 1.4 christos #endif
2727 1.1 skrll
2728 1.1 skrll status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
2729 1.4 christos if (status == 0)
2730 1.1 skrll {
2731 1.4 christos int insn;
2732 1.1 skrll
2733 1.1 skrll if (endianness == BFD_ENDIAN_BIG)
2734 1.1 skrll insn = bfd_getb32 (buffer);
2735 1.1 skrll else
2736 1.1 skrll insn = bfd_getl32 (buffer);
2737 1.1 skrll
2738 1.1 skrll return print_insn_mips (memaddr, insn, info);
2739 1.1 skrll }
2740 1.1 skrll else
2741 1.1 skrll {
2742 1.1 skrll (*info->memory_error_func) (status, memaddr, info);
2743 1.1 skrll return -1;
2744 1.1 skrll }
2745 1.1 skrll }
2746 1.1 skrll
2747 1.1 skrll int
2748 1.1 skrll print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info)
2749 1.1 skrll {
2750 1.1 skrll return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
2751 1.1 skrll }
2752 1.1 skrll
2753 1.1 skrll int
2754 1.9 christos print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info)
2755 1.9 christos {
2756 1.9 christos return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
2757 1.9 christos }
2758 1.9 christos
2759 1.9 christos /* Indices into option argument vector for options accepting an argument.
2761 1.9 christos Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2762 1.9 christos typedef enum
2763 1.9 christos {
2764 1.9 christos MIPS_OPTION_ARG_NONE = -1,
2765 1.9 christos MIPS_OPTION_ARG_ABI,
2766 1.9 christos MIPS_OPTION_ARG_ARCH,
2767 1.9 christos MIPS_OPTION_ARG_SIZE
2768 1.9 christos } mips_option_arg_t;
2769 1.9 christos
2770 1.9 christos /* Valid MIPS disassembler options. */
2771 1.9 christos static struct
2772 1.9 christos {
2773 1.9 christos const char *name;
2774 1.9 christos const char *description;
2775 1.9 christos mips_option_arg_t arg;
2776 1.9 christos } mips_options[] =
2777 1.9 christos {
2778 1.9 christos { "no-aliases", N_("Use canonical instruction forms.\n"),
2779 1.9 christos MIPS_OPTION_ARG_NONE },
2780 1.9 christos { "msa", N_("Recognize MSA instructions.\n"),
2781 1.9 christos MIPS_OPTION_ARG_NONE },
2782 1.9 christos { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2783 1.9 christos MIPS_OPTION_ARG_NONE },
2784 1.9 christos { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2785 1.9 christos instructions.\n"),
2786 1.9 christos MIPS_OPTION_ARG_NONE },
2787 1.9 christos { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2788 1.9 christos "instructions.\n"),
2789 1.9 christos MIPS_OPTION_ARG_NONE },
2790 1.9 christos { "loongson-mmi",
2791 1.9 christos N_("Recognize the Loongson MultiMedia extensions "
2792 1.9 christos "Instructions (MMI) ASE instructions.\n"),
2793 1.9 christos MIPS_OPTION_ARG_NONE },
2794 1.9 christos { "loongson-cam",
2795 1.9 christos N_("Recognize the Loongson Content Address Memory (CAM) "
2796 1.9 christos " instructions.\n"),
2797 1.9 christos MIPS_OPTION_ARG_NONE },
2798 1.9 christos { "loongson-ext",
2799 1.9 christos N_("Recognize the Loongson EXTensions (EXT) "
2800 1.9 christos " instructions.\n"),
2801 1.9 christos MIPS_OPTION_ARG_NONE },
2802 1.9 christos { "loongson-ext2",
2803 1.9 christos N_("Recognize the Loongson EXTensions R2 (EXT2) "
2804 1.9 christos " instructions.\n"),
2805 1.9 christos MIPS_OPTION_ARG_NONE },
2806 1.9 christos { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2807 1.9 christos Default: based on binary being disassembled.\n"),
2808 1.9 christos MIPS_OPTION_ARG_ABI },
2809 1.9 christos { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2810 1.9 christos Default: numeric.\n"),
2811 1.9 christos MIPS_OPTION_ARG_ABI },
2812 1.9 christos { "cp0-names=", N_("Print CP0 register names according to specified "
2813 1.9 christos "architecture.\n\
2814 1.9 christos Default: based on binary being disassembled.\n"),
2815 1.9 christos MIPS_OPTION_ARG_ARCH },
2816 1.9 christos { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2817 1.9 christos Default: based on binary being disassembled.\n"),
2818 1.9 christos MIPS_OPTION_ARG_ARCH },
2819 1.9 christos { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2820 1.9 christos MIPS_OPTION_ARG_ABI },
2821 1.9 christos { "reg-names=", N_("Print CP0 register and HWR names according to "
2822 1.9 christos "specified\n\
2823 1.9 christos architecture."),
2824 1.9 christos MIPS_OPTION_ARG_ARCH }
2825 1.9 christos };
2826 1.9 christos
2827 1.9 christos /* Build the structure representing valid MIPS disassembler options.
2828 1.9 christos This is done dynamically for maintenance ease purpose; a static
2829 1.9 christos initializer would be unreadable. */
2830 1.9 christos
2831 1.9 christos const disasm_options_and_args_t *
2832 1.9 christos disassembler_options_mips (void)
2833 1.9 christos {
2834 1.9 christos static disasm_options_and_args_t *opts_and_args;
2835 1.9 christos
2836 1.9 christos if (opts_and_args == NULL)
2837 1.9 christos {
2838 1.9 christos size_t num_options = ARRAY_SIZE (mips_options);
2839 1.9 christos size_t num_args = MIPS_OPTION_ARG_SIZE;
2840 1.9 christos disasm_option_arg_t *args;
2841 1.9 christos disasm_options_t *opts;
2842 1.9 christos size_t i;
2843 1.9 christos size_t j;
2844 1.9 christos
2845 1.9 christos args = XNEWVEC (disasm_option_arg_t, num_args + 1);
2846 1.9 christos
2847 1.9 christos args[MIPS_OPTION_ARG_ABI].name = "ABI";
2848 1.9 christos args[MIPS_OPTION_ARG_ABI].values
2849 1.9 christos = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices) + 1);
2850 1.9 christos for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
2851 1.9 christos args[MIPS_OPTION_ARG_ABI].values[i] = mips_abi_choices[i].name;
2852 1.9 christos /* The array we return must be NULL terminated. */
2853 1.9 christos args[MIPS_OPTION_ARG_ABI].values[i] = NULL;
2854 1.9 christos
2855 1.9 christos args[MIPS_OPTION_ARG_ARCH].name = "ARCH";
2856 1.9 christos args[MIPS_OPTION_ARG_ARCH].values
2857 1.9 christos = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices) + 1);
2858 1.9 christos for (i = 0, j = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
2859 1.9 christos if (*mips_arch_choices[i].name != '\0')
2860 1.9 christos args[MIPS_OPTION_ARG_ARCH].values[j++] = mips_arch_choices[i].name;
2861 1.9 christos /* The array we return must be NULL terminated. */
2862 1.9 christos args[MIPS_OPTION_ARG_ARCH].values[j] = NULL;
2863 1.9 christos
2864 1.9 christos /* The array we return must be NULL terminated. */
2865 1.9 christos args[MIPS_OPTION_ARG_SIZE].name = NULL;
2866 1.9 christos args[MIPS_OPTION_ARG_SIZE].values = NULL;
2867 1.9 christos
2868 1.9 christos opts_and_args = XNEW (disasm_options_and_args_t);
2869 1.9 christos opts_and_args->args = args;
2870 1.9 christos
2871 1.9 christos opts = &opts_and_args->options;
2872 1.9 christos opts->name = XNEWVEC (const char *, num_options + 1);
2873 1.9 christos opts->description = XNEWVEC (const char *, num_options + 1);
2874 1.9 christos opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1);
2875 1.9 christos for (i = 0; i < num_options; i++)
2876 1.9 christos {
2877 1.9 christos opts->name[i] = mips_options[i].name;
2878 1.9 christos opts->description[i] = _(mips_options[i].description);
2879 1.9 christos if (mips_options[i].arg != MIPS_OPTION_ARG_NONE)
2880 1.9 christos opts->arg[i] = &args[mips_options[i].arg];
2881 1.9 christos else
2882 1.9 christos opts->arg[i] = NULL;
2883 1.9 christos }
2884 1.9 christos /* The array we return must be NULL terminated. */
2885 1.9 christos opts->name[i] = NULL;
2886 1.9 christos opts->description[i] = NULL;
2887 1.1 skrll opts->arg[i] = NULL;
2888 1.1 skrll }
2889 1.1 skrll
2890 1.9 christos return opts_and_args;
2891 1.9 christos }
2892 1.9 christos
2893 1.9 christos void
2894 1.9 christos print_mips_disassembler_options (FILE *stream)
2895 1.9 christos {
2896 1.9 christos const disasm_options_and_args_t *opts_and_args;
2897 1.9 christos const disasm_option_arg_t *args;
2898 1.9 christos const disasm_options_t *opts;
2899 1.9 christos size_t max_len = 0;
2900 1.1 skrll size_t i;
2901 1.1 skrll size_t j;
2902 1.1 skrll
2903 1.9 christos opts_and_args = disassembler_options_mips ();
2904 1.1 skrll opts = &opts_and_args->options;
2905 1.9 christos args = opts_and_args->args;
2906 1.9 christos
2907 1.9 christos fprintf (stream, _("\n\
2908 1.9 christos The following MIPS specific disassembler options are supported for use\n\
2909 1.7 christos with the -M switch (multiple options should be separated by commas):\n\n"));
2910 1.9 christos
2911 1.9 christos /* Compute the length of the longest option name. */
2912 1.9 christos for (i = 0; opts->name[i] != NULL; i++)
2913 1.9 christos {
2914 1.9 christos size_t len = strlen (opts->name[i]);
2915 1.5 christos
2916 1.9 christos if (opts->arg[i] != NULL)
2917 1.9 christos len += strlen (opts->arg[i]->name);
2918 1.9 christos if (max_len < len)
2919 1.9 christos max_len = len;
2920 1.9 christos }
2921 1.9 christos
2922 1.9 christos for (i = 0, max_len++; opts->name[i] != NULL; i++)
2923 1.9 christos {
2924 1.5 christos fprintf (stream, " %s", opts->name[i]);
2925 1.9 christos if (opts->arg[i] != NULL)
2926 1.9 christos fprintf (stream, "%s", opts->arg[i]->name);
2927 1.9 christos if (opts->description[i] != NULL)
2928 1.9 christos {
2929 1.9 christos size_t len = strlen (opts->name[i]);
2930 1.9 christos
2931 1.9 christos if (opts->arg[i] != NULL)
2932 1.5 christos len += strlen (opts->arg[i]->name);
2933 1.9 christos fprintf (stream,
2934 1.9 christos "%*c %s", (int) (max_len - len), ' ', opts->description[i]);
2935 1.11 christos }
2936 1.11 christos fprintf (stream, _("\n"));
2937 1.9 christos }
2938 1.9 christos
2939 1.9 christos for (i = 0; args[i].name != NULL; i++)
2940 1.9 christos {
2941 1.9 christos if (args[i].values == NULL)
2942 1.9 christos continue;
2943 1.9 christos fprintf (stream, _("\n\
2944 1.1 skrll For the options above, the following values are supported for \"%s\":\n "),
2945 1.1 skrll args[i].name);
2946 1.1 skrll for (j = 0; args[i].values[j] != NULL; j++)
2947 fprintf (stream, " %s", args[i].values[j]);
2948 fprintf (stream, _("\n"));
2949 }
2950
2951 fprintf (stream, _("\n"));
2952 }
2953