1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 Copyright (C) 1989-2018 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"
28 /* FIXME: These are needed to figure out if the code is mips16 or
29 not. The low bit of the address is often a good indicator. No
30 symbol table is available when this code runs out in an embedded
31 system as when it is used for disassembler support in a monitor. */
33 #if !defined(EMBEDDED_ENV)
34 #define SYMTAB_AVAILABLE 1
39 /* Mips instructions are at maximum this many bytes long. */
43 /* FIXME: These should be shared with gdb somehow. */
45 struct mips_cp0sel_name
49 const char * const name
;
52 static const char * const mips_gpr_names_numeric
[32] =
54 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
55 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
56 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
57 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
60 static const char * const mips_gpr_names_oldabi
[32] =
62 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
63 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
64 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
65 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
68 static const char * const mips_gpr_names_newabi
[32] =
70 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
71 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
72 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
73 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
76 static const char * const mips_fpr_names_numeric
[32] =
78 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
79 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
80 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
81 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
84 static const char * const mips_fpr_names_32
[32] =
86 "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
87 "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
88 "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f",
89 "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f"
92 static const char * const mips_fpr_names_n32
[32] =
94 "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3",
95 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
96 "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9",
97 "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13"
100 static const char * const mips_fpr_names_64
[32] =
102 "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
103 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
104 "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
105 "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
108 static const char * const mips_cp0_names_numeric
[32] =
110 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
111 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
112 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
113 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
116 static const char * const mips_cp1_names_numeric
[32] =
118 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
119 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
120 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
121 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
124 static const char * const mips_cp0_names_r3000
[32] =
126 "c0_index", "c0_random", "c0_entrylo", "$3",
127 "c0_context", "$5", "$6", "$7",
128 "c0_badvaddr", "$9", "c0_entryhi", "$11",
129 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
130 "$16", "$17", "$18", "$19",
131 "$20", "$21", "$22", "$23",
132 "$24", "$25", "$26", "$27",
133 "$28", "$29", "$30", "$31",
136 static const char * const mips_cp0_names_r4000
[32] =
138 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
139 "c0_context", "c0_pagemask", "c0_wired", "$7",
140 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
141 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
142 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
143 "c0_xcontext", "$21", "$22", "$23",
144 "$24", "$25", "c0_ecc", "c0_cacheerr",
145 "c0_taglo", "c0_taghi", "c0_errorepc", "$31",
148 static const char * const mips_cp0_names_r5900
[32] =
150 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
151 "c0_context", "c0_pagemask", "c0_wired", "$7",
152 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
153 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
154 "c0_config", "$17", "$18", "$19",
155 "$20", "$21", "$22", "c0_badpaddr",
156 "c0_depc", "c0_perfcnt", "$26", "$27",
157 "c0_taglo", "c0_taghi", "c0_errorepc", "$31"
160 static const char * const mips_cp0_names_mips3264
[32] =
162 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
163 "c0_context", "c0_pagemask", "c0_wired", "$7",
164 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
165 "c0_status", "c0_cause", "c0_epc", "c0_prid",
166 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
167 "c0_xcontext", "$21", "$22", "c0_debug",
168 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
169 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
172 static const char * const mips_cp1_names_mips3264
[32] =
174 "c1_fir", "c1_ufr", "$2", "$3",
175 "c1_unfr", "$5", "$6", "$7",
176 "$8", "$9", "$10", "$11",
177 "$12", "$13", "$14", "$15",
178 "$16", "$17", "$18", "$19",
179 "$20", "$21", "$22", "$23",
180 "$24", "c1_fccr", "c1_fexr", "$27",
181 "c1_fenr", "$29", "$30", "c1_fcsr"
184 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264
[] =
186 { 16, 1, "c0_config1" },
187 { 16, 2, "c0_config2" },
188 { 16, 3, "c0_config3" },
189 { 18, 1, "c0_watchlo,1" },
190 { 18, 2, "c0_watchlo,2" },
191 { 18, 3, "c0_watchlo,3" },
192 { 18, 4, "c0_watchlo,4" },
193 { 18, 5, "c0_watchlo,5" },
194 { 18, 6, "c0_watchlo,6" },
195 { 18, 7, "c0_watchlo,7" },
196 { 19, 1, "c0_watchhi,1" },
197 { 19, 2, "c0_watchhi,2" },
198 { 19, 3, "c0_watchhi,3" },
199 { 19, 4, "c0_watchhi,4" },
200 { 19, 5, "c0_watchhi,5" },
201 { 19, 6, "c0_watchhi,6" },
202 { 19, 7, "c0_watchhi,7" },
203 { 25, 1, "c0_perfcnt,1" },
204 { 25, 2, "c0_perfcnt,2" },
205 { 25, 3, "c0_perfcnt,3" },
206 { 25, 4, "c0_perfcnt,4" },
207 { 25, 5, "c0_perfcnt,5" },
208 { 25, 6, "c0_perfcnt,6" },
209 { 25, 7, "c0_perfcnt,7" },
210 { 27, 1, "c0_cacheerr,1" },
211 { 27, 2, "c0_cacheerr,2" },
212 { 27, 3, "c0_cacheerr,3" },
213 { 28, 1, "c0_datalo" },
214 { 29, 1, "c0_datahi" }
217 static const char * const mips_cp0_names_mips3264r2
[32] =
219 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
220 "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
221 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
222 "c0_status", "c0_cause", "c0_epc", "c0_prid",
223 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
224 "c0_xcontext", "$21", "$22", "c0_debug",
225 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
226 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
229 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2
[] =
231 { 4, 1, "c0_contextconfig" },
232 { 0, 1, "c0_mvpcontrol" },
233 { 0, 2, "c0_mvpconf0" },
234 { 0, 3, "c0_mvpconf1" },
235 { 1, 1, "c0_vpecontrol" },
236 { 1, 2, "c0_vpeconf0" },
237 { 1, 3, "c0_vpeconf1" },
238 { 1, 4, "c0_yqmask" },
239 { 1, 5, "c0_vpeschedule" },
240 { 1, 6, "c0_vpeschefback" },
241 { 2, 1, "c0_tcstatus" },
242 { 2, 2, "c0_tcbind" },
243 { 2, 3, "c0_tcrestart" },
244 { 2, 4, "c0_tchalt" },
245 { 2, 5, "c0_tccontext" },
246 { 2, 6, "c0_tcschedule" },
247 { 2, 7, "c0_tcschefback" },
248 { 5, 1, "c0_pagegrain" },
249 { 6, 1, "c0_srsconf0" },
250 { 6, 2, "c0_srsconf1" },
251 { 6, 3, "c0_srsconf2" },
252 { 6, 4, "c0_srsconf3" },
253 { 6, 5, "c0_srsconf4" },
254 { 12, 1, "c0_intctl" },
255 { 12, 2, "c0_srsctl" },
256 { 12, 3, "c0_srsmap" },
257 { 15, 1, "c0_ebase" },
258 { 16, 1, "c0_config1" },
259 { 16, 2, "c0_config2" },
260 { 16, 3, "c0_config3" },
261 { 18, 1, "c0_watchlo,1" },
262 { 18, 2, "c0_watchlo,2" },
263 { 18, 3, "c0_watchlo,3" },
264 { 18, 4, "c0_watchlo,4" },
265 { 18, 5, "c0_watchlo,5" },
266 { 18, 6, "c0_watchlo,6" },
267 { 18, 7, "c0_watchlo,7" },
268 { 19, 1, "c0_watchhi,1" },
269 { 19, 2, "c0_watchhi,2" },
270 { 19, 3, "c0_watchhi,3" },
271 { 19, 4, "c0_watchhi,4" },
272 { 19, 5, "c0_watchhi,5" },
273 { 19, 6, "c0_watchhi,6" },
274 { 19, 7, "c0_watchhi,7" },
275 { 23, 1, "c0_tracecontrol" },
276 { 23, 2, "c0_tracecontrol2" },
277 { 23, 3, "c0_usertracedata" },
278 { 23, 4, "c0_tracebpc" },
279 { 25, 1, "c0_perfcnt,1" },
280 { 25, 2, "c0_perfcnt,2" },
281 { 25, 3, "c0_perfcnt,3" },
282 { 25, 4, "c0_perfcnt,4" },
283 { 25, 5, "c0_perfcnt,5" },
284 { 25, 6, "c0_perfcnt,6" },
285 { 25, 7, "c0_perfcnt,7" },
286 { 27, 1, "c0_cacheerr,1" },
287 { 27, 2, "c0_cacheerr,2" },
288 { 27, 3, "c0_cacheerr,3" },
289 { 28, 1, "c0_datalo" },
290 { 28, 2, "c0_taglo1" },
291 { 28, 3, "c0_datalo1" },
292 { 28, 4, "c0_taglo2" },
293 { 28, 5, "c0_datalo2" },
294 { 28, 6, "c0_taglo3" },
295 { 28, 7, "c0_datalo3" },
296 { 29, 1, "c0_datahi" },
297 { 29, 2, "c0_taghi1" },
298 { 29, 3, "c0_datahi1" },
299 { 29, 4, "c0_taghi2" },
300 { 29, 5, "c0_datahi2" },
301 { 29, 6, "c0_taghi3" },
302 { 29, 7, "c0_datahi3" },
305 /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
306 static const char * const mips_cp0_names_sb1
[32] =
308 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
309 "c0_context", "c0_pagemask", "c0_wired", "$7",
310 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
311 "c0_status", "c0_cause", "c0_epc", "c0_prid",
312 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
313 "c0_xcontext", "$21", "$22", "c0_debug",
314 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
315 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
318 static const struct mips_cp0sel_name mips_cp0sel_names_sb1
[] =
320 { 16, 1, "c0_config1" },
321 { 18, 1, "c0_watchlo,1" },
322 { 19, 1, "c0_watchhi,1" },
323 { 22, 0, "c0_perftrace" },
324 { 23, 3, "c0_edebug" },
325 { 25, 1, "c0_perfcnt,1" },
326 { 25, 2, "c0_perfcnt,2" },
327 { 25, 3, "c0_perfcnt,3" },
328 { 25, 4, "c0_perfcnt,4" },
329 { 25, 5, "c0_perfcnt,5" },
330 { 25, 6, "c0_perfcnt,6" },
331 { 25, 7, "c0_perfcnt,7" },
332 { 26, 1, "c0_buserr_pa" },
333 { 27, 1, "c0_cacheerr_d" },
334 { 27, 3, "c0_cacheerr_d_pa" },
335 { 28, 1, "c0_datalo_i" },
336 { 28, 2, "c0_taglo_d" },
337 { 28, 3, "c0_datalo_d" },
338 { 29, 1, "c0_datahi_i" },
339 { 29, 2, "c0_taghi_d" },
340 { 29, 3, "c0_datahi_d" },
343 /* Xlr cop0 register names. */
344 static const char * const mips_cp0_names_xlr
[32] = {
345 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
346 "c0_context", "c0_pagemask", "c0_wired", "$7",
347 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
348 "c0_status", "c0_cause", "c0_epc", "c0_prid",
349 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
350 "c0_xcontext", "$21", "$22", "c0_debug",
351 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
352 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
355 /* XLR's CP0 Select Registers. */
357 static const struct mips_cp0sel_name mips_cp0sel_names_xlr
[] = {
358 { 9, 6, "c0_extintreq" },
359 { 9, 7, "c0_extintmask" },
360 { 15, 1, "c0_ebase" },
361 { 16, 1, "c0_config1" },
362 { 16, 2, "c0_config2" },
363 { 16, 3, "c0_config3" },
364 { 16, 7, "c0_procid2" },
365 { 18, 1, "c0_watchlo,1" },
366 { 18, 2, "c0_watchlo,2" },
367 { 18, 3, "c0_watchlo,3" },
368 { 18, 4, "c0_watchlo,4" },
369 { 18, 5, "c0_watchlo,5" },
370 { 18, 6, "c0_watchlo,6" },
371 { 18, 7, "c0_watchlo,7" },
372 { 19, 1, "c0_watchhi,1" },
373 { 19, 2, "c0_watchhi,2" },
374 { 19, 3, "c0_watchhi,3" },
375 { 19, 4, "c0_watchhi,4" },
376 { 19, 5, "c0_watchhi,5" },
377 { 19, 6, "c0_watchhi,6" },
378 { 19, 7, "c0_watchhi,7" },
379 { 25, 1, "c0_perfcnt,1" },
380 { 25, 2, "c0_perfcnt,2" },
381 { 25, 3, "c0_perfcnt,3" },
382 { 25, 4, "c0_perfcnt,4" },
383 { 25, 5, "c0_perfcnt,5" },
384 { 25, 6, "c0_perfcnt,6" },
385 { 25, 7, "c0_perfcnt,7" },
386 { 27, 1, "c0_cacheerr,1" },
387 { 27, 2, "c0_cacheerr,2" },
388 { 27, 3, "c0_cacheerr,3" },
389 { 28, 1, "c0_datalo" },
390 { 29, 1, "c0_datahi" }
393 static const char * const mips_hwr_names_numeric
[32] =
395 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
396 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
397 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
398 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
401 static const char * const mips_hwr_names_mips3264r2
[32] =
403 "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
404 "$4", "$5", "$6", "$7",
405 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
406 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
407 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
410 static const char * const msa_control_names
[32] =
412 "msa_ir", "msa_csr", "msa_access", "msa_save",
413 "msa_modify", "msa_request", "msa_map", "msa_unmap",
414 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
415 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
416 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
419 struct mips_abi_choice
422 const char * const *gpr_names
;
423 const char * const *fpr_names
;
426 struct mips_abi_choice mips_abi_choices
[] =
428 { "numeric", mips_gpr_names_numeric
, mips_fpr_names_numeric
},
429 { "32", mips_gpr_names_oldabi
, mips_fpr_names_32
},
430 { "n32", mips_gpr_names_newabi
, mips_fpr_names_n32
},
431 { "64", mips_gpr_names_newabi
, mips_fpr_names_64
},
434 struct mips_arch_choice
438 unsigned long bfd_mach
;
442 const char * const *cp0_names
;
443 const struct mips_cp0sel_name
*cp0sel_names
;
444 unsigned int cp0sel_names_len
;
445 const char * const *cp1_names
;
446 const char * const *hwr_names
;
449 const struct mips_arch_choice mips_arch_choices
[] =
451 { "numeric", 0, 0, 0, 0, 0,
452 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
453 mips_hwr_names_numeric
},
455 { "r3000", 1, bfd_mach_mips3000
, CPU_R3000
, ISA_MIPS1
, 0,
456 mips_cp0_names_r3000
, NULL
, 0, mips_cp1_names_numeric
,
457 mips_hwr_names_numeric
},
458 { "r3900", 1, bfd_mach_mips3900
, CPU_R3900
, ISA_MIPS1
, 0,
459 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
460 mips_hwr_names_numeric
},
461 { "r4000", 1, bfd_mach_mips4000
, CPU_R4000
, ISA_MIPS3
, 0,
462 mips_cp0_names_r4000
, NULL
, 0, mips_cp1_names_numeric
,
463 mips_hwr_names_numeric
},
464 { "r4010", 1, bfd_mach_mips4010
, CPU_R4010
, ISA_MIPS2
, 0,
465 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
466 mips_hwr_names_numeric
},
467 { "vr4100", 1, bfd_mach_mips4100
, CPU_VR4100
, ISA_MIPS3
, 0,
468 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
469 mips_hwr_names_numeric
},
470 { "vr4111", 1, bfd_mach_mips4111
, CPU_R4111
, ISA_MIPS3
, 0,
471 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
472 mips_hwr_names_numeric
},
473 { "vr4120", 1, bfd_mach_mips4120
, CPU_VR4120
, ISA_MIPS3
, 0,
474 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
475 mips_hwr_names_numeric
},
476 { "r4300", 1, bfd_mach_mips4300
, CPU_R4300
, ISA_MIPS3
, 0,
477 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
478 mips_hwr_names_numeric
},
479 { "r4400", 1, bfd_mach_mips4400
, CPU_R4400
, ISA_MIPS3
, 0,
480 mips_cp0_names_r4000
, NULL
, 0, mips_cp1_names_numeric
,
481 mips_hwr_names_numeric
},
482 { "r4600", 1, bfd_mach_mips4600
, CPU_R4600
, ISA_MIPS3
, 0,
483 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
484 mips_hwr_names_numeric
},
485 { "r4650", 1, bfd_mach_mips4650
, CPU_R4650
, ISA_MIPS3
, 0,
486 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
487 mips_hwr_names_numeric
},
488 { "r5000", 1, bfd_mach_mips5000
, CPU_R5000
, ISA_MIPS4
, 0,
489 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
490 mips_hwr_names_numeric
},
491 { "vr5400", 1, bfd_mach_mips5400
, CPU_VR5400
, ISA_MIPS4
, 0,
492 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
493 mips_hwr_names_numeric
},
494 { "vr5500", 1, bfd_mach_mips5500
, CPU_VR5500
, ISA_MIPS4
, 0,
495 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
496 mips_hwr_names_numeric
},
497 { "r5900", 1, bfd_mach_mips5900
, CPU_R5900
, ISA_MIPS3
, 0,
498 mips_cp0_names_r5900
, NULL
, 0, mips_cp1_names_numeric
,
499 mips_hwr_names_numeric
},
500 { "r6000", 1, bfd_mach_mips6000
, CPU_R6000
, ISA_MIPS2
, 0,
501 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
502 mips_hwr_names_numeric
},
503 { "rm7000", 1, bfd_mach_mips7000
, CPU_RM7000
, ISA_MIPS4
, 0,
504 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
505 mips_hwr_names_numeric
},
506 { "rm9000", 1, bfd_mach_mips7000
, CPU_RM7000
, ISA_MIPS4
, 0,
507 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
508 mips_hwr_names_numeric
},
509 { "r8000", 1, bfd_mach_mips8000
, CPU_R8000
, ISA_MIPS4
, 0,
510 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
511 mips_hwr_names_numeric
},
512 { "r10000", 1, bfd_mach_mips10000
, CPU_R10000
, ISA_MIPS4
, 0,
513 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
514 mips_hwr_names_numeric
},
515 { "r12000", 1, bfd_mach_mips12000
, CPU_R12000
, ISA_MIPS4
, 0,
516 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
517 mips_hwr_names_numeric
},
518 { "r14000", 1, bfd_mach_mips14000
, CPU_R14000
, ISA_MIPS4
, 0,
519 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
520 mips_hwr_names_numeric
},
521 { "r16000", 1, bfd_mach_mips16000
, CPU_R16000
, ISA_MIPS4
, 0,
522 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
523 mips_hwr_names_numeric
},
524 { "mips5", 1, bfd_mach_mips5
, CPU_MIPS5
, ISA_MIPS5
, 0,
525 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
526 mips_hwr_names_numeric
},
528 /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
529 Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
530 _MIPS32 Architecture For Programmers Volume I: Introduction to the
531 MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
533 { "mips32", 1, bfd_mach_mipsisa32
, CPU_MIPS32
,
534 ISA_MIPS32
, ASE_SMARTMIPS
,
535 mips_cp0_names_mips3264
,
536 mips_cp0sel_names_mips3264
, ARRAY_SIZE (mips_cp0sel_names_mips3264
),
537 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
539 { "mips32r2", 1, bfd_mach_mipsisa32r2
, CPU_MIPS32R2
,
541 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
542 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
543 mips_cp0_names_mips3264r2
,
544 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
545 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
547 { "mips32r3", 1, bfd_mach_mipsisa32r3
, CPU_MIPS32R3
,
549 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
550 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
551 mips_cp0_names_mips3264r2
,
552 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
553 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
555 { "mips32r5", 1, bfd_mach_mipsisa32r5
, CPU_MIPS32R5
,
557 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
558 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
559 mips_cp0_names_mips3264r2
,
560 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
561 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
563 { "mips32r6", 1, bfd_mach_mipsisa32r6
, CPU_MIPS32R6
,
565 (ASE_EVA
| ASE_MSA
| ASE_VIRT
| ASE_XPA
| ASE_MCU
| ASE_MT
| ASE_DSP
566 | ASE_DSPR2
| ASE_DSPR3
| ASE_CRC
| ASE_GINV
),
567 mips_cp0_names_mips3264r2
,
568 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
569 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
571 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
572 { "mips64", 1, bfd_mach_mipsisa64
, CPU_MIPS64
,
573 ISA_MIPS64
, ASE_MIPS3D
| ASE_MDMX
,
574 mips_cp0_names_mips3264
,
575 mips_cp0sel_names_mips3264
, ARRAY_SIZE (mips_cp0sel_names_mips3264
),
576 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
578 { "mips64r2", 1, bfd_mach_mipsisa64r2
, CPU_MIPS64R2
,
580 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
581 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
582 mips_cp0_names_mips3264r2
,
583 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
584 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
586 { "mips64r3", 1, bfd_mach_mipsisa64r3
, CPU_MIPS64R3
,
588 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
589 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
590 mips_cp0_names_mips3264r2
,
591 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
592 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
594 { "mips64r5", 1, bfd_mach_mipsisa64r5
, CPU_MIPS64R5
,
596 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
597 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
598 mips_cp0_names_mips3264r2
,
599 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
600 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
602 { "mips64r6", 1, bfd_mach_mipsisa64r6
, CPU_MIPS64R6
,
604 (ASE_EVA
| ASE_MSA
| ASE_MSA64
| ASE_XPA
| ASE_VIRT
| ASE_VIRT64
605 | ASE_MCU
| ASE_MT
| ASE_DSP
| ASE_DSPR2
| ASE_DSPR3
| ASE_CRC
606 | ASE_CRC64
| ASE_GINV
),
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 { "interaptiv-mr2", 1, bfd_mach_mips_interaptiv_mr2
, CPU_INTERAPTIV_MR2
,
613 ASE_MT
| ASE_EVA
| ASE_DSP
| ASE_DSPR2
| ASE_MIPS16E2
| ASE_MIPS16E2_MT
,
614 mips_cp0_names_mips3264r2
,
615 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
616 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
618 { "sb1", 1, bfd_mach_mips_sb1
, CPU_SB1
,
619 ISA_MIPS64
| INSN_SB1
, ASE_MIPS3D
,
621 mips_cp0sel_names_sb1
, ARRAY_SIZE (mips_cp0sel_names_sb1
),
622 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
624 { "loongson2e", 1, bfd_mach_mips_loongson_2e
, CPU_LOONGSON_2E
,
625 ISA_MIPS3
| INSN_LOONGSON_2E
, 0, mips_cp0_names_numeric
,
626 NULL
, 0, mips_cp1_names_numeric
, mips_hwr_names_numeric
},
628 { "loongson2f", 1, bfd_mach_mips_loongson_2f
, CPU_LOONGSON_2F
,
629 ISA_MIPS3
| INSN_LOONGSON_2F
, ASE_LOONGSON_MMI
, mips_cp0_names_numeric
,
630 NULL
, 0, mips_cp1_names_numeric
, mips_hwr_names_numeric
},
632 { "loongson3a", 1, bfd_mach_mips_loongson_3a
, CPU_LOONGSON_3A
,
633 ISA_MIPS64R2
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
| ASE_LOONGSON_EXT
,
634 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips3264
,
635 mips_hwr_names_numeric
},
637 { "octeon", 1, bfd_mach_mips_octeon
, CPU_OCTEON
,
638 ISA_MIPS64R2
| INSN_OCTEON
, 0, mips_cp0_names_numeric
, NULL
, 0,
639 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
641 { "octeon+", 1, bfd_mach_mips_octeonp
, CPU_OCTEONP
,
642 ISA_MIPS64R2
| INSN_OCTEONP
, 0, mips_cp0_names_numeric
,
643 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
645 { "octeon2", 1, bfd_mach_mips_octeon2
, CPU_OCTEON2
,
646 ISA_MIPS64R2
| INSN_OCTEON2
, 0, mips_cp0_names_numeric
,
647 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
649 { "octeon3", 1, bfd_mach_mips_octeon3
, CPU_OCTEON3
,
650 ISA_MIPS64R5
| INSN_OCTEON3
, ASE_VIRT
| ASE_VIRT64
,
651 mips_cp0_names_numeric
,
652 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
654 { "xlr", 1, bfd_mach_mips_xlr
, CPU_XLR
,
655 ISA_MIPS64
| INSN_XLR
, 0,
657 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
658 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
660 /* XLP is mostly like XLR, with the prominent exception it is being
662 { "xlp", 1, bfd_mach_mips_xlr
, CPU_XLR
,
663 ISA_MIPS64R2
| INSN_XLR
, 0,
665 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
666 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
668 /* This entry, mips16, is here only for ISA/processor selection; do
669 not print its name. */
670 { "", 1, bfd_mach_mips16
, CPU_MIPS16
, ISA_MIPS64
,
671 ASE_MIPS16E2
| ASE_MIPS16E2_MT
,
672 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
673 mips_hwr_names_numeric
},
676 /* ISA and processor type to disassemble for, and register names to use.
677 set_default_mips_dis_options and parse_mips_dis_options fill in these
679 static int mips_processor
;
682 static int micromips_ase
;
683 static const char * const *mips_gpr_names
;
684 static const char * const *mips_fpr_names
;
685 static const char * const *mips_cp0_names
;
686 static const struct mips_cp0sel_name
*mips_cp0sel_names
;
687 static int mips_cp0sel_names_len
;
688 static const char * const *mips_cp1_names
;
689 static const char * const *mips_hwr_names
;
692 static int no_aliases
; /* If set disassemble as most general inst. */
694 static const struct mips_abi_choice
*
695 choose_abi_by_name (const char *name
, unsigned int namelen
)
697 const struct mips_abi_choice
*c
;
700 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_abi_choices
) && c
== NULL
; i
++)
701 if (strncmp (mips_abi_choices
[i
].name
, name
, namelen
) == 0
702 && strlen (mips_abi_choices
[i
].name
) == namelen
)
703 c
= &mips_abi_choices
[i
];
708 static const struct mips_arch_choice
*
709 choose_arch_by_name (const char *name
, unsigned int namelen
)
711 const struct mips_arch_choice
*c
= NULL
;
714 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
715 if (strncmp (mips_arch_choices
[i
].name
, name
, namelen
) == 0
716 && strlen (mips_arch_choices
[i
].name
) == namelen
)
717 c
= &mips_arch_choices
[i
];
722 static const struct mips_arch_choice
*
723 choose_arch_by_number (unsigned long mach
)
725 static unsigned long hint_bfd_mach
;
726 static const struct mips_arch_choice
*hint_arch_choice
;
727 const struct mips_arch_choice
*c
;
730 /* We optimize this because even if the user specifies no
731 flags, this will be done for every instruction! */
732 if (hint_bfd_mach
== mach
733 && hint_arch_choice
!= NULL
734 && hint_arch_choice
->bfd_mach
== hint_bfd_mach
)
735 return hint_arch_choice
;
737 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
739 if (mips_arch_choices
[i
].bfd_mach_valid
740 && mips_arch_choices
[i
].bfd_mach
== mach
)
742 c
= &mips_arch_choices
[i
];
743 hint_bfd_mach
= mach
;
744 hint_arch_choice
= c
;
750 /* Check if the object uses NewABI conventions. */
753 is_newabi (Elf_Internal_Ehdr
*header
)
755 /* There are no old-style ABIs which use 64-bit ELF. */
756 if (header
->e_ident
[EI_CLASS
] == ELFCLASS64
)
759 /* If a 32-bit ELF file, n32 is a new-style ABI. */
760 if ((header
->e_flags
& EF_MIPS_ABI2
) != 0)
766 /* Check if the object has microMIPS ASE code. */
769 is_micromips (Elf_Internal_Ehdr
*header
)
771 if ((header
->e_flags
& EF_MIPS_ARCH_ASE_MICROMIPS
) != 0)
777 /* Convert ASE flags from .MIPS.abiflags to internal values. */
780 mips_convert_abiflags_ases (unsigned long afl_ases
)
782 unsigned long opcode_ases
= 0;
784 if (afl_ases
& AFL_ASE_DSP
)
785 opcode_ases
|= ASE_DSP
;
786 if (afl_ases
& AFL_ASE_DSPR2
)
787 opcode_ases
|= ASE_DSPR2
;
788 if (afl_ases
& AFL_ASE_EVA
)
789 opcode_ases
|= ASE_EVA
;
790 if (afl_ases
& AFL_ASE_MCU
)
791 opcode_ases
|= ASE_MCU
;
792 if (afl_ases
& AFL_ASE_MDMX
)
793 opcode_ases
|= ASE_MDMX
;
794 if (afl_ases
& AFL_ASE_MIPS3D
)
795 opcode_ases
|= ASE_MIPS3D
;
796 if (afl_ases
& AFL_ASE_MT
)
797 opcode_ases
|= ASE_MT
;
798 if (afl_ases
& AFL_ASE_SMARTMIPS
)
799 opcode_ases
|= ASE_SMARTMIPS
;
800 if (afl_ases
& AFL_ASE_VIRT
)
801 opcode_ases
|= ASE_VIRT
;
802 if (afl_ases
& AFL_ASE_MSA
)
803 opcode_ases
|= ASE_MSA
;
804 if (afl_ases
& AFL_ASE_XPA
)
805 opcode_ases
|= ASE_XPA
;
806 if (afl_ases
& AFL_ASE_DSPR3
)
807 opcode_ases
|= ASE_DSPR3
;
808 if (afl_ases
& AFL_ASE_MIPS16E2
)
809 opcode_ases
|= ASE_MIPS16E2
;
813 /* Calculate combination ASE flags from regular ASE flags. */
816 mips_calculate_combination_ases (unsigned long opcode_ases
)
818 unsigned long combination_ases
= 0;
820 if ((opcode_ases
& (ASE_XPA
| ASE_VIRT
)) == (ASE_XPA
| ASE_VIRT
))
821 combination_ases
|= ASE_XPA_VIRT
;
822 if ((opcode_ases
& (ASE_MIPS16E2
| ASE_MT
)) == (ASE_MIPS16E2
| ASE_MT
))
823 combination_ases
|= ASE_MIPS16E2_MT
;
824 return combination_ases
;
828 set_default_mips_dis_options (struct disassemble_info
*info
)
830 const struct mips_arch_choice
*chosen_arch
;
832 /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
833 is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
834 CP0 register, and HWR names. */
835 mips_isa
= ISA_MIPS3
;
836 mips_processor
= CPU_R3000
;
839 mips_gpr_names
= mips_gpr_names_oldabi
;
840 mips_fpr_names
= mips_fpr_names_numeric
;
841 mips_cp0_names
= mips_cp0_names_numeric
;
842 mips_cp0sel_names
= NULL
;
843 mips_cp0sel_names_len
= 0;
844 mips_cp1_names
= mips_cp1_names_numeric
;
845 mips_hwr_names
= mips_hwr_names_numeric
;
848 /* Set ISA, architecture, and cp0 register names as best we can. */
849 #if ! SYMTAB_AVAILABLE
850 /* This is running out on a target machine, not in a host tool.
851 FIXME: Where does mips_target_info come from? */
852 target_processor
= mips_target_info
.processor
;
853 mips_isa
= mips_target_info
.isa
;
854 mips_ase
= mips_target_info
.ase
;
856 chosen_arch
= choose_arch_by_number (info
->mach
);
857 if (chosen_arch
!= NULL
)
859 mips_processor
= chosen_arch
->processor
;
860 mips_isa
= chosen_arch
->isa
;
861 mips_ase
= chosen_arch
->ase
;
862 mips_cp0_names
= chosen_arch
->cp0_names
;
863 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
864 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
865 mips_cp1_names
= chosen_arch
->cp1_names
;
866 mips_hwr_names
= chosen_arch
->hwr_names
;
869 /* Update settings according to the ELF file header flags. */
870 if (info
->flavour
== bfd_target_elf_flavour
&& info
->section
!= NULL
)
872 struct bfd
*abfd
= info
->section
->owner
;
873 Elf_Internal_Ehdr
*header
= elf_elfheader (abfd
);
874 Elf_Internal_ABIFlags_v0
*abiflags
= NULL
;
876 /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
877 because we won't then have a MIPS/ELF BFD, however we need
878 to guard against a link error in a `--enable-targets=...'
879 configuration with a 32-bit host where the MIPS target is
880 a secondary, or with MIPS/ECOFF configurations. */
881 #ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
882 abiflags
= bfd_mips_elf_get_abiflags (abfd
);
884 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
885 if (is_newabi (header
))
886 mips_gpr_names
= mips_gpr_names_newabi
;
887 /* If a microMIPS binary, then don't use MIPS16 bindings. */
888 micromips_ase
= is_micromips (header
);
889 /* OR in any extra ASE flags set in ELF file structures. */
891 mips_ase
|= mips_convert_abiflags_ases (abiflags
->ases
);
892 else if (header
->e_flags
& EF_MIPS_ARCH_ASE_MDMX
)
893 mips_ase
|= ASE_MDMX
;
896 mips_ase
|= mips_calculate_combination_ases (mips_ase
);
899 /* Parse an ASE disassembler option and set the corresponding global
900 ASE flag(s). Return TRUE if successful, FALSE otherwise. */
903 parse_mips_ase_option (const char *option
)
905 if (CONST_STRNEQ (option
, "msa"))
908 if ((mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R2
909 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R3
910 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R5
911 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
)
912 mips_ase
|= ASE_MSA64
;
916 if (CONST_STRNEQ (option
, "virt"))
918 mips_ase
|= ASE_VIRT
;
919 if (mips_isa
& ISA_MIPS64R2
920 || mips_isa
& ISA_MIPS64R3
921 || mips_isa
& ISA_MIPS64R5
922 || mips_isa
& ISA_MIPS64R6
)
923 mips_ase
|= ASE_VIRT64
;
927 if (CONST_STRNEQ (option
, "xpa"))
933 if (CONST_STRNEQ (option
, "ginv"))
935 mips_ase
|= ASE_GINV
;
939 if (CONST_STRNEQ (option
, "loongson-mmi"))
941 mips_ase
|= ASE_LOONGSON_MMI
;
945 if (CONST_STRNEQ (option
, "loongson-cam"))
947 mips_ase
|= ASE_LOONGSON_CAM
;
951 if (CONST_STRNEQ (option
, "loongson-ext"))
953 mips_ase
|= ASE_LOONGSON_EXT
;
961 parse_mips_dis_option (const char *option
, unsigned int len
)
963 unsigned int i
, optionlen
, vallen
;
965 const struct mips_abi_choice
*chosen_abi
;
966 const struct mips_arch_choice
*chosen_arch
;
968 /* Try to match options that are simple flags */
969 if (CONST_STRNEQ (option
, "no-aliases"))
975 if (parse_mips_ase_option (option
))
977 mips_ase
|= mips_calculate_combination_ases (mips_ase
);
981 /* Look for the = that delimits the end of the option name. */
982 for (i
= 0; i
< len
; i
++)
983 if (option
[i
] == '=')
986 if (i
== 0) /* Invalid option: no name before '='. */
988 if (i
== len
) /* Invalid option: no '='. */
990 if (i
== (len
- 1)) /* Invalid option: no value after '='. */
994 val
= option
+ (optionlen
+ 1);
995 vallen
= len
- (optionlen
+ 1);
997 if (strncmp ("gpr-names", option
, optionlen
) == 0
998 && strlen ("gpr-names") == optionlen
)
1000 chosen_abi
= choose_abi_by_name (val
, vallen
);
1001 if (chosen_abi
!= NULL
)
1002 mips_gpr_names
= chosen_abi
->gpr_names
;
1006 if (strncmp ("fpr-names", option
, optionlen
) == 0
1007 && strlen ("fpr-names") == optionlen
)
1009 chosen_abi
= choose_abi_by_name (val
, vallen
);
1010 if (chosen_abi
!= NULL
)
1011 mips_fpr_names
= chosen_abi
->fpr_names
;
1015 if (strncmp ("cp0-names", option
, optionlen
) == 0
1016 && strlen ("cp0-names") == optionlen
)
1018 chosen_arch
= choose_arch_by_name (val
, vallen
);
1019 if (chosen_arch
!= NULL
)
1021 mips_cp0_names
= chosen_arch
->cp0_names
;
1022 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1023 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1028 if (strncmp ("cp1-names", option
, optionlen
) == 0
1029 && strlen ("cp1-names") == optionlen
)
1031 chosen_arch
= choose_arch_by_name (val
, vallen
);
1032 if (chosen_arch
!= NULL
)
1033 mips_cp1_names
= chosen_arch
->cp1_names
;
1037 if (strncmp ("hwr-names", option
, optionlen
) == 0
1038 && strlen ("hwr-names") == optionlen
)
1040 chosen_arch
= choose_arch_by_name (val
, vallen
);
1041 if (chosen_arch
!= NULL
)
1042 mips_hwr_names
= chosen_arch
->hwr_names
;
1046 if (strncmp ("reg-names", option
, optionlen
) == 0
1047 && strlen ("reg-names") == optionlen
)
1049 /* We check both ABI and ARCH here unconditionally, so
1050 that "numeric" will do the desirable thing: select
1051 numeric register names for all registers. Other than
1052 that, a given name probably won't match both. */
1053 chosen_abi
= choose_abi_by_name (val
, vallen
);
1054 if (chosen_abi
!= NULL
)
1056 mips_gpr_names
= chosen_abi
->gpr_names
;
1057 mips_fpr_names
= chosen_abi
->fpr_names
;
1059 chosen_arch
= choose_arch_by_name (val
, vallen
);
1060 if (chosen_arch
!= NULL
)
1062 mips_cp0_names
= chosen_arch
->cp0_names
;
1063 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1064 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1065 mips_cp1_names
= chosen_arch
->cp1_names
;
1066 mips_hwr_names
= chosen_arch
->hwr_names
;
1071 /* Invalid option. */
1075 parse_mips_dis_options (const char *options
)
1077 const char *option_end
;
1079 if (options
== NULL
)
1082 while (*options
!= '\0')
1084 /* Skip empty options. */
1085 if (*options
== ',')
1091 /* We know that *options is neither NUL or a comma. */
1092 option_end
= options
+ 1;
1093 while (*option_end
!= ',' && *option_end
!= '\0')
1096 parse_mips_dis_option (options
, option_end
- options
);
1098 /* Go on to the next one. If option_end points to a comma, it
1099 will be skipped above. */
1100 options
= option_end
;
1104 static const struct mips_cp0sel_name
*
1105 lookup_mips_cp0sel_name (const struct mips_cp0sel_name
*names
,
1107 unsigned int cp0reg
,
1112 for (i
= 0; i
< len
; i
++)
1113 if (names
[i
].cp0reg
== cp0reg
&& names
[i
].sel
== sel
)
1118 /* Print register REGNO, of type TYPE, for instruction OPCODE. */
1121 print_reg (struct disassemble_info
*info
, const struct mips_opcode
*opcode
,
1122 enum mips_reg_operand_type type
, int regno
)
1127 info
->fprintf_func (info
->stream
, "%s", mips_gpr_names
[regno
]);
1131 info
->fprintf_func (info
->stream
, "%s", mips_fpr_names
[regno
]);
1135 if (opcode
->pinfo
& (FP_D
| FP_S
))
1136 info
->fprintf_func (info
->stream
, "$fcc%d", regno
);
1138 info
->fprintf_func (info
->stream
, "$cc%d", regno
);
1142 if (opcode
->membership
& INSN_5400
)
1143 info
->fprintf_func (info
->stream
, "$f%d", regno
);
1145 info
->fprintf_func (info
->stream
, "$v%d", regno
);
1149 info
->fprintf_func (info
->stream
, "$ac%d", regno
);
1153 if (opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1154 info
->fprintf_func (info
->stream
, "%s", mips_cp0_names
[regno
]);
1155 else if (opcode
->name
[strlen (opcode
->name
) - 1] == '1')
1156 info
->fprintf_func (info
->stream
, "%s", mips_cp1_names
[regno
]);
1158 info
->fprintf_func (info
->stream
, "$%d", regno
);
1162 info
->fprintf_func (info
->stream
, "%s", mips_hwr_names
[regno
]);
1166 info
->fprintf_func (info
->stream
, "$vf%d", regno
);
1170 info
->fprintf_func (info
->stream
, "$vi%d", regno
);
1173 case OP_REG_R5900_I
:
1174 info
->fprintf_func (info
->stream
, "$I");
1177 case OP_REG_R5900_Q
:
1178 info
->fprintf_func (info
->stream
, "$Q");
1181 case OP_REG_R5900_R
:
1182 info
->fprintf_func (info
->stream
, "$R");
1185 case OP_REG_R5900_ACC
:
1186 info
->fprintf_func (info
->stream
, "$ACC");
1190 info
->fprintf_func (info
->stream
, "$w%d", regno
);
1193 case OP_REG_MSA_CTRL
:
1194 info
->fprintf_func (info
->stream
, "%s", msa_control_names
[regno
]);
1200 /* Used to track the state carried over from previous operands in
1202 struct mips_print_arg_state
{
1203 /* The value of the last OP_INT seen. We only use this for OP_MSB,
1204 where the value is known to be unsigned and small. */
1205 unsigned int last_int
;
1207 /* The type and number of the last OP_REG seen. We only use this for
1208 OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1209 enum mips_reg_operand_type last_reg_type
;
1210 unsigned int last_regno
;
1211 unsigned int dest_regno
;
1212 unsigned int seen_dest
;
1215 /* Initialize STATE for the start of an instruction. */
1218 init_print_arg_state (struct mips_print_arg_state
*state
)
1220 memset (state
, 0, sizeof (*state
));
1223 /* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1224 whose value is given by UVAL. */
1227 print_vu0_channel (struct disassemble_info
*info
,
1228 const struct mips_operand
*operand
, unsigned int uval
)
1230 if (operand
->size
== 4)
1231 info
->fprintf_func (info
->stream
, "%s%s%s%s",
1232 uval
& 8 ? "x" : "",
1233 uval
& 4 ? "y" : "",
1234 uval
& 2 ? "z" : "",
1235 uval
& 1 ? "w" : "");
1236 else if (operand
->size
== 2)
1237 info
->fprintf_func (info
->stream
, "%c", "xyzw"[uval
]);
1242 /* Record information about a register operand. */
1245 mips_seen_register (struct mips_print_arg_state
*state
,
1247 enum mips_reg_operand_type reg_type
)
1249 state
->last_reg_type
= reg_type
;
1250 state
->last_regno
= regno
;
1252 if (!state
->seen_dest
)
1254 state
->seen_dest
= 1;
1255 state
->dest_regno
= regno
;
1259 /* Print SAVE/RESTORE instruction operands according to the argument
1260 register mask AMASK, the number of static registers saved NSREG,
1261 the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1262 and the frame size FRAME_SIZE. */
1265 mips_print_save_restore (struct disassemble_info
*info
, unsigned int amask
,
1266 unsigned int nsreg
, unsigned int ra
,
1267 unsigned int s0
, unsigned int s1
,
1268 unsigned int frame_size
)
1270 const fprintf_ftype infprintf
= info
->fprintf_func
;
1271 unsigned int nargs
, nstatics
, smask
, i
, j
;
1272 void *is
= info
->stream
;
1275 if (amask
== MIPS_SVRS_ALL_ARGS
)
1280 else if (amask
== MIPS_SVRS_ALL_STATICS
)
1288 nstatics
= amask
& 3;
1294 infprintf (is
, "%s", mips_gpr_names
[4]);
1296 infprintf (is
, "-%s", mips_gpr_names
[4 + nargs
- 1]);
1300 infprintf (is
, "%s%d", sep
, frame_size
);
1303 infprintf (is
, ",%s", mips_gpr_names
[31]);
1310 if (nsreg
> 0) /* $s2-$s8 */
1311 smask
|= ((1 << nsreg
) - 1) << 2;
1313 for (i
= 0; i
< 9; i
++)
1314 if (smask
& (1 << i
))
1316 infprintf (is
, ",%s", mips_gpr_names
[i
== 8 ? 30 : (16 + i
)]);
1317 /* Skip over string of set bits. */
1318 for (j
= i
; smask
& (2 << j
); j
++)
1321 infprintf (is
, "-%s", mips_gpr_names
[j
== 8 ? 30 : (16 + j
)]);
1324 /* Statics $ax - $a3. */
1326 infprintf (is
, ",%s", mips_gpr_names
[7]);
1327 else if (nstatics
> 0)
1328 infprintf (is
, ",%s-%s",
1329 mips_gpr_names
[7 - nstatics
+ 1],
1334 /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1335 UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1336 the base address for OP_PCREL operands. */
1339 print_insn_arg (struct disassemble_info
*info
,
1340 struct mips_print_arg_state
*state
,
1341 const struct mips_opcode
*opcode
,
1342 const struct mips_operand
*operand
,
1346 const fprintf_ftype infprintf
= info
->fprintf_func
;
1347 void *is
= info
->stream
;
1349 switch (operand
->type
)
1353 const struct mips_int_operand
*int_op
;
1355 int_op
= (const struct mips_int_operand
*) operand
;
1356 uval
= mips_decode_int_operand (int_op
, uval
);
1357 state
->last_int
= uval
;
1358 if (int_op
->print_hex
)
1359 infprintf (is
, "0x%x", uval
);
1361 infprintf (is
, "%d", uval
);
1367 const struct mips_mapped_int_operand
*mint_op
;
1369 mint_op
= (const struct mips_mapped_int_operand
*) operand
;
1370 uval
= mint_op
->int_map
[uval
];
1371 state
->last_int
= uval
;
1372 if (mint_op
->print_hex
)
1373 infprintf (is
, "0x%x", uval
);
1375 infprintf (is
, "%d", uval
);
1381 const struct mips_msb_operand
*msb_op
;
1383 msb_op
= (const struct mips_msb_operand
*) operand
;
1384 uval
+= msb_op
->bias
;
1385 if (msb_op
->add_lsb
)
1386 uval
-= state
->last_int
;
1387 infprintf (is
, "0x%x", uval
);
1392 case OP_OPTIONAL_REG
:
1394 const struct mips_reg_operand
*reg_op
;
1396 reg_op
= (const struct mips_reg_operand
*) operand
;
1397 uval
= mips_decode_reg_operand (reg_op
, uval
);
1398 print_reg (info
, opcode
, reg_op
->reg_type
, uval
);
1400 mips_seen_register (state
, uval
, reg_op
->reg_type
);
1406 const struct mips_reg_pair_operand
*pair_op
;
1408 pair_op
= (const struct mips_reg_pair_operand
*) operand
;
1409 print_reg (info
, opcode
, pair_op
->reg_type
,
1410 pair_op
->reg1_map
[uval
]);
1411 infprintf (is
, ",");
1412 print_reg (info
, opcode
, pair_op
->reg_type
,
1413 pair_op
->reg2_map
[uval
]);
1419 const struct mips_pcrel_operand
*pcrel_op
;
1421 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1422 info
->target
= mips_decode_pcrel_operand (pcrel_op
, base_pc
, uval
);
1424 /* For jumps and branches clear the ISA bit except for
1425 the GDB disassembler. */
1426 if (pcrel_op
->include_isa_bit
1427 && info
->flavour
!= bfd_target_unknown_flavour
)
1430 (*info
->print_address_func
) (info
->target
, info
);
1435 infprintf (is
, "%d", uval
);
1438 case OP_ADDIUSP_INT
:
1442 sval
= mips_signed_operand (operand
, uval
) * 4;
1443 if (sval
>= -8 && sval
< 8)
1445 infprintf (is
, "%d", sval
);
1449 case OP_CLO_CLZ_DEST
:
1451 unsigned int reg1
, reg2
;
1455 /* If one is zero use the other. */
1456 if (reg1
== reg2
|| reg2
== 0)
1457 infprintf (is
, "%s", mips_gpr_names
[reg1
]);
1459 infprintf (is
, "%s", mips_gpr_names
[reg2
]);
1461 /* Bogus, result depends on processor. */
1462 infprintf (is
, "%s or %s", mips_gpr_names
[reg1
],
1463 mips_gpr_names
[reg2
]);
1469 case OP_NON_ZERO_REG
:
1471 print_reg (info
, opcode
, OP_REG_GP
, uval
& 31);
1472 mips_seen_register (state
, uval
, OP_REG_GP
);
1476 case OP_LWM_SWM_LIST
:
1477 if (operand
->size
== 2)
1480 infprintf (is
, "%s,%s",
1482 mips_gpr_names
[31]);
1484 infprintf (is
, "%s-%s,%s",
1486 mips_gpr_names
[16 + uval
],
1487 mips_gpr_names
[31]);
1493 s_reg_encode
= uval
& 0xf;
1494 if (s_reg_encode
!= 0)
1496 if (s_reg_encode
== 1)
1497 infprintf (is
, "%s", mips_gpr_names
[16]);
1498 else if (s_reg_encode
< 9)
1499 infprintf (is
, "%s-%s",
1501 mips_gpr_names
[15 + s_reg_encode
]);
1502 else if (s_reg_encode
== 9)
1503 infprintf (is
, "%s-%s,%s",
1506 mips_gpr_names
[30]);
1508 infprintf (is
, "UNKNOWN");
1511 if (uval
& 0x10) /* For ra. */
1513 if (s_reg_encode
== 0)
1514 infprintf (is
, "%s", mips_gpr_names
[31]);
1516 infprintf (is
, ",%s", mips_gpr_names
[31]);
1521 case OP_ENTRY_EXIT_LIST
:
1524 unsigned int amask
, smask
;
1527 amask
= (uval
>> 3) & 7;
1528 if (amask
> 0 && amask
< 5)
1530 infprintf (is
, "%s", mips_gpr_names
[4]);
1532 infprintf (is
, "-%s", mips_gpr_names
[amask
+ 3]);
1536 smask
= (uval
>> 1) & 3;
1539 infprintf (is
, "%s??", sep
);
1544 infprintf (is
, "%s%s", sep
, mips_gpr_names
[16]);
1546 infprintf (is
, "-%s", mips_gpr_names
[smask
+ 15]);
1552 infprintf (is
, "%s%s", sep
, mips_gpr_names
[31]);
1556 if (amask
== 5 || amask
== 6)
1558 infprintf (is
, "%s%s", sep
, mips_fpr_names
[0]);
1560 infprintf (is
, "-%s", mips_fpr_names
[1]);
1565 case OP_SAVE_RESTORE_LIST
:
1566 /* Should be handled by the caller due to complex behavior. */
1569 case OP_MDMX_IMM_REG
:
1575 if ((vsel
& 0x10) == 0)
1580 for (fmt
= 0; fmt
< 3; fmt
++, vsel
>>= 1)
1581 if ((vsel
& 1) == 0)
1583 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1584 infprintf (is
, "[%d]", vsel
>> 1);
1586 else if ((vsel
& 0x08) == 0)
1587 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1589 infprintf (is
, "0x%x", uval
);
1593 case OP_REPEAT_PREV_REG
:
1594 print_reg (info
, opcode
, state
->last_reg_type
, state
->last_regno
);
1597 case OP_REPEAT_DEST_REG
:
1598 print_reg (info
, opcode
, state
->last_reg_type
, state
->dest_regno
);
1602 infprintf (is
, "$pc");
1606 print_reg (info
, opcode
, OP_REG_GP
, 28);
1610 case OP_VU0_MATCH_SUFFIX
:
1611 print_vu0_channel (info
, operand
, uval
);
1615 infprintf (is
, "[%d]", uval
);
1619 infprintf (is
, "[");
1620 print_reg (info
, opcode
, OP_REG_GP
, uval
);
1621 infprintf (is
, "]");
1626 /* Validate the arguments for INSN, which is described by OPCODE.
1627 Use DECODE_OPERAND to get the encoding of each operand. */
1630 validate_insn_args (const struct mips_opcode
*opcode
,
1631 const struct mips_operand
*(*decode_operand
) (const char *),
1634 struct mips_print_arg_state state
;
1635 const struct mips_operand
*operand
;
1639 init_print_arg_state (&state
);
1640 for (s
= opcode
->args
; *s
; ++s
)
1654 operand
= decode_operand (s
);
1658 uval
= mips_extract_operand (operand
, insn
);
1659 switch (operand
->type
)
1662 case OP_OPTIONAL_REG
:
1664 const struct mips_reg_operand
*reg_op
;
1666 reg_op
= (const struct mips_reg_operand
*) operand
;
1667 uval
= mips_decode_reg_operand (reg_op
, uval
);
1668 mips_seen_register (&state
, uval
, reg_op
->reg_type
);
1674 unsigned int reg1
, reg2
;
1679 if (reg1
!= reg2
|| reg1
== 0)
1686 const struct mips_check_prev_operand
*prev_op
;
1688 prev_op
= (const struct mips_check_prev_operand
*) operand
;
1690 if (!prev_op
->zero_ok
&& uval
== 0)
1693 if (((prev_op
->less_than_ok
&& uval
< state
.last_regno
)
1694 || (prev_op
->greater_than_ok
&& uval
> state
.last_regno
)
1695 || (prev_op
->equal_ok
&& uval
== state
.last_regno
)))
1701 case OP_NON_ZERO_REG
:
1714 case OP_ADDIUSP_INT
:
1715 case OP_CLO_CLZ_DEST
:
1716 case OP_LWM_SWM_LIST
:
1717 case OP_ENTRY_EXIT_LIST
:
1718 case OP_MDMX_IMM_REG
:
1719 case OP_REPEAT_PREV_REG
:
1720 case OP_REPEAT_DEST_REG
:
1724 case OP_VU0_MATCH_SUFFIX
:
1727 case OP_SAVE_RESTORE_LIST
:
1731 if (*s
== 'm' || *s
== '+' || *s
== '-')
1738 /* Print the arguments for INSN, which is described by OPCODE.
1739 Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
1740 as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1741 operand is for a branch or jump. */
1744 print_insn_args (struct disassemble_info
*info
,
1745 const struct mips_opcode
*opcode
,
1746 const struct mips_operand
*(*decode_operand
) (const char *),
1747 unsigned int insn
, bfd_vma insn_pc
, unsigned int length
)
1749 const fprintf_ftype infprintf
= info
->fprintf_func
;
1750 void *is
= info
->stream
;
1751 struct mips_print_arg_state state
;
1752 const struct mips_operand
*operand
;
1755 init_print_arg_state (&state
);
1756 for (s
= opcode
->args
; *s
; ++s
)
1763 infprintf (is
, "%c", *s
);
1768 infprintf (is
, "%c%c", *s
, *s
);
1772 operand
= decode_operand (s
);
1775 /* xgettext:c-format */
1777 _("# internal error, undefined operand in `%s %s'"),
1778 opcode
->name
, opcode
->args
);
1782 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
1784 /* Handle this case here because of the complex behavior. */
1785 unsigned int amask
= (insn
>> 15) & 0xf;
1786 unsigned int nsreg
= (insn
>> 23) & 0x7;
1787 unsigned int ra
= insn
& 0x1000; /* $ra */
1788 unsigned int s0
= insn
& 0x800; /* $s0 */
1789 unsigned int s1
= insn
& 0x400; /* $s1 */
1790 unsigned int frame_size
= (((insn
>> 15) & 0xf0)
1791 | ((insn
>> 6) & 0x0f)) * 8;
1792 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
,
1795 else if (operand
->type
== OP_REG
1798 && opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1800 /* Coprocessor register 0 with sel field. */
1801 const struct mips_cp0sel_name
*n
;
1802 unsigned int reg
, sel
;
1804 reg
= mips_extract_operand (operand
, insn
);
1806 operand
= decode_operand (s
);
1807 sel
= mips_extract_operand (operand
, insn
);
1809 /* CP0 register including 'sel' code for mftc0, to be
1810 printed textually if known. If not known, print both
1811 CP0 register name and sel numerically since CP0 register
1812 with sel 0 may have a name unrelated to register being
1814 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
1815 mips_cp0sel_names_len
,
1818 infprintf (is
, "%s", n
->name
);
1820 infprintf (is
, "$%d,%d", reg
, sel
);
1824 bfd_vma base_pc
= insn_pc
;
1826 /* Adjust the PC relative base so that branch/jump insns use
1827 the following PC as the base but genuinely PC relative
1828 operands use the current PC. */
1829 if (operand
->type
== OP_PCREL
)
1831 const struct mips_pcrel_operand
*pcrel_op
;
1833 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1834 /* The include_isa_bit flag is sufficient to distinguish
1835 branch/jump from other PC relative operands. */
1836 if (pcrel_op
->include_isa_bit
)
1840 print_insn_arg (info
, &state
, opcode
, operand
, base_pc
,
1841 mips_extract_operand (operand
, insn
));
1843 if (*s
== 'm' || *s
== '+' || *s
== '-')
1850 /* Print the mips instruction at address MEMADDR in debugged memory,
1851 on using INFO. Returns length of the instruction, in bytes, which is
1852 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
1853 this is little-endian code. */
1856 print_insn_mips (bfd_vma memaddr
,
1858 struct disassemble_info
*info
)
1860 #define GET_OP(insn, field) \
1861 (((insn) >> OP_SH_##field) & OP_MASK_##field)
1862 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
1863 const fprintf_ftype infprintf
= info
->fprintf_func
;
1864 const struct mips_opcode
*op
;
1865 static bfd_boolean init
= 0;
1866 void *is
= info
->stream
;
1868 /* Build a hash table to shorten the search time. */
1873 for (i
= 0; i
<= OP_MASK_OP
; i
++)
1875 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1877 if (op
->pinfo
== INSN_MACRO
1878 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
1880 if (i
== GET_OP (op
->match
, OP
))
1891 info
->bytes_per_chunk
= INSNLEN
;
1892 info
->display_endian
= info
->endian
;
1893 info
->insn_info_valid
= 1;
1894 info
->branch_delay_insns
= 0;
1895 info
->data_size
= 0;
1896 info
->insn_type
= dis_nonbranch
;
1900 op
= mips_hash
[GET_OP (word
, OP
)];
1903 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1905 if (op
->pinfo
!= INSN_MACRO
1906 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
1907 && (word
& op
->mask
) == op
->match
)
1909 /* We always disassemble the jalx instruction, except for MIPS r6. */
1910 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
)
1911 && (strcmp (op
->name
, "jalx")
1912 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS32R6
1913 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
))
1916 /* Figure out instruction type and branch delay information. */
1917 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
1919 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
1920 info
->insn_type
= dis_jsr
;
1922 info
->insn_type
= dis_branch
;
1923 info
->branch_delay_insns
= 1;
1925 else if ((op
->pinfo
& (INSN_COND_BRANCH_DELAY
1926 | INSN_COND_BRANCH_LIKELY
)) != 0)
1928 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
1929 info
->insn_type
= dis_condjsr
;
1931 info
->insn_type
= dis_condbranch
;
1932 info
->branch_delay_insns
= 1;
1934 else if ((op
->pinfo
& (INSN_STORE_MEMORY
1935 | INSN_LOAD_MEMORY
)) != 0)
1936 info
->insn_type
= dis_dref
;
1938 if (!validate_insn_args (op
, decode_mips_operand
, word
))
1941 infprintf (is
, "%s", op
->name
);
1942 if (op
->pinfo2
& INSN2_VU0_CHANNEL_SUFFIX
)
1946 infprintf (is
, ".");
1947 uval
= mips_extract_operand (&mips_vu0_channel_mask
, word
);
1948 print_vu0_channel (info
, &mips_vu0_channel_mask
, uval
);
1953 infprintf (is
, "\t");
1954 print_insn_args (info
, op
, decode_mips_operand
, word
,
1964 /* Handle undefined instructions. */
1965 info
->insn_type
= dis_noninsn
;
1966 infprintf (is
, "0x%x", word
);
1970 /* Disassemble an operand for a mips16 instruction. */
1973 print_mips16_insn_arg (struct disassemble_info
*info
,
1974 struct mips_print_arg_state
*state
,
1975 const struct mips_opcode
*opcode
,
1976 char type
, bfd_vma memaddr
,
1977 unsigned insn
, bfd_boolean use_extend
,
1978 unsigned extend
, bfd_boolean is_offset
)
1980 const fprintf_ftype infprintf
= info
->fprintf_func
;
1981 void *is
= info
->stream
;
1982 const struct mips_operand
*operand
, *ext_operand
;
1983 unsigned short ext_size
;
1995 infprintf (is
, "%c", type
);
1999 operand
= decode_mips16_operand (type
, FALSE
);
2002 /* xgettext:c-format */
2003 infprintf (is
, _("# internal error, undefined operand in `%s %s'"),
2004 opcode
->name
, opcode
->args
);
2008 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
2010 /* Handle this case here because of the complex interaction
2011 with the EXTEND opcode. */
2012 unsigned int amask
= extend
& 0xf;
2013 unsigned int nsreg
= (extend
>> 8) & 0x7;
2014 unsigned int ra
= insn
& 0x40; /* $ra */
2015 unsigned int s0
= insn
& 0x20; /* $s0 */
2016 unsigned int s1
= insn
& 0x10; /* $s1 */
2017 unsigned int frame_size
= ((extend
& 0xf0) | (insn
& 0x0f)) * 8;
2018 if (frame_size
== 0 && !use_extend
)
2020 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
, frame_size
);
2024 if (is_offset
&& operand
->type
== OP_INT
)
2026 const struct mips_int_operand
*int_op
;
2028 int_op
= (const struct mips_int_operand
*) operand
;
2029 info
->insn_type
= dis_dref
;
2030 info
->data_size
= 1 << int_op
->shift
;
2036 ext_operand
= decode_mips16_operand (type
, TRUE
);
2037 if (ext_operand
!= operand
2038 || (operand
->type
== OP_INT
&& operand
->lsb
== 0
2039 && mips_opcode_32bit_p (opcode
)))
2041 ext_size
= ext_operand
->size
;
2042 operand
= ext_operand
;
2045 if (operand
->size
== 26)
2046 uval
= ((extend
& 0x1f) << 21) | ((extend
& 0x3e0) << 11) | insn
;
2047 else if (ext_size
== 16 || ext_size
== 9)
2048 uval
= ((extend
& 0x1f) << 11) | (extend
& 0x7e0) | (insn
& 0x1f);
2049 else if (ext_size
== 15)
2050 uval
= ((extend
& 0xf) << 11) | (extend
& 0x7f0) | (insn
& 0xf);
2051 else if (ext_size
== 6)
2052 uval
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
2054 uval
= mips_extract_operand (operand
, (extend
<< 16) | insn
);
2056 uval
&= (1U << ext_size
) - 1;
2058 baseaddr
= memaddr
+ 2;
2059 if (operand
->type
== OP_PCREL
)
2061 const struct mips_pcrel_operand
*pcrel_op
;
2063 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
2064 if (!pcrel_op
->include_isa_bit
&& use_extend
)
2065 baseaddr
= memaddr
- 2;
2066 else if (!pcrel_op
->include_isa_bit
)
2070 /* If this instruction is in the delay slot of a JAL/JALX
2071 instruction, the base address is the address of the
2072 JAL/JALX instruction. If it is in the delay slot of
2073 a JR/JALR instruction, the base address is the address
2074 of the JR/JALR instruction. This test is unreliable:
2075 we have no way of knowing whether the previous word is
2076 instruction or data. */
2077 if (info
->read_memory_func (memaddr
- 4, buffer
, 2, info
) == 0
2078 && (((info
->endian
== BFD_ENDIAN_BIG
2079 ? bfd_getb16 (buffer
)
2080 : bfd_getl16 (buffer
))
2081 & 0xf800) == 0x1800))
2082 baseaddr
= memaddr
- 4;
2083 else if (info
->read_memory_func (memaddr
- 2, buffer
, 2,
2085 && (((info
->endian
== BFD_ENDIAN_BIG
2086 ? bfd_getb16 (buffer
)
2087 : bfd_getl16 (buffer
))
2088 & 0xf89f) == 0xe800)
2089 && (((info
->endian
== BFD_ENDIAN_BIG
2090 ? bfd_getb16 (buffer
)
2091 : bfd_getl16 (buffer
))
2092 & 0x0060) != 0x0060))
2093 baseaddr
= memaddr
- 2;
2099 print_insn_arg (info
, state
, opcode
, operand
, baseaddr
+ 1, uval
);
2105 /* Check if the given address is the last word of a MIPS16 PLT entry.
2106 This word is data and depending on the value it may interfere with
2107 disassembly of further PLT entries. We make use of the fact PLT
2108 symbols are marked BSF_SYNTHETIC. */
2110 is_mips16_plt_tail (struct disassemble_info
*info
, bfd_vma addr
)
2114 && (info
->symbols
[0]->flags
& BSF_SYNTHETIC
)
2115 && addr
== bfd_asymbol_value (info
->symbols
[0]) + 12)
2121 /* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2130 /* Disassemble mips16 instructions. */
2133 print_insn_mips16 (bfd_vma memaddr
, struct disassemble_info
*info
)
2135 const fprintf_ftype infprintf
= info
->fprintf_func
;
2138 const struct mips_opcode
*op
, *opend
;
2139 struct mips_print_arg_state state
;
2140 void *is
= info
->stream
;
2141 bfd_boolean have_second
;
2142 bfd_boolean extend_only
;
2143 unsigned int second
;
2147 info
->bytes_per_chunk
= 2;
2148 info
->display_endian
= info
->endian
;
2149 info
->insn_info_valid
= 1;
2150 info
->branch_delay_insns
= 0;
2151 info
->data_size
= 0;
2155 #define GET_OP(insn, field) \
2156 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
2157 /* Decode PLT entry's GOT slot address word. */
2158 if (is_mips16_plt_tail (info
, memaddr
))
2160 info
->insn_type
= dis_noninsn
;
2161 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
2164 unsigned int gotslot
;
2166 if (info
->endian
== BFD_ENDIAN_BIG
)
2167 gotslot
= bfd_getb32 (buffer
);
2169 gotslot
= bfd_getl32 (buffer
);
2170 infprintf (is
, ".word\t0x%x", gotslot
);
2177 info
->insn_type
= dis_nonbranch
;
2178 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2182 (*info
->memory_error_func
) (status
, memaddr
, info
);
2186 extend_only
= FALSE
;
2188 if (info
->endian
== BFD_ENDIAN_BIG
)
2189 first
= bfd_getb16 (buffer
);
2191 first
= bfd_getl16 (buffer
);
2193 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2197 if (info
->endian
== BFD_ENDIAN_BIG
)
2198 second
= bfd_getb16 (buffer
);
2200 second
= bfd_getl16 (buffer
);
2201 full
= (first
<< 16) | second
;
2205 have_second
= FALSE
;
2210 /* FIXME: Should probably use a hash table on the major opcode here. */
2212 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
2213 for (op
= mips16_opcodes
; op
< opend
; op
++)
2215 enum match_kind match
;
2217 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
))
2220 if (op
->pinfo
== INSN_MACRO
2221 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
2223 else if (mips_opcode_32bit_p (op
))
2226 && (full
& op
->mask
) == op
->match
)
2231 else if ((first
& op
->mask
) == op
->match
)
2233 match
= MATCH_SHORT
;
2237 else if ((first
& 0xf800) == 0xf000
2240 && (second
& op
->mask
) == op
->match
)
2242 if (op
->pinfo2
& INSN2_SHORT_ONLY
)
2253 if (match
!= MATCH_NONE
)
2257 infprintf (is
, "%s", op
->name
);
2258 if (op
->args
[0] != '\0')
2259 infprintf (is
, "\t");
2261 init_print_arg_state (&state
);
2262 for (s
= op
->args
; *s
!= '\0'; s
++)
2266 && GET_OP (full
, RX
) == GET_OP (full
, RY
))
2268 /* Skip the register and the comma. */
2274 && GET_OP (full
, RZ
) == GET_OP (full
, RX
))
2276 /* Skip the register and the comma. */
2283 && op
->name
[strlen (op
->name
) - 1] == '0')
2285 /* Coprocessor register 0 with sel field. */
2286 const struct mips_cp0sel_name
*n
;
2287 const struct mips_operand
*operand
;
2288 unsigned int reg
, sel
;
2290 operand
= decode_mips16_operand (*s
, TRUE
);
2291 reg
= mips_extract_operand (operand
, (first
<< 16) | second
);
2293 operand
= decode_mips16_operand (*s
, TRUE
);
2294 sel
= mips_extract_operand (operand
, (first
<< 16) | second
);
2296 /* CP0 register including 'sel' code for mftc0, to be
2297 printed textually if known. If not known, print both
2298 CP0 register name and sel numerically since CP0 register
2299 with sel 0 may have a name unrelated to register being
2301 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
2302 mips_cp0sel_names_len
,
2305 infprintf (is
, "%s", n
->name
);
2307 infprintf (is
, "$%d,%d", reg
, sel
);
2313 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
+ 2,
2314 second
, TRUE
, first
, s
[1] == '(');
2317 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
,
2318 first
, FALSE
, 0, s
[1] == '(');
2320 case MATCH_NONE
: /* Stop the compiler complaining. */
2325 /* Figure out branch instruction type and delay slot information. */
2326 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
2327 info
->branch_delay_insns
= 1;
2328 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0
2329 || (op
->pinfo2
& INSN2_UNCOND_BRANCH
) != 0)
2331 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2332 info
->insn_type
= dis_jsr
;
2334 info
->insn_type
= dis_branch
;
2336 else if ((op
->pinfo2
& INSN2_COND_BRANCH
) != 0)
2337 info
->insn_type
= dis_condbranch
;
2339 return match
== MATCH_FULL
? 4 : 2;
2344 infprintf (is
, "0x%x", first
);
2345 info
->insn_type
= dis_noninsn
;
2350 /* Disassemble microMIPS instructions. */
2353 print_insn_micromips (bfd_vma memaddr
, struct disassemble_info
*info
)
2355 const fprintf_ftype infprintf
= info
->fprintf_func
;
2356 const struct mips_opcode
*op
, *opend
;
2357 void *is
= info
->stream
;
2359 unsigned int higher
;
2360 unsigned int length
;
2364 info
->bytes_per_chunk
= 2;
2365 info
->display_endian
= info
->endian
;
2366 info
->insn_info_valid
= 1;
2367 info
->branch_delay_insns
= 0;
2368 info
->data_size
= 0;
2369 info
->insn_type
= dis_nonbranch
;
2373 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2376 (*info
->memory_error_func
) (status
, memaddr
, info
);
2382 if (info
->endian
== BFD_ENDIAN_BIG
)
2383 insn
= bfd_getb16 (buffer
);
2385 insn
= bfd_getl16 (buffer
);
2387 if ((insn
& 0x1c00) == 0x0000 || (insn
& 0x1000) == 0x1000)
2389 /* This is a 32-bit microMIPS instruction. */
2392 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2395 infprintf (is
, "micromips 0x%x", higher
);
2396 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
2400 if (info
->endian
== BFD_ENDIAN_BIG
)
2401 insn
= bfd_getb16 (buffer
);
2403 insn
= bfd_getl16 (buffer
);
2405 insn
= insn
| (higher
<< 16);
2410 /* FIXME: Should probably use a hash table on the major opcode here. */
2412 opend
= micromips_opcodes
+ bfd_micromips_num_opcodes
;
2413 for (op
= micromips_opcodes
; op
< opend
; op
++)
2415 if (op
->pinfo
!= INSN_MACRO
2416 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
2417 && (insn
& op
->mask
) == op
->match
2418 && ((length
== 2 && (op
->mask
& 0xffff0000) == 0)
2419 || (length
== 4 && (op
->mask
& 0xffff0000) != 0)))
2421 if (!validate_insn_args (op
, decode_micromips_operand
, insn
))
2424 infprintf (is
, "%s", op
->name
);
2428 infprintf (is
, "\t");
2429 print_insn_args (info
, op
, decode_micromips_operand
, insn
,
2430 memaddr
+ 1, length
);
2433 /* Figure out instruction type and branch delay information. */
2435 & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
)) != 0)
2436 info
->branch_delay_insns
= 1;
2437 if (((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
2438 | (op
->pinfo2
& INSN2_UNCOND_BRANCH
)) != 0)
2440 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
2441 info
->insn_type
= dis_jsr
;
2443 info
->insn_type
= dis_branch
;
2445 else if (((op
->pinfo
& INSN_COND_BRANCH_DELAY
)
2446 | (op
->pinfo2
& INSN2_COND_BRANCH
)) != 0)
2448 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2449 info
->insn_type
= dis_condjsr
;
2451 info
->insn_type
= dis_condbranch
;
2454 & (INSN_STORE_MEMORY
| INSN_LOAD_MEMORY
)) != 0)
2455 info
->insn_type
= dis_dref
;
2461 infprintf (is
, "0x%x", insn
);
2462 info
->insn_type
= dis_noninsn
;
2467 /* Return 1 if a symbol associated with the location being disassembled
2468 indicates a compressed mode, either MIPS16 or microMIPS, according to
2469 MICROMIPS_P. We iterate over all the symbols at the address being
2470 considered assuming if at least one of them indicates code compression,
2471 then such code has been genuinely produced here (other symbols could
2472 have been derived from function symbols defined elsewhere or could
2473 define data). Otherwise, return 0. */
2476 is_compressed_mode_p (struct disassemble_info
*info
, bfd_boolean micromips_p
)
2481 for (i
= info
->symtab_pos
, l
= i
+ info
->num_symbols
; i
< l
; i
++)
2482 if (((info
->symtab
[i
])->flags
& BSF_SYNTHETIC
) != 0
2484 && ELF_ST_IS_MIPS16 ((*info
->symbols
)->udata
.i
))
2486 && ELF_ST_IS_MICROMIPS ((*info
->symbols
)->udata
.i
))))
2488 else if (bfd_asymbol_flavour (info
->symtab
[i
]) == bfd_target_elf_flavour
2489 && info
->symtab
[i
]->section
== info
->section
)
2491 elf_symbol_type
*symbol
= (elf_symbol_type
*) info
->symtab
[i
];
2493 && ELF_ST_IS_MIPS16 (symbol
->internal_elf_sym
.st_other
))
2495 && ELF_ST_IS_MICROMIPS (symbol
->internal_elf_sym
.st_other
)))
2502 /* In an environment where we do not know the symbol type of the
2503 instruction we are forced to assume that the low order bit of the
2504 instructions' address may mark it as a mips16 instruction. If we
2505 are single stepping, or the pc is within the disassembled function,
2506 this works. Otherwise, we need a clue. Sometimes. */
2509 _print_insn_mips (bfd_vma memaddr
,
2510 struct disassemble_info
*info
,
2511 enum bfd_endian endianness
)
2513 bfd_byte buffer
[INSNLEN
];
2516 set_default_mips_dis_options (info
);
2517 parse_mips_dis_options (info
->disassembler_options
);
2519 if (info
->mach
== bfd_mach_mips16
)
2520 return print_insn_mips16 (memaddr
, info
);
2521 if (info
->mach
== bfd_mach_mips_micromips
)
2522 return print_insn_micromips (memaddr
, info
);
2525 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
2526 /* Only a few tools will work this way. */
2530 return print_insn_micromips (memaddr
, info
);
2532 return print_insn_mips16 (memaddr
, info
);
2536 #if SYMTAB_AVAILABLE
2537 if (is_compressed_mode_p (info
, TRUE
))
2538 return print_insn_micromips (memaddr
, info
);
2539 if (is_compressed_mode_p (info
, FALSE
))
2540 return print_insn_mips16 (memaddr
, info
);
2543 status
= (*info
->read_memory_func
) (memaddr
, buffer
, INSNLEN
, info
);
2548 if (endianness
== BFD_ENDIAN_BIG
)
2549 insn
= bfd_getb32 (buffer
);
2551 insn
= bfd_getl32 (buffer
);
2553 return print_insn_mips (memaddr
, insn
, info
);
2557 (*info
->memory_error_func
) (status
, memaddr
, info
);
2563 print_insn_big_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2565 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_BIG
);
2569 print_insn_little_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2571 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_LITTLE
);
2574 /* Indices into option argument vector for options accepting an argument.
2575 Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2578 MIPS_OPTION_ARG_NONE
= -1,
2579 MIPS_OPTION_ARG_ABI
,
2580 MIPS_OPTION_ARG_ARCH
,
2581 MIPS_OPTION_ARG_SIZE
2582 } mips_option_arg_t
;
2584 /* Valid MIPS disassembler options. */
2588 const char *description
;
2589 mips_option_arg_t arg
;
2592 { "no-aliases", N_("Use canonical instruction forms.\n"),
2593 MIPS_OPTION_ARG_NONE
},
2594 { "msa", N_("Recognize MSA instructions.\n"),
2595 MIPS_OPTION_ARG_NONE
},
2596 { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2597 MIPS_OPTION_ARG_NONE
},
2598 { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2600 MIPS_OPTION_ARG_NONE
},
2601 { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2603 MIPS_OPTION_ARG_NONE
},
2605 N_("Recognize the Loongson MultiMedia extensions "
2606 "Instructions (MMI) ASE instructions.\n"),
2607 MIPS_OPTION_ARG_NONE
},
2609 N_("Recognize the Loongson Content Address Memory (CAM) "
2610 " instructions.\n"),
2611 MIPS_OPTION_ARG_NONE
},
2613 N_("Recognize the Loongson EXTensions (EXT) "
2614 " instructions.\n"),
2615 MIPS_OPTION_ARG_NONE
},
2616 { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2617 Default: based on binary being disassembled.\n"),
2618 MIPS_OPTION_ARG_ABI
},
2619 { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2620 Default: numeric.\n"),
2621 MIPS_OPTION_ARG_ABI
},
2622 { "cp0-names=", N_("Print CP0 register names according to specified "
2624 Default: based on binary being disassembled.\n"),
2625 MIPS_OPTION_ARG_ARCH
},
2626 { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2627 Default: based on binary being disassembled.\n"),
2628 MIPS_OPTION_ARG_ARCH
},
2629 { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2630 MIPS_OPTION_ARG_ABI
},
2631 { "reg-names=", N_("Print CP0 register and HWR names according to "
2634 MIPS_OPTION_ARG_ARCH
}
2637 /* Build the structure representing valid MIPS disassembler options.
2638 This is done dynamically for maintenance ease purpose; a static
2639 initializer would be unreadable. */
2641 const disasm_options_and_args_t
*
2642 disassembler_options_mips (void)
2644 static disasm_options_and_args_t
*opts_and_args
;
2646 if (opts_and_args
== NULL
)
2648 size_t num_options
= ARRAY_SIZE (mips_options
);
2649 size_t num_args
= MIPS_OPTION_ARG_SIZE
;
2650 disasm_option_arg_t
*args
;
2651 disasm_options_t
*opts
;
2655 args
= XNEWVEC (disasm_option_arg_t
, num_args
+ 1);
2657 args
[MIPS_OPTION_ARG_ABI
].name
= "ABI";
2658 args
[MIPS_OPTION_ARG_ABI
].values
2659 = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices
) + 1);
2660 for (i
= 0; i
< ARRAY_SIZE (mips_abi_choices
); i
++)
2661 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = mips_abi_choices
[i
].name
;
2662 /* The array we return must be NULL terminated. */
2663 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = NULL
;
2665 args
[MIPS_OPTION_ARG_ARCH
].name
= "ARCH";
2666 args
[MIPS_OPTION_ARG_ARCH
].values
2667 = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices
) + 1);
2668 for (i
= 0, j
= 0; i
< ARRAY_SIZE (mips_arch_choices
); i
++)
2669 if (*mips_arch_choices
[i
].name
!= '\0')
2670 args
[MIPS_OPTION_ARG_ARCH
].values
[j
++] = mips_arch_choices
[i
].name
;
2671 /* The array we return must be NULL terminated. */
2672 args
[MIPS_OPTION_ARG_ARCH
].values
[j
] = NULL
;
2674 /* The array we return must be NULL terminated. */
2675 args
[MIPS_OPTION_ARG_SIZE
].name
= NULL
;
2676 args
[MIPS_OPTION_ARG_SIZE
].values
= NULL
;
2678 opts_and_args
= XNEW (disasm_options_and_args_t
);
2679 opts_and_args
->args
= args
;
2681 opts
= &opts_and_args
->options
;
2682 opts
->name
= XNEWVEC (const char *, num_options
+ 1);
2683 opts
->description
= XNEWVEC (const char *, num_options
+ 1);
2684 opts
->arg
= XNEWVEC (const disasm_option_arg_t
*, num_options
+ 1);
2685 for (i
= 0; i
< num_options
; i
++)
2687 opts
->name
[i
] = mips_options
[i
].name
;
2688 opts
->description
[i
] = _(mips_options
[i
].description
);
2689 if (mips_options
[i
].arg
!= MIPS_OPTION_ARG_NONE
)
2690 opts
->arg
[i
] = &args
[mips_options
[i
].arg
];
2692 opts
->arg
[i
] = NULL
;
2694 /* The array we return must be NULL terminated. */
2695 opts
->name
[i
] = NULL
;
2696 opts
->description
[i
] = NULL
;
2697 opts
->arg
[i
] = NULL
;
2700 return opts_and_args
;
2704 print_mips_disassembler_options (FILE *stream
)
2706 const disasm_options_and_args_t
*opts_and_args
;
2707 const disasm_option_arg_t
*args
;
2708 const disasm_options_t
*opts
;
2713 opts_and_args
= disassembler_options_mips ();
2714 opts
= &opts_and_args
->options
;
2715 args
= opts_and_args
->args
;
2717 fprintf (stream
, _("\n\
2718 The following MIPS specific disassembler options are supported for use\n\
2719 with the -M switch (multiple options should be separated by commas):\n\n"));
2721 /* Compute the length of the longest option name. */
2722 for (i
= 0; opts
->name
[i
] != NULL
; i
++)
2724 size_t len
= strlen (opts
->name
[i
]);
2726 if (opts
->arg
[i
] != NULL
)
2727 len
+= strlen (opts
->arg
[i
]->name
);
2732 for (i
= 0, max_len
++; opts
->name
[i
] != NULL
; i
++)
2734 fprintf (stream
, " %s", opts
->name
[i
]);
2735 if (opts
->arg
[i
] != NULL
)
2736 fprintf (stream
, "%s", opts
->arg
[i
]->name
);
2737 if (opts
->description
[i
] != NULL
)
2739 size_t len
= strlen (opts
->name
[i
]);
2741 if (opts
->arg
[i
] != NULL
)
2742 len
+= strlen (opts
->arg
[i
]->name
);
2744 "%*c %s", (int) (max_len
- len
), ' ', opts
->description
[i
]);
2746 fprintf (stream
, _("\n"));
2749 for (i
= 0; args
[i
].name
!= NULL
; i
++)
2751 fprintf (stream
, _("\n\
2752 For the options above, the following values are supported for \"%s\":\n "),
2754 for (j
= 0; args
[i
].values
[j
] != NULL
; j
++)
2755 fprintf (stream
, " %s", args
[i
].values
[j
]);
2756 fprintf (stream
, _("\n"));
2759 fprintf (stream
, _("\n"));