1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 Copyright (C) 1989-2022 Free Software Foundation, Inc.
3 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
5 This file is part of the GNU opcodes library.
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
23 #include "disassemble.h"
24 #include "libiberty.h"
25 #include "opcode/mips.h"
29 #include "elfxx-mips.h"
31 /* FIXME: These are needed to figure out if the code is mips16 or
32 not. The low bit of the address is often a good indicator. No
33 symbol table is available when this code runs out in an embedded
34 system as when it is used for disassembler support in a monitor. */
36 #if !defined(EMBEDDED_ENV)
37 #define SYMTAB_AVAILABLE 1
40 /* Mips instructions are at maximum this many bytes long. */
44 /* FIXME: These should be shared with gdb somehow. */
46 struct mips_cp0sel_name
50 const char * const name
;
53 static const char * const mips_gpr_names_numeric
[32] =
55 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
56 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
57 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
58 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
61 static const char * const mips_gpr_names_oldabi
[32] =
63 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
64 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
65 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
66 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
69 static const char * const mips_gpr_names_newabi
[32] =
71 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
72 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
73 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
74 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
77 static const char * const mips_fpr_names_numeric
[32] =
79 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
80 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
81 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
82 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
85 static const char * const mips_fpr_names_32
[32] =
87 "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
88 "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
89 "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f",
90 "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f"
93 static const char * const mips_fpr_names_n32
[32] =
95 "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3",
96 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
97 "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9",
98 "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13"
101 static const char * const mips_fpr_names_64
[32] =
103 "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
104 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
105 "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
106 "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
109 static const char * const mips_cp0_names_numeric
[32] =
111 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
112 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
113 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
114 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
117 static const char * const mips_cp1_names_numeric
[32] =
119 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
120 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
121 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
122 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
125 static const char * const mips_cp0_names_r3900
[32] =
127 "$0", "$1", "$2", "c0_config",
128 "$4", "$5", "$6", "c0_cache",
129 "c0_badvaddr", "$9", "$10", "$11",
130 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
131 "c0_debug", "c0_depc", "$18", "$19",
132 "$20", "$21", "$22", "$23",
133 "$24", "$25", "$26", "$27",
134 "$28", "$29", "$30", "$31",
137 static const char * const mips_cp0_names_r3000
[32] =
139 "c0_index", "c0_random", "c0_entrylo", "$3",
140 "c0_context", "$5", "$6", "$7",
141 "c0_badvaddr", "$9", "c0_entryhi", "$11",
142 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
143 "$16", "$17", "$18", "$19",
144 "$20", "$21", "$22", "$23",
145 "$24", "$25", "$26", "$27",
146 "$28", "$29", "$30", "$31",
149 static const char * const mips_cp0_names_r4000
[32] =
151 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
152 "c0_context", "c0_pagemask", "c0_wired", "$7",
153 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
154 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
155 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
156 "c0_xcontext", "$21", "$22", "$23",
157 "$24", "$25", "c0_ecc", "c0_cacheerr",
158 "c0_taglo", "c0_taghi", "c0_errorepc", "$31",
161 static const char * const mips_cp0_names_r5900
[32] =
163 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
164 "c0_context", "c0_pagemask", "c0_wired", "$7",
165 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
166 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
167 "c0_config", "$17", "$18", "$19",
168 "$20", "$21", "$22", "c0_badpaddr",
169 "c0_depc", "c0_perfcnt", "$26", "$27",
170 "c0_taglo", "c0_taghi", "c0_errorepc", "$31"
173 static const char * const mips_cp0_names_mips3264
[32] =
175 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
176 "c0_context", "c0_pagemask", "c0_wired", "$7",
177 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
178 "c0_status", "c0_cause", "c0_epc", "c0_prid",
179 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
180 "c0_xcontext", "$21", "$22", "c0_debug",
181 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
182 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
185 static const char * const mips_cp1_names_mips
[32] =
187 "c1_fir", "$1", "$2", "$3",
188 "$4", "$5", "$6", "$7",
189 "$8", "$9", "$10", "$11",
190 "$12", "$13", "$14", "$15",
191 "$16", "$17", "$18", "$19",
192 "$20", "$21", "$22", "$23",
193 "$24", "$25", "$26", "$27",
194 "$28", "$29", "$30", "c1_fcsr"
197 static const char * const mips_cp1_names_mips3264
[32] =
199 "c1_fir", "c1_ufr", "$2", "$3",
200 "c1_unfr", "$5", "$6", "$7",
201 "$8", "$9", "$10", "$11",
202 "$12", "$13", "$14", "$15",
203 "$16", "$17", "$18", "$19",
204 "$20", "$21", "$22", "$23",
205 "$24", "c1_fccr", "c1_fexr", "$27",
206 "c1_fenr", "$29", "$30", "c1_fcsr"
209 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264
[] =
211 { 16, 1, "c0_config1" },
212 { 16, 2, "c0_config2" },
213 { 16, 3, "c0_config3" },
214 { 18, 1, "c0_watchlo,1" },
215 { 18, 2, "c0_watchlo,2" },
216 { 18, 3, "c0_watchlo,3" },
217 { 18, 4, "c0_watchlo,4" },
218 { 18, 5, "c0_watchlo,5" },
219 { 18, 6, "c0_watchlo,6" },
220 { 18, 7, "c0_watchlo,7" },
221 { 19, 1, "c0_watchhi,1" },
222 { 19, 2, "c0_watchhi,2" },
223 { 19, 3, "c0_watchhi,3" },
224 { 19, 4, "c0_watchhi,4" },
225 { 19, 5, "c0_watchhi,5" },
226 { 19, 6, "c0_watchhi,6" },
227 { 19, 7, "c0_watchhi,7" },
228 { 25, 1, "c0_perfcnt,1" },
229 { 25, 2, "c0_perfcnt,2" },
230 { 25, 3, "c0_perfcnt,3" },
231 { 25, 4, "c0_perfcnt,4" },
232 { 25, 5, "c0_perfcnt,5" },
233 { 25, 6, "c0_perfcnt,6" },
234 { 25, 7, "c0_perfcnt,7" },
235 { 27, 1, "c0_cacheerr,1" },
236 { 27, 2, "c0_cacheerr,2" },
237 { 27, 3, "c0_cacheerr,3" },
238 { 28, 1, "c0_datalo" },
239 { 29, 1, "c0_datahi" }
242 static const char * const mips_cp0_names_mips3264r2
[32] =
244 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
245 "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
246 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
247 "c0_status", "c0_cause", "c0_epc", "c0_prid",
248 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
249 "c0_xcontext", "$21", "$22", "c0_debug",
250 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
251 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
254 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2
[] =
256 { 4, 1, "c0_contextconfig" },
257 { 0, 1, "c0_mvpcontrol" },
258 { 0, 2, "c0_mvpconf0" },
259 { 0, 3, "c0_mvpconf1" },
260 { 1, 1, "c0_vpecontrol" },
261 { 1, 2, "c0_vpeconf0" },
262 { 1, 3, "c0_vpeconf1" },
263 { 1, 4, "c0_yqmask" },
264 { 1, 5, "c0_vpeschedule" },
265 { 1, 6, "c0_vpeschefback" },
266 { 2, 1, "c0_tcstatus" },
267 { 2, 2, "c0_tcbind" },
268 { 2, 3, "c0_tcrestart" },
269 { 2, 4, "c0_tchalt" },
270 { 2, 5, "c0_tccontext" },
271 { 2, 6, "c0_tcschedule" },
272 { 2, 7, "c0_tcschefback" },
273 { 5, 1, "c0_pagegrain" },
274 { 6, 1, "c0_srsconf0" },
275 { 6, 2, "c0_srsconf1" },
276 { 6, 3, "c0_srsconf2" },
277 { 6, 4, "c0_srsconf3" },
278 { 6, 5, "c0_srsconf4" },
279 { 12, 1, "c0_intctl" },
280 { 12, 2, "c0_srsctl" },
281 { 12, 3, "c0_srsmap" },
282 { 15, 1, "c0_ebase" },
283 { 16, 1, "c0_config1" },
284 { 16, 2, "c0_config2" },
285 { 16, 3, "c0_config3" },
286 { 18, 1, "c0_watchlo,1" },
287 { 18, 2, "c0_watchlo,2" },
288 { 18, 3, "c0_watchlo,3" },
289 { 18, 4, "c0_watchlo,4" },
290 { 18, 5, "c0_watchlo,5" },
291 { 18, 6, "c0_watchlo,6" },
292 { 18, 7, "c0_watchlo,7" },
293 { 19, 1, "c0_watchhi,1" },
294 { 19, 2, "c0_watchhi,2" },
295 { 19, 3, "c0_watchhi,3" },
296 { 19, 4, "c0_watchhi,4" },
297 { 19, 5, "c0_watchhi,5" },
298 { 19, 6, "c0_watchhi,6" },
299 { 19, 7, "c0_watchhi,7" },
300 { 23, 1, "c0_tracecontrol" },
301 { 23, 2, "c0_tracecontrol2" },
302 { 23, 3, "c0_usertracedata" },
303 { 23, 4, "c0_tracebpc" },
304 { 25, 1, "c0_perfcnt,1" },
305 { 25, 2, "c0_perfcnt,2" },
306 { 25, 3, "c0_perfcnt,3" },
307 { 25, 4, "c0_perfcnt,4" },
308 { 25, 5, "c0_perfcnt,5" },
309 { 25, 6, "c0_perfcnt,6" },
310 { 25, 7, "c0_perfcnt,7" },
311 { 27, 1, "c0_cacheerr,1" },
312 { 27, 2, "c0_cacheerr,2" },
313 { 27, 3, "c0_cacheerr,3" },
314 { 28, 1, "c0_datalo" },
315 { 28, 2, "c0_taglo1" },
316 { 28, 3, "c0_datalo1" },
317 { 28, 4, "c0_taglo2" },
318 { 28, 5, "c0_datalo2" },
319 { 28, 6, "c0_taglo3" },
320 { 28, 7, "c0_datalo3" },
321 { 29, 1, "c0_datahi" },
322 { 29, 2, "c0_taghi1" },
323 { 29, 3, "c0_datahi1" },
324 { 29, 4, "c0_taghi2" },
325 { 29, 5, "c0_datahi2" },
326 { 29, 6, "c0_taghi3" },
327 { 29, 7, "c0_datahi3" },
330 /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
331 static const char * const mips_cp0_names_sb1
[32] =
333 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
334 "c0_context", "c0_pagemask", "c0_wired", "$7",
335 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
336 "c0_status", "c0_cause", "c0_epc", "c0_prid",
337 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
338 "c0_xcontext", "$21", "$22", "c0_debug",
339 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
340 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
343 static const struct mips_cp0sel_name mips_cp0sel_names_sb1
[] =
345 { 16, 1, "c0_config1" },
346 { 18, 1, "c0_watchlo,1" },
347 { 19, 1, "c0_watchhi,1" },
348 { 22, 0, "c0_perftrace" },
349 { 23, 3, "c0_edebug" },
350 { 25, 1, "c0_perfcnt,1" },
351 { 25, 2, "c0_perfcnt,2" },
352 { 25, 3, "c0_perfcnt,3" },
353 { 25, 4, "c0_perfcnt,4" },
354 { 25, 5, "c0_perfcnt,5" },
355 { 25, 6, "c0_perfcnt,6" },
356 { 25, 7, "c0_perfcnt,7" },
357 { 26, 1, "c0_buserr_pa" },
358 { 27, 1, "c0_cacheerr_d" },
359 { 27, 3, "c0_cacheerr_d_pa" },
360 { 28, 1, "c0_datalo_i" },
361 { 28, 2, "c0_taglo_d" },
362 { 28, 3, "c0_datalo_d" },
363 { 29, 1, "c0_datahi_i" },
364 { 29, 2, "c0_taghi_d" },
365 { 29, 3, "c0_datahi_d" },
368 /* Xlr cop0 register names. */
369 static const char * const mips_cp0_names_xlr
[32] = {
370 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
371 "c0_context", "c0_pagemask", "c0_wired", "$7",
372 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
373 "c0_status", "c0_cause", "c0_epc", "c0_prid",
374 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
375 "c0_xcontext", "$21", "$22", "c0_debug",
376 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
377 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
380 /* XLR's CP0 Select Registers. */
382 static const struct mips_cp0sel_name mips_cp0sel_names_xlr
[] = {
383 { 9, 6, "c0_extintreq" },
384 { 9, 7, "c0_extintmask" },
385 { 15, 1, "c0_ebase" },
386 { 16, 1, "c0_config1" },
387 { 16, 2, "c0_config2" },
388 { 16, 3, "c0_config3" },
389 { 16, 7, "c0_procid2" },
390 { 18, 1, "c0_watchlo,1" },
391 { 18, 2, "c0_watchlo,2" },
392 { 18, 3, "c0_watchlo,3" },
393 { 18, 4, "c0_watchlo,4" },
394 { 18, 5, "c0_watchlo,5" },
395 { 18, 6, "c0_watchlo,6" },
396 { 18, 7, "c0_watchlo,7" },
397 { 19, 1, "c0_watchhi,1" },
398 { 19, 2, "c0_watchhi,2" },
399 { 19, 3, "c0_watchhi,3" },
400 { 19, 4, "c0_watchhi,4" },
401 { 19, 5, "c0_watchhi,5" },
402 { 19, 6, "c0_watchhi,6" },
403 { 19, 7, "c0_watchhi,7" },
404 { 25, 1, "c0_perfcnt,1" },
405 { 25, 2, "c0_perfcnt,2" },
406 { 25, 3, "c0_perfcnt,3" },
407 { 25, 4, "c0_perfcnt,4" },
408 { 25, 5, "c0_perfcnt,5" },
409 { 25, 6, "c0_perfcnt,6" },
410 { 25, 7, "c0_perfcnt,7" },
411 { 27, 1, "c0_cacheerr,1" },
412 { 27, 2, "c0_cacheerr,2" },
413 { 27, 3, "c0_cacheerr,3" },
414 { 28, 1, "c0_datalo" },
415 { 29, 1, "c0_datahi" }
418 static const char * const mips_hwr_names_numeric
[32] =
420 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
421 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
422 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
423 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
426 static const char * const mips_hwr_names_mips3264r2
[32] =
428 "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
429 "$4", "$5", "$6", "$7",
430 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
431 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
432 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
435 static const char * const msa_control_names
[32] =
437 "msa_ir", "msa_csr", "msa_access", "msa_save",
438 "msa_modify", "msa_request", "msa_map", "msa_unmap",
439 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
440 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
441 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
444 struct mips_abi_choice
447 const char * const *gpr_names
;
448 const char * const *fpr_names
;
451 struct mips_abi_choice mips_abi_choices
[] =
453 { "numeric", mips_gpr_names_numeric
, mips_fpr_names_numeric
},
454 { "32", mips_gpr_names_oldabi
, mips_fpr_names_32
},
455 { "n32", mips_gpr_names_newabi
, mips_fpr_names_n32
},
456 { "64", mips_gpr_names_newabi
, mips_fpr_names_64
},
459 struct mips_arch_choice
463 unsigned long bfd_mach
;
467 const char * const *cp0_names
;
468 const struct mips_cp0sel_name
*cp0sel_names
;
469 unsigned int cp0sel_names_len
;
470 const char * const *cp1_names
;
471 const char * const *hwr_names
;
474 const struct mips_arch_choice mips_arch_choices
[] =
476 { "numeric", 0, 0, 0, 0, 0,
477 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
478 mips_hwr_names_numeric
},
480 { "r3000", 1, bfd_mach_mips3000
, CPU_R3000
, ISA_MIPS1
, 0,
481 mips_cp0_names_r3000
, NULL
, 0, mips_cp1_names_mips
,
482 mips_hwr_names_numeric
},
483 { "r3900", 1, bfd_mach_mips3900
, CPU_R3900
, ISA_MIPS1
, 0,
484 mips_cp0_names_r3900
, NULL
, 0, mips_cp1_names_numeric
,
485 mips_hwr_names_numeric
},
486 { "r4000", 1, bfd_mach_mips4000
, CPU_R4000
, ISA_MIPS3
, 0,
487 mips_cp0_names_r4000
, NULL
, 0, mips_cp1_names_mips
,
488 mips_hwr_names_numeric
},
489 { "r4010", 1, bfd_mach_mips4010
, CPU_R4010
, ISA_MIPS2
, 0,
490 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
491 mips_hwr_names_numeric
},
492 { "vr4100", 1, bfd_mach_mips4100
, CPU_VR4100
, ISA_MIPS3
, 0,
493 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
494 mips_hwr_names_numeric
},
495 { "vr4111", 1, bfd_mach_mips4111
, CPU_R4111
, ISA_MIPS3
, 0,
496 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
497 mips_hwr_names_numeric
},
498 { "vr4120", 1, bfd_mach_mips4120
, CPU_VR4120
, ISA_MIPS3
, 0,
499 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
500 mips_hwr_names_numeric
},
501 { "r4300", 1, bfd_mach_mips4300
, CPU_R4300
, ISA_MIPS3
, 0,
502 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
503 mips_hwr_names_numeric
},
504 { "r4400", 1, bfd_mach_mips4400
, CPU_R4400
, ISA_MIPS3
, 0,
505 mips_cp0_names_r4000
, NULL
, 0, mips_cp1_names_mips
,
506 mips_hwr_names_numeric
},
507 { "r4600", 1, bfd_mach_mips4600
, CPU_R4600
, ISA_MIPS3
, 0,
508 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
509 mips_hwr_names_numeric
},
510 { "r4650", 1, bfd_mach_mips4650
, CPU_R4650
, ISA_MIPS3
, 0,
511 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
512 mips_hwr_names_numeric
},
513 { "r5000", 1, bfd_mach_mips5000
, CPU_R5000
, ISA_MIPS4
, 0,
514 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
515 mips_hwr_names_numeric
},
516 { "vr5400", 1, bfd_mach_mips5400
, CPU_VR5400
, ISA_MIPS4
, 0,
517 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
518 mips_hwr_names_numeric
},
519 { "vr5500", 1, bfd_mach_mips5500
, CPU_VR5500
, ISA_MIPS4
, 0,
520 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
521 mips_hwr_names_numeric
},
522 { "r5900", 1, bfd_mach_mips5900
, CPU_R5900
, ISA_MIPS3
, 0,
523 mips_cp0_names_r5900
, NULL
, 0, mips_cp1_names_mips
,
524 mips_hwr_names_numeric
},
525 { "r6000", 1, bfd_mach_mips6000
, CPU_R6000
, ISA_MIPS2
, 0,
526 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
527 mips_hwr_names_numeric
},
528 { "rm7000", 1, bfd_mach_mips7000
, CPU_RM7000
, ISA_MIPS4
, 0,
529 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
530 mips_hwr_names_numeric
},
531 { "rm9000", 1, bfd_mach_mips7000
, CPU_RM7000
, ISA_MIPS4
, 0,
532 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
533 mips_hwr_names_numeric
},
534 { "r8000", 1, bfd_mach_mips8000
, CPU_R8000
, ISA_MIPS4
, 0,
535 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
536 mips_hwr_names_numeric
},
537 { "r10000", 1, bfd_mach_mips10000
, CPU_R10000
, ISA_MIPS4
, 0,
538 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
539 mips_hwr_names_numeric
},
540 { "r12000", 1, bfd_mach_mips12000
, CPU_R12000
, ISA_MIPS4
, 0,
541 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
542 mips_hwr_names_numeric
},
543 { "r14000", 1, bfd_mach_mips14000
, CPU_R14000
, ISA_MIPS4
, 0,
544 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
545 mips_hwr_names_numeric
},
546 { "r16000", 1, bfd_mach_mips16000
, CPU_R16000
, ISA_MIPS4
, 0,
547 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
548 mips_hwr_names_numeric
},
549 { "mips5", 1, bfd_mach_mips5
, CPU_MIPS5
, ISA_MIPS5
, 0,
550 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips
,
551 mips_hwr_names_numeric
},
553 /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
554 Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
555 _MIPS32 Architecture For Programmers Volume I: Introduction to the
556 MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
558 { "mips32", 1, bfd_mach_mipsisa32
, CPU_MIPS32
,
559 ISA_MIPS32
, ASE_SMARTMIPS
,
560 mips_cp0_names_mips3264
,
561 mips_cp0sel_names_mips3264
, ARRAY_SIZE (mips_cp0sel_names_mips3264
),
562 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
564 { "mips32r2", 1, bfd_mach_mipsisa32r2
, CPU_MIPS32R2
,
566 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
567 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
568 mips_cp0_names_mips3264r2
,
569 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
570 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
572 { "mips32r3", 1, bfd_mach_mipsisa32r3
, CPU_MIPS32R3
,
574 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
575 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
576 mips_cp0_names_mips3264r2
,
577 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
578 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
580 { "mips32r5", 1, bfd_mach_mipsisa32r5
, CPU_MIPS32R5
,
582 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
583 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
584 mips_cp0_names_mips3264r2
,
585 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
586 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
588 { "mips32r6", 1, bfd_mach_mipsisa32r6
, CPU_MIPS32R6
,
590 (ASE_EVA
| ASE_MSA
| ASE_VIRT
| ASE_XPA
| ASE_MCU
| ASE_MT
| ASE_DSP
591 | ASE_DSPR2
| ASE_DSPR3
| ASE_CRC
| ASE_GINV
),
592 mips_cp0_names_mips3264r2
,
593 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
594 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
596 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
597 { "mips64", 1, bfd_mach_mipsisa64
, CPU_MIPS64
,
598 ISA_MIPS64
, ASE_MIPS3D
| ASE_MDMX
,
599 mips_cp0_names_mips3264
,
600 mips_cp0sel_names_mips3264
, ARRAY_SIZE (mips_cp0sel_names_mips3264
),
601 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
603 { "mips64r2", 1, bfd_mach_mipsisa64r2
, CPU_MIPS64R2
,
605 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
606 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
607 mips_cp0_names_mips3264r2
,
608 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
609 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
611 { "mips64r3", 1, bfd_mach_mipsisa64r3
, CPU_MIPS64R3
,
613 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
614 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
615 mips_cp0_names_mips3264r2
,
616 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
617 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
619 { "mips64r5", 1, bfd_mach_mipsisa64r5
, CPU_MIPS64R5
,
621 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
622 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
623 mips_cp0_names_mips3264r2
,
624 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
625 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
627 { "mips64r6", 1, bfd_mach_mipsisa64r6
, CPU_MIPS64R6
,
629 (ASE_EVA
| ASE_MSA
| ASE_MSA64
| ASE_XPA
| ASE_VIRT
| ASE_VIRT64
630 | ASE_MCU
| ASE_MT
| ASE_DSP
| ASE_DSPR2
| ASE_DSPR3
| ASE_CRC
631 | ASE_CRC64
| ASE_GINV
),
632 mips_cp0_names_mips3264r2
,
633 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
634 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
636 { "interaptiv-mr2", 1, bfd_mach_mips_interaptiv_mr2
, CPU_INTERAPTIV_MR2
,
638 ASE_MT
| ASE_EVA
| ASE_DSP
| ASE_DSPR2
| ASE_MIPS16E2
| ASE_MIPS16E2_MT
,
639 mips_cp0_names_mips3264r2
,
640 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
641 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
643 { "sb1", 1, bfd_mach_mips_sb1
, CPU_SB1
,
644 ISA_MIPS64
| INSN_SB1
, ASE_MIPS3D
,
646 mips_cp0sel_names_sb1
, ARRAY_SIZE (mips_cp0sel_names_sb1
),
647 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
649 { "loongson2e", 1, bfd_mach_mips_loongson_2e
, CPU_LOONGSON_2E
,
650 ISA_MIPS3
| INSN_LOONGSON_2E
, 0, mips_cp0_names_numeric
,
651 NULL
, 0, mips_cp1_names_mips
, mips_hwr_names_numeric
},
653 { "loongson2f", 1, bfd_mach_mips_loongson_2f
, CPU_LOONGSON_2F
,
654 ISA_MIPS3
| INSN_LOONGSON_2F
, ASE_LOONGSON_MMI
, mips_cp0_names_numeric
,
655 NULL
, 0, mips_cp1_names_mips
, mips_hwr_names_numeric
},
657 /* The loongson3a is an alias of gs464 for compatibility */
658 { "loongson3a", 1, bfd_mach_mips_gs464
, CPU_GS464
,
659 ISA_MIPS64R2
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
| ASE_LOONGSON_EXT
,
660 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips3264
,
661 mips_hwr_names_numeric
},
663 { "gs464", 1, bfd_mach_mips_gs464
, CPU_GS464
,
664 ISA_MIPS64R2
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
| ASE_LOONGSON_EXT
,
665 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips3264
,
666 mips_hwr_names_numeric
},
668 { "gs464e", 1, bfd_mach_mips_gs464e
, CPU_GS464E
,
669 ISA_MIPS64R2
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
| ASE_LOONGSON_EXT
670 | ASE_LOONGSON_EXT2
, mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips3264
,
671 mips_hwr_names_numeric
},
673 { "gs264e", 1, bfd_mach_mips_gs264e
, CPU_GS264E
,
674 ISA_MIPS64R2
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
| ASE_LOONGSON_EXT
675 | ASE_LOONGSON_EXT2
| ASE_MSA
| ASE_MSA64
, mips_cp0_names_numeric
, NULL
,
676 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
678 { "octeon", 1, bfd_mach_mips_octeon
, CPU_OCTEON
,
679 ISA_MIPS64R2
| INSN_OCTEON
, 0, mips_cp0_names_numeric
, NULL
, 0,
680 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
682 { "octeon+", 1, bfd_mach_mips_octeonp
, CPU_OCTEONP
,
683 ISA_MIPS64R2
| INSN_OCTEONP
, 0, mips_cp0_names_numeric
,
684 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
686 { "octeon2", 1, bfd_mach_mips_octeon2
, CPU_OCTEON2
,
687 ISA_MIPS64R2
| INSN_OCTEON2
, 0, mips_cp0_names_numeric
,
688 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
690 { "octeon3", 1, bfd_mach_mips_octeon3
, CPU_OCTEON3
,
691 ISA_MIPS64R5
| INSN_OCTEON3
, ASE_VIRT
| ASE_VIRT64
,
692 mips_cp0_names_numeric
,
693 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
695 { "xlr", 1, bfd_mach_mips_xlr
, CPU_XLR
,
696 ISA_MIPS64
| INSN_XLR
, 0,
698 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
699 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
701 /* XLP is mostly like XLR, with the prominent exception it is being
703 { "xlp", 1, bfd_mach_mips_xlr
, CPU_XLR
,
704 ISA_MIPS64R2
| INSN_XLR
, 0,
706 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
707 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
709 /* This entry, mips16, is here only for ISA/processor selection; do
710 not print its name. */
711 { "", 1, bfd_mach_mips16
, CPU_MIPS16
, ISA_MIPS64
,
712 ASE_MIPS16E2
| ASE_MIPS16E2_MT
,
713 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
714 mips_hwr_names_numeric
},
717 /* ISA and processor type to disassemble for, and register names to use.
718 set_default_mips_dis_options and parse_mips_dis_options fill in these
720 static int mips_processor
;
723 static int micromips_ase
;
724 static const char * const *mips_gpr_names
;
725 static const char * const *mips_fpr_names
;
726 static const char * const *mips_cp0_names
;
727 static const struct mips_cp0sel_name
*mips_cp0sel_names
;
728 static int mips_cp0sel_names_len
;
729 static const char * const *mips_cp1_names
;
730 static const char * const *mips_hwr_names
;
733 static int no_aliases
; /* If set disassemble as most general inst. */
735 static const struct mips_abi_choice
*
736 choose_abi_by_name (const char *name
, unsigned int namelen
)
738 const struct mips_abi_choice
*c
;
741 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_abi_choices
) && c
== NULL
; i
++)
742 if (strncmp (mips_abi_choices
[i
].name
, name
, namelen
) == 0
743 && strlen (mips_abi_choices
[i
].name
) == namelen
)
744 c
= &mips_abi_choices
[i
];
749 static const struct mips_arch_choice
*
750 choose_arch_by_name (const char *name
, unsigned int namelen
)
752 const struct mips_arch_choice
*c
= NULL
;
755 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
756 if (strncmp (mips_arch_choices
[i
].name
, name
, namelen
) == 0
757 && strlen (mips_arch_choices
[i
].name
) == namelen
)
758 c
= &mips_arch_choices
[i
];
763 static const struct mips_arch_choice
*
764 choose_arch_by_number (unsigned long mach
)
766 static unsigned long hint_bfd_mach
;
767 static const struct mips_arch_choice
*hint_arch_choice
;
768 const struct mips_arch_choice
*c
;
771 /* We optimize this because even if the user specifies no
772 flags, this will be done for every instruction! */
773 if (hint_bfd_mach
== mach
774 && hint_arch_choice
!= NULL
775 && hint_arch_choice
->bfd_mach
== hint_bfd_mach
)
776 return hint_arch_choice
;
778 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
780 if (mips_arch_choices
[i
].bfd_mach_valid
781 && mips_arch_choices
[i
].bfd_mach
== mach
)
783 c
= &mips_arch_choices
[i
];
784 hint_bfd_mach
= mach
;
785 hint_arch_choice
= c
;
791 /* Check if the object uses NewABI conventions. */
794 is_newabi (Elf_Internal_Ehdr
*header
)
796 /* There are no old-style ABIs which use 64-bit ELF. */
797 if (header
->e_ident
[EI_CLASS
] == ELFCLASS64
)
800 /* If a 32-bit ELF file, n32 is a new-style ABI. */
801 if ((header
->e_flags
& EF_MIPS_ABI2
) != 0)
807 /* Check if the object has microMIPS ASE code. */
810 is_micromips (Elf_Internal_Ehdr
*header
)
812 if ((header
->e_flags
& EF_MIPS_ARCH_ASE_MICROMIPS
) != 0)
818 /* Convert ASE flags from .MIPS.abiflags to internal values. */
821 mips_convert_abiflags_ases (unsigned long afl_ases
)
823 unsigned long opcode_ases
= 0;
825 if (afl_ases
& AFL_ASE_DSP
)
826 opcode_ases
|= ASE_DSP
;
827 if (afl_ases
& AFL_ASE_DSPR2
)
828 opcode_ases
|= ASE_DSPR2
;
829 if (afl_ases
& AFL_ASE_EVA
)
830 opcode_ases
|= ASE_EVA
;
831 if (afl_ases
& AFL_ASE_MCU
)
832 opcode_ases
|= ASE_MCU
;
833 if (afl_ases
& AFL_ASE_MDMX
)
834 opcode_ases
|= ASE_MDMX
;
835 if (afl_ases
& AFL_ASE_MIPS3D
)
836 opcode_ases
|= ASE_MIPS3D
;
837 if (afl_ases
& AFL_ASE_MT
)
838 opcode_ases
|= ASE_MT
;
839 if (afl_ases
& AFL_ASE_SMARTMIPS
)
840 opcode_ases
|= ASE_SMARTMIPS
;
841 if (afl_ases
& AFL_ASE_VIRT
)
842 opcode_ases
|= ASE_VIRT
;
843 if (afl_ases
& AFL_ASE_MSA
)
844 opcode_ases
|= ASE_MSA
;
845 if (afl_ases
& AFL_ASE_XPA
)
846 opcode_ases
|= ASE_XPA
;
847 if (afl_ases
& AFL_ASE_DSPR3
)
848 opcode_ases
|= ASE_DSPR3
;
849 if (afl_ases
& AFL_ASE_MIPS16E2
)
850 opcode_ases
|= ASE_MIPS16E2
;
854 /* Calculate combination ASE flags from regular ASE flags. */
857 mips_calculate_combination_ases (int opcode_isa
, unsigned long opcode_ases
)
859 unsigned long combination_ases
= 0;
861 if ((opcode_ases
& (ASE_XPA
| ASE_VIRT
)) == (ASE_XPA
| ASE_VIRT
))
862 combination_ases
|= ASE_XPA_VIRT
;
863 if ((opcode_ases
& (ASE_MIPS16E2
| ASE_MT
)) == (ASE_MIPS16E2
| ASE_MT
))
864 combination_ases
|= ASE_MIPS16E2_MT
;
865 if ((opcode_ases
& ASE_EVA
)
866 && ((opcode_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
867 || (opcode_isa
& INSN_ISA_MASK
) == ISA_MIPS32R6
))
868 combination_ases
|= ASE_EVA_R6
;
869 return combination_ases
;
873 set_default_mips_dis_options (struct disassemble_info
*info
)
875 const struct mips_arch_choice
*chosen_arch
;
877 /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
878 is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
879 CP0 register, and HWR names. */
880 mips_isa
= ISA_MIPS3
;
881 mips_processor
= CPU_R3000
;
884 mips_gpr_names
= mips_gpr_names_oldabi
;
885 mips_fpr_names
= mips_fpr_names_numeric
;
886 mips_cp0_names
= mips_cp0_names_numeric
;
887 mips_cp0sel_names
= NULL
;
888 mips_cp0sel_names_len
= 0;
889 mips_cp1_names
= mips_cp1_names_numeric
;
890 mips_hwr_names
= mips_hwr_names_numeric
;
893 /* Set ISA, architecture, and cp0 register names as best we can. */
894 #if ! SYMTAB_AVAILABLE
895 /* This is running out on a target machine, not in a host tool.
896 FIXME: Where does mips_target_info come from? */
897 target_processor
= mips_target_info
.processor
;
898 mips_isa
= mips_target_info
.isa
;
899 mips_ase
= mips_target_info
.ase
;
901 chosen_arch
= choose_arch_by_number (info
->mach
);
902 if (chosen_arch
!= NULL
)
904 mips_processor
= chosen_arch
->processor
;
905 mips_isa
= chosen_arch
->isa
;
906 mips_ase
= chosen_arch
->ase
;
907 mips_cp0_names
= chosen_arch
->cp0_names
;
908 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
909 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
910 mips_cp1_names
= chosen_arch
->cp1_names
;
911 mips_hwr_names
= chosen_arch
->hwr_names
;
914 /* Update settings according to the ELF file header flags. */
915 if (info
->flavour
== bfd_target_elf_flavour
&& info
->section
!= NULL
)
917 struct bfd
*abfd
= info
->section
->owner
;
918 Elf_Internal_Ehdr
*header
= elf_elfheader (abfd
);
919 Elf_Internal_ABIFlags_v0
*abiflags
= NULL
;
921 /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
922 because we won't then have a MIPS/ELF BFD, however we need
923 to guard against a link error in a `--enable-targets=...'
924 configuration with a 32-bit host where the MIPS target is
925 a secondary, or with MIPS/ECOFF configurations. */
926 #ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
927 abiflags
= bfd_mips_elf_get_abiflags (abfd
);
929 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
930 if (is_newabi (header
))
931 mips_gpr_names
= mips_gpr_names_newabi
;
932 /* If a microMIPS binary, then don't use MIPS16 bindings. */
933 micromips_ase
= is_micromips (header
);
934 /* OR in any extra ASE flags set in ELF file structures. */
936 mips_ase
|= mips_convert_abiflags_ases (abiflags
->ases
);
937 else if (header
->e_flags
& EF_MIPS_ARCH_ASE_MDMX
)
938 mips_ase
|= ASE_MDMX
;
941 mips_ase
|= mips_calculate_combination_ases (mips_isa
, mips_ase
);
944 /* Parse an ASE disassembler option and set the corresponding global
945 ASE flag(s). Return TRUE if successful, FALSE otherwise. */
948 parse_mips_ase_option (const char *option
)
950 if (startswith (option
, "msa"))
953 if ((mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R2
954 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R3
955 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R5
956 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
)
957 mips_ase
|= ASE_MSA64
;
961 if (startswith (option
, "virt"))
963 mips_ase
|= ASE_VIRT
;
964 if (mips_isa
& ISA_MIPS64R2
965 || mips_isa
& ISA_MIPS64R3
966 || mips_isa
& ISA_MIPS64R5
967 || mips_isa
& ISA_MIPS64R6
)
968 mips_ase
|= ASE_VIRT64
;
972 if (startswith (option
, "xpa"))
978 if (startswith (option
, "ginv"))
980 mips_ase
|= ASE_GINV
;
984 if (startswith (option
, "loongson-mmi"))
986 mips_ase
|= ASE_LOONGSON_MMI
;
990 if (startswith (option
, "loongson-cam"))
992 mips_ase
|= ASE_LOONGSON_CAM
;
996 /* Put here for match ext2 frist */
997 if (startswith (option
, "loongson-ext2"))
999 mips_ase
|= ASE_LOONGSON_EXT2
;
1003 if (startswith (option
, "loongson-ext"))
1005 mips_ase
|= ASE_LOONGSON_EXT
;
1013 parse_mips_dis_option (const char *option
, unsigned int len
)
1015 unsigned int i
, optionlen
, vallen
;
1017 const struct mips_abi_choice
*chosen_abi
;
1018 const struct mips_arch_choice
*chosen_arch
;
1020 /* Try to match options that are simple flags */
1021 if (startswith (option
, "no-aliases"))
1027 if (parse_mips_ase_option (option
))
1029 mips_ase
|= mips_calculate_combination_ases (mips_isa
, mips_ase
);
1033 /* Look for the = that delimits the end of the option name. */
1034 for (i
= 0; i
< len
; i
++)
1035 if (option
[i
] == '=')
1038 if (i
== 0) /* Invalid option: no name before '='. */
1040 if (i
== len
) /* Invalid option: no '='. */
1042 if (i
== (len
- 1)) /* Invalid option: no value after '='. */
1046 val
= option
+ (optionlen
+ 1);
1047 vallen
= len
- (optionlen
+ 1);
1049 if (strncmp ("gpr-names", option
, optionlen
) == 0
1050 && strlen ("gpr-names") == optionlen
)
1052 chosen_abi
= choose_abi_by_name (val
, vallen
);
1053 if (chosen_abi
!= NULL
)
1054 mips_gpr_names
= chosen_abi
->gpr_names
;
1058 if (strncmp ("fpr-names", option
, optionlen
) == 0
1059 && strlen ("fpr-names") == optionlen
)
1061 chosen_abi
= choose_abi_by_name (val
, vallen
);
1062 if (chosen_abi
!= NULL
)
1063 mips_fpr_names
= chosen_abi
->fpr_names
;
1067 if (strncmp ("cp0-names", option
, optionlen
) == 0
1068 && strlen ("cp0-names") == optionlen
)
1070 chosen_arch
= choose_arch_by_name (val
, vallen
);
1071 if (chosen_arch
!= NULL
)
1073 mips_cp0_names
= chosen_arch
->cp0_names
;
1074 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1075 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1080 if (strncmp ("cp1-names", option
, optionlen
) == 0
1081 && strlen ("cp1-names") == optionlen
)
1083 chosen_arch
= choose_arch_by_name (val
, vallen
);
1084 if (chosen_arch
!= NULL
)
1085 mips_cp1_names
= chosen_arch
->cp1_names
;
1089 if (strncmp ("hwr-names", option
, optionlen
) == 0
1090 && strlen ("hwr-names") == optionlen
)
1092 chosen_arch
= choose_arch_by_name (val
, vallen
);
1093 if (chosen_arch
!= NULL
)
1094 mips_hwr_names
= chosen_arch
->hwr_names
;
1098 if (strncmp ("reg-names", option
, optionlen
) == 0
1099 && strlen ("reg-names") == optionlen
)
1101 /* We check both ABI and ARCH here unconditionally, so
1102 that "numeric" will do the desirable thing: select
1103 numeric register names for all registers. Other than
1104 that, a given name probably won't match both. */
1105 chosen_abi
= choose_abi_by_name (val
, vallen
);
1106 if (chosen_abi
!= NULL
)
1108 mips_gpr_names
= chosen_abi
->gpr_names
;
1109 mips_fpr_names
= chosen_abi
->fpr_names
;
1111 chosen_arch
= choose_arch_by_name (val
, vallen
);
1112 if (chosen_arch
!= NULL
)
1114 mips_cp0_names
= chosen_arch
->cp0_names
;
1115 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1116 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1117 mips_cp1_names
= chosen_arch
->cp1_names
;
1118 mips_hwr_names
= chosen_arch
->hwr_names
;
1123 /* Invalid option. */
1127 parse_mips_dis_options (const char *options
)
1129 const char *option_end
;
1131 if (options
== NULL
)
1134 while (*options
!= '\0')
1136 /* Skip empty options. */
1137 if (*options
== ',')
1143 /* We know that *options is neither NUL or a comma. */
1144 option_end
= options
+ 1;
1145 while (*option_end
!= ',' && *option_end
!= '\0')
1148 parse_mips_dis_option (options
, option_end
- options
);
1150 /* Go on to the next one. If option_end points to a comma, it
1151 will be skipped above. */
1152 options
= option_end
;
1156 static const struct mips_cp0sel_name
*
1157 lookup_mips_cp0sel_name (const struct mips_cp0sel_name
*names
,
1159 unsigned int cp0reg
,
1164 for (i
= 0; i
< len
; i
++)
1165 if (names
[i
].cp0reg
== cp0reg
&& names
[i
].sel
== sel
)
1170 /* Print register REGNO, of type TYPE, for instruction OPCODE. */
1173 print_reg (struct disassemble_info
*info
, const struct mips_opcode
*opcode
,
1174 enum mips_reg_operand_type type
, int regno
)
1176 const fprintf_styled_ftype infprintf
= info
->fprintf_styled_func
;
1181 infprintf (info
->stream
, dis_style_register
, "%s",
1182 mips_gpr_names
[regno
]);
1186 infprintf (info
->stream
, dis_style_register
, "%s",
1187 mips_fpr_names
[regno
]);
1191 if (opcode
->pinfo
& (FP_D
| FP_S
))
1192 infprintf (info
->stream
, dis_style_register
, "$fcc%d", regno
);
1194 infprintf (info
->stream
, dis_style_register
, "$cc%d", regno
);
1198 if (opcode
->membership
& INSN_5400
)
1199 infprintf (info
->stream
, dis_style_register
, "$f%d", regno
);
1201 infprintf (info
->stream
, dis_style_register
, "$v%d", regno
);
1205 infprintf (info
->stream
, dis_style_register
, "$ac%d", regno
);
1209 if (opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1210 infprintf (info
->stream
, dis_style_register
, "%s", mips_cp0_names
[regno
]);
1212 infprintf (info
->stream
, dis_style_register
, "$%d", regno
);
1215 case OP_REG_CONTROL
:
1216 if (opcode
->name
[strlen (opcode
->name
) - 1] == '1')
1217 infprintf (info
->stream
, dis_style_register
, "%s", mips_cp1_names
[regno
]);
1219 infprintf (info
->stream
, dis_style_register
, "$%d", regno
);
1223 infprintf (info
->stream
, dis_style_register
, "%s", mips_hwr_names
[regno
]);
1227 infprintf (info
->stream
, dis_style_register
, "$vf%d", regno
);
1231 infprintf (info
->stream
, dis_style_register
, "$vi%d", regno
);
1234 case OP_REG_R5900_I
:
1235 infprintf (info
->stream
, dis_style_register
, "$I");
1238 case OP_REG_R5900_Q
:
1239 infprintf (info
->stream
, dis_style_register
, "$Q");
1242 case OP_REG_R5900_R
:
1243 infprintf (info
->stream
, dis_style_register
, "$R");
1246 case OP_REG_R5900_ACC
:
1247 infprintf (info
->stream
, dis_style_register
, "$ACC");
1251 infprintf (info
->stream
, dis_style_register
, "$w%d", regno
);
1254 case OP_REG_MSA_CTRL
:
1255 infprintf (info
->stream
, dis_style_register
, "%s",
1256 msa_control_names
[regno
]);
1262 /* Used to track the state carried over from previous operands in
1264 struct mips_print_arg_state
{
1265 /* The value of the last OP_INT seen. We only use this for OP_MSB,
1266 where the value is known to be unsigned and small. */
1267 unsigned int last_int
;
1269 /* The type and number of the last OP_REG seen. We only use this for
1270 OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1271 enum mips_reg_operand_type last_reg_type
;
1272 unsigned int last_regno
;
1273 unsigned int dest_regno
;
1274 unsigned int seen_dest
;
1277 /* Initialize STATE for the start of an instruction. */
1280 init_print_arg_state (struct mips_print_arg_state
*state
)
1282 memset (state
, 0, sizeof (*state
));
1285 /* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1286 whose value is given by UVAL. */
1289 print_vu0_channel (struct disassemble_info
*info
,
1290 const struct mips_operand
*operand
, unsigned int uval
,
1291 enum disassembler_style style
)
1293 const fprintf_styled_ftype infprintf
= info
->fprintf_styled_func
;
1295 if (operand
->size
== 4)
1296 infprintf (info
->stream
, style
, "%s%s%s%s",
1297 uval
& 8 ? "x" : "",
1298 uval
& 4 ? "y" : "",
1299 uval
& 2 ? "z" : "",
1300 uval
& 1 ? "w" : "");
1301 else if (operand
->size
== 2)
1302 infprintf (info
->stream
, style
, "%c", "xyzw"[uval
]);
1307 /* Record information about a register operand. */
1310 mips_seen_register (struct mips_print_arg_state
*state
,
1312 enum mips_reg_operand_type reg_type
)
1314 state
->last_reg_type
= reg_type
;
1315 state
->last_regno
= regno
;
1317 if (!state
->seen_dest
)
1319 state
->seen_dest
= 1;
1320 state
->dest_regno
= regno
;
1324 /* Print SAVE/RESTORE instruction operands according to the argument
1325 register mask AMASK, the number of static registers saved NSREG,
1326 the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1327 and the frame size FRAME_SIZE. */
1330 mips_print_save_restore (struct disassemble_info
*info
, unsigned int amask
,
1331 unsigned int nsreg
, unsigned int ra
,
1332 unsigned int s0
, unsigned int s1
,
1333 unsigned int frame_size
)
1335 const fprintf_styled_ftype infprintf
= info
->fprintf_styled_func
;
1336 unsigned int nargs
, nstatics
, smask
, i
, j
;
1337 void *is
= info
->stream
;
1340 if (amask
== MIPS_SVRS_ALL_ARGS
)
1345 else if (amask
== MIPS_SVRS_ALL_STATICS
)
1353 nstatics
= amask
& 3;
1359 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[4]);
1361 infprintf (is
, dis_style_register
, "-%s", mips_gpr_names
[4 + nargs
- 1]);
1365 infprintf (is
, dis_style_text
, "%s", sep
);
1366 infprintf (is
, dis_style_immediate
, "%d", frame_size
);
1370 infprintf (is
, dis_style_text
, ",");
1371 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[31]);
1379 if (nsreg
> 0) /* $s2-$s8 */
1380 smask
|= ((1 << nsreg
) - 1) << 2;
1382 for (i
= 0; i
< 9; i
++)
1383 if (smask
& (1 << i
))
1385 infprintf (is
, dis_style_text
, ",");
1386 infprintf (is
, dis_style_register
, "%s",
1387 mips_gpr_names
[i
== 8 ? 30 : (16 + i
)]);
1388 /* Skip over string of set bits. */
1389 for (j
= i
; smask
& (2 << j
); j
++)
1393 infprintf (is
, dis_style_text
, "-");
1394 infprintf (is
, dis_style_register
, "%s",
1395 mips_gpr_names
[j
== 8 ? 30 : (16 + j
)]);
1399 /* Statics $ax - $a3. */
1402 infprintf (is
, dis_style_text
, ",");
1403 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[7]);
1405 else if (nstatics
> 0)
1407 infprintf (is
, dis_style_text
, ",");
1408 infprintf (is
, dis_style_register
, "%s",
1409 mips_gpr_names
[7 - nstatics
+ 1]);
1410 infprintf (is
, dis_style_text
, "-");
1411 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[7]);
1416 /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1417 UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1418 the base address for OP_PCREL operands. */
1421 print_insn_arg (struct disassemble_info
*info
,
1422 struct mips_print_arg_state
*state
,
1423 const struct mips_opcode
*opcode
,
1424 const struct mips_operand
*operand
,
1428 const fprintf_styled_ftype infprintf
= info
->fprintf_styled_func
;
1429 void *is
= info
->stream
;
1431 switch (operand
->type
)
1435 const struct mips_int_operand
*int_op
;
1437 int_op
= (const struct mips_int_operand
*) operand
;
1438 uval
= mips_decode_int_operand (int_op
, uval
);
1439 state
->last_int
= uval
;
1440 if (int_op
->print_hex
)
1441 infprintf (is
, dis_style_immediate
, "0x%x", uval
);
1443 infprintf (is
, dis_style_immediate
, "%d", uval
);
1449 const struct mips_mapped_int_operand
*mint_op
;
1451 mint_op
= (const struct mips_mapped_int_operand
*) operand
;
1452 uval
= mint_op
->int_map
[uval
];
1453 state
->last_int
= uval
;
1454 if (mint_op
->print_hex
)
1455 infprintf (is
, dis_style_immediate
, "0x%x", uval
);
1457 infprintf (is
, dis_style_immediate
, "%d", uval
);
1463 const struct mips_msb_operand
*msb_op
;
1465 msb_op
= (const struct mips_msb_operand
*) operand
;
1466 uval
+= msb_op
->bias
;
1467 if (msb_op
->add_lsb
)
1468 uval
-= state
->last_int
;
1469 infprintf (is
, dis_style_immediate
, "0x%x", uval
);
1474 case OP_OPTIONAL_REG
:
1476 const struct mips_reg_operand
*reg_op
;
1478 reg_op
= (const struct mips_reg_operand
*) operand
;
1479 uval
= mips_decode_reg_operand (reg_op
, uval
);
1480 print_reg (info
, opcode
, reg_op
->reg_type
, uval
);
1482 mips_seen_register (state
, uval
, reg_op
->reg_type
);
1488 const struct mips_reg_pair_operand
*pair_op
;
1490 pair_op
= (const struct mips_reg_pair_operand
*) operand
;
1491 print_reg (info
, opcode
, pair_op
->reg_type
,
1492 pair_op
->reg1_map
[uval
]);
1493 infprintf (is
, dis_style_text
, ",");
1494 print_reg (info
, opcode
, pair_op
->reg_type
,
1495 pair_op
->reg2_map
[uval
]);
1501 const struct mips_pcrel_operand
*pcrel_op
;
1503 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1504 info
->target
= mips_decode_pcrel_operand (pcrel_op
, base_pc
, uval
);
1506 /* For jumps and branches clear the ISA bit except for
1507 the GDB disassembler. */
1508 if (pcrel_op
->include_isa_bit
1509 && info
->flavour
!= bfd_target_unknown_flavour
)
1512 (*info
->print_address_func
) (info
->target
, info
);
1517 infprintf (is
, dis_style_register
, "%d", uval
);
1520 case OP_ADDIUSP_INT
:
1524 sval
= mips_signed_operand (operand
, uval
) * 4;
1525 if (sval
>= -8 && sval
< 8)
1527 infprintf (is
, dis_style_immediate
, "%d", sval
);
1531 case OP_CLO_CLZ_DEST
:
1533 unsigned int reg1
, reg2
;
1537 /* If one is zero use the other. */
1538 if (reg1
== reg2
|| reg2
== 0)
1539 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[reg1
]);
1541 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[reg2
]);
1544 /* Bogus, result depends on processor. */
1545 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[reg1
]);
1546 infprintf (is
, dis_style_text
, " or ");
1547 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[reg2
]);
1554 case OP_NON_ZERO_REG
:
1556 print_reg (info
, opcode
, OP_REG_GP
, uval
& 31);
1557 mips_seen_register (state
, uval
, OP_REG_GP
);
1561 case OP_LWM_SWM_LIST
:
1562 if (operand
->size
== 2)
1566 infprintf (is
, dis_style_register
, "%s",
1567 mips_gpr_names
[16]);
1568 infprintf (is
, dis_style_text
, ",");
1569 infprintf (is
, dis_style_register
, "%s",
1570 mips_gpr_names
[31]);
1574 infprintf (is
, dis_style_register
, "%s",
1575 mips_gpr_names
[16]);
1576 infprintf (is
, dis_style_text
, "-");
1577 infprintf (is
, dis_style_register
, "%s",
1578 mips_gpr_names
[16 + uval
]);
1579 infprintf (is
, dis_style_text
, ",");
1580 infprintf (is
, dis_style_register
, "%s",
1581 mips_gpr_names
[31]);
1588 s_reg_encode
= uval
& 0xf;
1589 if (s_reg_encode
!= 0)
1591 if (s_reg_encode
== 1)
1592 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[16]);
1593 else if (s_reg_encode
< 9)
1595 infprintf (is
, dis_style_register
, "%s",
1596 mips_gpr_names
[16]);
1597 infprintf (is
, dis_style_text
, "-");
1598 infprintf (is
, dis_style_register
, "%s",
1599 mips_gpr_names
[15 + s_reg_encode
]);
1601 else if (s_reg_encode
== 9)
1603 infprintf (is
, dis_style_register
, "%s",
1604 mips_gpr_names
[16]);
1605 infprintf (is
, dis_style_text
, "-");
1606 infprintf (is
, dis_style_register
, "%s",
1607 mips_gpr_names
[23]);
1608 infprintf (is
, dis_style_text
, ",");
1609 infprintf (is
, dis_style_register
, "%s",
1610 mips_gpr_names
[30]);
1613 infprintf (is
, dis_style_text
, "UNKNOWN");
1616 if (uval
& 0x10) /* For ra. */
1618 if (s_reg_encode
== 0)
1619 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[31]);
1622 infprintf (is
, dis_style_text
, ",");
1623 infprintf (is
, dis_style_register
, "%s",
1624 mips_gpr_names
[31]);
1630 case OP_ENTRY_EXIT_LIST
:
1633 unsigned int amask
, smask
;
1636 amask
= (uval
>> 3) & 7;
1637 if (amask
> 0 && amask
< 5)
1639 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[4]);
1642 infprintf (is
, dis_style_text
, "-");
1643 infprintf (is
, dis_style_register
, "%s",
1644 mips_gpr_names
[amask
+ 3]);
1649 smask
= (uval
>> 1) & 3;
1652 infprintf (is
, dis_style_text
, "%s??", sep
);
1657 infprintf (is
, dis_style_text
, "%s", sep
);
1658 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[16]);
1661 infprintf (is
, dis_style_text
, "-");
1662 infprintf (is
, dis_style_register
, "%s",
1663 mips_gpr_names
[smask
+ 15]);
1670 infprintf (is
, dis_style_text
, "%s", sep
);
1671 infprintf (is
, dis_style_register
, "%s", mips_gpr_names
[31]);
1675 if (amask
== 5 || amask
== 6)
1677 infprintf (is
, dis_style_text
, "%s", sep
);
1678 infprintf (is
, dis_style_register
, "%s", mips_fpr_names
[0]);
1681 infprintf (is
, dis_style_text
, "-");
1682 infprintf (is
, dis_style_register
, "%s", mips_fpr_names
[1]);
1688 case OP_SAVE_RESTORE_LIST
:
1689 /* Should be handled by the caller due to complex behavior. */
1692 case OP_MDMX_IMM_REG
:
1698 if ((vsel
& 0x10) == 0)
1703 for (fmt
= 0; fmt
< 3; fmt
++, vsel
>>= 1)
1704 if ((vsel
& 1) == 0)
1706 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1707 infprintf (is
, dis_style_text
, "[");
1708 infprintf (is
, dis_style_immediate
, "%d", vsel
>> 1);
1709 infprintf (is
, dis_style_text
, "]");
1711 else if ((vsel
& 0x08) == 0)
1712 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1714 infprintf (is
, dis_style_immediate
, "0x%x", uval
);
1718 case OP_REPEAT_PREV_REG
:
1719 print_reg (info
, opcode
, state
->last_reg_type
, state
->last_regno
);
1722 case OP_REPEAT_DEST_REG
:
1723 print_reg (info
, opcode
, state
->last_reg_type
, state
->dest_regno
);
1727 infprintf (is
, dis_style_register
, "$pc");
1731 print_reg (info
, opcode
, OP_REG_GP
, 28);
1735 case OP_VU0_MATCH_SUFFIX
:
1736 print_vu0_channel (info
, operand
, uval
, dis_style_register
);
1740 infprintf (is
, dis_style_text
, "[");
1741 infprintf (is
, dis_style_immediate
, "%d", uval
);
1742 infprintf (is
, dis_style_text
, "]");
1746 infprintf (is
, dis_style_text
, "[");
1747 print_reg (info
, opcode
, OP_REG_GP
, uval
);
1748 infprintf (is
, dis_style_text
, "]");
1753 /* Validate the arguments for INSN, which is described by OPCODE.
1754 Use DECODE_OPERAND to get the encoding of each operand. */
1757 validate_insn_args (const struct mips_opcode
*opcode
,
1758 const struct mips_operand
*(*decode_operand
) (const char *),
1761 struct mips_print_arg_state state
;
1762 const struct mips_operand
*operand
;
1766 init_print_arg_state (&state
);
1767 for (s
= opcode
->args
; *s
; ++s
)
1781 operand
= decode_operand (s
);
1785 uval
= mips_extract_operand (operand
, insn
);
1786 switch (operand
->type
)
1789 case OP_OPTIONAL_REG
:
1791 const struct mips_reg_operand
*reg_op
;
1793 reg_op
= (const struct mips_reg_operand
*) operand
;
1794 uval
= mips_decode_reg_operand (reg_op
, uval
);
1795 mips_seen_register (&state
, uval
, reg_op
->reg_type
);
1801 unsigned int reg1
, reg2
;
1806 if (reg1
!= reg2
|| reg1
== 0)
1813 const struct mips_check_prev_operand
*prev_op
;
1815 prev_op
= (const struct mips_check_prev_operand
*) operand
;
1817 if (!prev_op
->zero_ok
&& uval
== 0)
1820 if (((prev_op
->less_than_ok
&& uval
< state
.last_regno
)
1821 || (prev_op
->greater_than_ok
&& uval
> state
.last_regno
)
1822 || (prev_op
->equal_ok
&& uval
== state
.last_regno
)))
1828 case OP_NON_ZERO_REG
:
1841 case OP_ADDIUSP_INT
:
1842 case OP_CLO_CLZ_DEST
:
1843 case OP_LWM_SWM_LIST
:
1844 case OP_ENTRY_EXIT_LIST
:
1845 case OP_MDMX_IMM_REG
:
1846 case OP_REPEAT_PREV_REG
:
1847 case OP_REPEAT_DEST_REG
:
1851 case OP_VU0_MATCH_SUFFIX
:
1854 case OP_SAVE_RESTORE_LIST
:
1858 if (*s
== 'm' || *s
== '+' || *s
== '-')
1865 /* Print the arguments for INSN, which is described by OPCODE.
1866 Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
1867 as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1868 operand is for a branch or jump. */
1871 print_insn_args (struct disassemble_info
*info
,
1872 const struct mips_opcode
*opcode
,
1873 const struct mips_operand
*(*decode_operand
) (const char *),
1874 unsigned int insn
, bfd_vma insn_pc
, unsigned int length
)
1876 const fprintf_styled_ftype infprintf
= info
->fprintf_styled_func
;
1877 void *is
= info
->stream
;
1878 struct mips_print_arg_state state
;
1879 const struct mips_operand
*operand
;
1882 init_print_arg_state (&state
);
1883 for (s
= opcode
->args
; *s
; ++s
)
1890 infprintf (is
, dis_style_text
, "%c", *s
);
1895 infprintf (is
, dis_style_text
, "%c%c", *s
, *s
);
1899 operand
= decode_operand (s
);
1902 /* xgettext:c-format */
1903 infprintf (is
, dis_style_text
,
1904 _("# internal error, undefined operand in `%s %s'"),
1905 opcode
->name
, opcode
->args
);
1909 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
1911 /* Handle this case here because of the complex behavior. */
1912 unsigned int amask
= (insn
>> 15) & 0xf;
1913 unsigned int nsreg
= (insn
>> 23) & 0x7;
1914 unsigned int ra
= insn
& 0x1000; /* $ra */
1915 unsigned int s0
= insn
& 0x800; /* $s0 */
1916 unsigned int s1
= insn
& 0x400; /* $s1 */
1917 unsigned int frame_size
= (((insn
>> 15) & 0xf0)
1918 | ((insn
>> 6) & 0x0f)) * 8;
1919 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
,
1922 else if (operand
->type
== OP_REG
1925 && opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1927 /* Coprocessor register 0 with sel field. */
1928 const struct mips_cp0sel_name
*n
;
1929 unsigned int reg
, sel
;
1931 reg
= mips_extract_operand (operand
, insn
);
1933 operand
= decode_operand (s
);
1934 sel
= mips_extract_operand (operand
, insn
);
1936 /* CP0 register including 'sel' code for mftc0, to be
1937 printed textually if known. If not known, print both
1938 CP0 register name and sel numerically since CP0 register
1939 with sel 0 may have a name unrelated to register being
1941 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
1942 mips_cp0sel_names_len
,
1945 infprintf (is
, dis_style_register
, "%s", n
->name
);
1948 infprintf (is
, dis_style_register
, "$%d", reg
);
1949 infprintf (is
, dis_style_text
, ",");
1950 infprintf (is
, dis_style_immediate
, "%d", sel
);
1955 bfd_vma base_pc
= insn_pc
;
1957 /* Adjust the PC relative base so that branch/jump insns use
1958 the following PC as the base but genuinely PC relative
1959 operands use the current PC. */
1960 if (operand
->type
== OP_PCREL
)
1962 const struct mips_pcrel_operand
*pcrel_op
;
1964 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1965 /* The include_isa_bit flag is sufficient to distinguish
1966 branch/jump from other PC relative operands. */
1967 if (pcrel_op
->include_isa_bit
)
1971 print_insn_arg (info
, &state
, opcode
, operand
, base_pc
,
1972 mips_extract_operand (operand
, insn
));
1974 if (*s
== 'm' || *s
== '+' || *s
== '-')
1981 /* Print the mips instruction at address MEMADDR in debugged memory,
1982 on using INFO. Returns length of the instruction, in bytes, which is
1983 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
1984 this is little-endian code. */
1987 print_insn_mips (bfd_vma memaddr
,
1989 struct disassemble_info
*info
)
1991 #define GET_OP(insn, field) \
1992 (((insn) >> OP_SH_##field) & OP_MASK_##field)
1993 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
1994 const fprintf_styled_ftype infprintf
= info
->fprintf_styled_func
;
1995 const struct mips_opcode
*op
;
1996 static bool init
= 0;
1997 void *is
= info
->stream
;
1999 /* Build a hash table to shorten the search time. */
2004 for (i
= 0; i
<= OP_MASK_OP
; i
++)
2006 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
2008 if (op
->pinfo
== INSN_MACRO
2009 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
2011 if (i
== GET_OP (op
->match
, OP
))
2022 info
->bytes_per_chunk
= INSNLEN
;
2023 info
->display_endian
= info
->endian
;
2024 info
->insn_info_valid
= 1;
2025 info
->branch_delay_insns
= 0;
2026 info
->data_size
= 0;
2027 info
->insn_type
= dis_nonbranch
;
2031 op
= mips_hash
[GET_OP (word
, OP
)];
2034 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
2036 if (op
->pinfo
!= INSN_MACRO
2037 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
2038 && (word
& op
->mask
) == op
->match
)
2040 /* We always disassemble the jalx instruction, except for MIPS r6. */
2041 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
)
2042 && (strcmp (op
->name
, "jalx")
2043 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS32R6
2044 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
))
2047 /* Figure out instruction type and branch delay information. */
2048 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
2050 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
2051 info
->insn_type
= dis_jsr
;
2053 info
->insn_type
= dis_branch
;
2054 info
->branch_delay_insns
= 1;
2056 else if ((op
->pinfo
& (INSN_COND_BRANCH_DELAY
2057 | INSN_COND_BRANCH_LIKELY
)) != 0)
2059 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2060 info
->insn_type
= dis_condjsr
;
2062 info
->insn_type
= dis_condbranch
;
2063 info
->branch_delay_insns
= 1;
2065 else if ((op
->pinfo
& (INSN_STORE_MEMORY
2066 | INSN_LOAD_MEMORY
)) != 0)
2067 info
->insn_type
= dis_dref
;
2069 if (!validate_insn_args (op
, decode_mips_operand
, word
))
2072 infprintf (is
, dis_style_mnemonic
, "%s", op
->name
);
2073 if (op
->pinfo2
& INSN2_VU0_CHANNEL_SUFFIX
)
2077 infprintf (is
, dis_style_mnemonic
, ".");
2078 uval
= mips_extract_operand (&mips_vu0_channel_mask
, word
);
2079 print_vu0_channel (info
, &mips_vu0_channel_mask
, uval
,
2080 dis_style_mnemonic
);
2085 infprintf (is
, dis_style_text
, "\t");
2086 print_insn_args (info
, op
, decode_mips_operand
, word
,
2096 /* Handle undefined instructions. */
2097 info
->insn_type
= dis_noninsn
;
2098 infprintf (is
, dis_style_assembler_directive
, ".word");
2099 infprintf (is
, dis_style_text
, "\t");
2100 infprintf (is
, dis_style_immediate
, "0x%x", word
);
2104 /* Disassemble an operand for a mips16 instruction. */
2107 print_mips16_insn_arg (struct disassemble_info
*info
,
2108 struct mips_print_arg_state
*state
,
2109 const struct mips_opcode
*opcode
,
2110 char type
, bfd_vma memaddr
,
2111 unsigned insn
, bool use_extend
,
2112 unsigned extend
, bool is_offset
)
2114 const fprintf_styled_ftype infprintf
= info
->fprintf_styled_func
;
2115 void *is
= info
->stream
;
2116 const struct mips_operand
*operand
, *ext_operand
;
2117 unsigned short ext_size
;
2129 infprintf (is
, dis_style_text
, "%c", type
);
2133 operand
= decode_mips16_operand (type
, false);
2136 /* xgettext:c-format */
2137 infprintf (is
, dis_style_text
, _("# internal error, undefined operand in `%s %s'"),
2138 opcode
->name
, opcode
->args
);
2142 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
2144 /* Handle this case here because of the complex interaction
2145 with the EXTEND opcode. */
2146 unsigned int amask
= extend
& 0xf;
2147 unsigned int nsreg
= (extend
>> 8) & 0x7;
2148 unsigned int ra
= insn
& 0x40; /* $ra */
2149 unsigned int s0
= insn
& 0x20; /* $s0 */
2150 unsigned int s1
= insn
& 0x10; /* $s1 */
2151 unsigned int frame_size
= ((extend
& 0xf0) | (insn
& 0x0f)) * 8;
2152 if (frame_size
== 0 && !use_extend
)
2154 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
, frame_size
);
2158 if (is_offset
&& operand
->type
== OP_INT
)
2160 const struct mips_int_operand
*int_op
;
2162 int_op
= (const struct mips_int_operand
*) operand
;
2163 info
->insn_type
= dis_dref
;
2164 info
->data_size
= 1 << int_op
->shift
;
2170 ext_operand
= decode_mips16_operand (type
, true);
2171 if (ext_operand
!= operand
2172 || (operand
->type
== OP_INT
&& operand
->lsb
== 0
2173 && mips_opcode_32bit_p (opcode
)))
2175 ext_size
= ext_operand
->size
;
2176 operand
= ext_operand
;
2179 if (operand
->size
== 26)
2180 uval
= ((extend
& 0x1f) << 21) | ((extend
& 0x3e0) << 11) | insn
;
2181 else if (ext_size
== 16 || ext_size
== 9)
2182 uval
= ((extend
& 0x1f) << 11) | (extend
& 0x7e0) | (insn
& 0x1f);
2183 else if (ext_size
== 15)
2184 uval
= ((extend
& 0xf) << 11) | (extend
& 0x7f0) | (insn
& 0xf);
2185 else if (ext_size
== 6)
2186 uval
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
2188 uval
= mips_extract_operand (operand
, (extend
<< 16) | insn
);
2190 uval
&= (1U << ext_size
) - 1;
2192 baseaddr
= memaddr
+ 2;
2193 if (operand
->type
== OP_PCREL
)
2195 const struct mips_pcrel_operand
*pcrel_op
;
2197 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
2198 if (!pcrel_op
->include_isa_bit
&& use_extend
)
2199 baseaddr
= memaddr
- 2;
2200 else if (!pcrel_op
->include_isa_bit
)
2204 /* If this instruction is in the delay slot of a JAL/JALX
2205 instruction, the base address is the address of the
2206 JAL/JALX instruction. If it is in the delay slot of
2207 a JR/JALR instruction, the base address is the address
2208 of the JR/JALR instruction. This test is unreliable:
2209 we have no way of knowing whether the previous word is
2210 instruction or data. */
2211 if (info
->read_memory_func (memaddr
- 4, buffer
, 2, info
) == 0
2212 && (((info
->endian
== BFD_ENDIAN_BIG
2213 ? bfd_getb16 (buffer
)
2214 : bfd_getl16 (buffer
))
2215 & 0xf800) == 0x1800))
2216 baseaddr
= memaddr
- 4;
2217 else if (info
->read_memory_func (memaddr
- 2, buffer
, 2,
2219 && (((info
->endian
== BFD_ENDIAN_BIG
2220 ? bfd_getb16 (buffer
)
2221 : bfd_getl16 (buffer
))
2222 & 0xf89f) == 0xe800)
2223 && (((info
->endian
== BFD_ENDIAN_BIG
2224 ? bfd_getb16 (buffer
)
2225 : bfd_getl16 (buffer
))
2226 & 0x0060) != 0x0060))
2227 baseaddr
= memaddr
- 2;
2233 print_insn_arg (info
, state
, opcode
, operand
, baseaddr
+ 1, uval
);
2239 /* Check if the given address is the last word of a MIPS16 PLT entry.
2240 This word is data and depending on the value it may interfere with
2241 disassembly of further PLT entries. We make use of the fact PLT
2242 symbols are marked BSF_SYNTHETIC. */
2244 is_mips16_plt_tail (struct disassemble_info
*info
, bfd_vma addr
)
2248 && (info
->symbols
[0]->flags
& BSF_SYNTHETIC
)
2249 && addr
== bfd_asymbol_value (info
->symbols
[0]) + 12)
2255 /* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2264 /* Disassemble mips16 instructions. */
2267 print_insn_mips16 (bfd_vma memaddr
, struct disassemble_info
*info
)
2269 const fprintf_styled_ftype infprintf
= info
->fprintf_styled_func
;
2272 const struct mips_opcode
*op
, *opend
;
2273 struct mips_print_arg_state state
;
2274 void *is
= info
->stream
;
2277 unsigned int second
;
2281 info
->bytes_per_chunk
= 2;
2282 info
->display_endian
= info
->endian
;
2283 info
->insn_info_valid
= 1;
2284 info
->branch_delay_insns
= 0;
2285 info
->data_size
= 0;
2289 #define GET_OP(insn, field) \
2290 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
2291 /* Decode PLT entry's GOT slot address word. */
2292 if (is_mips16_plt_tail (info
, memaddr
))
2294 info
->insn_type
= dis_noninsn
;
2295 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
2298 unsigned int gotslot
;
2300 if (info
->endian
== BFD_ENDIAN_BIG
)
2301 gotslot
= bfd_getb32 (buffer
);
2303 gotslot
= bfd_getl32 (buffer
);
2304 infprintf (is
, dis_style_assembler_directive
, ".word");
2305 infprintf (is
, dis_style_text
, "\t");
2306 infprintf (is
, dis_style_immediate
, "0x%x", gotslot
);
2313 info
->insn_type
= dis_nonbranch
;
2314 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2318 (*info
->memory_error_func
) (status
, memaddr
, info
);
2322 extend_only
= false;
2324 if (info
->endian
== BFD_ENDIAN_BIG
)
2325 first
= bfd_getb16 (buffer
);
2327 first
= bfd_getl16 (buffer
);
2329 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2333 if (info
->endian
== BFD_ENDIAN_BIG
)
2334 second
= bfd_getb16 (buffer
);
2336 second
= bfd_getl16 (buffer
);
2337 full
= (first
<< 16) | second
;
2341 have_second
= false;
2346 /* FIXME: Should probably use a hash table on the major opcode here. */
2348 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
2349 for (op
= mips16_opcodes
; op
< opend
; op
++)
2351 enum match_kind match
;
2353 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
))
2356 if (op
->pinfo
== INSN_MACRO
2357 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
2359 else if (mips_opcode_32bit_p (op
))
2362 && (full
& op
->mask
) == op
->match
)
2367 else if ((first
& op
->mask
) == op
->match
)
2369 match
= MATCH_SHORT
;
2373 else if ((first
& 0xf800) == 0xf000
2376 && (second
& op
->mask
) == op
->match
)
2378 if (op
->pinfo2
& INSN2_SHORT_ONLY
)
2389 if (match
!= MATCH_NONE
)
2393 infprintf (is
, dis_style_mnemonic
, "%s", op
->name
);
2394 if (op
->args
[0] != '\0')
2395 infprintf (is
, dis_style_text
, "\t");
2397 init_print_arg_state (&state
);
2398 for (s
= op
->args
; *s
!= '\0'; s
++)
2402 && GET_OP (full
, RX
) == GET_OP (full
, RY
))
2404 /* Skip the register and the comma. */
2410 && GET_OP (full
, RZ
) == GET_OP (full
, RX
))
2412 /* Skip the register and the comma. */
2419 && op
->name
[strlen (op
->name
) - 1] == '0')
2421 /* Coprocessor register 0 with sel field. */
2422 const struct mips_cp0sel_name
*n
;
2423 const struct mips_operand
*operand
;
2424 unsigned int reg
, sel
;
2426 operand
= decode_mips16_operand (*s
, true);
2427 reg
= mips_extract_operand (operand
, (first
<< 16) | second
);
2429 operand
= decode_mips16_operand (*s
, true);
2430 sel
= mips_extract_operand (operand
, (first
<< 16) | second
);
2432 /* CP0 register including 'sel' code for mftc0, to be
2433 printed textually if known. If not known, print both
2434 CP0 register name and sel numerically since CP0 register
2435 with sel 0 may have a name unrelated to register being
2437 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
2438 mips_cp0sel_names_len
,
2441 infprintf (is
, dis_style_register
, "%s", n
->name
);
2444 infprintf (is
, dis_style_register
, "$%d", reg
);
2445 infprintf (is
, dis_style_text
, ",");
2446 infprintf (is
, dis_style_immediate
, "%d", sel
);
2453 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
+ 2,
2454 second
, true, first
, s
[1] == '(');
2457 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
,
2458 first
, false, 0, s
[1] == '(');
2460 case MATCH_NONE
: /* Stop the compiler complaining. */
2465 /* Figure out branch instruction type and delay slot information. */
2466 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
2467 info
->branch_delay_insns
= 1;
2468 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0
2469 || (op
->pinfo2
& INSN2_UNCOND_BRANCH
) != 0)
2471 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2472 info
->insn_type
= dis_jsr
;
2474 info
->insn_type
= dis_branch
;
2476 else if ((op
->pinfo2
& INSN2_COND_BRANCH
) != 0)
2477 info
->insn_type
= dis_condbranch
;
2479 return match
== MATCH_FULL
? 4 : 2;
2484 infprintf (is
, dis_style_assembler_directive
, ".short");
2485 infprintf (is
, dis_style_text
, "\t");
2486 infprintf (is
, dis_style_immediate
, "0x%x", first
);
2487 info
->insn_type
= dis_noninsn
;
2492 /* Disassemble microMIPS instructions. */
2495 print_insn_micromips (bfd_vma memaddr
, struct disassemble_info
*info
)
2497 const fprintf_styled_ftype infprintf
= info
->fprintf_styled_func
;
2498 const struct mips_opcode
*op
, *opend
;
2499 void *is
= info
->stream
;
2501 unsigned int higher
;
2502 unsigned int length
;
2506 info
->bytes_per_chunk
= 2;
2507 info
->display_endian
= info
->endian
;
2508 info
->insn_info_valid
= 1;
2509 info
->branch_delay_insns
= 0;
2510 info
->data_size
= 0;
2511 info
->insn_type
= dis_nonbranch
;
2515 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2518 (*info
->memory_error_func
) (status
, memaddr
, info
);
2524 if (info
->endian
== BFD_ENDIAN_BIG
)
2525 insn
= bfd_getb16 (buffer
);
2527 insn
= bfd_getl16 (buffer
);
2529 if ((insn
& 0x1c00) == 0x0000 || (insn
& 0x1000) == 0x1000)
2531 /* This is a 32-bit microMIPS instruction. */
2534 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2537 infprintf (is
, dis_style_text
, "micromips 0x%x", higher
);
2538 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
2542 if (info
->endian
== BFD_ENDIAN_BIG
)
2543 insn
= bfd_getb16 (buffer
);
2545 insn
= bfd_getl16 (buffer
);
2547 insn
= insn
| (higher
<< 16);
2552 /* FIXME: Should probably use a hash table on the major opcode here. */
2554 opend
= micromips_opcodes
+ bfd_micromips_num_opcodes
;
2555 for (op
= micromips_opcodes
; op
< opend
; op
++)
2557 if (op
->pinfo
!= INSN_MACRO
2558 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
2559 && (insn
& op
->mask
) == op
->match
2560 && ((length
== 2 && (op
->mask
& 0xffff0000) == 0)
2561 || (length
== 4 && (op
->mask
& 0xffff0000) != 0)))
2563 if (!validate_insn_args (op
, decode_micromips_operand
, insn
))
2566 infprintf (is
, dis_style_mnemonic
, "%s", op
->name
);
2570 infprintf (is
, dis_style_text
, "\t");
2571 print_insn_args (info
, op
, decode_micromips_operand
, insn
,
2572 memaddr
+ 1, length
);
2575 /* Figure out instruction type and branch delay information. */
2577 & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
)) != 0)
2578 info
->branch_delay_insns
= 1;
2579 if (((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
2580 | (op
->pinfo2
& INSN2_UNCOND_BRANCH
)) != 0)
2582 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
2583 info
->insn_type
= dis_jsr
;
2585 info
->insn_type
= dis_branch
;
2587 else if (((op
->pinfo
& INSN_COND_BRANCH_DELAY
)
2588 | (op
->pinfo2
& INSN2_COND_BRANCH
)) != 0)
2590 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2591 info
->insn_type
= dis_condjsr
;
2593 info
->insn_type
= dis_condbranch
;
2596 & (INSN_STORE_MEMORY
| INSN_LOAD_MEMORY
)) != 0)
2597 info
->insn_type
= dis_dref
;
2604 infprintf (is
, dis_style_assembler_directive
, ".short");
2606 infprintf (is
, dis_style_assembler_directive
, ".word");
2607 infprintf (is
, dis_style_text
, "\t");
2608 infprintf (is
, dis_style_immediate
, "0x%x", insn
);
2609 info
->insn_type
= dis_noninsn
;
2614 /* Return 1 if a symbol associated with the location being disassembled
2615 indicates a compressed mode, either MIPS16 or microMIPS, according to
2616 MICROMIPS_P. We iterate over all the symbols at the address being
2617 considered assuming if at least one of them indicates code compression,
2618 then such code has been genuinely produced here (other symbols could
2619 have been derived from function symbols defined elsewhere or could
2620 define data). Otherwise, return 0. */
2623 is_compressed_mode_p (struct disassemble_info
*info
, bool micromips_p
)
2628 for (i
= info
->symtab_pos
, l
= i
+ info
->num_symbols
; i
< l
; i
++)
2629 if (((info
->symtab
[i
])->flags
& BSF_SYNTHETIC
) != 0
2631 && ELF_ST_IS_MIPS16 ((*info
->symbols
)->udata
.i
))
2633 && ELF_ST_IS_MICROMIPS ((*info
->symbols
)->udata
.i
))))
2635 else if (bfd_asymbol_flavour (info
->symtab
[i
]) == bfd_target_elf_flavour
2636 && info
->symtab
[i
]->section
== info
->section
)
2638 elf_symbol_type
*symbol
= (elf_symbol_type
*) info
->symtab
[i
];
2640 && ELF_ST_IS_MIPS16 (symbol
->internal_elf_sym
.st_other
))
2642 && ELF_ST_IS_MICROMIPS (symbol
->internal_elf_sym
.st_other
)))
2649 /* In an environment where we do not know the symbol type of the
2650 instruction we are forced to assume that the low order bit of the
2651 instructions' address may mark it as a mips16 instruction. If we
2652 are single stepping, or the pc is within the disassembled function,
2653 this works. Otherwise, we need a clue. Sometimes. */
2656 _print_insn_mips (bfd_vma memaddr
,
2657 struct disassemble_info
*info
,
2658 enum bfd_endian endianness
)
2660 bfd_byte buffer
[INSNLEN
];
2663 set_default_mips_dis_options (info
);
2664 parse_mips_dis_options (info
->disassembler_options
);
2666 if (info
->mach
== bfd_mach_mips16
)
2667 return print_insn_mips16 (memaddr
, info
);
2668 if (info
->mach
== bfd_mach_mips_micromips
)
2669 return print_insn_micromips (memaddr
, info
);
2672 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
2673 /* Only a few tools will work this way. */
2677 return print_insn_micromips (memaddr
, info
);
2679 return print_insn_mips16 (memaddr
, info
);
2683 #if SYMTAB_AVAILABLE
2684 if (is_compressed_mode_p (info
, true))
2685 return print_insn_micromips (memaddr
, info
);
2686 if (is_compressed_mode_p (info
, false))
2687 return print_insn_mips16 (memaddr
, info
);
2690 status
= (*info
->read_memory_func
) (memaddr
, buffer
, INSNLEN
, info
);
2695 if (endianness
== BFD_ENDIAN_BIG
)
2696 insn
= bfd_getb32 (buffer
);
2698 insn
= bfd_getl32 (buffer
);
2700 return print_insn_mips (memaddr
, insn
, info
);
2704 (*info
->memory_error_func
) (status
, memaddr
, info
);
2710 print_insn_big_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2712 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_BIG
);
2716 print_insn_little_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2718 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_LITTLE
);
2721 /* Indices into option argument vector for options accepting an argument.
2722 Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2725 MIPS_OPTION_ARG_NONE
= -1,
2726 MIPS_OPTION_ARG_ABI
,
2727 MIPS_OPTION_ARG_ARCH
,
2728 MIPS_OPTION_ARG_SIZE
2729 } mips_option_arg_t
;
2731 /* Valid MIPS disassembler options. */
2735 const char *description
;
2736 mips_option_arg_t arg
;
2739 { "no-aliases", N_("Use canonical instruction forms.\n"),
2740 MIPS_OPTION_ARG_NONE
},
2741 { "msa", N_("Recognize MSA instructions.\n"),
2742 MIPS_OPTION_ARG_NONE
},
2743 { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2744 MIPS_OPTION_ARG_NONE
},
2745 { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2747 MIPS_OPTION_ARG_NONE
},
2748 { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2750 MIPS_OPTION_ARG_NONE
},
2752 N_("Recognize the Loongson MultiMedia extensions "
2753 "Instructions (MMI) ASE instructions.\n"),
2754 MIPS_OPTION_ARG_NONE
},
2756 N_("Recognize the Loongson Content Address Memory (CAM) "
2757 " instructions.\n"),
2758 MIPS_OPTION_ARG_NONE
},
2760 N_("Recognize the Loongson EXTensions (EXT) "
2761 " instructions.\n"),
2762 MIPS_OPTION_ARG_NONE
},
2764 N_("Recognize the Loongson EXTensions R2 (EXT2) "
2765 " instructions.\n"),
2766 MIPS_OPTION_ARG_NONE
},
2767 { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2768 Default: based on binary being disassembled.\n"),
2769 MIPS_OPTION_ARG_ABI
},
2770 { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2771 Default: numeric.\n"),
2772 MIPS_OPTION_ARG_ABI
},
2773 { "cp0-names=", N_("Print CP0 register names according to specified "
2775 Default: based on binary being disassembled.\n"),
2776 MIPS_OPTION_ARG_ARCH
},
2777 { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2778 Default: based on binary being disassembled.\n"),
2779 MIPS_OPTION_ARG_ARCH
},
2780 { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2781 MIPS_OPTION_ARG_ABI
},
2782 { "reg-names=", N_("Print CP0 register and HWR names according to "
2785 MIPS_OPTION_ARG_ARCH
}
2788 /* Build the structure representing valid MIPS disassembler options.
2789 This is done dynamically for maintenance ease purpose; a static
2790 initializer would be unreadable. */
2792 const disasm_options_and_args_t
*
2793 disassembler_options_mips (void)
2795 static disasm_options_and_args_t
*opts_and_args
;
2797 if (opts_and_args
== NULL
)
2799 size_t num_options
= ARRAY_SIZE (mips_options
);
2800 size_t num_args
= MIPS_OPTION_ARG_SIZE
;
2801 disasm_option_arg_t
*args
;
2802 disasm_options_t
*opts
;
2806 args
= XNEWVEC (disasm_option_arg_t
, num_args
+ 1);
2808 args
[MIPS_OPTION_ARG_ABI
].name
= "ABI";
2809 args
[MIPS_OPTION_ARG_ABI
].values
2810 = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices
) + 1);
2811 for (i
= 0; i
< ARRAY_SIZE (mips_abi_choices
); i
++)
2812 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = mips_abi_choices
[i
].name
;
2813 /* The array we return must be NULL terminated. */
2814 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = NULL
;
2816 args
[MIPS_OPTION_ARG_ARCH
].name
= "ARCH";
2817 args
[MIPS_OPTION_ARG_ARCH
].values
2818 = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices
) + 1);
2819 for (i
= 0, j
= 0; i
< ARRAY_SIZE (mips_arch_choices
); i
++)
2820 if (*mips_arch_choices
[i
].name
!= '\0')
2821 args
[MIPS_OPTION_ARG_ARCH
].values
[j
++] = mips_arch_choices
[i
].name
;
2822 /* The array we return must be NULL terminated. */
2823 args
[MIPS_OPTION_ARG_ARCH
].values
[j
] = NULL
;
2825 /* The array we return must be NULL terminated. */
2826 args
[MIPS_OPTION_ARG_SIZE
].name
= NULL
;
2827 args
[MIPS_OPTION_ARG_SIZE
].values
= NULL
;
2829 opts_and_args
= XNEW (disasm_options_and_args_t
);
2830 opts_and_args
->args
= args
;
2832 opts
= &opts_and_args
->options
;
2833 opts
->name
= XNEWVEC (const char *, num_options
+ 1);
2834 opts
->description
= XNEWVEC (const char *, num_options
+ 1);
2835 opts
->arg
= XNEWVEC (const disasm_option_arg_t
*, num_options
+ 1);
2836 for (i
= 0; i
< num_options
; i
++)
2838 opts
->name
[i
] = mips_options
[i
].name
;
2839 opts
->description
[i
] = _(mips_options
[i
].description
);
2840 if (mips_options
[i
].arg
!= MIPS_OPTION_ARG_NONE
)
2841 opts
->arg
[i
] = &args
[mips_options
[i
].arg
];
2843 opts
->arg
[i
] = NULL
;
2845 /* The array we return must be NULL terminated. */
2846 opts
->name
[i
] = NULL
;
2847 opts
->description
[i
] = NULL
;
2848 opts
->arg
[i
] = NULL
;
2851 return opts_and_args
;
2855 print_mips_disassembler_options (FILE *stream
)
2857 const disasm_options_and_args_t
*opts_and_args
;
2858 const disasm_option_arg_t
*args
;
2859 const disasm_options_t
*opts
;
2864 opts_and_args
= disassembler_options_mips ();
2865 opts
= &opts_and_args
->options
;
2866 args
= opts_and_args
->args
;
2868 fprintf (stream
, _("\n\
2869 The following MIPS specific disassembler options are supported for use\n\
2870 with the -M switch (multiple options should be separated by commas):\n\n"));
2872 /* Compute the length of the longest option name. */
2873 for (i
= 0; opts
->name
[i
] != NULL
; i
++)
2875 size_t len
= strlen (opts
->name
[i
]);
2877 if (opts
->arg
[i
] != NULL
)
2878 len
+= strlen (opts
->arg
[i
]->name
);
2883 for (i
= 0, max_len
++; opts
->name
[i
] != NULL
; i
++)
2885 fprintf (stream
, " %s", opts
->name
[i
]);
2886 if (opts
->arg
[i
] != NULL
)
2887 fprintf (stream
, "%s", opts
->arg
[i
]->name
);
2888 if (opts
->description
[i
] != NULL
)
2890 size_t len
= strlen (opts
->name
[i
]);
2892 if (opts
->arg
[i
] != NULL
)
2893 len
+= strlen (opts
->arg
[i
]->name
);
2895 "%*c %s", (int) (max_len
- len
), ' ', opts
->description
[i
]);
2897 fprintf (stream
, _("\n"));
2900 for (i
= 0; args
[i
].name
!= NULL
; i
++)
2902 if (args
[i
].values
== NULL
)
2904 fprintf (stream
, _("\n\
2905 For the options above, the following values are supported for \"%s\":\n "),
2907 for (j
= 0; args
[i
].values
[j
] != NULL
; j
++)
2908 fprintf (stream
, " %s", args
[i
].values
[j
]);
2909 fprintf (stream
, _("\n"));
2912 fprintf (stream
, _("\n"));