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
)
1179 info
->fprintf_func (info
->stream
, "%s", mips_gpr_names
[regno
]);
1183 info
->fprintf_func (info
->stream
, "%s", mips_fpr_names
[regno
]);
1187 if (opcode
->pinfo
& (FP_D
| FP_S
))
1188 info
->fprintf_func (info
->stream
, "$fcc%d", regno
);
1190 info
->fprintf_func (info
->stream
, "$cc%d", regno
);
1194 if (opcode
->membership
& INSN_5400
)
1195 info
->fprintf_func (info
->stream
, "$f%d", regno
);
1197 info
->fprintf_func (info
->stream
, "$v%d", regno
);
1201 info
->fprintf_func (info
->stream
, "$ac%d", regno
);
1205 if (opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1206 info
->fprintf_func (info
->stream
, "%s", mips_cp0_names
[regno
]);
1208 info
->fprintf_func (info
->stream
, "$%d", regno
);
1211 case OP_REG_CONTROL
:
1212 if (opcode
->name
[strlen (opcode
->name
) - 1] == '1')
1213 info
->fprintf_func (info
->stream
, "%s", mips_cp1_names
[regno
]);
1215 info
->fprintf_func (info
->stream
, "$%d", regno
);
1219 info
->fprintf_func (info
->stream
, "%s", mips_hwr_names
[regno
]);
1223 info
->fprintf_func (info
->stream
, "$vf%d", regno
);
1227 info
->fprintf_func (info
->stream
, "$vi%d", regno
);
1230 case OP_REG_R5900_I
:
1231 info
->fprintf_func (info
->stream
, "$I");
1234 case OP_REG_R5900_Q
:
1235 info
->fprintf_func (info
->stream
, "$Q");
1238 case OP_REG_R5900_R
:
1239 info
->fprintf_func (info
->stream
, "$R");
1242 case OP_REG_R5900_ACC
:
1243 info
->fprintf_func (info
->stream
, "$ACC");
1247 info
->fprintf_func (info
->stream
, "$w%d", regno
);
1250 case OP_REG_MSA_CTRL
:
1251 info
->fprintf_func (info
->stream
, "%s", msa_control_names
[regno
]);
1257 /* Used to track the state carried over from previous operands in
1259 struct mips_print_arg_state
{
1260 /* The value of the last OP_INT seen. We only use this for OP_MSB,
1261 where the value is known to be unsigned and small. */
1262 unsigned int last_int
;
1264 /* The type and number of the last OP_REG seen. We only use this for
1265 OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1266 enum mips_reg_operand_type last_reg_type
;
1267 unsigned int last_regno
;
1268 unsigned int dest_regno
;
1269 unsigned int seen_dest
;
1272 /* Initialize STATE for the start of an instruction. */
1275 init_print_arg_state (struct mips_print_arg_state
*state
)
1277 memset (state
, 0, sizeof (*state
));
1280 /* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1281 whose value is given by UVAL. */
1284 print_vu0_channel (struct disassemble_info
*info
,
1285 const struct mips_operand
*operand
, unsigned int uval
)
1287 if (operand
->size
== 4)
1288 info
->fprintf_func (info
->stream
, "%s%s%s%s",
1289 uval
& 8 ? "x" : "",
1290 uval
& 4 ? "y" : "",
1291 uval
& 2 ? "z" : "",
1292 uval
& 1 ? "w" : "");
1293 else if (operand
->size
== 2)
1294 info
->fprintf_func (info
->stream
, "%c", "xyzw"[uval
]);
1299 /* Record information about a register operand. */
1302 mips_seen_register (struct mips_print_arg_state
*state
,
1304 enum mips_reg_operand_type reg_type
)
1306 state
->last_reg_type
= reg_type
;
1307 state
->last_regno
= regno
;
1309 if (!state
->seen_dest
)
1311 state
->seen_dest
= 1;
1312 state
->dest_regno
= regno
;
1316 /* Print SAVE/RESTORE instruction operands according to the argument
1317 register mask AMASK, the number of static registers saved NSREG,
1318 the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1319 and the frame size FRAME_SIZE. */
1322 mips_print_save_restore (struct disassemble_info
*info
, unsigned int amask
,
1323 unsigned int nsreg
, unsigned int ra
,
1324 unsigned int s0
, unsigned int s1
,
1325 unsigned int frame_size
)
1327 const fprintf_ftype infprintf
= info
->fprintf_func
;
1328 unsigned int nargs
, nstatics
, smask
, i
, j
;
1329 void *is
= info
->stream
;
1332 if (amask
== MIPS_SVRS_ALL_ARGS
)
1337 else if (amask
== MIPS_SVRS_ALL_STATICS
)
1345 nstatics
= amask
& 3;
1351 infprintf (is
, "%s", mips_gpr_names
[4]);
1353 infprintf (is
, "-%s", mips_gpr_names
[4 + nargs
- 1]);
1357 infprintf (is
, "%s%d", sep
, frame_size
);
1360 infprintf (is
, ",%s", mips_gpr_names
[31]);
1367 if (nsreg
> 0) /* $s2-$s8 */
1368 smask
|= ((1 << nsreg
) - 1) << 2;
1370 for (i
= 0; i
< 9; i
++)
1371 if (smask
& (1 << i
))
1373 infprintf (is
, ",%s", mips_gpr_names
[i
== 8 ? 30 : (16 + i
)]);
1374 /* Skip over string of set bits. */
1375 for (j
= i
; smask
& (2 << j
); j
++)
1378 infprintf (is
, "-%s", mips_gpr_names
[j
== 8 ? 30 : (16 + j
)]);
1381 /* Statics $ax - $a3. */
1383 infprintf (is
, ",%s", mips_gpr_names
[7]);
1384 else if (nstatics
> 0)
1385 infprintf (is
, ",%s-%s",
1386 mips_gpr_names
[7 - nstatics
+ 1],
1391 /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1392 UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1393 the base address for OP_PCREL operands. */
1396 print_insn_arg (struct disassemble_info
*info
,
1397 struct mips_print_arg_state
*state
,
1398 const struct mips_opcode
*opcode
,
1399 const struct mips_operand
*operand
,
1403 const fprintf_ftype infprintf
= info
->fprintf_func
;
1404 void *is
= info
->stream
;
1406 switch (operand
->type
)
1410 const struct mips_int_operand
*int_op
;
1412 int_op
= (const struct mips_int_operand
*) operand
;
1413 uval
= mips_decode_int_operand (int_op
, uval
);
1414 state
->last_int
= uval
;
1415 if (int_op
->print_hex
)
1416 infprintf (is
, "0x%x", uval
);
1418 infprintf (is
, "%d", uval
);
1424 const struct mips_mapped_int_operand
*mint_op
;
1426 mint_op
= (const struct mips_mapped_int_operand
*) operand
;
1427 uval
= mint_op
->int_map
[uval
];
1428 state
->last_int
= uval
;
1429 if (mint_op
->print_hex
)
1430 infprintf (is
, "0x%x", uval
);
1432 infprintf (is
, "%d", uval
);
1438 const struct mips_msb_operand
*msb_op
;
1440 msb_op
= (const struct mips_msb_operand
*) operand
;
1441 uval
+= msb_op
->bias
;
1442 if (msb_op
->add_lsb
)
1443 uval
-= state
->last_int
;
1444 infprintf (is
, "0x%x", uval
);
1449 case OP_OPTIONAL_REG
:
1451 const struct mips_reg_operand
*reg_op
;
1453 reg_op
= (const struct mips_reg_operand
*) operand
;
1454 uval
= mips_decode_reg_operand (reg_op
, uval
);
1455 print_reg (info
, opcode
, reg_op
->reg_type
, uval
);
1457 mips_seen_register (state
, uval
, reg_op
->reg_type
);
1463 const struct mips_reg_pair_operand
*pair_op
;
1465 pair_op
= (const struct mips_reg_pair_operand
*) operand
;
1466 print_reg (info
, opcode
, pair_op
->reg_type
,
1467 pair_op
->reg1_map
[uval
]);
1468 infprintf (is
, ",");
1469 print_reg (info
, opcode
, pair_op
->reg_type
,
1470 pair_op
->reg2_map
[uval
]);
1476 const struct mips_pcrel_operand
*pcrel_op
;
1478 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1479 info
->target
= mips_decode_pcrel_operand (pcrel_op
, base_pc
, uval
);
1481 /* For jumps and branches clear the ISA bit except for
1482 the GDB disassembler. */
1483 if (pcrel_op
->include_isa_bit
1484 && info
->flavour
!= bfd_target_unknown_flavour
)
1487 (*info
->print_address_func
) (info
->target
, info
);
1492 infprintf (is
, "%d", uval
);
1495 case OP_ADDIUSP_INT
:
1499 sval
= mips_signed_operand (operand
, uval
) * 4;
1500 if (sval
>= -8 && sval
< 8)
1502 infprintf (is
, "%d", sval
);
1506 case OP_CLO_CLZ_DEST
:
1508 unsigned int reg1
, reg2
;
1512 /* If one is zero use the other. */
1513 if (reg1
== reg2
|| reg2
== 0)
1514 infprintf (is
, "%s", mips_gpr_names
[reg1
]);
1516 infprintf (is
, "%s", mips_gpr_names
[reg2
]);
1518 /* Bogus, result depends on processor. */
1519 infprintf (is
, "%s or %s", mips_gpr_names
[reg1
],
1520 mips_gpr_names
[reg2
]);
1526 case OP_NON_ZERO_REG
:
1528 print_reg (info
, opcode
, OP_REG_GP
, uval
& 31);
1529 mips_seen_register (state
, uval
, OP_REG_GP
);
1533 case OP_LWM_SWM_LIST
:
1534 if (operand
->size
== 2)
1537 infprintf (is
, "%s,%s",
1539 mips_gpr_names
[31]);
1541 infprintf (is
, "%s-%s,%s",
1543 mips_gpr_names
[16 + uval
],
1544 mips_gpr_names
[31]);
1550 s_reg_encode
= uval
& 0xf;
1551 if (s_reg_encode
!= 0)
1553 if (s_reg_encode
== 1)
1554 infprintf (is
, "%s", mips_gpr_names
[16]);
1555 else if (s_reg_encode
< 9)
1556 infprintf (is
, "%s-%s",
1558 mips_gpr_names
[15 + s_reg_encode
]);
1559 else if (s_reg_encode
== 9)
1560 infprintf (is
, "%s-%s,%s",
1563 mips_gpr_names
[30]);
1565 infprintf (is
, "UNKNOWN");
1568 if (uval
& 0x10) /* For ra. */
1570 if (s_reg_encode
== 0)
1571 infprintf (is
, "%s", mips_gpr_names
[31]);
1573 infprintf (is
, ",%s", mips_gpr_names
[31]);
1578 case OP_ENTRY_EXIT_LIST
:
1581 unsigned int amask
, smask
;
1584 amask
= (uval
>> 3) & 7;
1585 if (amask
> 0 && amask
< 5)
1587 infprintf (is
, "%s", mips_gpr_names
[4]);
1589 infprintf (is
, "-%s", mips_gpr_names
[amask
+ 3]);
1593 smask
= (uval
>> 1) & 3;
1596 infprintf (is
, "%s??", sep
);
1601 infprintf (is
, "%s%s", sep
, mips_gpr_names
[16]);
1603 infprintf (is
, "-%s", mips_gpr_names
[smask
+ 15]);
1609 infprintf (is
, "%s%s", sep
, mips_gpr_names
[31]);
1613 if (amask
== 5 || amask
== 6)
1615 infprintf (is
, "%s%s", sep
, mips_fpr_names
[0]);
1617 infprintf (is
, "-%s", mips_fpr_names
[1]);
1622 case OP_SAVE_RESTORE_LIST
:
1623 /* Should be handled by the caller due to complex behavior. */
1626 case OP_MDMX_IMM_REG
:
1632 if ((vsel
& 0x10) == 0)
1637 for (fmt
= 0; fmt
< 3; fmt
++, vsel
>>= 1)
1638 if ((vsel
& 1) == 0)
1640 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1641 infprintf (is
, "[%d]", vsel
>> 1);
1643 else if ((vsel
& 0x08) == 0)
1644 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1646 infprintf (is
, "0x%x", uval
);
1650 case OP_REPEAT_PREV_REG
:
1651 print_reg (info
, opcode
, state
->last_reg_type
, state
->last_regno
);
1654 case OP_REPEAT_DEST_REG
:
1655 print_reg (info
, opcode
, state
->last_reg_type
, state
->dest_regno
);
1659 infprintf (is
, "$pc");
1663 print_reg (info
, opcode
, OP_REG_GP
, 28);
1667 case OP_VU0_MATCH_SUFFIX
:
1668 print_vu0_channel (info
, operand
, uval
);
1672 infprintf (is
, "[%d]", uval
);
1676 infprintf (is
, "[");
1677 print_reg (info
, opcode
, OP_REG_GP
, uval
);
1678 infprintf (is
, "]");
1683 /* Validate the arguments for INSN, which is described by OPCODE.
1684 Use DECODE_OPERAND to get the encoding of each operand. */
1687 validate_insn_args (const struct mips_opcode
*opcode
,
1688 const struct mips_operand
*(*decode_operand
) (const char *),
1691 struct mips_print_arg_state state
;
1692 const struct mips_operand
*operand
;
1696 init_print_arg_state (&state
);
1697 for (s
= opcode
->args
; *s
; ++s
)
1711 operand
= decode_operand (s
);
1715 uval
= mips_extract_operand (operand
, insn
);
1716 switch (operand
->type
)
1719 case OP_OPTIONAL_REG
:
1721 const struct mips_reg_operand
*reg_op
;
1723 reg_op
= (const struct mips_reg_operand
*) operand
;
1724 uval
= mips_decode_reg_operand (reg_op
, uval
);
1725 mips_seen_register (&state
, uval
, reg_op
->reg_type
);
1731 unsigned int reg1
, reg2
;
1736 if (reg1
!= reg2
|| reg1
== 0)
1743 const struct mips_check_prev_operand
*prev_op
;
1745 prev_op
= (const struct mips_check_prev_operand
*) operand
;
1747 if (!prev_op
->zero_ok
&& uval
== 0)
1750 if (((prev_op
->less_than_ok
&& uval
< state
.last_regno
)
1751 || (prev_op
->greater_than_ok
&& uval
> state
.last_regno
)
1752 || (prev_op
->equal_ok
&& uval
== state
.last_regno
)))
1758 case OP_NON_ZERO_REG
:
1771 case OP_ADDIUSP_INT
:
1772 case OP_CLO_CLZ_DEST
:
1773 case OP_LWM_SWM_LIST
:
1774 case OP_ENTRY_EXIT_LIST
:
1775 case OP_MDMX_IMM_REG
:
1776 case OP_REPEAT_PREV_REG
:
1777 case OP_REPEAT_DEST_REG
:
1781 case OP_VU0_MATCH_SUFFIX
:
1784 case OP_SAVE_RESTORE_LIST
:
1788 if (*s
== 'm' || *s
== '+' || *s
== '-')
1795 /* Print the arguments for INSN, which is described by OPCODE.
1796 Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
1797 as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1798 operand is for a branch or jump. */
1801 print_insn_args (struct disassemble_info
*info
,
1802 const struct mips_opcode
*opcode
,
1803 const struct mips_operand
*(*decode_operand
) (const char *),
1804 unsigned int insn
, bfd_vma insn_pc
, unsigned int length
)
1806 const fprintf_ftype infprintf
= info
->fprintf_func
;
1807 void *is
= info
->stream
;
1808 struct mips_print_arg_state state
;
1809 const struct mips_operand
*operand
;
1812 init_print_arg_state (&state
);
1813 for (s
= opcode
->args
; *s
; ++s
)
1820 infprintf (is
, "%c", *s
);
1825 infprintf (is
, "%c%c", *s
, *s
);
1829 operand
= decode_operand (s
);
1832 /* xgettext:c-format */
1834 _("# internal error, undefined operand in `%s %s'"),
1835 opcode
->name
, opcode
->args
);
1839 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
1841 /* Handle this case here because of the complex behavior. */
1842 unsigned int amask
= (insn
>> 15) & 0xf;
1843 unsigned int nsreg
= (insn
>> 23) & 0x7;
1844 unsigned int ra
= insn
& 0x1000; /* $ra */
1845 unsigned int s0
= insn
& 0x800; /* $s0 */
1846 unsigned int s1
= insn
& 0x400; /* $s1 */
1847 unsigned int frame_size
= (((insn
>> 15) & 0xf0)
1848 | ((insn
>> 6) & 0x0f)) * 8;
1849 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
,
1852 else if (operand
->type
== OP_REG
1855 && opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1857 /* Coprocessor register 0 with sel field. */
1858 const struct mips_cp0sel_name
*n
;
1859 unsigned int reg
, sel
;
1861 reg
= mips_extract_operand (operand
, insn
);
1863 operand
= decode_operand (s
);
1864 sel
= mips_extract_operand (operand
, insn
);
1866 /* CP0 register including 'sel' code for mftc0, to be
1867 printed textually if known. If not known, print both
1868 CP0 register name and sel numerically since CP0 register
1869 with sel 0 may have a name unrelated to register being
1871 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
1872 mips_cp0sel_names_len
,
1875 infprintf (is
, "%s", n
->name
);
1877 infprintf (is
, "$%d,%d", reg
, sel
);
1881 bfd_vma base_pc
= insn_pc
;
1883 /* Adjust the PC relative base so that branch/jump insns use
1884 the following PC as the base but genuinely PC relative
1885 operands use the current PC. */
1886 if (operand
->type
== OP_PCREL
)
1888 const struct mips_pcrel_operand
*pcrel_op
;
1890 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1891 /* The include_isa_bit flag is sufficient to distinguish
1892 branch/jump from other PC relative operands. */
1893 if (pcrel_op
->include_isa_bit
)
1897 print_insn_arg (info
, &state
, opcode
, operand
, base_pc
,
1898 mips_extract_operand (operand
, insn
));
1900 if (*s
== 'm' || *s
== '+' || *s
== '-')
1907 /* Print the mips instruction at address MEMADDR in debugged memory,
1908 on using INFO. Returns length of the instruction, in bytes, which is
1909 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
1910 this is little-endian code. */
1913 print_insn_mips (bfd_vma memaddr
,
1915 struct disassemble_info
*info
)
1917 #define GET_OP(insn, field) \
1918 (((insn) >> OP_SH_##field) & OP_MASK_##field)
1919 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
1920 const fprintf_ftype infprintf
= info
->fprintf_func
;
1921 const struct mips_opcode
*op
;
1922 static bool init
= 0;
1923 void *is
= info
->stream
;
1925 /* Build a hash table to shorten the search time. */
1930 for (i
= 0; i
<= OP_MASK_OP
; i
++)
1932 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1934 if (op
->pinfo
== INSN_MACRO
1935 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
1937 if (i
== GET_OP (op
->match
, OP
))
1948 info
->bytes_per_chunk
= INSNLEN
;
1949 info
->display_endian
= info
->endian
;
1950 info
->insn_info_valid
= 1;
1951 info
->branch_delay_insns
= 0;
1952 info
->data_size
= 0;
1953 info
->insn_type
= dis_nonbranch
;
1957 op
= mips_hash
[GET_OP (word
, OP
)];
1960 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1962 if (op
->pinfo
!= INSN_MACRO
1963 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
1964 && (word
& op
->mask
) == op
->match
)
1966 /* We always disassemble the jalx instruction, except for MIPS r6. */
1967 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
)
1968 && (strcmp (op
->name
, "jalx")
1969 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS32R6
1970 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
))
1973 /* Figure out instruction type and branch delay information. */
1974 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
1976 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
1977 info
->insn_type
= dis_jsr
;
1979 info
->insn_type
= dis_branch
;
1980 info
->branch_delay_insns
= 1;
1982 else if ((op
->pinfo
& (INSN_COND_BRANCH_DELAY
1983 | INSN_COND_BRANCH_LIKELY
)) != 0)
1985 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
1986 info
->insn_type
= dis_condjsr
;
1988 info
->insn_type
= dis_condbranch
;
1989 info
->branch_delay_insns
= 1;
1991 else if ((op
->pinfo
& (INSN_STORE_MEMORY
1992 | INSN_LOAD_MEMORY
)) != 0)
1993 info
->insn_type
= dis_dref
;
1995 if (!validate_insn_args (op
, decode_mips_operand
, word
))
1998 infprintf (is
, "%s", op
->name
);
1999 if (op
->pinfo2
& INSN2_VU0_CHANNEL_SUFFIX
)
2003 infprintf (is
, ".");
2004 uval
= mips_extract_operand (&mips_vu0_channel_mask
, word
);
2005 print_vu0_channel (info
, &mips_vu0_channel_mask
, uval
);
2010 infprintf (is
, "\t");
2011 print_insn_args (info
, op
, decode_mips_operand
, word
,
2021 /* Handle undefined instructions. */
2022 info
->insn_type
= dis_noninsn
;
2023 infprintf (is
, "0x%x", word
);
2027 /* Disassemble an operand for a mips16 instruction. */
2030 print_mips16_insn_arg (struct disassemble_info
*info
,
2031 struct mips_print_arg_state
*state
,
2032 const struct mips_opcode
*opcode
,
2033 char type
, bfd_vma memaddr
,
2034 unsigned insn
, bool use_extend
,
2035 unsigned extend
, bool is_offset
)
2037 const fprintf_ftype infprintf
= info
->fprintf_func
;
2038 void *is
= info
->stream
;
2039 const struct mips_operand
*operand
, *ext_operand
;
2040 unsigned short ext_size
;
2052 infprintf (is
, "%c", type
);
2056 operand
= decode_mips16_operand (type
, false);
2059 /* xgettext:c-format */
2060 infprintf (is
, _("# internal error, undefined operand in `%s %s'"),
2061 opcode
->name
, opcode
->args
);
2065 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
2067 /* Handle this case here because of the complex interaction
2068 with the EXTEND opcode. */
2069 unsigned int amask
= extend
& 0xf;
2070 unsigned int nsreg
= (extend
>> 8) & 0x7;
2071 unsigned int ra
= insn
& 0x40; /* $ra */
2072 unsigned int s0
= insn
& 0x20; /* $s0 */
2073 unsigned int s1
= insn
& 0x10; /* $s1 */
2074 unsigned int frame_size
= ((extend
& 0xf0) | (insn
& 0x0f)) * 8;
2075 if (frame_size
== 0 && !use_extend
)
2077 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
, frame_size
);
2081 if (is_offset
&& operand
->type
== OP_INT
)
2083 const struct mips_int_operand
*int_op
;
2085 int_op
= (const struct mips_int_operand
*) operand
;
2086 info
->insn_type
= dis_dref
;
2087 info
->data_size
= 1 << int_op
->shift
;
2093 ext_operand
= decode_mips16_operand (type
, true);
2094 if (ext_operand
!= operand
2095 || (operand
->type
== OP_INT
&& operand
->lsb
== 0
2096 && mips_opcode_32bit_p (opcode
)))
2098 ext_size
= ext_operand
->size
;
2099 operand
= ext_operand
;
2102 if (operand
->size
== 26)
2103 uval
= ((extend
& 0x1f) << 21) | ((extend
& 0x3e0) << 11) | insn
;
2104 else if (ext_size
== 16 || ext_size
== 9)
2105 uval
= ((extend
& 0x1f) << 11) | (extend
& 0x7e0) | (insn
& 0x1f);
2106 else if (ext_size
== 15)
2107 uval
= ((extend
& 0xf) << 11) | (extend
& 0x7f0) | (insn
& 0xf);
2108 else if (ext_size
== 6)
2109 uval
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
2111 uval
= mips_extract_operand (operand
, (extend
<< 16) | insn
);
2113 uval
&= (1U << ext_size
) - 1;
2115 baseaddr
= memaddr
+ 2;
2116 if (operand
->type
== OP_PCREL
)
2118 const struct mips_pcrel_operand
*pcrel_op
;
2120 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
2121 if (!pcrel_op
->include_isa_bit
&& use_extend
)
2122 baseaddr
= memaddr
- 2;
2123 else if (!pcrel_op
->include_isa_bit
)
2127 /* If this instruction is in the delay slot of a JAL/JALX
2128 instruction, the base address is the address of the
2129 JAL/JALX instruction. If it is in the delay slot of
2130 a JR/JALR instruction, the base address is the address
2131 of the JR/JALR instruction. This test is unreliable:
2132 we have no way of knowing whether the previous word is
2133 instruction or data. */
2134 if (info
->read_memory_func (memaddr
- 4, buffer
, 2, info
) == 0
2135 && (((info
->endian
== BFD_ENDIAN_BIG
2136 ? bfd_getb16 (buffer
)
2137 : bfd_getl16 (buffer
))
2138 & 0xf800) == 0x1800))
2139 baseaddr
= memaddr
- 4;
2140 else if (info
->read_memory_func (memaddr
- 2, buffer
, 2,
2142 && (((info
->endian
== BFD_ENDIAN_BIG
2143 ? bfd_getb16 (buffer
)
2144 : bfd_getl16 (buffer
))
2145 & 0xf89f) == 0xe800)
2146 && (((info
->endian
== BFD_ENDIAN_BIG
2147 ? bfd_getb16 (buffer
)
2148 : bfd_getl16 (buffer
))
2149 & 0x0060) != 0x0060))
2150 baseaddr
= memaddr
- 2;
2156 print_insn_arg (info
, state
, opcode
, operand
, baseaddr
+ 1, uval
);
2162 /* Check if the given address is the last word of a MIPS16 PLT entry.
2163 This word is data and depending on the value it may interfere with
2164 disassembly of further PLT entries. We make use of the fact PLT
2165 symbols are marked BSF_SYNTHETIC. */
2167 is_mips16_plt_tail (struct disassemble_info
*info
, bfd_vma addr
)
2171 && (info
->symbols
[0]->flags
& BSF_SYNTHETIC
)
2172 && addr
== bfd_asymbol_value (info
->symbols
[0]) + 12)
2178 /* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2187 /* Disassemble mips16 instructions. */
2190 print_insn_mips16 (bfd_vma memaddr
, struct disassemble_info
*info
)
2192 const fprintf_ftype infprintf
= info
->fprintf_func
;
2195 const struct mips_opcode
*op
, *opend
;
2196 struct mips_print_arg_state state
;
2197 void *is
= info
->stream
;
2200 unsigned int second
;
2204 info
->bytes_per_chunk
= 2;
2205 info
->display_endian
= info
->endian
;
2206 info
->insn_info_valid
= 1;
2207 info
->branch_delay_insns
= 0;
2208 info
->data_size
= 0;
2212 #define GET_OP(insn, field) \
2213 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
2214 /* Decode PLT entry's GOT slot address word. */
2215 if (is_mips16_plt_tail (info
, memaddr
))
2217 info
->insn_type
= dis_noninsn
;
2218 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
2221 unsigned int gotslot
;
2223 if (info
->endian
== BFD_ENDIAN_BIG
)
2224 gotslot
= bfd_getb32 (buffer
);
2226 gotslot
= bfd_getl32 (buffer
);
2227 infprintf (is
, ".word\t0x%x", gotslot
);
2234 info
->insn_type
= dis_nonbranch
;
2235 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2239 (*info
->memory_error_func
) (status
, memaddr
, info
);
2243 extend_only
= false;
2245 if (info
->endian
== BFD_ENDIAN_BIG
)
2246 first
= bfd_getb16 (buffer
);
2248 first
= bfd_getl16 (buffer
);
2250 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2254 if (info
->endian
== BFD_ENDIAN_BIG
)
2255 second
= bfd_getb16 (buffer
);
2257 second
= bfd_getl16 (buffer
);
2258 full
= (first
<< 16) | second
;
2262 have_second
= false;
2267 /* FIXME: Should probably use a hash table on the major opcode here. */
2269 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
2270 for (op
= mips16_opcodes
; op
< opend
; op
++)
2272 enum match_kind match
;
2274 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
))
2277 if (op
->pinfo
== INSN_MACRO
2278 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
2280 else if (mips_opcode_32bit_p (op
))
2283 && (full
& op
->mask
) == op
->match
)
2288 else if ((first
& op
->mask
) == op
->match
)
2290 match
= MATCH_SHORT
;
2294 else if ((first
& 0xf800) == 0xf000
2297 && (second
& op
->mask
) == op
->match
)
2299 if (op
->pinfo2
& INSN2_SHORT_ONLY
)
2310 if (match
!= MATCH_NONE
)
2314 infprintf (is
, "%s", op
->name
);
2315 if (op
->args
[0] != '\0')
2316 infprintf (is
, "\t");
2318 init_print_arg_state (&state
);
2319 for (s
= op
->args
; *s
!= '\0'; s
++)
2323 && GET_OP (full
, RX
) == GET_OP (full
, RY
))
2325 /* Skip the register and the comma. */
2331 && GET_OP (full
, RZ
) == GET_OP (full
, RX
))
2333 /* Skip the register and the comma. */
2340 && op
->name
[strlen (op
->name
) - 1] == '0')
2342 /* Coprocessor register 0 with sel field. */
2343 const struct mips_cp0sel_name
*n
;
2344 const struct mips_operand
*operand
;
2345 unsigned int reg
, sel
;
2347 operand
= decode_mips16_operand (*s
, true);
2348 reg
= mips_extract_operand (operand
, (first
<< 16) | second
);
2350 operand
= decode_mips16_operand (*s
, true);
2351 sel
= mips_extract_operand (operand
, (first
<< 16) | second
);
2353 /* CP0 register including 'sel' code for mftc0, to be
2354 printed textually if known. If not known, print both
2355 CP0 register name and sel numerically since CP0 register
2356 with sel 0 may have a name unrelated to register being
2358 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
2359 mips_cp0sel_names_len
,
2362 infprintf (is
, "%s", n
->name
);
2364 infprintf (is
, "$%d,%d", reg
, sel
);
2370 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
+ 2,
2371 second
, true, first
, s
[1] == '(');
2374 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
,
2375 first
, false, 0, s
[1] == '(');
2377 case MATCH_NONE
: /* Stop the compiler complaining. */
2382 /* Figure out branch instruction type and delay slot information. */
2383 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
2384 info
->branch_delay_insns
= 1;
2385 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0
2386 || (op
->pinfo2
& INSN2_UNCOND_BRANCH
) != 0)
2388 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2389 info
->insn_type
= dis_jsr
;
2391 info
->insn_type
= dis_branch
;
2393 else if ((op
->pinfo2
& INSN2_COND_BRANCH
) != 0)
2394 info
->insn_type
= dis_condbranch
;
2396 return match
== MATCH_FULL
? 4 : 2;
2401 infprintf (is
, "0x%x", first
);
2402 info
->insn_type
= dis_noninsn
;
2407 /* Disassemble microMIPS instructions. */
2410 print_insn_micromips (bfd_vma memaddr
, struct disassemble_info
*info
)
2412 const fprintf_ftype infprintf
= info
->fprintf_func
;
2413 const struct mips_opcode
*op
, *opend
;
2414 void *is
= info
->stream
;
2416 unsigned int higher
;
2417 unsigned int length
;
2421 info
->bytes_per_chunk
= 2;
2422 info
->display_endian
= info
->endian
;
2423 info
->insn_info_valid
= 1;
2424 info
->branch_delay_insns
= 0;
2425 info
->data_size
= 0;
2426 info
->insn_type
= dis_nonbranch
;
2430 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2433 (*info
->memory_error_func
) (status
, memaddr
, info
);
2439 if (info
->endian
== BFD_ENDIAN_BIG
)
2440 insn
= bfd_getb16 (buffer
);
2442 insn
= bfd_getl16 (buffer
);
2444 if ((insn
& 0x1c00) == 0x0000 || (insn
& 0x1000) == 0x1000)
2446 /* This is a 32-bit microMIPS instruction. */
2449 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2452 infprintf (is
, "micromips 0x%x", higher
);
2453 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
2457 if (info
->endian
== BFD_ENDIAN_BIG
)
2458 insn
= bfd_getb16 (buffer
);
2460 insn
= bfd_getl16 (buffer
);
2462 insn
= insn
| (higher
<< 16);
2467 /* FIXME: Should probably use a hash table on the major opcode here. */
2469 opend
= micromips_opcodes
+ bfd_micromips_num_opcodes
;
2470 for (op
= micromips_opcodes
; op
< opend
; op
++)
2472 if (op
->pinfo
!= INSN_MACRO
2473 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
2474 && (insn
& op
->mask
) == op
->match
2475 && ((length
== 2 && (op
->mask
& 0xffff0000) == 0)
2476 || (length
== 4 && (op
->mask
& 0xffff0000) != 0)))
2478 if (!validate_insn_args (op
, decode_micromips_operand
, insn
))
2481 infprintf (is
, "%s", op
->name
);
2485 infprintf (is
, "\t");
2486 print_insn_args (info
, op
, decode_micromips_operand
, insn
,
2487 memaddr
+ 1, length
);
2490 /* Figure out instruction type and branch delay information. */
2492 & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
)) != 0)
2493 info
->branch_delay_insns
= 1;
2494 if (((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
2495 | (op
->pinfo2
& INSN2_UNCOND_BRANCH
)) != 0)
2497 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
2498 info
->insn_type
= dis_jsr
;
2500 info
->insn_type
= dis_branch
;
2502 else if (((op
->pinfo
& INSN_COND_BRANCH_DELAY
)
2503 | (op
->pinfo2
& INSN2_COND_BRANCH
)) != 0)
2505 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2506 info
->insn_type
= dis_condjsr
;
2508 info
->insn_type
= dis_condbranch
;
2511 & (INSN_STORE_MEMORY
| INSN_LOAD_MEMORY
)) != 0)
2512 info
->insn_type
= dis_dref
;
2518 infprintf (is
, "0x%x", insn
);
2519 info
->insn_type
= dis_noninsn
;
2524 /* Return 1 if a symbol associated with the location being disassembled
2525 indicates a compressed mode, either MIPS16 or microMIPS, according to
2526 MICROMIPS_P. We iterate over all the symbols at the address being
2527 considered assuming if at least one of them indicates code compression,
2528 then such code has been genuinely produced here (other symbols could
2529 have been derived from function symbols defined elsewhere or could
2530 define data). Otherwise, return 0. */
2533 is_compressed_mode_p (struct disassemble_info
*info
, bool micromips_p
)
2538 for (i
= info
->symtab_pos
, l
= i
+ info
->num_symbols
; i
< l
; i
++)
2539 if (((info
->symtab
[i
])->flags
& BSF_SYNTHETIC
) != 0
2541 && ELF_ST_IS_MIPS16 ((*info
->symbols
)->udata
.i
))
2543 && ELF_ST_IS_MICROMIPS ((*info
->symbols
)->udata
.i
))))
2545 else if (bfd_asymbol_flavour (info
->symtab
[i
]) == bfd_target_elf_flavour
2546 && info
->symtab
[i
]->section
== info
->section
)
2548 elf_symbol_type
*symbol
= (elf_symbol_type
*) info
->symtab
[i
];
2550 && ELF_ST_IS_MIPS16 (symbol
->internal_elf_sym
.st_other
))
2552 && ELF_ST_IS_MICROMIPS (symbol
->internal_elf_sym
.st_other
)))
2559 /* In an environment where we do not know the symbol type of the
2560 instruction we are forced to assume that the low order bit of the
2561 instructions' address may mark it as a mips16 instruction. If we
2562 are single stepping, or the pc is within the disassembled function,
2563 this works. Otherwise, we need a clue. Sometimes. */
2566 _print_insn_mips (bfd_vma memaddr
,
2567 struct disassemble_info
*info
,
2568 enum bfd_endian endianness
)
2570 bfd_byte buffer
[INSNLEN
];
2573 set_default_mips_dis_options (info
);
2574 parse_mips_dis_options (info
->disassembler_options
);
2576 if (info
->mach
== bfd_mach_mips16
)
2577 return print_insn_mips16 (memaddr
, info
);
2578 if (info
->mach
== bfd_mach_mips_micromips
)
2579 return print_insn_micromips (memaddr
, info
);
2582 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
2583 /* Only a few tools will work this way. */
2587 return print_insn_micromips (memaddr
, info
);
2589 return print_insn_mips16 (memaddr
, info
);
2593 #if SYMTAB_AVAILABLE
2594 if (is_compressed_mode_p (info
, true))
2595 return print_insn_micromips (memaddr
, info
);
2596 if (is_compressed_mode_p (info
, false))
2597 return print_insn_mips16 (memaddr
, info
);
2600 status
= (*info
->read_memory_func
) (memaddr
, buffer
, INSNLEN
, info
);
2605 if (endianness
== BFD_ENDIAN_BIG
)
2606 insn
= bfd_getb32 (buffer
);
2608 insn
= bfd_getl32 (buffer
);
2610 return print_insn_mips (memaddr
, insn
, info
);
2614 (*info
->memory_error_func
) (status
, memaddr
, info
);
2620 print_insn_big_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2622 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_BIG
);
2626 print_insn_little_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2628 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_LITTLE
);
2631 /* Indices into option argument vector for options accepting an argument.
2632 Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2635 MIPS_OPTION_ARG_NONE
= -1,
2636 MIPS_OPTION_ARG_ABI
,
2637 MIPS_OPTION_ARG_ARCH
,
2638 MIPS_OPTION_ARG_SIZE
2639 } mips_option_arg_t
;
2641 /* Valid MIPS disassembler options. */
2645 const char *description
;
2646 mips_option_arg_t arg
;
2649 { "no-aliases", N_("Use canonical instruction forms.\n"),
2650 MIPS_OPTION_ARG_NONE
},
2651 { "msa", N_("Recognize MSA instructions.\n"),
2652 MIPS_OPTION_ARG_NONE
},
2653 { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2654 MIPS_OPTION_ARG_NONE
},
2655 { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2657 MIPS_OPTION_ARG_NONE
},
2658 { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2660 MIPS_OPTION_ARG_NONE
},
2662 N_("Recognize the Loongson MultiMedia extensions "
2663 "Instructions (MMI) ASE instructions.\n"),
2664 MIPS_OPTION_ARG_NONE
},
2666 N_("Recognize the Loongson Content Address Memory (CAM) "
2667 " instructions.\n"),
2668 MIPS_OPTION_ARG_NONE
},
2670 N_("Recognize the Loongson EXTensions (EXT) "
2671 " instructions.\n"),
2672 MIPS_OPTION_ARG_NONE
},
2674 N_("Recognize the Loongson EXTensions R2 (EXT2) "
2675 " instructions.\n"),
2676 MIPS_OPTION_ARG_NONE
},
2677 { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2678 Default: based on binary being disassembled.\n"),
2679 MIPS_OPTION_ARG_ABI
},
2680 { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2681 Default: numeric.\n"),
2682 MIPS_OPTION_ARG_ABI
},
2683 { "cp0-names=", N_("Print CP0 register names according to specified "
2685 Default: based on binary being disassembled.\n"),
2686 MIPS_OPTION_ARG_ARCH
},
2687 { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2688 Default: based on binary being disassembled.\n"),
2689 MIPS_OPTION_ARG_ARCH
},
2690 { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2691 MIPS_OPTION_ARG_ABI
},
2692 { "reg-names=", N_("Print CP0 register and HWR names according to "
2695 MIPS_OPTION_ARG_ARCH
}
2698 /* Build the structure representing valid MIPS disassembler options.
2699 This is done dynamically for maintenance ease purpose; a static
2700 initializer would be unreadable. */
2702 const disasm_options_and_args_t
*
2703 disassembler_options_mips (void)
2705 static disasm_options_and_args_t
*opts_and_args
;
2707 if (opts_and_args
== NULL
)
2709 size_t num_options
= ARRAY_SIZE (mips_options
);
2710 size_t num_args
= MIPS_OPTION_ARG_SIZE
;
2711 disasm_option_arg_t
*args
;
2712 disasm_options_t
*opts
;
2716 args
= XNEWVEC (disasm_option_arg_t
, num_args
+ 1);
2718 args
[MIPS_OPTION_ARG_ABI
].name
= "ABI";
2719 args
[MIPS_OPTION_ARG_ABI
].values
2720 = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices
) + 1);
2721 for (i
= 0; i
< ARRAY_SIZE (mips_abi_choices
); i
++)
2722 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = mips_abi_choices
[i
].name
;
2723 /* The array we return must be NULL terminated. */
2724 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = NULL
;
2726 args
[MIPS_OPTION_ARG_ARCH
].name
= "ARCH";
2727 args
[MIPS_OPTION_ARG_ARCH
].values
2728 = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices
) + 1);
2729 for (i
= 0, j
= 0; i
< ARRAY_SIZE (mips_arch_choices
); i
++)
2730 if (*mips_arch_choices
[i
].name
!= '\0')
2731 args
[MIPS_OPTION_ARG_ARCH
].values
[j
++] = mips_arch_choices
[i
].name
;
2732 /* The array we return must be NULL terminated. */
2733 args
[MIPS_OPTION_ARG_ARCH
].values
[j
] = NULL
;
2735 /* The array we return must be NULL terminated. */
2736 args
[MIPS_OPTION_ARG_SIZE
].name
= NULL
;
2737 args
[MIPS_OPTION_ARG_SIZE
].values
= NULL
;
2739 opts_and_args
= XNEW (disasm_options_and_args_t
);
2740 opts_and_args
->args
= args
;
2742 opts
= &opts_and_args
->options
;
2743 opts
->name
= XNEWVEC (const char *, num_options
+ 1);
2744 opts
->description
= XNEWVEC (const char *, num_options
+ 1);
2745 opts
->arg
= XNEWVEC (const disasm_option_arg_t
*, num_options
+ 1);
2746 for (i
= 0; i
< num_options
; i
++)
2748 opts
->name
[i
] = mips_options
[i
].name
;
2749 opts
->description
[i
] = _(mips_options
[i
].description
);
2750 if (mips_options
[i
].arg
!= MIPS_OPTION_ARG_NONE
)
2751 opts
->arg
[i
] = &args
[mips_options
[i
].arg
];
2753 opts
->arg
[i
] = NULL
;
2755 /* The array we return must be NULL terminated. */
2756 opts
->name
[i
] = NULL
;
2757 opts
->description
[i
] = NULL
;
2758 opts
->arg
[i
] = NULL
;
2761 return opts_and_args
;
2765 print_mips_disassembler_options (FILE *stream
)
2767 const disasm_options_and_args_t
*opts_and_args
;
2768 const disasm_option_arg_t
*args
;
2769 const disasm_options_t
*opts
;
2774 opts_and_args
= disassembler_options_mips ();
2775 opts
= &opts_and_args
->options
;
2776 args
= opts_and_args
->args
;
2778 fprintf (stream
, _("\n\
2779 The following MIPS specific disassembler options are supported for use\n\
2780 with the -M switch (multiple options should be separated by commas):\n\n"));
2782 /* Compute the length of the longest option name. */
2783 for (i
= 0; opts
->name
[i
] != NULL
; i
++)
2785 size_t len
= strlen (opts
->name
[i
]);
2787 if (opts
->arg
[i
] != NULL
)
2788 len
+= strlen (opts
->arg
[i
]->name
);
2793 for (i
= 0, max_len
++; opts
->name
[i
] != NULL
; i
++)
2795 fprintf (stream
, " %s", opts
->name
[i
]);
2796 if (opts
->arg
[i
] != NULL
)
2797 fprintf (stream
, "%s", opts
->arg
[i
]->name
);
2798 if (opts
->description
[i
] != NULL
)
2800 size_t len
= strlen (opts
->name
[i
]);
2802 if (opts
->arg
[i
] != NULL
)
2803 len
+= strlen (opts
->arg
[i
]->name
);
2805 "%*c %s", (int) (max_len
- len
), ' ', opts
->description
[i
]);
2807 fprintf (stream
, _("\n"));
2810 for (i
= 0; args
[i
].name
!= NULL
; i
++)
2812 fprintf (stream
, _("\n\
2813 For the options above, the following values are supported for \"%s\":\n "),
2815 for (j
= 0; args
[i
].values
[j
] != NULL
; j
++)
2816 fprintf (stream
, " %s", args
[i
].values
[j
]);
2817 fprintf (stream
, _("\n"));
2820 fprintf (stream
, _("\n"));