1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 Copyright (C) 1989-2020 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_r3000
[32] =
127 "c0_index", "c0_random", "c0_entrylo", "$3",
128 "c0_context", "$5", "$6", "$7",
129 "c0_badvaddr", "$9", "c0_entryhi", "$11",
130 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
131 "$16", "$17", "$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_r4000
[32] =
139 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
140 "c0_context", "c0_pagemask", "c0_wired", "$7",
141 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
142 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
143 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
144 "c0_xcontext", "$21", "$22", "$23",
145 "$24", "$25", "c0_ecc", "c0_cacheerr",
146 "c0_taglo", "c0_taghi", "c0_errorepc", "$31",
149 static const char * const mips_cp0_names_r5900
[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", "$17", "$18", "$19",
156 "$20", "$21", "$22", "c0_badpaddr",
157 "c0_depc", "c0_perfcnt", "$26", "$27",
158 "c0_taglo", "c0_taghi", "c0_errorepc", "$31"
161 static const char * const mips_cp0_names_mips3264
[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_status", "c0_cause", "c0_epc", "c0_prid",
167 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
168 "c0_xcontext", "$21", "$22", "c0_debug",
169 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
170 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
173 static const char * const mips_cp1_names_mips3264
[32] =
175 "c1_fir", "c1_ufr", "$2", "$3",
176 "c1_unfr", "$5", "$6", "$7",
177 "$8", "$9", "$10", "$11",
178 "$12", "$13", "$14", "$15",
179 "$16", "$17", "$18", "$19",
180 "$20", "$21", "$22", "$23",
181 "$24", "c1_fccr", "c1_fexr", "$27",
182 "c1_fenr", "$29", "$30", "c1_fcsr"
185 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264
[] =
187 { 16, 1, "c0_config1" },
188 { 16, 2, "c0_config2" },
189 { 16, 3, "c0_config3" },
190 { 18, 1, "c0_watchlo,1" },
191 { 18, 2, "c0_watchlo,2" },
192 { 18, 3, "c0_watchlo,3" },
193 { 18, 4, "c0_watchlo,4" },
194 { 18, 5, "c0_watchlo,5" },
195 { 18, 6, "c0_watchlo,6" },
196 { 18, 7, "c0_watchlo,7" },
197 { 19, 1, "c0_watchhi,1" },
198 { 19, 2, "c0_watchhi,2" },
199 { 19, 3, "c0_watchhi,3" },
200 { 19, 4, "c0_watchhi,4" },
201 { 19, 5, "c0_watchhi,5" },
202 { 19, 6, "c0_watchhi,6" },
203 { 19, 7, "c0_watchhi,7" },
204 { 25, 1, "c0_perfcnt,1" },
205 { 25, 2, "c0_perfcnt,2" },
206 { 25, 3, "c0_perfcnt,3" },
207 { 25, 4, "c0_perfcnt,4" },
208 { 25, 5, "c0_perfcnt,5" },
209 { 25, 6, "c0_perfcnt,6" },
210 { 25, 7, "c0_perfcnt,7" },
211 { 27, 1, "c0_cacheerr,1" },
212 { 27, 2, "c0_cacheerr,2" },
213 { 27, 3, "c0_cacheerr,3" },
214 { 28, 1, "c0_datalo" },
215 { 29, 1, "c0_datahi" }
218 static const char * const mips_cp0_names_mips3264r2
[32] =
220 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
221 "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
222 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
223 "c0_status", "c0_cause", "c0_epc", "c0_prid",
224 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
225 "c0_xcontext", "$21", "$22", "c0_debug",
226 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
227 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
230 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2
[] =
232 { 4, 1, "c0_contextconfig" },
233 { 0, 1, "c0_mvpcontrol" },
234 { 0, 2, "c0_mvpconf0" },
235 { 0, 3, "c0_mvpconf1" },
236 { 1, 1, "c0_vpecontrol" },
237 { 1, 2, "c0_vpeconf0" },
238 { 1, 3, "c0_vpeconf1" },
239 { 1, 4, "c0_yqmask" },
240 { 1, 5, "c0_vpeschedule" },
241 { 1, 6, "c0_vpeschefback" },
242 { 2, 1, "c0_tcstatus" },
243 { 2, 2, "c0_tcbind" },
244 { 2, 3, "c0_tcrestart" },
245 { 2, 4, "c0_tchalt" },
246 { 2, 5, "c0_tccontext" },
247 { 2, 6, "c0_tcschedule" },
248 { 2, 7, "c0_tcschefback" },
249 { 5, 1, "c0_pagegrain" },
250 { 6, 1, "c0_srsconf0" },
251 { 6, 2, "c0_srsconf1" },
252 { 6, 3, "c0_srsconf2" },
253 { 6, 4, "c0_srsconf3" },
254 { 6, 5, "c0_srsconf4" },
255 { 12, 1, "c0_intctl" },
256 { 12, 2, "c0_srsctl" },
257 { 12, 3, "c0_srsmap" },
258 { 15, 1, "c0_ebase" },
259 { 16, 1, "c0_config1" },
260 { 16, 2, "c0_config2" },
261 { 16, 3, "c0_config3" },
262 { 18, 1, "c0_watchlo,1" },
263 { 18, 2, "c0_watchlo,2" },
264 { 18, 3, "c0_watchlo,3" },
265 { 18, 4, "c0_watchlo,4" },
266 { 18, 5, "c0_watchlo,5" },
267 { 18, 6, "c0_watchlo,6" },
268 { 18, 7, "c0_watchlo,7" },
269 { 19, 1, "c0_watchhi,1" },
270 { 19, 2, "c0_watchhi,2" },
271 { 19, 3, "c0_watchhi,3" },
272 { 19, 4, "c0_watchhi,4" },
273 { 19, 5, "c0_watchhi,5" },
274 { 19, 6, "c0_watchhi,6" },
275 { 19, 7, "c0_watchhi,7" },
276 { 23, 1, "c0_tracecontrol" },
277 { 23, 2, "c0_tracecontrol2" },
278 { 23, 3, "c0_usertracedata" },
279 { 23, 4, "c0_tracebpc" },
280 { 25, 1, "c0_perfcnt,1" },
281 { 25, 2, "c0_perfcnt,2" },
282 { 25, 3, "c0_perfcnt,3" },
283 { 25, 4, "c0_perfcnt,4" },
284 { 25, 5, "c0_perfcnt,5" },
285 { 25, 6, "c0_perfcnt,6" },
286 { 25, 7, "c0_perfcnt,7" },
287 { 27, 1, "c0_cacheerr,1" },
288 { 27, 2, "c0_cacheerr,2" },
289 { 27, 3, "c0_cacheerr,3" },
290 { 28, 1, "c0_datalo" },
291 { 28, 2, "c0_taglo1" },
292 { 28, 3, "c0_datalo1" },
293 { 28, 4, "c0_taglo2" },
294 { 28, 5, "c0_datalo2" },
295 { 28, 6, "c0_taglo3" },
296 { 28, 7, "c0_datalo3" },
297 { 29, 1, "c0_datahi" },
298 { 29, 2, "c0_taghi1" },
299 { 29, 3, "c0_datahi1" },
300 { 29, 4, "c0_taghi2" },
301 { 29, 5, "c0_datahi2" },
302 { 29, 6, "c0_taghi3" },
303 { 29, 7, "c0_datahi3" },
306 /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
307 static const char * const mips_cp0_names_sb1
[32] =
309 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
310 "c0_context", "c0_pagemask", "c0_wired", "$7",
311 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
312 "c0_status", "c0_cause", "c0_epc", "c0_prid",
313 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
314 "c0_xcontext", "$21", "$22", "c0_debug",
315 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
316 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
319 static const struct mips_cp0sel_name mips_cp0sel_names_sb1
[] =
321 { 16, 1, "c0_config1" },
322 { 18, 1, "c0_watchlo,1" },
323 { 19, 1, "c0_watchhi,1" },
324 { 22, 0, "c0_perftrace" },
325 { 23, 3, "c0_edebug" },
326 { 25, 1, "c0_perfcnt,1" },
327 { 25, 2, "c0_perfcnt,2" },
328 { 25, 3, "c0_perfcnt,3" },
329 { 25, 4, "c0_perfcnt,4" },
330 { 25, 5, "c0_perfcnt,5" },
331 { 25, 6, "c0_perfcnt,6" },
332 { 25, 7, "c0_perfcnt,7" },
333 { 26, 1, "c0_buserr_pa" },
334 { 27, 1, "c0_cacheerr_d" },
335 { 27, 3, "c0_cacheerr_d_pa" },
336 { 28, 1, "c0_datalo_i" },
337 { 28, 2, "c0_taglo_d" },
338 { 28, 3, "c0_datalo_d" },
339 { 29, 1, "c0_datahi_i" },
340 { 29, 2, "c0_taghi_d" },
341 { 29, 3, "c0_datahi_d" },
344 /* Xlr cop0 register names. */
345 static const char * const mips_cp0_names_xlr
[32] = {
346 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
347 "c0_context", "c0_pagemask", "c0_wired", "$7",
348 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
349 "c0_status", "c0_cause", "c0_epc", "c0_prid",
350 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
351 "c0_xcontext", "$21", "$22", "c0_debug",
352 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
353 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
356 /* XLR's CP0 Select Registers. */
358 static const struct mips_cp0sel_name mips_cp0sel_names_xlr
[] = {
359 { 9, 6, "c0_extintreq" },
360 { 9, 7, "c0_extintmask" },
361 { 15, 1, "c0_ebase" },
362 { 16, 1, "c0_config1" },
363 { 16, 2, "c0_config2" },
364 { 16, 3, "c0_config3" },
365 { 16, 7, "c0_procid2" },
366 { 18, 1, "c0_watchlo,1" },
367 { 18, 2, "c0_watchlo,2" },
368 { 18, 3, "c0_watchlo,3" },
369 { 18, 4, "c0_watchlo,4" },
370 { 18, 5, "c0_watchlo,5" },
371 { 18, 6, "c0_watchlo,6" },
372 { 18, 7, "c0_watchlo,7" },
373 { 19, 1, "c0_watchhi,1" },
374 { 19, 2, "c0_watchhi,2" },
375 { 19, 3, "c0_watchhi,3" },
376 { 19, 4, "c0_watchhi,4" },
377 { 19, 5, "c0_watchhi,5" },
378 { 19, 6, "c0_watchhi,6" },
379 { 19, 7, "c0_watchhi,7" },
380 { 25, 1, "c0_perfcnt,1" },
381 { 25, 2, "c0_perfcnt,2" },
382 { 25, 3, "c0_perfcnt,3" },
383 { 25, 4, "c0_perfcnt,4" },
384 { 25, 5, "c0_perfcnt,5" },
385 { 25, 6, "c0_perfcnt,6" },
386 { 25, 7, "c0_perfcnt,7" },
387 { 27, 1, "c0_cacheerr,1" },
388 { 27, 2, "c0_cacheerr,2" },
389 { 27, 3, "c0_cacheerr,3" },
390 { 28, 1, "c0_datalo" },
391 { 29, 1, "c0_datahi" }
394 static const char * const mips_hwr_names_numeric
[32] =
396 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
397 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
398 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
399 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
402 static const char * const mips_hwr_names_mips3264r2
[32] =
404 "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
405 "$4", "$5", "$6", "$7",
406 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
407 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
408 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
411 static const char * const msa_control_names
[32] =
413 "msa_ir", "msa_csr", "msa_access", "msa_save",
414 "msa_modify", "msa_request", "msa_map", "msa_unmap",
415 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
416 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
417 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
420 struct mips_abi_choice
423 const char * const *gpr_names
;
424 const char * const *fpr_names
;
427 struct mips_abi_choice mips_abi_choices
[] =
429 { "numeric", mips_gpr_names_numeric
, mips_fpr_names_numeric
},
430 { "32", mips_gpr_names_oldabi
, mips_fpr_names_32
},
431 { "n32", mips_gpr_names_newabi
, mips_fpr_names_n32
},
432 { "64", mips_gpr_names_newabi
, mips_fpr_names_64
},
435 struct mips_arch_choice
439 unsigned long bfd_mach
;
443 const char * const *cp0_names
;
444 const struct mips_cp0sel_name
*cp0sel_names
;
445 unsigned int cp0sel_names_len
;
446 const char * const *cp1_names
;
447 const char * const *hwr_names
;
450 const struct mips_arch_choice mips_arch_choices
[] =
452 { "numeric", 0, 0, 0, 0, 0,
453 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
454 mips_hwr_names_numeric
},
456 { "r3000", 1, bfd_mach_mips3000
, CPU_R3000
, ISA_MIPS1
, 0,
457 mips_cp0_names_r3000
, NULL
, 0, mips_cp1_names_numeric
,
458 mips_hwr_names_numeric
},
459 { "r3900", 1, bfd_mach_mips3900
, CPU_R3900
, ISA_MIPS1
, 0,
460 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
461 mips_hwr_names_numeric
},
462 { "r4000", 1, bfd_mach_mips4000
, CPU_R4000
, ISA_MIPS3
, 0,
463 mips_cp0_names_r4000
, NULL
, 0, mips_cp1_names_numeric
,
464 mips_hwr_names_numeric
},
465 { "r4010", 1, bfd_mach_mips4010
, CPU_R4010
, ISA_MIPS2
, 0,
466 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
467 mips_hwr_names_numeric
},
468 { "vr4100", 1, bfd_mach_mips4100
, CPU_VR4100
, ISA_MIPS3
, 0,
469 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
470 mips_hwr_names_numeric
},
471 { "vr4111", 1, bfd_mach_mips4111
, CPU_R4111
, ISA_MIPS3
, 0,
472 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
473 mips_hwr_names_numeric
},
474 { "vr4120", 1, bfd_mach_mips4120
, CPU_VR4120
, ISA_MIPS3
, 0,
475 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
476 mips_hwr_names_numeric
},
477 { "r4300", 1, bfd_mach_mips4300
, CPU_R4300
, ISA_MIPS3
, 0,
478 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
479 mips_hwr_names_numeric
},
480 { "r4400", 1, bfd_mach_mips4400
, CPU_R4400
, ISA_MIPS3
, 0,
481 mips_cp0_names_r4000
, NULL
, 0, mips_cp1_names_numeric
,
482 mips_hwr_names_numeric
},
483 { "r4600", 1, bfd_mach_mips4600
, CPU_R4600
, ISA_MIPS3
, 0,
484 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
485 mips_hwr_names_numeric
},
486 { "r4650", 1, bfd_mach_mips4650
, CPU_R4650
, ISA_MIPS3
, 0,
487 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
488 mips_hwr_names_numeric
},
489 { "r5000", 1, bfd_mach_mips5000
, CPU_R5000
, ISA_MIPS4
, 0,
490 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
491 mips_hwr_names_numeric
},
492 { "vr5400", 1, bfd_mach_mips5400
, CPU_VR5400
, ISA_MIPS4
, 0,
493 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
494 mips_hwr_names_numeric
},
495 { "vr5500", 1, bfd_mach_mips5500
, CPU_VR5500
, ISA_MIPS4
, 0,
496 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
497 mips_hwr_names_numeric
},
498 { "r5900", 1, bfd_mach_mips5900
, CPU_R5900
, ISA_MIPS3
, 0,
499 mips_cp0_names_r5900
, NULL
, 0, mips_cp1_names_numeric
,
500 mips_hwr_names_numeric
},
501 { "r6000", 1, bfd_mach_mips6000
, CPU_R6000
, ISA_MIPS2
, 0,
502 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
503 mips_hwr_names_numeric
},
504 { "rm7000", 1, bfd_mach_mips7000
, CPU_RM7000
, ISA_MIPS4
, 0,
505 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
506 mips_hwr_names_numeric
},
507 { "rm9000", 1, bfd_mach_mips7000
, CPU_RM7000
, ISA_MIPS4
, 0,
508 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
509 mips_hwr_names_numeric
},
510 { "r8000", 1, bfd_mach_mips8000
, CPU_R8000
, ISA_MIPS4
, 0,
511 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
512 mips_hwr_names_numeric
},
513 { "r10000", 1, bfd_mach_mips10000
, CPU_R10000
, ISA_MIPS4
, 0,
514 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
515 mips_hwr_names_numeric
},
516 { "r12000", 1, bfd_mach_mips12000
, CPU_R12000
, ISA_MIPS4
, 0,
517 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
518 mips_hwr_names_numeric
},
519 { "r14000", 1, bfd_mach_mips14000
, CPU_R14000
, ISA_MIPS4
, 0,
520 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
521 mips_hwr_names_numeric
},
522 { "r16000", 1, bfd_mach_mips16000
, CPU_R16000
, ISA_MIPS4
, 0,
523 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
524 mips_hwr_names_numeric
},
525 { "mips5", 1, bfd_mach_mips5
, CPU_MIPS5
, ISA_MIPS5
, 0,
526 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
527 mips_hwr_names_numeric
},
529 /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
530 Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
531 _MIPS32 Architecture For Programmers Volume I: Introduction to the
532 MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
534 { "mips32", 1, bfd_mach_mipsisa32
, CPU_MIPS32
,
535 ISA_MIPS32
, ASE_SMARTMIPS
,
536 mips_cp0_names_mips3264
,
537 mips_cp0sel_names_mips3264
, ARRAY_SIZE (mips_cp0sel_names_mips3264
),
538 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
540 { "mips32r2", 1, bfd_mach_mipsisa32r2
, CPU_MIPS32R2
,
542 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
543 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
544 mips_cp0_names_mips3264r2
,
545 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
546 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
548 { "mips32r3", 1, bfd_mach_mipsisa32r3
, CPU_MIPS32R3
,
550 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
551 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
552 mips_cp0_names_mips3264r2
,
553 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
554 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
556 { "mips32r5", 1, bfd_mach_mipsisa32r5
, CPU_MIPS32R5
,
558 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
559 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
560 mips_cp0_names_mips3264r2
,
561 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
562 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
564 { "mips32r6", 1, bfd_mach_mipsisa32r6
, CPU_MIPS32R6
,
566 (ASE_EVA
| ASE_MSA
| ASE_VIRT
| ASE_XPA
| ASE_MCU
| ASE_MT
| ASE_DSP
567 | ASE_DSPR2
| ASE_DSPR3
| ASE_CRC
| ASE_GINV
),
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 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
573 { "mips64", 1, bfd_mach_mipsisa64
, CPU_MIPS64
,
574 ISA_MIPS64
, ASE_MIPS3D
| ASE_MDMX
,
575 mips_cp0_names_mips3264
,
576 mips_cp0sel_names_mips3264
, ARRAY_SIZE (mips_cp0sel_names_mips3264
),
577 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
579 { "mips64r2", 1, bfd_mach_mipsisa64r2
, CPU_MIPS64R2
,
581 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
582 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
583 mips_cp0_names_mips3264r2
,
584 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
585 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
587 { "mips64r3", 1, bfd_mach_mipsisa64r3
, CPU_MIPS64R3
,
589 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
590 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
591 mips_cp0_names_mips3264r2
,
592 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
593 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
595 { "mips64r5", 1, bfd_mach_mipsisa64r5
, CPU_MIPS64R5
,
597 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
598 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
599 mips_cp0_names_mips3264r2
,
600 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
601 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
603 { "mips64r6", 1, bfd_mach_mipsisa64r6
, CPU_MIPS64R6
,
605 (ASE_EVA
| ASE_MSA
| ASE_MSA64
| ASE_XPA
| ASE_VIRT
| ASE_VIRT64
606 | ASE_MCU
| ASE_MT
| ASE_DSP
| ASE_DSPR2
| ASE_DSPR3
| ASE_CRC
607 | ASE_CRC64
| ASE_GINV
),
608 mips_cp0_names_mips3264r2
,
609 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
610 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
612 { "interaptiv-mr2", 1, bfd_mach_mips_interaptiv_mr2
, CPU_INTERAPTIV_MR2
,
614 ASE_MT
| ASE_EVA
| ASE_DSP
| ASE_DSPR2
| ASE_MIPS16E2
| ASE_MIPS16E2_MT
,
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 { "sb1", 1, bfd_mach_mips_sb1
, CPU_SB1
,
620 ISA_MIPS64
| INSN_SB1
, ASE_MIPS3D
,
622 mips_cp0sel_names_sb1
, ARRAY_SIZE (mips_cp0sel_names_sb1
),
623 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
625 { "loongson2e", 1, bfd_mach_mips_loongson_2e
, CPU_LOONGSON_2E
,
626 ISA_MIPS3
| INSN_LOONGSON_2E
, 0, mips_cp0_names_numeric
,
627 NULL
, 0, mips_cp1_names_numeric
, mips_hwr_names_numeric
},
629 { "loongson2f", 1, bfd_mach_mips_loongson_2f
, CPU_LOONGSON_2F
,
630 ISA_MIPS3
| INSN_LOONGSON_2F
, ASE_LOONGSON_MMI
, mips_cp0_names_numeric
,
631 NULL
, 0, mips_cp1_names_numeric
, mips_hwr_names_numeric
},
633 /* The loongson3a is an alias of gs464 for compatibility */
634 { "loongson3a", 1, bfd_mach_mips_gs464
, CPU_GS464
,
635 ISA_MIPS64R2
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
| ASE_LOONGSON_EXT
,
636 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips3264
,
637 mips_hwr_names_numeric
},
639 { "gs464", 1, bfd_mach_mips_gs464
, CPU_GS464
,
640 ISA_MIPS64R2
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
| ASE_LOONGSON_EXT
,
641 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips3264
,
642 mips_hwr_names_numeric
},
644 { "gs464e", 1, bfd_mach_mips_gs464e
, CPU_GS464E
,
645 ISA_MIPS64R2
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
| ASE_LOONGSON_EXT
646 | ASE_LOONGSON_EXT2
, mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips3264
,
647 mips_hwr_names_numeric
},
649 { "gs264e", 1, bfd_mach_mips_gs464e
, CPU_GS264E
,
650 ISA_MIPS64R2
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
| ASE_LOONGSON_EXT
651 | ASE_LOONGSON_EXT2
| ASE_MSA
| ASE_MSA64
, mips_cp0_names_numeric
, NULL
,
652 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
654 { "octeon", 1, bfd_mach_mips_octeon
, CPU_OCTEON
,
655 ISA_MIPS64R2
| INSN_OCTEON
, 0, mips_cp0_names_numeric
, NULL
, 0,
656 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
658 { "octeon+", 1, bfd_mach_mips_octeonp
, CPU_OCTEONP
,
659 ISA_MIPS64R2
| INSN_OCTEONP
, 0, mips_cp0_names_numeric
,
660 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
662 { "octeon2", 1, bfd_mach_mips_octeon2
, CPU_OCTEON2
,
663 ISA_MIPS64R2
| INSN_OCTEON2
, 0, mips_cp0_names_numeric
,
664 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
666 { "octeon3", 1, bfd_mach_mips_octeon3
, CPU_OCTEON3
,
667 ISA_MIPS64R5
| INSN_OCTEON3
, ASE_VIRT
| ASE_VIRT64
,
668 mips_cp0_names_numeric
,
669 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
671 { "xlr", 1, bfd_mach_mips_xlr
, CPU_XLR
,
672 ISA_MIPS64
| INSN_XLR
, 0,
674 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
675 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
677 /* XLP is mostly like XLR, with the prominent exception it is being
679 { "xlp", 1, bfd_mach_mips_xlr
, CPU_XLR
,
680 ISA_MIPS64R2
| INSN_XLR
, 0,
682 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
683 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
685 /* This entry, mips16, is here only for ISA/processor selection; do
686 not print its name. */
687 { "", 1, bfd_mach_mips16
, CPU_MIPS16
, ISA_MIPS64
,
688 ASE_MIPS16E2
| ASE_MIPS16E2_MT
,
689 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
690 mips_hwr_names_numeric
},
693 /* ISA and processor type to disassemble for, and register names to use.
694 set_default_mips_dis_options and parse_mips_dis_options fill in these
696 static int mips_processor
;
699 static int micromips_ase
;
700 static const char * const *mips_gpr_names
;
701 static const char * const *mips_fpr_names
;
702 static const char * const *mips_cp0_names
;
703 static const struct mips_cp0sel_name
*mips_cp0sel_names
;
704 static int mips_cp0sel_names_len
;
705 static const char * const *mips_cp1_names
;
706 static const char * const *mips_hwr_names
;
709 static int no_aliases
; /* If set disassemble as most general inst. */
711 static const struct mips_abi_choice
*
712 choose_abi_by_name (const char *name
, unsigned int namelen
)
714 const struct mips_abi_choice
*c
;
717 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_abi_choices
) && c
== NULL
; i
++)
718 if (strncmp (mips_abi_choices
[i
].name
, name
, namelen
) == 0
719 && strlen (mips_abi_choices
[i
].name
) == namelen
)
720 c
= &mips_abi_choices
[i
];
725 static const struct mips_arch_choice
*
726 choose_arch_by_name (const char *name
, unsigned int namelen
)
728 const struct mips_arch_choice
*c
= NULL
;
731 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
732 if (strncmp (mips_arch_choices
[i
].name
, name
, namelen
) == 0
733 && strlen (mips_arch_choices
[i
].name
) == namelen
)
734 c
= &mips_arch_choices
[i
];
739 static const struct mips_arch_choice
*
740 choose_arch_by_number (unsigned long mach
)
742 static unsigned long hint_bfd_mach
;
743 static const struct mips_arch_choice
*hint_arch_choice
;
744 const struct mips_arch_choice
*c
;
747 /* We optimize this because even if the user specifies no
748 flags, this will be done for every instruction! */
749 if (hint_bfd_mach
== mach
750 && hint_arch_choice
!= NULL
751 && hint_arch_choice
->bfd_mach
== hint_bfd_mach
)
752 return hint_arch_choice
;
754 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
756 if (mips_arch_choices
[i
].bfd_mach_valid
757 && mips_arch_choices
[i
].bfd_mach
== mach
)
759 c
= &mips_arch_choices
[i
];
760 hint_bfd_mach
= mach
;
761 hint_arch_choice
= c
;
767 /* Check if the object uses NewABI conventions. */
770 is_newabi (Elf_Internal_Ehdr
*header
)
772 /* There are no old-style ABIs which use 64-bit ELF. */
773 if (header
->e_ident
[EI_CLASS
] == ELFCLASS64
)
776 /* If a 32-bit ELF file, n32 is a new-style ABI. */
777 if ((header
->e_flags
& EF_MIPS_ABI2
) != 0)
783 /* Check if the object has microMIPS ASE code. */
786 is_micromips (Elf_Internal_Ehdr
*header
)
788 if ((header
->e_flags
& EF_MIPS_ARCH_ASE_MICROMIPS
) != 0)
794 /* Convert ASE flags from .MIPS.abiflags to internal values. */
797 mips_convert_abiflags_ases (unsigned long afl_ases
)
799 unsigned long opcode_ases
= 0;
801 if (afl_ases
& AFL_ASE_DSP
)
802 opcode_ases
|= ASE_DSP
;
803 if (afl_ases
& AFL_ASE_DSPR2
)
804 opcode_ases
|= ASE_DSPR2
;
805 if (afl_ases
& AFL_ASE_EVA
)
806 opcode_ases
|= ASE_EVA
;
807 if (afl_ases
& AFL_ASE_MCU
)
808 opcode_ases
|= ASE_MCU
;
809 if (afl_ases
& AFL_ASE_MDMX
)
810 opcode_ases
|= ASE_MDMX
;
811 if (afl_ases
& AFL_ASE_MIPS3D
)
812 opcode_ases
|= ASE_MIPS3D
;
813 if (afl_ases
& AFL_ASE_MT
)
814 opcode_ases
|= ASE_MT
;
815 if (afl_ases
& AFL_ASE_SMARTMIPS
)
816 opcode_ases
|= ASE_SMARTMIPS
;
817 if (afl_ases
& AFL_ASE_VIRT
)
818 opcode_ases
|= ASE_VIRT
;
819 if (afl_ases
& AFL_ASE_MSA
)
820 opcode_ases
|= ASE_MSA
;
821 if (afl_ases
& AFL_ASE_XPA
)
822 opcode_ases
|= ASE_XPA
;
823 if (afl_ases
& AFL_ASE_DSPR3
)
824 opcode_ases
|= ASE_DSPR3
;
825 if (afl_ases
& AFL_ASE_MIPS16E2
)
826 opcode_ases
|= ASE_MIPS16E2
;
830 /* Calculate combination ASE flags from regular ASE flags. */
833 mips_calculate_combination_ases (int opcode_isa
, unsigned long opcode_ases
)
835 unsigned long combination_ases
= 0;
837 if ((opcode_ases
& (ASE_XPA
| ASE_VIRT
)) == (ASE_XPA
| ASE_VIRT
))
838 combination_ases
|= ASE_XPA_VIRT
;
839 if ((opcode_ases
& (ASE_MIPS16E2
| ASE_MT
)) == (ASE_MIPS16E2
| ASE_MT
))
840 combination_ases
|= ASE_MIPS16E2_MT
;
841 if ((opcode_ases
& ASE_EVA
)
842 && ((opcode_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
843 || (opcode_isa
& INSN_ISA_MASK
) == ISA_MIPS32R6
))
844 combination_ases
|= ASE_EVA_R6
;
845 return combination_ases
;
849 set_default_mips_dis_options (struct disassemble_info
*info
)
851 const struct mips_arch_choice
*chosen_arch
;
853 /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
854 is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
855 CP0 register, and HWR names. */
856 mips_isa
= ISA_MIPS3
;
857 mips_processor
= CPU_R3000
;
860 mips_gpr_names
= mips_gpr_names_oldabi
;
861 mips_fpr_names
= mips_fpr_names_numeric
;
862 mips_cp0_names
= mips_cp0_names_numeric
;
863 mips_cp0sel_names
= NULL
;
864 mips_cp0sel_names_len
= 0;
865 mips_cp1_names
= mips_cp1_names_numeric
;
866 mips_hwr_names
= mips_hwr_names_numeric
;
869 /* Set ISA, architecture, and cp0 register names as best we can. */
870 #if ! SYMTAB_AVAILABLE
871 /* This is running out on a target machine, not in a host tool.
872 FIXME: Where does mips_target_info come from? */
873 target_processor
= mips_target_info
.processor
;
874 mips_isa
= mips_target_info
.isa
;
875 mips_ase
= mips_target_info
.ase
;
877 chosen_arch
= choose_arch_by_number (info
->mach
);
878 if (chosen_arch
!= NULL
)
880 mips_processor
= chosen_arch
->processor
;
881 mips_isa
= chosen_arch
->isa
;
882 mips_ase
= chosen_arch
->ase
;
883 mips_cp0_names
= chosen_arch
->cp0_names
;
884 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
885 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
886 mips_cp1_names
= chosen_arch
->cp1_names
;
887 mips_hwr_names
= chosen_arch
->hwr_names
;
890 /* Update settings according to the ELF file header flags. */
891 if (info
->flavour
== bfd_target_elf_flavour
&& info
->section
!= NULL
)
893 struct bfd
*abfd
= info
->section
->owner
;
894 Elf_Internal_Ehdr
*header
= elf_elfheader (abfd
);
895 Elf_Internal_ABIFlags_v0
*abiflags
= NULL
;
897 /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
898 because we won't then have a MIPS/ELF BFD, however we need
899 to guard against a link error in a `--enable-targets=...'
900 configuration with a 32-bit host where the MIPS target is
901 a secondary, or with MIPS/ECOFF configurations. */
902 #ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
903 abiflags
= bfd_mips_elf_get_abiflags (abfd
);
905 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
906 if (is_newabi (header
))
907 mips_gpr_names
= mips_gpr_names_newabi
;
908 /* If a microMIPS binary, then don't use MIPS16 bindings. */
909 micromips_ase
= is_micromips (header
);
910 /* OR in any extra ASE flags set in ELF file structures. */
912 mips_ase
|= mips_convert_abiflags_ases (abiflags
->ases
);
913 else if (header
->e_flags
& EF_MIPS_ARCH_ASE_MDMX
)
914 mips_ase
|= ASE_MDMX
;
917 mips_ase
|= mips_calculate_combination_ases (mips_isa
, mips_ase
);
920 /* Parse an ASE disassembler option and set the corresponding global
921 ASE flag(s). Return TRUE if successful, FALSE otherwise. */
924 parse_mips_ase_option (const char *option
)
926 if (CONST_STRNEQ (option
, "msa"))
929 if ((mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R2
930 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R3
931 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R5
932 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
)
933 mips_ase
|= ASE_MSA64
;
937 if (CONST_STRNEQ (option
, "virt"))
939 mips_ase
|= ASE_VIRT
;
940 if (mips_isa
& ISA_MIPS64R2
941 || mips_isa
& ISA_MIPS64R3
942 || mips_isa
& ISA_MIPS64R5
943 || mips_isa
& ISA_MIPS64R6
)
944 mips_ase
|= ASE_VIRT64
;
948 if (CONST_STRNEQ (option
, "xpa"))
954 if (CONST_STRNEQ (option
, "ginv"))
956 mips_ase
|= ASE_GINV
;
960 if (CONST_STRNEQ (option
, "loongson-mmi"))
962 mips_ase
|= ASE_LOONGSON_MMI
;
966 if (CONST_STRNEQ (option
, "loongson-cam"))
968 mips_ase
|= ASE_LOONGSON_CAM
;
972 /* Put here for match ext2 frist */
973 if (CONST_STRNEQ (option
, "loongson-ext2"))
975 mips_ase
|= ASE_LOONGSON_EXT2
;
979 if (CONST_STRNEQ (option
, "loongson-ext"))
981 mips_ase
|= ASE_LOONGSON_EXT
;
989 parse_mips_dis_option (const char *option
, unsigned int len
)
991 unsigned int i
, optionlen
, vallen
;
993 const struct mips_abi_choice
*chosen_abi
;
994 const struct mips_arch_choice
*chosen_arch
;
996 /* Try to match options that are simple flags */
997 if (CONST_STRNEQ (option
, "no-aliases"))
1003 if (parse_mips_ase_option (option
))
1005 mips_ase
|= mips_calculate_combination_ases (mips_isa
, mips_ase
);
1009 /* Look for the = that delimits the end of the option name. */
1010 for (i
= 0; i
< len
; i
++)
1011 if (option
[i
] == '=')
1014 if (i
== 0) /* Invalid option: no name before '='. */
1016 if (i
== len
) /* Invalid option: no '='. */
1018 if (i
== (len
- 1)) /* Invalid option: no value after '='. */
1022 val
= option
+ (optionlen
+ 1);
1023 vallen
= len
- (optionlen
+ 1);
1025 if (strncmp ("gpr-names", option
, optionlen
) == 0
1026 && strlen ("gpr-names") == optionlen
)
1028 chosen_abi
= choose_abi_by_name (val
, vallen
);
1029 if (chosen_abi
!= NULL
)
1030 mips_gpr_names
= chosen_abi
->gpr_names
;
1034 if (strncmp ("fpr-names", option
, optionlen
) == 0
1035 && strlen ("fpr-names") == optionlen
)
1037 chosen_abi
= choose_abi_by_name (val
, vallen
);
1038 if (chosen_abi
!= NULL
)
1039 mips_fpr_names
= chosen_abi
->fpr_names
;
1043 if (strncmp ("cp0-names", option
, optionlen
) == 0
1044 && strlen ("cp0-names") == optionlen
)
1046 chosen_arch
= choose_arch_by_name (val
, vallen
);
1047 if (chosen_arch
!= NULL
)
1049 mips_cp0_names
= chosen_arch
->cp0_names
;
1050 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1051 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1056 if (strncmp ("cp1-names", option
, optionlen
) == 0
1057 && strlen ("cp1-names") == optionlen
)
1059 chosen_arch
= choose_arch_by_name (val
, vallen
);
1060 if (chosen_arch
!= NULL
)
1061 mips_cp1_names
= chosen_arch
->cp1_names
;
1065 if (strncmp ("hwr-names", option
, optionlen
) == 0
1066 && strlen ("hwr-names") == optionlen
)
1068 chosen_arch
= choose_arch_by_name (val
, vallen
);
1069 if (chosen_arch
!= NULL
)
1070 mips_hwr_names
= chosen_arch
->hwr_names
;
1074 if (strncmp ("reg-names", option
, optionlen
) == 0
1075 && strlen ("reg-names") == optionlen
)
1077 /* We check both ABI and ARCH here unconditionally, so
1078 that "numeric" will do the desirable thing: select
1079 numeric register names for all registers. Other than
1080 that, a given name probably won't match both. */
1081 chosen_abi
= choose_abi_by_name (val
, vallen
);
1082 if (chosen_abi
!= NULL
)
1084 mips_gpr_names
= chosen_abi
->gpr_names
;
1085 mips_fpr_names
= chosen_abi
->fpr_names
;
1087 chosen_arch
= choose_arch_by_name (val
, vallen
);
1088 if (chosen_arch
!= NULL
)
1090 mips_cp0_names
= chosen_arch
->cp0_names
;
1091 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1092 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1093 mips_cp1_names
= chosen_arch
->cp1_names
;
1094 mips_hwr_names
= chosen_arch
->hwr_names
;
1099 /* Invalid option. */
1103 parse_mips_dis_options (const char *options
)
1105 const char *option_end
;
1107 if (options
== NULL
)
1110 while (*options
!= '\0')
1112 /* Skip empty options. */
1113 if (*options
== ',')
1119 /* We know that *options is neither NUL or a comma. */
1120 option_end
= options
+ 1;
1121 while (*option_end
!= ',' && *option_end
!= '\0')
1124 parse_mips_dis_option (options
, option_end
- options
);
1126 /* Go on to the next one. If option_end points to a comma, it
1127 will be skipped above. */
1128 options
= option_end
;
1132 static const struct mips_cp0sel_name
*
1133 lookup_mips_cp0sel_name (const struct mips_cp0sel_name
*names
,
1135 unsigned int cp0reg
,
1140 for (i
= 0; i
< len
; i
++)
1141 if (names
[i
].cp0reg
== cp0reg
&& names
[i
].sel
== sel
)
1146 /* Print register REGNO, of type TYPE, for instruction OPCODE. */
1149 print_reg (struct disassemble_info
*info
, const struct mips_opcode
*opcode
,
1150 enum mips_reg_operand_type type
, int regno
)
1155 info
->fprintf_func (info
->stream
, "%s", mips_gpr_names
[regno
]);
1159 info
->fprintf_func (info
->stream
, "%s", mips_fpr_names
[regno
]);
1163 if (opcode
->pinfo
& (FP_D
| FP_S
))
1164 info
->fprintf_func (info
->stream
, "$fcc%d", regno
);
1166 info
->fprintf_func (info
->stream
, "$cc%d", regno
);
1170 if (opcode
->membership
& INSN_5400
)
1171 info
->fprintf_func (info
->stream
, "$f%d", regno
);
1173 info
->fprintf_func (info
->stream
, "$v%d", regno
);
1177 info
->fprintf_func (info
->stream
, "$ac%d", regno
);
1181 if (opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1182 info
->fprintf_func (info
->stream
, "%s", mips_cp0_names
[regno
]);
1183 else if (opcode
->name
[strlen (opcode
->name
) - 1] == '1')
1184 info
->fprintf_func (info
->stream
, "%s", mips_cp1_names
[regno
]);
1186 info
->fprintf_func (info
->stream
, "$%d", regno
);
1190 info
->fprintf_func (info
->stream
, "%s", mips_hwr_names
[regno
]);
1194 info
->fprintf_func (info
->stream
, "$vf%d", regno
);
1198 info
->fprintf_func (info
->stream
, "$vi%d", regno
);
1201 case OP_REG_R5900_I
:
1202 info
->fprintf_func (info
->stream
, "$I");
1205 case OP_REG_R5900_Q
:
1206 info
->fprintf_func (info
->stream
, "$Q");
1209 case OP_REG_R5900_R
:
1210 info
->fprintf_func (info
->stream
, "$R");
1213 case OP_REG_R5900_ACC
:
1214 info
->fprintf_func (info
->stream
, "$ACC");
1218 info
->fprintf_func (info
->stream
, "$w%d", regno
);
1221 case OP_REG_MSA_CTRL
:
1222 info
->fprintf_func (info
->stream
, "%s", msa_control_names
[regno
]);
1228 /* Used to track the state carried over from previous operands in
1230 struct mips_print_arg_state
{
1231 /* The value of the last OP_INT seen. We only use this for OP_MSB,
1232 where the value is known to be unsigned and small. */
1233 unsigned int last_int
;
1235 /* The type and number of the last OP_REG seen. We only use this for
1236 OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1237 enum mips_reg_operand_type last_reg_type
;
1238 unsigned int last_regno
;
1239 unsigned int dest_regno
;
1240 unsigned int seen_dest
;
1243 /* Initialize STATE for the start of an instruction. */
1246 init_print_arg_state (struct mips_print_arg_state
*state
)
1248 memset (state
, 0, sizeof (*state
));
1251 /* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1252 whose value is given by UVAL. */
1255 print_vu0_channel (struct disassemble_info
*info
,
1256 const struct mips_operand
*operand
, unsigned int uval
)
1258 if (operand
->size
== 4)
1259 info
->fprintf_func (info
->stream
, "%s%s%s%s",
1260 uval
& 8 ? "x" : "",
1261 uval
& 4 ? "y" : "",
1262 uval
& 2 ? "z" : "",
1263 uval
& 1 ? "w" : "");
1264 else if (operand
->size
== 2)
1265 info
->fprintf_func (info
->stream
, "%c", "xyzw"[uval
]);
1270 /* Record information about a register operand. */
1273 mips_seen_register (struct mips_print_arg_state
*state
,
1275 enum mips_reg_operand_type reg_type
)
1277 state
->last_reg_type
= reg_type
;
1278 state
->last_regno
= regno
;
1280 if (!state
->seen_dest
)
1282 state
->seen_dest
= 1;
1283 state
->dest_regno
= regno
;
1287 /* Print SAVE/RESTORE instruction operands according to the argument
1288 register mask AMASK, the number of static registers saved NSREG,
1289 the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1290 and the frame size FRAME_SIZE. */
1293 mips_print_save_restore (struct disassemble_info
*info
, unsigned int amask
,
1294 unsigned int nsreg
, unsigned int ra
,
1295 unsigned int s0
, unsigned int s1
,
1296 unsigned int frame_size
)
1298 const fprintf_ftype infprintf
= info
->fprintf_func
;
1299 unsigned int nargs
, nstatics
, smask
, i
, j
;
1300 void *is
= info
->stream
;
1303 if (amask
== MIPS_SVRS_ALL_ARGS
)
1308 else if (amask
== MIPS_SVRS_ALL_STATICS
)
1316 nstatics
= amask
& 3;
1322 infprintf (is
, "%s", mips_gpr_names
[4]);
1324 infprintf (is
, "-%s", mips_gpr_names
[4 + nargs
- 1]);
1328 infprintf (is
, "%s%d", sep
, frame_size
);
1331 infprintf (is
, ",%s", mips_gpr_names
[31]);
1338 if (nsreg
> 0) /* $s2-$s8 */
1339 smask
|= ((1 << nsreg
) - 1) << 2;
1341 for (i
= 0; i
< 9; i
++)
1342 if (smask
& (1 << i
))
1344 infprintf (is
, ",%s", mips_gpr_names
[i
== 8 ? 30 : (16 + i
)]);
1345 /* Skip over string of set bits. */
1346 for (j
= i
; smask
& (2 << j
); j
++)
1349 infprintf (is
, "-%s", mips_gpr_names
[j
== 8 ? 30 : (16 + j
)]);
1352 /* Statics $ax - $a3. */
1354 infprintf (is
, ",%s", mips_gpr_names
[7]);
1355 else if (nstatics
> 0)
1356 infprintf (is
, ",%s-%s",
1357 mips_gpr_names
[7 - nstatics
+ 1],
1362 /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1363 UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1364 the base address for OP_PCREL operands. */
1367 print_insn_arg (struct disassemble_info
*info
,
1368 struct mips_print_arg_state
*state
,
1369 const struct mips_opcode
*opcode
,
1370 const struct mips_operand
*operand
,
1374 const fprintf_ftype infprintf
= info
->fprintf_func
;
1375 void *is
= info
->stream
;
1377 switch (operand
->type
)
1381 const struct mips_int_operand
*int_op
;
1383 int_op
= (const struct mips_int_operand
*) operand
;
1384 uval
= mips_decode_int_operand (int_op
, uval
);
1385 state
->last_int
= uval
;
1386 if (int_op
->print_hex
)
1387 infprintf (is
, "0x%x", uval
);
1389 infprintf (is
, "%d", uval
);
1395 const struct mips_mapped_int_operand
*mint_op
;
1397 mint_op
= (const struct mips_mapped_int_operand
*) operand
;
1398 uval
= mint_op
->int_map
[uval
];
1399 state
->last_int
= uval
;
1400 if (mint_op
->print_hex
)
1401 infprintf (is
, "0x%x", uval
);
1403 infprintf (is
, "%d", uval
);
1409 const struct mips_msb_operand
*msb_op
;
1411 msb_op
= (const struct mips_msb_operand
*) operand
;
1412 uval
+= msb_op
->bias
;
1413 if (msb_op
->add_lsb
)
1414 uval
-= state
->last_int
;
1415 infprintf (is
, "0x%x", uval
);
1420 case OP_OPTIONAL_REG
:
1422 const struct mips_reg_operand
*reg_op
;
1424 reg_op
= (const struct mips_reg_operand
*) operand
;
1425 uval
= mips_decode_reg_operand (reg_op
, uval
);
1426 print_reg (info
, opcode
, reg_op
->reg_type
, uval
);
1428 mips_seen_register (state
, uval
, reg_op
->reg_type
);
1434 const struct mips_reg_pair_operand
*pair_op
;
1436 pair_op
= (const struct mips_reg_pair_operand
*) operand
;
1437 print_reg (info
, opcode
, pair_op
->reg_type
,
1438 pair_op
->reg1_map
[uval
]);
1439 infprintf (is
, ",");
1440 print_reg (info
, opcode
, pair_op
->reg_type
,
1441 pair_op
->reg2_map
[uval
]);
1447 const struct mips_pcrel_operand
*pcrel_op
;
1449 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1450 info
->target
= mips_decode_pcrel_operand (pcrel_op
, base_pc
, uval
);
1452 /* For jumps and branches clear the ISA bit except for
1453 the GDB disassembler. */
1454 if (pcrel_op
->include_isa_bit
1455 && info
->flavour
!= bfd_target_unknown_flavour
)
1458 (*info
->print_address_func
) (info
->target
, info
);
1463 infprintf (is
, "%d", uval
);
1466 case OP_ADDIUSP_INT
:
1470 sval
= mips_signed_operand (operand
, uval
) * 4;
1471 if (sval
>= -8 && sval
< 8)
1473 infprintf (is
, "%d", sval
);
1477 case OP_CLO_CLZ_DEST
:
1479 unsigned int reg1
, reg2
;
1483 /* If one is zero use the other. */
1484 if (reg1
== reg2
|| reg2
== 0)
1485 infprintf (is
, "%s", mips_gpr_names
[reg1
]);
1487 infprintf (is
, "%s", mips_gpr_names
[reg2
]);
1489 /* Bogus, result depends on processor. */
1490 infprintf (is
, "%s or %s", mips_gpr_names
[reg1
],
1491 mips_gpr_names
[reg2
]);
1497 case OP_NON_ZERO_REG
:
1499 print_reg (info
, opcode
, OP_REG_GP
, uval
& 31);
1500 mips_seen_register (state
, uval
, OP_REG_GP
);
1504 case OP_LWM_SWM_LIST
:
1505 if (operand
->size
== 2)
1508 infprintf (is
, "%s,%s",
1510 mips_gpr_names
[31]);
1512 infprintf (is
, "%s-%s,%s",
1514 mips_gpr_names
[16 + uval
],
1515 mips_gpr_names
[31]);
1521 s_reg_encode
= uval
& 0xf;
1522 if (s_reg_encode
!= 0)
1524 if (s_reg_encode
== 1)
1525 infprintf (is
, "%s", mips_gpr_names
[16]);
1526 else if (s_reg_encode
< 9)
1527 infprintf (is
, "%s-%s",
1529 mips_gpr_names
[15 + s_reg_encode
]);
1530 else if (s_reg_encode
== 9)
1531 infprintf (is
, "%s-%s,%s",
1534 mips_gpr_names
[30]);
1536 infprintf (is
, "UNKNOWN");
1539 if (uval
& 0x10) /* For ra. */
1541 if (s_reg_encode
== 0)
1542 infprintf (is
, "%s", mips_gpr_names
[31]);
1544 infprintf (is
, ",%s", mips_gpr_names
[31]);
1549 case OP_ENTRY_EXIT_LIST
:
1552 unsigned int amask
, smask
;
1555 amask
= (uval
>> 3) & 7;
1556 if (amask
> 0 && amask
< 5)
1558 infprintf (is
, "%s", mips_gpr_names
[4]);
1560 infprintf (is
, "-%s", mips_gpr_names
[amask
+ 3]);
1564 smask
= (uval
>> 1) & 3;
1567 infprintf (is
, "%s??", sep
);
1572 infprintf (is
, "%s%s", sep
, mips_gpr_names
[16]);
1574 infprintf (is
, "-%s", mips_gpr_names
[smask
+ 15]);
1580 infprintf (is
, "%s%s", sep
, mips_gpr_names
[31]);
1584 if (amask
== 5 || amask
== 6)
1586 infprintf (is
, "%s%s", sep
, mips_fpr_names
[0]);
1588 infprintf (is
, "-%s", mips_fpr_names
[1]);
1593 case OP_SAVE_RESTORE_LIST
:
1594 /* Should be handled by the caller due to complex behavior. */
1597 case OP_MDMX_IMM_REG
:
1603 if ((vsel
& 0x10) == 0)
1608 for (fmt
= 0; fmt
< 3; fmt
++, vsel
>>= 1)
1609 if ((vsel
& 1) == 0)
1611 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1612 infprintf (is
, "[%d]", vsel
>> 1);
1614 else if ((vsel
& 0x08) == 0)
1615 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1617 infprintf (is
, "0x%x", uval
);
1621 case OP_REPEAT_PREV_REG
:
1622 print_reg (info
, opcode
, state
->last_reg_type
, state
->last_regno
);
1625 case OP_REPEAT_DEST_REG
:
1626 print_reg (info
, opcode
, state
->last_reg_type
, state
->dest_regno
);
1630 infprintf (is
, "$pc");
1634 print_reg (info
, opcode
, OP_REG_GP
, 28);
1638 case OP_VU0_MATCH_SUFFIX
:
1639 print_vu0_channel (info
, operand
, uval
);
1643 infprintf (is
, "[%d]", uval
);
1647 infprintf (is
, "[");
1648 print_reg (info
, opcode
, OP_REG_GP
, uval
);
1649 infprintf (is
, "]");
1654 /* Validate the arguments for INSN, which is described by OPCODE.
1655 Use DECODE_OPERAND to get the encoding of each operand. */
1658 validate_insn_args (const struct mips_opcode
*opcode
,
1659 const struct mips_operand
*(*decode_operand
) (const char *),
1662 struct mips_print_arg_state state
;
1663 const struct mips_operand
*operand
;
1667 init_print_arg_state (&state
);
1668 for (s
= opcode
->args
; *s
; ++s
)
1682 operand
= decode_operand (s
);
1686 uval
= mips_extract_operand (operand
, insn
);
1687 switch (operand
->type
)
1690 case OP_OPTIONAL_REG
:
1692 const struct mips_reg_operand
*reg_op
;
1694 reg_op
= (const struct mips_reg_operand
*) operand
;
1695 uval
= mips_decode_reg_operand (reg_op
, uval
);
1696 mips_seen_register (&state
, uval
, reg_op
->reg_type
);
1702 unsigned int reg1
, reg2
;
1707 if (reg1
!= reg2
|| reg1
== 0)
1714 const struct mips_check_prev_operand
*prev_op
;
1716 prev_op
= (const struct mips_check_prev_operand
*) operand
;
1718 if (!prev_op
->zero_ok
&& uval
== 0)
1721 if (((prev_op
->less_than_ok
&& uval
< state
.last_regno
)
1722 || (prev_op
->greater_than_ok
&& uval
> state
.last_regno
)
1723 || (prev_op
->equal_ok
&& uval
== state
.last_regno
)))
1729 case OP_NON_ZERO_REG
:
1742 case OP_ADDIUSP_INT
:
1743 case OP_CLO_CLZ_DEST
:
1744 case OP_LWM_SWM_LIST
:
1745 case OP_ENTRY_EXIT_LIST
:
1746 case OP_MDMX_IMM_REG
:
1747 case OP_REPEAT_PREV_REG
:
1748 case OP_REPEAT_DEST_REG
:
1752 case OP_VU0_MATCH_SUFFIX
:
1755 case OP_SAVE_RESTORE_LIST
:
1759 if (*s
== 'm' || *s
== '+' || *s
== '-')
1766 /* Print the arguments for INSN, which is described by OPCODE.
1767 Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
1768 as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1769 operand is for a branch or jump. */
1772 print_insn_args (struct disassemble_info
*info
,
1773 const struct mips_opcode
*opcode
,
1774 const struct mips_operand
*(*decode_operand
) (const char *),
1775 unsigned int insn
, bfd_vma insn_pc
, unsigned int length
)
1777 const fprintf_ftype infprintf
= info
->fprintf_func
;
1778 void *is
= info
->stream
;
1779 struct mips_print_arg_state state
;
1780 const struct mips_operand
*operand
;
1783 init_print_arg_state (&state
);
1784 for (s
= opcode
->args
; *s
; ++s
)
1791 infprintf (is
, "%c", *s
);
1796 infprintf (is
, "%c%c", *s
, *s
);
1800 operand
= decode_operand (s
);
1803 /* xgettext:c-format */
1805 _("# internal error, undefined operand in `%s %s'"),
1806 opcode
->name
, opcode
->args
);
1810 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
1812 /* Handle this case here because of the complex behavior. */
1813 unsigned int amask
= (insn
>> 15) & 0xf;
1814 unsigned int nsreg
= (insn
>> 23) & 0x7;
1815 unsigned int ra
= insn
& 0x1000; /* $ra */
1816 unsigned int s0
= insn
& 0x800; /* $s0 */
1817 unsigned int s1
= insn
& 0x400; /* $s1 */
1818 unsigned int frame_size
= (((insn
>> 15) & 0xf0)
1819 | ((insn
>> 6) & 0x0f)) * 8;
1820 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
,
1823 else if (operand
->type
== OP_REG
1826 && opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1828 /* Coprocessor register 0 with sel field. */
1829 const struct mips_cp0sel_name
*n
;
1830 unsigned int reg
, sel
;
1832 reg
= mips_extract_operand (operand
, insn
);
1834 operand
= decode_operand (s
);
1835 sel
= mips_extract_operand (operand
, insn
);
1837 /* CP0 register including 'sel' code for mftc0, to be
1838 printed textually if known. If not known, print both
1839 CP0 register name and sel numerically since CP0 register
1840 with sel 0 may have a name unrelated to register being
1842 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
1843 mips_cp0sel_names_len
,
1846 infprintf (is
, "%s", n
->name
);
1848 infprintf (is
, "$%d,%d", reg
, sel
);
1852 bfd_vma base_pc
= insn_pc
;
1854 /* Adjust the PC relative base so that branch/jump insns use
1855 the following PC as the base but genuinely PC relative
1856 operands use the current PC. */
1857 if (operand
->type
== OP_PCREL
)
1859 const struct mips_pcrel_operand
*pcrel_op
;
1861 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1862 /* The include_isa_bit flag is sufficient to distinguish
1863 branch/jump from other PC relative operands. */
1864 if (pcrel_op
->include_isa_bit
)
1868 print_insn_arg (info
, &state
, opcode
, operand
, base_pc
,
1869 mips_extract_operand (operand
, insn
));
1871 if (*s
== 'm' || *s
== '+' || *s
== '-')
1878 /* Print the mips instruction at address MEMADDR in debugged memory,
1879 on using INFO. Returns length of the instruction, in bytes, which is
1880 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
1881 this is little-endian code. */
1884 print_insn_mips (bfd_vma memaddr
,
1886 struct disassemble_info
*info
)
1888 #define GET_OP(insn, field) \
1889 (((insn) >> OP_SH_##field) & OP_MASK_##field)
1890 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
1891 const fprintf_ftype infprintf
= info
->fprintf_func
;
1892 const struct mips_opcode
*op
;
1893 static bfd_boolean init
= 0;
1894 void *is
= info
->stream
;
1896 /* Build a hash table to shorten the search time. */
1901 for (i
= 0; i
<= OP_MASK_OP
; i
++)
1903 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1905 if (op
->pinfo
== INSN_MACRO
1906 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
1908 if (i
== GET_OP (op
->match
, OP
))
1919 info
->bytes_per_chunk
= INSNLEN
;
1920 info
->display_endian
= info
->endian
;
1921 info
->insn_info_valid
= 1;
1922 info
->branch_delay_insns
= 0;
1923 info
->data_size
= 0;
1924 info
->insn_type
= dis_nonbranch
;
1928 op
= mips_hash
[GET_OP (word
, OP
)];
1931 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1933 if (op
->pinfo
!= INSN_MACRO
1934 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
1935 && (word
& op
->mask
) == op
->match
)
1937 /* We always disassemble the jalx instruction, except for MIPS r6. */
1938 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
)
1939 && (strcmp (op
->name
, "jalx")
1940 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS32R6
1941 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
))
1944 /* Figure out instruction type and branch delay information. */
1945 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
1947 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
1948 info
->insn_type
= dis_jsr
;
1950 info
->insn_type
= dis_branch
;
1951 info
->branch_delay_insns
= 1;
1953 else if ((op
->pinfo
& (INSN_COND_BRANCH_DELAY
1954 | INSN_COND_BRANCH_LIKELY
)) != 0)
1956 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
1957 info
->insn_type
= dis_condjsr
;
1959 info
->insn_type
= dis_condbranch
;
1960 info
->branch_delay_insns
= 1;
1962 else if ((op
->pinfo
& (INSN_STORE_MEMORY
1963 | INSN_LOAD_MEMORY
)) != 0)
1964 info
->insn_type
= dis_dref
;
1966 if (!validate_insn_args (op
, decode_mips_operand
, word
))
1969 infprintf (is
, "%s", op
->name
);
1970 if (op
->pinfo2
& INSN2_VU0_CHANNEL_SUFFIX
)
1974 infprintf (is
, ".");
1975 uval
= mips_extract_operand (&mips_vu0_channel_mask
, word
);
1976 print_vu0_channel (info
, &mips_vu0_channel_mask
, uval
);
1981 infprintf (is
, "\t");
1982 print_insn_args (info
, op
, decode_mips_operand
, word
,
1992 /* Handle undefined instructions. */
1993 info
->insn_type
= dis_noninsn
;
1994 infprintf (is
, "0x%x", word
);
1998 /* Disassemble an operand for a mips16 instruction. */
2001 print_mips16_insn_arg (struct disassemble_info
*info
,
2002 struct mips_print_arg_state
*state
,
2003 const struct mips_opcode
*opcode
,
2004 char type
, bfd_vma memaddr
,
2005 unsigned insn
, bfd_boolean use_extend
,
2006 unsigned extend
, bfd_boolean is_offset
)
2008 const fprintf_ftype infprintf
= info
->fprintf_func
;
2009 void *is
= info
->stream
;
2010 const struct mips_operand
*operand
, *ext_operand
;
2011 unsigned short ext_size
;
2023 infprintf (is
, "%c", type
);
2027 operand
= decode_mips16_operand (type
, FALSE
);
2030 /* xgettext:c-format */
2031 infprintf (is
, _("# internal error, undefined operand in `%s %s'"),
2032 opcode
->name
, opcode
->args
);
2036 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
2038 /* Handle this case here because of the complex interaction
2039 with the EXTEND opcode. */
2040 unsigned int amask
= extend
& 0xf;
2041 unsigned int nsreg
= (extend
>> 8) & 0x7;
2042 unsigned int ra
= insn
& 0x40; /* $ra */
2043 unsigned int s0
= insn
& 0x20; /* $s0 */
2044 unsigned int s1
= insn
& 0x10; /* $s1 */
2045 unsigned int frame_size
= ((extend
& 0xf0) | (insn
& 0x0f)) * 8;
2046 if (frame_size
== 0 && !use_extend
)
2048 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
, frame_size
);
2052 if (is_offset
&& operand
->type
== OP_INT
)
2054 const struct mips_int_operand
*int_op
;
2056 int_op
= (const struct mips_int_operand
*) operand
;
2057 info
->insn_type
= dis_dref
;
2058 info
->data_size
= 1 << int_op
->shift
;
2064 ext_operand
= decode_mips16_operand (type
, TRUE
);
2065 if (ext_operand
!= operand
2066 || (operand
->type
== OP_INT
&& operand
->lsb
== 0
2067 && mips_opcode_32bit_p (opcode
)))
2069 ext_size
= ext_operand
->size
;
2070 operand
= ext_operand
;
2073 if (operand
->size
== 26)
2074 uval
= ((extend
& 0x1f) << 21) | ((extend
& 0x3e0) << 11) | insn
;
2075 else if (ext_size
== 16 || ext_size
== 9)
2076 uval
= ((extend
& 0x1f) << 11) | (extend
& 0x7e0) | (insn
& 0x1f);
2077 else if (ext_size
== 15)
2078 uval
= ((extend
& 0xf) << 11) | (extend
& 0x7f0) | (insn
& 0xf);
2079 else if (ext_size
== 6)
2080 uval
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
2082 uval
= mips_extract_operand (operand
, (extend
<< 16) | insn
);
2084 uval
&= (1U << ext_size
) - 1;
2086 baseaddr
= memaddr
+ 2;
2087 if (operand
->type
== OP_PCREL
)
2089 const struct mips_pcrel_operand
*pcrel_op
;
2091 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
2092 if (!pcrel_op
->include_isa_bit
&& use_extend
)
2093 baseaddr
= memaddr
- 2;
2094 else if (!pcrel_op
->include_isa_bit
)
2098 /* If this instruction is in the delay slot of a JAL/JALX
2099 instruction, the base address is the address of the
2100 JAL/JALX instruction. If it is in the delay slot of
2101 a JR/JALR instruction, the base address is the address
2102 of the JR/JALR instruction. This test is unreliable:
2103 we have no way of knowing whether the previous word is
2104 instruction or data. */
2105 if (info
->read_memory_func (memaddr
- 4, buffer
, 2, info
) == 0
2106 && (((info
->endian
== BFD_ENDIAN_BIG
2107 ? bfd_getb16 (buffer
)
2108 : bfd_getl16 (buffer
))
2109 & 0xf800) == 0x1800))
2110 baseaddr
= memaddr
- 4;
2111 else if (info
->read_memory_func (memaddr
- 2, buffer
, 2,
2113 && (((info
->endian
== BFD_ENDIAN_BIG
2114 ? bfd_getb16 (buffer
)
2115 : bfd_getl16 (buffer
))
2116 & 0xf89f) == 0xe800)
2117 && (((info
->endian
== BFD_ENDIAN_BIG
2118 ? bfd_getb16 (buffer
)
2119 : bfd_getl16 (buffer
))
2120 & 0x0060) != 0x0060))
2121 baseaddr
= memaddr
- 2;
2127 print_insn_arg (info
, state
, opcode
, operand
, baseaddr
+ 1, uval
);
2133 /* Check if the given address is the last word of a MIPS16 PLT entry.
2134 This word is data and depending on the value it may interfere with
2135 disassembly of further PLT entries. We make use of the fact PLT
2136 symbols are marked BSF_SYNTHETIC. */
2138 is_mips16_plt_tail (struct disassemble_info
*info
, bfd_vma addr
)
2142 && (info
->symbols
[0]->flags
& BSF_SYNTHETIC
)
2143 && addr
== bfd_asymbol_value (info
->symbols
[0]) + 12)
2149 /* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2158 /* Disassemble mips16 instructions. */
2161 print_insn_mips16 (bfd_vma memaddr
, struct disassemble_info
*info
)
2163 const fprintf_ftype infprintf
= info
->fprintf_func
;
2166 const struct mips_opcode
*op
, *opend
;
2167 struct mips_print_arg_state state
;
2168 void *is
= info
->stream
;
2169 bfd_boolean have_second
;
2170 bfd_boolean extend_only
;
2171 unsigned int second
;
2175 info
->bytes_per_chunk
= 2;
2176 info
->display_endian
= info
->endian
;
2177 info
->insn_info_valid
= 1;
2178 info
->branch_delay_insns
= 0;
2179 info
->data_size
= 0;
2183 #define GET_OP(insn, field) \
2184 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
2185 /* Decode PLT entry's GOT slot address word. */
2186 if (is_mips16_plt_tail (info
, memaddr
))
2188 info
->insn_type
= dis_noninsn
;
2189 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
2192 unsigned int gotslot
;
2194 if (info
->endian
== BFD_ENDIAN_BIG
)
2195 gotslot
= bfd_getb32 (buffer
);
2197 gotslot
= bfd_getl32 (buffer
);
2198 infprintf (is
, ".word\t0x%x", gotslot
);
2205 info
->insn_type
= dis_nonbranch
;
2206 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2210 (*info
->memory_error_func
) (status
, memaddr
, info
);
2214 extend_only
= FALSE
;
2216 if (info
->endian
== BFD_ENDIAN_BIG
)
2217 first
= bfd_getb16 (buffer
);
2219 first
= bfd_getl16 (buffer
);
2221 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2225 if (info
->endian
== BFD_ENDIAN_BIG
)
2226 second
= bfd_getb16 (buffer
);
2228 second
= bfd_getl16 (buffer
);
2229 full
= (first
<< 16) | second
;
2233 have_second
= FALSE
;
2238 /* FIXME: Should probably use a hash table on the major opcode here. */
2240 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
2241 for (op
= mips16_opcodes
; op
< opend
; op
++)
2243 enum match_kind match
;
2245 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
))
2248 if (op
->pinfo
== INSN_MACRO
2249 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
2251 else if (mips_opcode_32bit_p (op
))
2254 && (full
& op
->mask
) == op
->match
)
2259 else if ((first
& op
->mask
) == op
->match
)
2261 match
= MATCH_SHORT
;
2265 else if ((first
& 0xf800) == 0xf000
2268 && (second
& op
->mask
) == op
->match
)
2270 if (op
->pinfo2
& INSN2_SHORT_ONLY
)
2281 if (match
!= MATCH_NONE
)
2285 infprintf (is
, "%s", op
->name
);
2286 if (op
->args
[0] != '\0')
2287 infprintf (is
, "\t");
2289 init_print_arg_state (&state
);
2290 for (s
= op
->args
; *s
!= '\0'; s
++)
2294 && GET_OP (full
, RX
) == GET_OP (full
, RY
))
2296 /* Skip the register and the comma. */
2302 && GET_OP (full
, RZ
) == GET_OP (full
, RX
))
2304 /* Skip the register and the comma. */
2311 && op
->name
[strlen (op
->name
) - 1] == '0')
2313 /* Coprocessor register 0 with sel field. */
2314 const struct mips_cp0sel_name
*n
;
2315 const struct mips_operand
*operand
;
2316 unsigned int reg
, sel
;
2318 operand
= decode_mips16_operand (*s
, TRUE
);
2319 reg
= mips_extract_operand (operand
, (first
<< 16) | second
);
2321 operand
= decode_mips16_operand (*s
, TRUE
);
2322 sel
= mips_extract_operand (operand
, (first
<< 16) | second
);
2324 /* CP0 register including 'sel' code for mftc0, to be
2325 printed textually if known. If not known, print both
2326 CP0 register name and sel numerically since CP0 register
2327 with sel 0 may have a name unrelated to register being
2329 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
2330 mips_cp0sel_names_len
,
2333 infprintf (is
, "%s", n
->name
);
2335 infprintf (is
, "$%d,%d", reg
, sel
);
2341 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
+ 2,
2342 second
, TRUE
, first
, s
[1] == '(');
2345 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
,
2346 first
, FALSE
, 0, s
[1] == '(');
2348 case MATCH_NONE
: /* Stop the compiler complaining. */
2353 /* Figure out branch instruction type and delay slot information. */
2354 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
2355 info
->branch_delay_insns
= 1;
2356 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0
2357 || (op
->pinfo2
& INSN2_UNCOND_BRANCH
) != 0)
2359 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2360 info
->insn_type
= dis_jsr
;
2362 info
->insn_type
= dis_branch
;
2364 else if ((op
->pinfo2
& INSN2_COND_BRANCH
) != 0)
2365 info
->insn_type
= dis_condbranch
;
2367 return match
== MATCH_FULL
? 4 : 2;
2372 infprintf (is
, "0x%x", first
);
2373 info
->insn_type
= dis_noninsn
;
2378 /* Disassemble microMIPS instructions. */
2381 print_insn_micromips (bfd_vma memaddr
, struct disassemble_info
*info
)
2383 const fprintf_ftype infprintf
= info
->fprintf_func
;
2384 const struct mips_opcode
*op
, *opend
;
2385 void *is
= info
->stream
;
2387 unsigned int higher
;
2388 unsigned int length
;
2392 info
->bytes_per_chunk
= 2;
2393 info
->display_endian
= info
->endian
;
2394 info
->insn_info_valid
= 1;
2395 info
->branch_delay_insns
= 0;
2396 info
->data_size
= 0;
2397 info
->insn_type
= dis_nonbranch
;
2401 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2404 (*info
->memory_error_func
) (status
, memaddr
, info
);
2410 if (info
->endian
== BFD_ENDIAN_BIG
)
2411 insn
= bfd_getb16 (buffer
);
2413 insn
= bfd_getl16 (buffer
);
2415 if ((insn
& 0x1c00) == 0x0000 || (insn
& 0x1000) == 0x1000)
2417 /* This is a 32-bit microMIPS instruction. */
2420 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2423 infprintf (is
, "micromips 0x%x", higher
);
2424 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
2428 if (info
->endian
== BFD_ENDIAN_BIG
)
2429 insn
= bfd_getb16 (buffer
);
2431 insn
= bfd_getl16 (buffer
);
2433 insn
= insn
| (higher
<< 16);
2438 /* FIXME: Should probably use a hash table on the major opcode here. */
2440 opend
= micromips_opcodes
+ bfd_micromips_num_opcodes
;
2441 for (op
= micromips_opcodes
; op
< opend
; op
++)
2443 if (op
->pinfo
!= INSN_MACRO
2444 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
2445 && (insn
& op
->mask
) == op
->match
2446 && ((length
== 2 && (op
->mask
& 0xffff0000) == 0)
2447 || (length
== 4 && (op
->mask
& 0xffff0000) != 0)))
2449 if (!validate_insn_args (op
, decode_micromips_operand
, insn
))
2452 infprintf (is
, "%s", op
->name
);
2456 infprintf (is
, "\t");
2457 print_insn_args (info
, op
, decode_micromips_operand
, insn
,
2458 memaddr
+ 1, length
);
2461 /* Figure out instruction type and branch delay information. */
2463 & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
)) != 0)
2464 info
->branch_delay_insns
= 1;
2465 if (((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
2466 | (op
->pinfo2
& INSN2_UNCOND_BRANCH
)) != 0)
2468 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
2469 info
->insn_type
= dis_jsr
;
2471 info
->insn_type
= dis_branch
;
2473 else if (((op
->pinfo
& INSN_COND_BRANCH_DELAY
)
2474 | (op
->pinfo2
& INSN2_COND_BRANCH
)) != 0)
2476 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2477 info
->insn_type
= dis_condjsr
;
2479 info
->insn_type
= dis_condbranch
;
2482 & (INSN_STORE_MEMORY
| INSN_LOAD_MEMORY
)) != 0)
2483 info
->insn_type
= dis_dref
;
2489 infprintf (is
, "0x%x", insn
);
2490 info
->insn_type
= dis_noninsn
;
2495 /* Return 1 if a symbol associated with the location being disassembled
2496 indicates a compressed mode, either MIPS16 or microMIPS, according to
2497 MICROMIPS_P. We iterate over all the symbols at the address being
2498 considered assuming if at least one of them indicates code compression,
2499 then such code has been genuinely produced here (other symbols could
2500 have been derived from function symbols defined elsewhere or could
2501 define data). Otherwise, return 0. */
2504 is_compressed_mode_p (struct disassemble_info
*info
, bfd_boolean micromips_p
)
2509 for (i
= info
->symtab_pos
, l
= i
+ info
->num_symbols
; i
< l
; i
++)
2510 if (((info
->symtab
[i
])->flags
& BSF_SYNTHETIC
) != 0
2512 && ELF_ST_IS_MIPS16 ((*info
->symbols
)->udata
.i
))
2514 && ELF_ST_IS_MICROMIPS ((*info
->symbols
)->udata
.i
))))
2516 else if (bfd_asymbol_flavour (info
->symtab
[i
]) == bfd_target_elf_flavour
2517 && info
->symtab
[i
]->section
== info
->section
)
2519 elf_symbol_type
*symbol
= (elf_symbol_type
*) info
->symtab
[i
];
2521 && ELF_ST_IS_MIPS16 (symbol
->internal_elf_sym
.st_other
))
2523 && ELF_ST_IS_MICROMIPS (symbol
->internal_elf_sym
.st_other
)))
2530 /* In an environment where we do not know the symbol type of the
2531 instruction we are forced to assume that the low order bit of the
2532 instructions' address may mark it as a mips16 instruction. If we
2533 are single stepping, or the pc is within the disassembled function,
2534 this works. Otherwise, we need a clue. Sometimes. */
2537 _print_insn_mips (bfd_vma memaddr
,
2538 struct disassemble_info
*info
,
2539 enum bfd_endian endianness
)
2541 bfd_byte buffer
[INSNLEN
];
2544 set_default_mips_dis_options (info
);
2545 parse_mips_dis_options (info
->disassembler_options
);
2547 if (info
->mach
== bfd_mach_mips16
)
2548 return print_insn_mips16 (memaddr
, info
);
2549 if (info
->mach
== bfd_mach_mips_micromips
)
2550 return print_insn_micromips (memaddr
, info
);
2553 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
2554 /* Only a few tools will work this way. */
2558 return print_insn_micromips (memaddr
, info
);
2560 return print_insn_mips16 (memaddr
, info
);
2564 #if SYMTAB_AVAILABLE
2565 if (is_compressed_mode_p (info
, TRUE
))
2566 return print_insn_micromips (memaddr
, info
);
2567 if (is_compressed_mode_p (info
, FALSE
))
2568 return print_insn_mips16 (memaddr
, info
);
2571 status
= (*info
->read_memory_func
) (memaddr
, buffer
, INSNLEN
, info
);
2576 if (endianness
== BFD_ENDIAN_BIG
)
2577 insn
= bfd_getb32 (buffer
);
2579 insn
= bfd_getl32 (buffer
);
2581 return print_insn_mips (memaddr
, insn
, info
);
2585 (*info
->memory_error_func
) (status
, memaddr
, info
);
2591 print_insn_big_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2593 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_BIG
);
2597 print_insn_little_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2599 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_LITTLE
);
2602 /* Indices into option argument vector for options accepting an argument.
2603 Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2606 MIPS_OPTION_ARG_NONE
= -1,
2607 MIPS_OPTION_ARG_ABI
,
2608 MIPS_OPTION_ARG_ARCH
,
2609 MIPS_OPTION_ARG_SIZE
2610 } mips_option_arg_t
;
2612 /* Valid MIPS disassembler options. */
2616 const char *description
;
2617 mips_option_arg_t arg
;
2620 { "no-aliases", N_("Use canonical instruction forms.\n"),
2621 MIPS_OPTION_ARG_NONE
},
2622 { "msa", N_("Recognize MSA instructions.\n"),
2623 MIPS_OPTION_ARG_NONE
},
2624 { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2625 MIPS_OPTION_ARG_NONE
},
2626 { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2628 MIPS_OPTION_ARG_NONE
},
2629 { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2631 MIPS_OPTION_ARG_NONE
},
2633 N_("Recognize the Loongson MultiMedia extensions "
2634 "Instructions (MMI) ASE instructions.\n"),
2635 MIPS_OPTION_ARG_NONE
},
2637 N_("Recognize the Loongson Content Address Memory (CAM) "
2638 " instructions.\n"),
2639 MIPS_OPTION_ARG_NONE
},
2641 N_("Recognize the Loongson EXTensions (EXT) "
2642 " instructions.\n"),
2643 MIPS_OPTION_ARG_NONE
},
2645 N_("Recognize the Loongson EXTensions R2 (EXT2) "
2646 " instructions.\n"),
2647 MIPS_OPTION_ARG_NONE
},
2648 { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2649 Default: based on binary being disassembled.\n"),
2650 MIPS_OPTION_ARG_ABI
},
2651 { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2652 Default: numeric.\n"),
2653 MIPS_OPTION_ARG_ABI
},
2654 { "cp0-names=", N_("Print CP0 register names according to specified "
2656 Default: based on binary being disassembled.\n"),
2657 MIPS_OPTION_ARG_ARCH
},
2658 { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2659 Default: based on binary being disassembled.\n"),
2660 MIPS_OPTION_ARG_ARCH
},
2661 { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2662 MIPS_OPTION_ARG_ABI
},
2663 { "reg-names=", N_("Print CP0 register and HWR names according to "
2666 MIPS_OPTION_ARG_ARCH
}
2669 /* Build the structure representing valid MIPS disassembler options.
2670 This is done dynamically for maintenance ease purpose; a static
2671 initializer would be unreadable. */
2673 const disasm_options_and_args_t
*
2674 disassembler_options_mips (void)
2676 static disasm_options_and_args_t
*opts_and_args
;
2678 if (opts_and_args
== NULL
)
2680 size_t num_options
= ARRAY_SIZE (mips_options
);
2681 size_t num_args
= MIPS_OPTION_ARG_SIZE
;
2682 disasm_option_arg_t
*args
;
2683 disasm_options_t
*opts
;
2687 args
= XNEWVEC (disasm_option_arg_t
, num_args
+ 1);
2689 args
[MIPS_OPTION_ARG_ABI
].name
= "ABI";
2690 args
[MIPS_OPTION_ARG_ABI
].values
2691 = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices
) + 1);
2692 for (i
= 0; i
< ARRAY_SIZE (mips_abi_choices
); i
++)
2693 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = mips_abi_choices
[i
].name
;
2694 /* The array we return must be NULL terminated. */
2695 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = NULL
;
2697 args
[MIPS_OPTION_ARG_ARCH
].name
= "ARCH";
2698 args
[MIPS_OPTION_ARG_ARCH
].values
2699 = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices
) + 1);
2700 for (i
= 0, j
= 0; i
< ARRAY_SIZE (mips_arch_choices
); i
++)
2701 if (*mips_arch_choices
[i
].name
!= '\0')
2702 args
[MIPS_OPTION_ARG_ARCH
].values
[j
++] = mips_arch_choices
[i
].name
;
2703 /* The array we return must be NULL terminated. */
2704 args
[MIPS_OPTION_ARG_ARCH
].values
[j
] = NULL
;
2706 /* The array we return must be NULL terminated. */
2707 args
[MIPS_OPTION_ARG_SIZE
].name
= NULL
;
2708 args
[MIPS_OPTION_ARG_SIZE
].values
= NULL
;
2710 opts_and_args
= XNEW (disasm_options_and_args_t
);
2711 opts_and_args
->args
= args
;
2713 opts
= &opts_and_args
->options
;
2714 opts
->name
= XNEWVEC (const char *, num_options
+ 1);
2715 opts
->description
= XNEWVEC (const char *, num_options
+ 1);
2716 opts
->arg
= XNEWVEC (const disasm_option_arg_t
*, num_options
+ 1);
2717 for (i
= 0; i
< num_options
; i
++)
2719 opts
->name
[i
] = mips_options
[i
].name
;
2720 opts
->description
[i
] = _(mips_options
[i
].description
);
2721 if (mips_options
[i
].arg
!= MIPS_OPTION_ARG_NONE
)
2722 opts
->arg
[i
] = &args
[mips_options
[i
].arg
];
2724 opts
->arg
[i
] = NULL
;
2726 /* The array we return must be NULL terminated. */
2727 opts
->name
[i
] = NULL
;
2728 opts
->description
[i
] = NULL
;
2729 opts
->arg
[i
] = NULL
;
2732 return opts_and_args
;
2736 print_mips_disassembler_options (FILE *stream
)
2738 const disasm_options_and_args_t
*opts_and_args
;
2739 const disasm_option_arg_t
*args
;
2740 const disasm_options_t
*opts
;
2745 opts_and_args
= disassembler_options_mips ();
2746 opts
= &opts_and_args
->options
;
2747 args
= opts_and_args
->args
;
2749 fprintf (stream
, _("\n\
2750 The following MIPS specific disassembler options are supported for use\n\
2751 with the -M switch (multiple options should be separated by commas):\n\n"));
2753 /* Compute the length of the longest option name. */
2754 for (i
= 0; opts
->name
[i
] != NULL
; i
++)
2756 size_t len
= strlen (opts
->name
[i
]);
2758 if (opts
->arg
[i
] != NULL
)
2759 len
+= strlen (opts
->arg
[i
]->name
);
2764 for (i
= 0, max_len
++; opts
->name
[i
] != NULL
; i
++)
2766 fprintf (stream
, " %s", opts
->name
[i
]);
2767 if (opts
->arg
[i
] != NULL
)
2768 fprintf (stream
, "%s", opts
->arg
[i
]->name
);
2769 if (opts
->description
[i
] != NULL
)
2771 size_t len
= strlen (opts
->name
[i
]);
2773 if (opts
->arg
[i
] != NULL
)
2774 len
+= strlen (opts
->arg
[i
]->name
);
2776 "%*c %s", (int) (max_len
- len
), ' ', opts
->description
[i
]);
2778 fprintf (stream
, _("\n"));
2781 for (i
= 0; args
[i
].name
!= NULL
; i
++)
2783 fprintf (stream
, _("\n\
2784 For the options above, the following values are supported for \"%s\":\n "),
2786 for (j
= 0; args
[i
].values
[j
] != NULL
; j
++)
2787 fprintf (stream
, " %s", args
[i
].values
[j
]);
2788 fprintf (stream
, _("\n"));
2791 fprintf (stream
, _("\n"));