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
| INSN_LOONGSON_3A
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
,
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
;
955 parse_mips_dis_option (const char *option
, unsigned int len
)
957 unsigned int i
, optionlen
, vallen
;
959 const struct mips_abi_choice
*chosen_abi
;
960 const struct mips_arch_choice
*chosen_arch
;
962 /* Try to match options that are simple flags */
963 if (CONST_STRNEQ (option
, "no-aliases"))
969 if (parse_mips_ase_option (option
))
971 mips_ase
|= mips_calculate_combination_ases (mips_ase
);
975 /* Look for the = that delimits the end of the option name. */
976 for (i
= 0; i
< len
; i
++)
977 if (option
[i
] == '=')
980 if (i
== 0) /* Invalid option: no name before '='. */
982 if (i
== len
) /* Invalid option: no '='. */
984 if (i
== (len
- 1)) /* Invalid option: no value after '='. */
988 val
= option
+ (optionlen
+ 1);
989 vallen
= len
- (optionlen
+ 1);
991 if (strncmp ("gpr-names", option
, optionlen
) == 0
992 && strlen ("gpr-names") == optionlen
)
994 chosen_abi
= choose_abi_by_name (val
, vallen
);
995 if (chosen_abi
!= NULL
)
996 mips_gpr_names
= chosen_abi
->gpr_names
;
1000 if (strncmp ("fpr-names", option
, optionlen
) == 0
1001 && strlen ("fpr-names") == optionlen
)
1003 chosen_abi
= choose_abi_by_name (val
, vallen
);
1004 if (chosen_abi
!= NULL
)
1005 mips_fpr_names
= chosen_abi
->fpr_names
;
1009 if (strncmp ("cp0-names", option
, optionlen
) == 0
1010 && strlen ("cp0-names") == optionlen
)
1012 chosen_arch
= choose_arch_by_name (val
, vallen
);
1013 if (chosen_arch
!= NULL
)
1015 mips_cp0_names
= chosen_arch
->cp0_names
;
1016 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1017 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1022 if (strncmp ("cp1-names", option
, optionlen
) == 0
1023 && strlen ("cp1-names") == optionlen
)
1025 chosen_arch
= choose_arch_by_name (val
, vallen
);
1026 if (chosen_arch
!= NULL
)
1027 mips_cp1_names
= chosen_arch
->cp1_names
;
1031 if (strncmp ("hwr-names", option
, optionlen
) == 0
1032 && strlen ("hwr-names") == optionlen
)
1034 chosen_arch
= choose_arch_by_name (val
, vallen
);
1035 if (chosen_arch
!= NULL
)
1036 mips_hwr_names
= chosen_arch
->hwr_names
;
1040 if (strncmp ("reg-names", option
, optionlen
) == 0
1041 && strlen ("reg-names") == optionlen
)
1043 /* We check both ABI and ARCH here unconditionally, so
1044 that "numeric" will do the desirable thing: select
1045 numeric register names for all registers. Other than
1046 that, a given name probably won't match both. */
1047 chosen_abi
= choose_abi_by_name (val
, vallen
);
1048 if (chosen_abi
!= NULL
)
1050 mips_gpr_names
= chosen_abi
->gpr_names
;
1051 mips_fpr_names
= chosen_abi
->fpr_names
;
1053 chosen_arch
= choose_arch_by_name (val
, vallen
);
1054 if (chosen_arch
!= NULL
)
1056 mips_cp0_names
= chosen_arch
->cp0_names
;
1057 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1058 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1059 mips_cp1_names
= chosen_arch
->cp1_names
;
1060 mips_hwr_names
= chosen_arch
->hwr_names
;
1065 /* Invalid option. */
1069 parse_mips_dis_options (const char *options
)
1071 const char *option_end
;
1073 if (options
== NULL
)
1076 while (*options
!= '\0')
1078 /* Skip empty options. */
1079 if (*options
== ',')
1085 /* We know that *options is neither NUL or a comma. */
1086 option_end
= options
+ 1;
1087 while (*option_end
!= ',' && *option_end
!= '\0')
1090 parse_mips_dis_option (options
, option_end
- options
);
1092 /* Go on to the next one. If option_end points to a comma, it
1093 will be skipped above. */
1094 options
= option_end
;
1098 static const struct mips_cp0sel_name
*
1099 lookup_mips_cp0sel_name (const struct mips_cp0sel_name
*names
,
1101 unsigned int cp0reg
,
1106 for (i
= 0; i
< len
; i
++)
1107 if (names
[i
].cp0reg
== cp0reg
&& names
[i
].sel
== sel
)
1112 /* Print register REGNO, of type TYPE, for instruction OPCODE. */
1115 print_reg (struct disassemble_info
*info
, const struct mips_opcode
*opcode
,
1116 enum mips_reg_operand_type type
, int regno
)
1121 info
->fprintf_func (info
->stream
, "%s", mips_gpr_names
[regno
]);
1125 info
->fprintf_func (info
->stream
, "%s", mips_fpr_names
[regno
]);
1129 if (opcode
->pinfo
& (FP_D
| FP_S
))
1130 info
->fprintf_func (info
->stream
, "$fcc%d", regno
);
1132 info
->fprintf_func (info
->stream
, "$cc%d", regno
);
1136 if (opcode
->membership
& INSN_5400
)
1137 info
->fprintf_func (info
->stream
, "$f%d", regno
);
1139 info
->fprintf_func (info
->stream
, "$v%d", regno
);
1143 info
->fprintf_func (info
->stream
, "$ac%d", regno
);
1147 if (opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1148 info
->fprintf_func (info
->stream
, "%s", mips_cp0_names
[regno
]);
1149 else if (opcode
->name
[strlen (opcode
->name
) - 1] == '1')
1150 info
->fprintf_func (info
->stream
, "%s", mips_cp1_names
[regno
]);
1152 info
->fprintf_func (info
->stream
, "$%d", regno
);
1156 info
->fprintf_func (info
->stream
, "%s", mips_hwr_names
[regno
]);
1160 info
->fprintf_func (info
->stream
, "$vf%d", regno
);
1164 info
->fprintf_func (info
->stream
, "$vi%d", regno
);
1167 case OP_REG_R5900_I
:
1168 info
->fprintf_func (info
->stream
, "$I");
1171 case OP_REG_R5900_Q
:
1172 info
->fprintf_func (info
->stream
, "$Q");
1175 case OP_REG_R5900_R
:
1176 info
->fprintf_func (info
->stream
, "$R");
1179 case OP_REG_R5900_ACC
:
1180 info
->fprintf_func (info
->stream
, "$ACC");
1184 info
->fprintf_func (info
->stream
, "$w%d", regno
);
1187 case OP_REG_MSA_CTRL
:
1188 info
->fprintf_func (info
->stream
, "%s", msa_control_names
[regno
]);
1194 /* Used to track the state carried over from previous operands in
1196 struct mips_print_arg_state
{
1197 /* The value of the last OP_INT seen. We only use this for OP_MSB,
1198 where the value is known to be unsigned and small. */
1199 unsigned int last_int
;
1201 /* The type and number of the last OP_REG seen. We only use this for
1202 OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1203 enum mips_reg_operand_type last_reg_type
;
1204 unsigned int last_regno
;
1205 unsigned int dest_regno
;
1206 unsigned int seen_dest
;
1209 /* Initialize STATE for the start of an instruction. */
1212 init_print_arg_state (struct mips_print_arg_state
*state
)
1214 memset (state
, 0, sizeof (*state
));
1217 /* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1218 whose value is given by UVAL. */
1221 print_vu0_channel (struct disassemble_info
*info
,
1222 const struct mips_operand
*operand
, unsigned int uval
)
1224 if (operand
->size
== 4)
1225 info
->fprintf_func (info
->stream
, "%s%s%s%s",
1226 uval
& 8 ? "x" : "",
1227 uval
& 4 ? "y" : "",
1228 uval
& 2 ? "z" : "",
1229 uval
& 1 ? "w" : "");
1230 else if (operand
->size
== 2)
1231 info
->fprintf_func (info
->stream
, "%c", "xyzw"[uval
]);
1236 /* Record information about a register operand. */
1239 mips_seen_register (struct mips_print_arg_state
*state
,
1241 enum mips_reg_operand_type reg_type
)
1243 state
->last_reg_type
= reg_type
;
1244 state
->last_regno
= regno
;
1246 if (!state
->seen_dest
)
1248 state
->seen_dest
= 1;
1249 state
->dest_regno
= regno
;
1253 /* Print SAVE/RESTORE instruction operands according to the argument
1254 register mask AMASK, the number of static registers saved NSREG,
1255 the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1256 and the frame size FRAME_SIZE. */
1259 mips_print_save_restore (struct disassemble_info
*info
, unsigned int amask
,
1260 unsigned int nsreg
, unsigned int ra
,
1261 unsigned int s0
, unsigned int s1
,
1262 unsigned int frame_size
)
1264 const fprintf_ftype infprintf
= info
->fprintf_func
;
1265 unsigned int nargs
, nstatics
, smask
, i
, j
;
1266 void *is
= info
->stream
;
1269 if (amask
== MIPS_SVRS_ALL_ARGS
)
1274 else if (amask
== MIPS_SVRS_ALL_STATICS
)
1282 nstatics
= amask
& 3;
1288 infprintf (is
, "%s", mips_gpr_names
[4]);
1290 infprintf (is
, "-%s", mips_gpr_names
[4 + nargs
- 1]);
1294 infprintf (is
, "%s%d", sep
, frame_size
);
1297 infprintf (is
, ",%s", mips_gpr_names
[31]);
1304 if (nsreg
> 0) /* $s2-$s8 */
1305 smask
|= ((1 << nsreg
) - 1) << 2;
1307 for (i
= 0; i
< 9; i
++)
1308 if (smask
& (1 << i
))
1310 infprintf (is
, ",%s", mips_gpr_names
[i
== 8 ? 30 : (16 + i
)]);
1311 /* Skip over string of set bits. */
1312 for (j
= i
; smask
& (2 << j
); j
++)
1315 infprintf (is
, "-%s", mips_gpr_names
[j
== 8 ? 30 : (16 + j
)]);
1318 /* Statics $ax - $a3. */
1320 infprintf (is
, ",%s", mips_gpr_names
[7]);
1321 else if (nstatics
> 0)
1322 infprintf (is
, ",%s-%s",
1323 mips_gpr_names
[7 - nstatics
+ 1],
1328 /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1329 UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1330 the base address for OP_PCREL operands. */
1333 print_insn_arg (struct disassemble_info
*info
,
1334 struct mips_print_arg_state
*state
,
1335 const struct mips_opcode
*opcode
,
1336 const struct mips_operand
*operand
,
1340 const fprintf_ftype infprintf
= info
->fprintf_func
;
1341 void *is
= info
->stream
;
1343 switch (operand
->type
)
1347 const struct mips_int_operand
*int_op
;
1349 int_op
= (const struct mips_int_operand
*) operand
;
1350 uval
= mips_decode_int_operand (int_op
, uval
);
1351 state
->last_int
= uval
;
1352 if (int_op
->print_hex
)
1353 infprintf (is
, "0x%x", uval
);
1355 infprintf (is
, "%d", uval
);
1361 const struct mips_mapped_int_operand
*mint_op
;
1363 mint_op
= (const struct mips_mapped_int_operand
*) operand
;
1364 uval
= mint_op
->int_map
[uval
];
1365 state
->last_int
= uval
;
1366 if (mint_op
->print_hex
)
1367 infprintf (is
, "0x%x", uval
);
1369 infprintf (is
, "%d", uval
);
1375 const struct mips_msb_operand
*msb_op
;
1377 msb_op
= (const struct mips_msb_operand
*) operand
;
1378 uval
+= msb_op
->bias
;
1379 if (msb_op
->add_lsb
)
1380 uval
-= state
->last_int
;
1381 infprintf (is
, "0x%x", uval
);
1386 case OP_OPTIONAL_REG
:
1388 const struct mips_reg_operand
*reg_op
;
1390 reg_op
= (const struct mips_reg_operand
*) operand
;
1391 uval
= mips_decode_reg_operand (reg_op
, uval
);
1392 print_reg (info
, opcode
, reg_op
->reg_type
, uval
);
1394 mips_seen_register (state
, uval
, reg_op
->reg_type
);
1400 const struct mips_reg_pair_operand
*pair_op
;
1402 pair_op
= (const struct mips_reg_pair_operand
*) operand
;
1403 print_reg (info
, opcode
, pair_op
->reg_type
,
1404 pair_op
->reg1_map
[uval
]);
1405 infprintf (is
, ",");
1406 print_reg (info
, opcode
, pair_op
->reg_type
,
1407 pair_op
->reg2_map
[uval
]);
1413 const struct mips_pcrel_operand
*pcrel_op
;
1415 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1416 info
->target
= mips_decode_pcrel_operand (pcrel_op
, base_pc
, uval
);
1418 /* For jumps and branches clear the ISA bit except for
1419 the GDB disassembler. */
1420 if (pcrel_op
->include_isa_bit
1421 && info
->flavour
!= bfd_target_unknown_flavour
)
1424 (*info
->print_address_func
) (info
->target
, info
);
1429 infprintf (is
, "%d", uval
);
1432 case OP_ADDIUSP_INT
:
1436 sval
= mips_signed_operand (operand
, uval
) * 4;
1437 if (sval
>= -8 && sval
< 8)
1439 infprintf (is
, "%d", sval
);
1443 case OP_CLO_CLZ_DEST
:
1445 unsigned int reg1
, reg2
;
1449 /* If one is zero use the other. */
1450 if (reg1
== reg2
|| reg2
== 0)
1451 infprintf (is
, "%s", mips_gpr_names
[reg1
]);
1453 infprintf (is
, "%s", mips_gpr_names
[reg2
]);
1455 /* Bogus, result depends on processor. */
1456 infprintf (is
, "%s or %s", mips_gpr_names
[reg1
],
1457 mips_gpr_names
[reg2
]);
1463 case OP_NON_ZERO_REG
:
1465 print_reg (info
, opcode
, OP_REG_GP
, uval
& 31);
1466 mips_seen_register (state
, uval
, OP_REG_GP
);
1470 case OP_LWM_SWM_LIST
:
1471 if (operand
->size
== 2)
1474 infprintf (is
, "%s,%s",
1476 mips_gpr_names
[31]);
1478 infprintf (is
, "%s-%s,%s",
1480 mips_gpr_names
[16 + uval
],
1481 mips_gpr_names
[31]);
1487 s_reg_encode
= uval
& 0xf;
1488 if (s_reg_encode
!= 0)
1490 if (s_reg_encode
== 1)
1491 infprintf (is
, "%s", mips_gpr_names
[16]);
1492 else if (s_reg_encode
< 9)
1493 infprintf (is
, "%s-%s",
1495 mips_gpr_names
[15 + s_reg_encode
]);
1496 else if (s_reg_encode
== 9)
1497 infprintf (is
, "%s-%s,%s",
1500 mips_gpr_names
[30]);
1502 infprintf (is
, "UNKNOWN");
1505 if (uval
& 0x10) /* For ra. */
1507 if (s_reg_encode
== 0)
1508 infprintf (is
, "%s", mips_gpr_names
[31]);
1510 infprintf (is
, ",%s", mips_gpr_names
[31]);
1515 case OP_ENTRY_EXIT_LIST
:
1518 unsigned int amask
, smask
;
1521 amask
= (uval
>> 3) & 7;
1522 if (amask
> 0 && amask
< 5)
1524 infprintf (is
, "%s", mips_gpr_names
[4]);
1526 infprintf (is
, "-%s", mips_gpr_names
[amask
+ 3]);
1530 smask
= (uval
>> 1) & 3;
1533 infprintf (is
, "%s??", sep
);
1538 infprintf (is
, "%s%s", sep
, mips_gpr_names
[16]);
1540 infprintf (is
, "-%s", mips_gpr_names
[smask
+ 15]);
1546 infprintf (is
, "%s%s", sep
, mips_gpr_names
[31]);
1550 if (amask
== 5 || amask
== 6)
1552 infprintf (is
, "%s%s", sep
, mips_fpr_names
[0]);
1554 infprintf (is
, "-%s", mips_fpr_names
[1]);
1559 case OP_SAVE_RESTORE_LIST
:
1560 /* Should be handled by the caller due to complex behavior. */
1563 case OP_MDMX_IMM_REG
:
1569 if ((vsel
& 0x10) == 0)
1574 for (fmt
= 0; fmt
< 3; fmt
++, vsel
>>= 1)
1575 if ((vsel
& 1) == 0)
1577 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1578 infprintf (is
, "[%d]", vsel
>> 1);
1580 else if ((vsel
& 0x08) == 0)
1581 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1583 infprintf (is
, "0x%x", uval
);
1587 case OP_REPEAT_PREV_REG
:
1588 print_reg (info
, opcode
, state
->last_reg_type
, state
->last_regno
);
1591 case OP_REPEAT_DEST_REG
:
1592 print_reg (info
, opcode
, state
->last_reg_type
, state
->dest_regno
);
1596 infprintf (is
, "$pc");
1600 print_reg (info
, opcode
, OP_REG_GP
, 28);
1604 case OP_VU0_MATCH_SUFFIX
:
1605 print_vu0_channel (info
, operand
, uval
);
1609 infprintf (is
, "[%d]", uval
);
1613 infprintf (is
, "[");
1614 print_reg (info
, opcode
, OP_REG_GP
, uval
);
1615 infprintf (is
, "]");
1620 /* Validate the arguments for INSN, which is described by OPCODE.
1621 Use DECODE_OPERAND to get the encoding of each operand. */
1624 validate_insn_args (const struct mips_opcode
*opcode
,
1625 const struct mips_operand
*(*decode_operand
) (const char *),
1628 struct mips_print_arg_state state
;
1629 const struct mips_operand
*operand
;
1633 init_print_arg_state (&state
);
1634 for (s
= opcode
->args
; *s
; ++s
)
1648 operand
= decode_operand (s
);
1652 uval
= mips_extract_operand (operand
, insn
);
1653 switch (operand
->type
)
1656 case OP_OPTIONAL_REG
:
1658 const struct mips_reg_operand
*reg_op
;
1660 reg_op
= (const struct mips_reg_operand
*) operand
;
1661 uval
= mips_decode_reg_operand (reg_op
, uval
);
1662 mips_seen_register (&state
, uval
, reg_op
->reg_type
);
1668 unsigned int reg1
, reg2
;
1673 if (reg1
!= reg2
|| reg1
== 0)
1680 const struct mips_check_prev_operand
*prev_op
;
1682 prev_op
= (const struct mips_check_prev_operand
*) operand
;
1684 if (!prev_op
->zero_ok
&& uval
== 0)
1687 if (((prev_op
->less_than_ok
&& uval
< state
.last_regno
)
1688 || (prev_op
->greater_than_ok
&& uval
> state
.last_regno
)
1689 || (prev_op
->equal_ok
&& uval
== state
.last_regno
)))
1695 case OP_NON_ZERO_REG
:
1708 case OP_ADDIUSP_INT
:
1709 case OP_CLO_CLZ_DEST
:
1710 case OP_LWM_SWM_LIST
:
1711 case OP_ENTRY_EXIT_LIST
:
1712 case OP_MDMX_IMM_REG
:
1713 case OP_REPEAT_PREV_REG
:
1714 case OP_REPEAT_DEST_REG
:
1718 case OP_VU0_MATCH_SUFFIX
:
1721 case OP_SAVE_RESTORE_LIST
:
1725 if (*s
== 'm' || *s
== '+' || *s
== '-')
1732 /* Print the arguments for INSN, which is described by OPCODE.
1733 Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
1734 as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1735 operand is for a branch or jump. */
1738 print_insn_args (struct disassemble_info
*info
,
1739 const struct mips_opcode
*opcode
,
1740 const struct mips_operand
*(*decode_operand
) (const char *),
1741 unsigned int insn
, bfd_vma insn_pc
, unsigned int length
)
1743 const fprintf_ftype infprintf
= info
->fprintf_func
;
1744 void *is
= info
->stream
;
1745 struct mips_print_arg_state state
;
1746 const struct mips_operand
*operand
;
1749 init_print_arg_state (&state
);
1750 for (s
= opcode
->args
; *s
; ++s
)
1757 infprintf (is
, "%c", *s
);
1762 infprintf (is
, "%c%c", *s
, *s
);
1766 operand
= decode_operand (s
);
1769 /* xgettext:c-format */
1771 _("# internal error, undefined operand in `%s %s'"),
1772 opcode
->name
, opcode
->args
);
1776 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
1778 /* Handle this case here because of the complex behavior. */
1779 unsigned int amask
= (insn
>> 15) & 0xf;
1780 unsigned int nsreg
= (insn
>> 23) & 0x7;
1781 unsigned int ra
= insn
& 0x1000; /* $ra */
1782 unsigned int s0
= insn
& 0x800; /* $s0 */
1783 unsigned int s1
= insn
& 0x400; /* $s1 */
1784 unsigned int frame_size
= (((insn
>> 15) & 0xf0)
1785 | ((insn
>> 6) & 0x0f)) * 8;
1786 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
,
1789 else if (operand
->type
== OP_REG
1792 && opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1794 /* Coprocessor register 0 with sel field. */
1795 const struct mips_cp0sel_name
*n
;
1796 unsigned int reg
, sel
;
1798 reg
= mips_extract_operand (operand
, insn
);
1800 operand
= decode_operand (s
);
1801 sel
= mips_extract_operand (operand
, insn
);
1803 /* CP0 register including 'sel' code for mftc0, to be
1804 printed textually if known. If not known, print both
1805 CP0 register name and sel numerically since CP0 register
1806 with sel 0 may have a name unrelated to register being
1808 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
1809 mips_cp0sel_names_len
,
1812 infprintf (is
, "%s", n
->name
);
1814 infprintf (is
, "$%d,%d", reg
, sel
);
1818 bfd_vma base_pc
= insn_pc
;
1820 /* Adjust the PC relative base so that branch/jump insns use
1821 the following PC as the base but genuinely PC relative
1822 operands use the current PC. */
1823 if (operand
->type
== OP_PCREL
)
1825 const struct mips_pcrel_operand
*pcrel_op
;
1827 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1828 /* The include_isa_bit flag is sufficient to distinguish
1829 branch/jump from other PC relative operands. */
1830 if (pcrel_op
->include_isa_bit
)
1834 print_insn_arg (info
, &state
, opcode
, operand
, base_pc
,
1835 mips_extract_operand (operand
, insn
));
1837 if (*s
== 'm' || *s
== '+' || *s
== '-')
1844 /* Print the mips instruction at address MEMADDR in debugged memory,
1845 on using INFO. Returns length of the instruction, in bytes, which is
1846 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
1847 this is little-endian code. */
1850 print_insn_mips (bfd_vma memaddr
,
1852 struct disassemble_info
*info
)
1854 #define GET_OP(insn, field) \
1855 (((insn) >> OP_SH_##field) & OP_MASK_##field)
1856 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
1857 const fprintf_ftype infprintf
= info
->fprintf_func
;
1858 const struct mips_opcode
*op
;
1859 static bfd_boolean init
= 0;
1860 void *is
= info
->stream
;
1862 /* Build a hash table to shorten the search time. */
1867 for (i
= 0; i
<= OP_MASK_OP
; i
++)
1869 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1871 if (op
->pinfo
== INSN_MACRO
1872 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
1874 if (i
== GET_OP (op
->match
, OP
))
1885 info
->bytes_per_chunk
= INSNLEN
;
1886 info
->display_endian
= info
->endian
;
1887 info
->insn_info_valid
= 1;
1888 info
->branch_delay_insns
= 0;
1889 info
->data_size
= 0;
1890 info
->insn_type
= dis_nonbranch
;
1894 op
= mips_hash
[GET_OP (word
, OP
)];
1897 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1899 if (op
->pinfo
!= INSN_MACRO
1900 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
1901 && (word
& op
->mask
) == op
->match
)
1903 /* We always disassemble the jalx instruction, except for MIPS r6. */
1904 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
)
1905 && (strcmp (op
->name
, "jalx")
1906 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS32R6
1907 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
))
1910 /* Figure out instruction type and branch delay information. */
1911 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
1913 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
1914 info
->insn_type
= dis_jsr
;
1916 info
->insn_type
= dis_branch
;
1917 info
->branch_delay_insns
= 1;
1919 else if ((op
->pinfo
& (INSN_COND_BRANCH_DELAY
1920 | INSN_COND_BRANCH_LIKELY
)) != 0)
1922 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
1923 info
->insn_type
= dis_condjsr
;
1925 info
->insn_type
= dis_condbranch
;
1926 info
->branch_delay_insns
= 1;
1928 else if ((op
->pinfo
& (INSN_STORE_MEMORY
1929 | INSN_LOAD_MEMORY
)) != 0)
1930 info
->insn_type
= dis_dref
;
1932 if (!validate_insn_args (op
, decode_mips_operand
, word
))
1935 infprintf (is
, "%s", op
->name
);
1936 if (op
->pinfo2
& INSN2_VU0_CHANNEL_SUFFIX
)
1940 infprintf (is
, ".");
1941 uval
= mips_extract_operand (&mips_vu0_channel_mask
, word
);
1942 print_vu0_channel (info
, &mips_vu0_channel_mask
, uval
);
1947 infprintf (is
, "\t");
1948 print_insn_args (info
, op
, decode_mips_operand
, word
,
1958 /* Handle undefined instructions. */
1959 info
->insn_type
= dis_noninsn
;
1960 infprintf (is
, "0x%x", word
);
1964 /* Disassemble an operand for a mips16 instruction. */
1967 print_mips16_insn_arg (struct disassemble_info
*info
,
1968 struct mips_print_arg_state
*state
,
1969 const struct mips_opcode
*opcode
,
1970 char type
, bfd_vma memaddr
,
1971 unsigned insn
, bfd_boolean use_extend
,
1972 unsigned extend
, bfd_boolean is_offset
)
1974 const fprintf_ftype infprintf
= info
->fprintf_func
;
1975 void *is
= info
->stream
;
1976 const struct mips_operand
*operand
, *ext_operand
;
1977 unsigned short ext_size
;
1989 infprintf (is
, "%c", type
);
1993 operand
= decode_mips16_operand (type
, FALSE
);
1996 /* xgettext:c-format */
1997 infprintf (is
, _("# internal error, undefined operand in `%s %s'"),
1998 opcode
->name
, opcode
->args
);
2002 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
2004 /* Handle this case here because of the complex interaction
2005 with the EXTEND opcode. */
2006 unsigned int amask
= extend
& 0xf;
2007 unsigned int nsreg
= (extend
>> 8) & 0x7;
2008 unsigned int ra
= insn
& 0x40; /* $ra */
2009 unsigned int s0
= insn
& 0x20; /* $s0 */
2010 unsigned int s1
= insn
& 0x10; /* $s1 */
2011 unsigned int frame_size
= ((extend
& 0xf0) | (insn
& 0x0f)) * 8;
2012 if (frame_size
== 0 && !use_extend
)
2014 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
, frame_size
);
2018 if (is_offset
&& operand
->type
== OP_INT
)
2020 const struct mips_int_operand
*int_op
;
2022 int_op
= (const struct mips_int_operand
*) operand
;
2023 info
->insn_type
= dis_dref
;
2024 info
->data_size
= 1 << int_op
->shift
;
2030 ext_operand
= decode_mips16_operand (type
, TRUE
);
2031 if (ext_operand
!= operand
2032 || (operand
->type
== OP_INT
&& operand
->lsb
== 0
2033 && mips_opcode_32bit_p (opcode
)))
2035 ext_size
= ext_operand
->size
;
2036 operand
= ext_operand
;
2039 if (operand
->size
== 26)
2040 uval
= ((extend
& 0x1f) << 21) | ((extend
& 0x3e0) << 11) | insn
;
2041 else if (ext_size
== 16 || ext_size
== 9)
2042 uval
= ((extend
& 0x1f) << 11) | (extend
& 0x7e0) | (insn
& 0x1f);
2043 else if (ext_size
== 15)
2044 uval
= ((extend
& 0xf) << 11) | (extend
& 0x7f0) | (insn
& 0xf);
2045 else if (ext_size
== 6)
2046 uval
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
2048 uval
= mips_extract_operand (operand
, (extend
<< 16) | insn
);
2050 uval
&= (1U << ext_size
) - 1;
2052 baseaddr
= memaddr
+ 2;
2053 if (operand
->type
== OP_PCREL
)
2055 const struct mips_pcrel_operand
*pcrel_op
;
2057 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
2058 if (!pcrel_op
->include_isa_bit
&& use_extend
)
2059 baseaddr
= memaddr
- 2;
2060 else if (!pcrel_op
->include_isa_bit
)
2064 /* If this instruction is in the delay slot of a JAL/JALX
2065 instruction, the base address is the address of the
2066 JAL/JALX instruction. If it is in the delay slot of
2067 a JR/JALR instruction, the base address is the address
2068 of the JR/JALR instruction. This test is unreliable:
2069 we have no way of knowing whether the previous word is
2070 instruction or data. */
2071 if (info
->read_memory_func (memaddr
- 4, buffer
, 2, info
) == 0
2072 && (((info
->endian
== BFD_ENDIAN_BIG
2073 ? bfd_getb16 (buffer
)
2074 : bfd_getl16 (buffer
))
2075 & 0xf800) == 0x1800))
2076 baseaddr
= memaddr
- 4;
2077 else if (info
->read_memory_func (memaddr
- 2, buffer
, 2,
2079 && (((info
->endian
== BFD_ENDIAN_BIG
2080 ? bfd_getb16 (buffer
)
2081 : bfd_getl16 (buffer
))
2082 & 0xf89f) == 0xe800)
2083 && (((info
->endian
== BFD_ENDIAN_BIG
2084 ? bfd_getb16 (buffer
)
2085 : bfd_getl16 (buffer
))
2086 & 0x0060) != 0x0060))
2087 baseaddr
= memaddr
- 2;
2093 print_insn_arg (info
, state
, opcode
, operand
, baseaddr
+ 1, uval
);
2099 /* Check if the given address is the last word of a MIPS16 PLT entry.
2100 This word is data and depending on the value it may interfere with
2101 disassembly of further PLT entries. We make use of the fact PLT
2102 symbols are marked BSF_SYNTHETIC. */
2104 is_mips16_plt_tail (struct disassemble_info
*info
, bfd_vma addr
)
2108 && (info
->symbols
[0]->flags
& BSF_SYNTHETIC
)
2109 && addr
== bfd_asymbol_value (info
->symbols
[0]) + 12)
2115 /* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2124 /* Disassemble mips16 instructions. */
2127 print_insn_mips16 (bfd_vma memaddr
, struct disassemble_info
*info
)
2129 const fprintf_ftype infprintf
= info
->fprintf_func
;
2132 const struct mips_opcode
*op
, *opend
;
2133 struct mips_print_arg_state state
;
2134 void *is
= info
->stream
;
2135 bfd_boolean have_second
;
2136 bfd_boolean extend_only
;
2137 unsigned int second
;
2141 info
->bytes_per_chunk
= 2;
2142 info
->display_endian
= info
->endian
;
2143 info
->insn_info_valid
= 1;
2144 info
->branch_delay_insns
= 0;
2145 info
->data_size
= 0;
2149 #define GET_OP(insn, field) \
2150 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
2151 /* Decode PLT entry's GOT slot address word. */
2152 if (is_mips16_plt_tail (info
, memaddr
))
2154 info
->insn_type
= dis_noninsn
;
2155 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
2158 unsigned int gotslot
;
2160 if (info
->endian
== BFD_ENDIAN_BIG
)
2161 gotslot
= bfd_getb32 (buffer
);
2163 gotslot
= bfd_getl32 (buffer
);
2164 infprintf (is
, ".word\t0x%x", gotslot
);
2171 info
->insn_type
= dis_nonbranch
;
2172 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2176 (*info
->memory_error_func
) (status
, memaddr
, info
);
2180 extend_only
= FALSE
;
2182 if (info
->endian
== BFD_ENDIAN_BIG
)
2183 first
= bfd_getb16 (buffer
);
2185 first
= bfd_getl16 (buffer
);
2187 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2191 if (info
->endian
== BFD_ENDIAN_BIG
)
2192 second
= bfd_getb16 (buffer
);
2194 second
= bfd_getl16 (buffer
);
2195 full
= (first
<< 16) | second
;
2199 have_second
= FALSE
;
2204 /* FIXME: Should probably use a hash table on the major opcode here. */
2206 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
2207 for (op
= mips16_opcodes
; op
< opend
; op
++)
2209 enum match_kind match
;
2211 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
))
2214 if (op
->pinfo
== INSN_MACRO
2215 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
2217 else if (mips_opcode_32bit_p (op
))
2220 && (full
& op
->mask
) == op
->match
)
2225 else if ((first
& op
->mask
) == op
->match
)
2227 match
= MATCH_SHORT
;
2231 else if ((first
& 0xf800) == 0xf000
2234 && (second
& op
->mask
) == op
->match
)
2236 if (op
->pinfo2
& INSN2_SHORT_ONLY
)
2247 if (match
!= MATCH_NONE
)
2251 infprintf (is
, "%s", op
->name
);
2252 if (op
->args
[0] != '\0')
2253 infprintf (is
, "\t");
2255 init_print_arg_state (&state
);
2256 for (s
= op
->args
; *s
!= '\0'; s
++)
2260 && GET_OP (full
, RX
) == GET_OP (full
, RY
))
2262 /* Skip the register and the comma. */
2268 && GET_OP (full
, RZ
) == GET_OP (full
, RX
))
2270 /* Skip the register and the comma. */
2277 && op
->name
[strlen (op
->name
) - 1] == '0')
2279 /* Coprocessor register 0 with sel field. */
2280 const struct mips_cp0sel_name
*n
;
2281 const struct mips_operand
*operand
;
2282 unsigned int reg
, sel
;
2284 operand
= decode_mips16_operand (*s
, TRUE
);
2285 reg
= mips_extract_operand (operand
, (first
<< 16) | second
);
2287 operand
= decode_mips16_operand (*s
, TRUE
);
2288 sel
= mips_extract_operand (operand
, (first
<< 16) | second
);
2290 /* CP0 register including 'sel' code for mftc0, to be
2291 printed textually if known. If not known, print both
2292 CP0 register name and sel numerically since CP0 register
2293 with sel 0 may have a name unrelated to register being
2295 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
2296 mips_cp0sel_names_len
,
2299 infprintf (is
, "%s", n
->name
);
2301 infprintf (is
, "$%d,%d", reg
, sel
);
2307 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
+ 2,
2308 second
, TRUE
, first
, s
[1] == '(');
2311 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
,
2312 first
, FALSE
, 0, s
[1] == '(');
2314 case MATCH_NONE
: /* Stop the compiler complaining. */
2319 /* Figure out branch instruction type and delay slot information. */
2320 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
2321 info
->branch_delay_insns
= 1;
2322 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0
2323 || (op
->pinfo2
& INSN2_UNCOND_BRANCH
) != 0)
2325 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2326 info
->insn_type
= dis_jsr
;
2328 info
->insn_type
= dis_branch
;
2330 else if ((op
->pinfo2
& INSN2_COND_BRANCH
) != 0)
2331 info
->insn_type
= dis_condbranch
;
2333 return match
== MATCH_FULL
? 4 : 2;
2338 infprintf (is
, "0x%x", first
);
2339 info
->insn_type
= dis_noninsn
;
2344 /* Disassemble microMIPS instructions. */
2347 print_insn_micromips (bfd_vma memaddr
, struct disassemble_info
*info
)
2349 const fprintf_ftype infprintf
= info
->fprintf_func
;
2350 const struct mips_opcode
*op
, *opend
;
2351 void *is
= info
->stream
;
2353 unsigned int higher
;
2354 unsigned int length
;
2358 info
->bytes_per_chunk
= 2;
2359 info
->display_endian
= info
->endian
;
2360 info
->insn_info_valid
= 1;
2361 info
->branch_delay_insns
= 0;
2362 info
->data_size
= 0;
2363 info
->insn_type
= dis_nonbranch
;
2367 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2370 (*info
->memory_error_func
) (status
, memaddr
, info
);
2376 if (info
->endian
== BFD_ENDIAN_BIG
)
2377 insn
= bfd_getb16 (buffer
);
2379 insn
= bfd_getl16 (buffer
);
2381 if ((insn
& 0x1c00) == 0x0000 || (insn
& 0x1000) == 0x1000)
2383 /* This is a 32-bit microMIPS instruction. */
2386 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2389 infprintf (is
, "micromips 0x%x", higher
);
2390 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
2394 if (info
->endian
== BFD_ENDIAN_BIG
)
2395 insn
= bfd_getb16 (buffer
);
2397 insn
= bfd_getl16 (buffer
);
2399 insn
= insn
| (higher
<< 16);
2404 /* FIXME: Should probably use a hash table on the major opcode here. */
2406 opend
= micromips_opcodes
+ bfd_micromips_num_opcodes
;
2407 for (op
= micromips_opcodes
; op
< opend
; op
++)
2409 if (op
->pinfo
!= INSN_MACRO
2410 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
2411 && (insn
& op
->mask
) == op
->match
2412 && ((length
== 2 && (op
->mask
& 0xffff0000) == 0)
2413 || (length
== 4 && (op
->mask
& 0xffff0000) != 0)))
2415 if (!validate_insn_args (op
, decode_micromips_operand
, insn
))
2418 infprintf (is
, "%s", op
->name
);
2422 infprintf (is
, "\t");
2423 print_insn_args (info
, op
, decode_micromips_operand
, insn
,
2424 memaddr
+ 1, length
);
2427 /* Figure out instruction type and branch delay information. */
2429 & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
)) != 0)
2430 info
->branch_delay_insns
= 1;
2431 if (((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
2432 | (op
->pinfo2
& INSN2_UNCOND_BRANCH
)) != 0)
2434 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
2435 info
->insn_type
= dis_jsr
;
2437 info
->insn_type
= dis_branch
;
2439 else if (((op
->pinfo
& INSN_COND_BRANCH_DELAY
)
2440 | (op
->pinfo2
& INSN2_COND_BRANCH
)) != 0)
2442 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2443 info
->insn_type
= dis_condjsr
;
2445 info
->insn_type
= dis_condbranch
;
2448 & (INSN_STORE_MEMORY
| INSN_LOAD_MEMORY
)) != 0)
2449 info
->insn_type
= dis_dref
;
2455 infprintf (is
, "0x%x", insn
);
2456 info
->insn_type
= dis_noninsn
;
2461 /* Return 1 if a symbol associated with the location being disassembled
2462 indicates a compressed mode, either MIPS16 or microMIPS, according to
2463 MICROMIPS_P. We iterate over all the symbols at the address being
2464 considered assuming if at least one of them indicates code compression,
2465 then such code has been genuinely produced here (other symbols could
2466 have been derived from function symbols defined elsewhere or could
2467 define data). Otherwise, return 0. */
2470 is_compressed_mode_p (struct disassemble_info
*info
, bfd_boolean micromips_p
)
2475 for (i
= info
->symtab_pos
, l
= i
+ info
->num_symbols
; i
< l
; i
++)
2476 if (((info
->symtab
[i
])->flags
& BSF_SYNTHETIC
) != 0
2478 && ELF_ST_IS_MIPS16 ((*info
->symbols
)->udata
.i
))
2480 && ELF_ST_IS_MICROMIPS ((*info
->symbols
)->udata
.i
))))
2482 else if (bfd_asymbol_flavour (info
->symtab
[i
]) == bfd_target_elf_flavour
2483 && info
->symtab
[i
]->section
== info
->section
)
2485 elf_symbol_type
*symbol
= (elf_symbol_type
*) info
->symtab
[i
];
2487 && ELF_ST_IS_MIPS16 (symbol
->internal_elf_sym
.st_other
))
2489 && ELF_ST_IS_MICROMIPS (symbol
->internal_elf_sym
.st_other
)))
2496 /* In an environment where we do not know the symbol type of the
2497 instruction we are forced to assume that the low order bit of the
2498 instructions' address may mark it as a mips16 instruction. If we
2499 are single stepping, or the pc is within the disassembled function,
2500 this works. Otherwise, we need a clue. Sometimes. */
2503 _print_insn_mips (bfd_vma memaddr
,
2504 struct disassemble_info
*info
,
2505 enum bfd_endian endianness
)
2507 bfd_byte buffer
[INSNLEN
];
2510 set_default_mips_dis_options (info
);
2511 parse_mips_dis_options (info
->disassembler_options
);
2513 if (info
->mach
== bfd_mach_mips16
)
2514 return print_insn_mips16 (memaddr
, info
);
2515 if (info
->mach
== bfd_mach_mips_micromips
)
2516 return print_insn_micromips (memaddr
, info
);
2519 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
2520 /* Only a few tools will work this way. */
2524 return print_insn_micromips (memaddr
, info
);
2526 return print_insn_mips16 (memaddr
, info
);
2530 #if SYMTAB_AVAILABLE
2531 if (is_compressed_mode_p (info
, TRUE
))
2532 return print_insn_micromips (memaddr
, info
);
2533 if (is_compressed_mode_p (info
, FALSE
))
2534 return print_insn_mips16 (memaddr
, info
);
2537 status
= (*info
->read_memory_func
) (memaddr
, buffer
, INSNLEN
, info
);
2542 if (endianness
== BFD_ENDIAN_BIG
)
2543 insn
= bfd_getb32 (buffer
);
2545 insn
= bfd_getl32 (buffer
);
2547 return print_insn_mips (memaddr
, insn
, info
);
2551 (*info
->memory_error_func
) (status
, memaddr
, info
);
2557 print_insn_big_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2559 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_BIG
);
2563 print_insn_little_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2565 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_LITTLE
);
2568 /* Indices into option argument vector for options accepting an argument.
2569 Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2572 MIPS_OPTION_ARG_NONE
= -1,
2573 MIPS_OPTION_ARG_ABI
,
2574 MIPS_OPTION_ARG_ARCH
,
2575 MIPS_OPTION_ARG_SIZE
2576 } mips_option_arg_t
;
2578 /* Valid MIPS disassembler options. */
2582 const char *description
;
2583 mips_option_arg_t arg
;
2586 { "no-aliases", N_("Use canonical instruction forms.\n"),
2587 MIPS_OPTION_ARG_NONE
},
2588 { "msa", N_("Recognize MSA instructions.\n"),
2589 MIPS_OPTION_ARG_NONE
},
2590 { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2591 MIPS_OPTION_ARG_NONE
},
2592 { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2594 MIPS_OPTION_ARG_NONE
},
2595 { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2597 MIPS_OPTION_ARG_NONE
},
2599 N_("Recognize the Loongson MultiMedia extensions "
2600 "Instructions (MMI) ASE instructions.\n"),
2601 MIPS_OPTION_ARG_NONE
},
2603 N_("Recognize the Loongson Content Address Memory (CAM) "
2604 " instructions.\n"),
2605 MIPS_OPTION_ARG_NONE
},
2606 { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2607 Default: based on binary being disassembled.\n"),
2608 MIPS_OPTION_ARG_ABI
},
2609 { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2610 Default: numeric.\n"),
2611 MIPS_OPTION_ARG_ABI
},
2612 { "cp0-names=", N_("Print CP0 register names according to specified "
2614 Default: based on binary being disassembled.\n"),
2615 MIPS_OPTION_ARG_ARCH
},
2616 { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2617 Default: based on binary being disassembled.\n"),
2618 MIPS_OPTION_ARG_ARCH
},
2619 { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2620 MIPS_OPTION_ARG_ABI
},
2621 { "reg-names=", N_("Print CP0 register and HWR names according to "
2624 MIPS_OPTION_ARG_ARCH
}
2627 /* Build the structure representing valid MIPS disassembler options.
2628 This is done dynamically for maintenance ease purpose; a static
2629 initializer would be unreadable. */
2631 const disasm_options_and_args_t
*
2632 disassembler_options_mips (void)
2634 static disasm_options_and_args_t
*opts_and_args
;
2636 if (opts_and_args
== NULL
)
2638 size_t num_options
= ARRAY_SIZE (mips_options
);
2639 size_t num_args
= MIPS_OPTION_ARG_SIZE
;
2640 disasm_option_arg_t
*args
;
2641 disasm_options_t
*opts
;
2645 args
= XNEWVEC (disasm_option_arg_t
, num_args
+ 1);
2647 args
[MIPS_OPTION_ARG_ABI
].name
= "ABI";
2648 args
[MIPS_OPTION_ARG_ABI
].values
2649 = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices
) + 1);
2650 for (i
= 0; i
< ARRAY_SIZE (mips_abi_choices
); i
++)
2651 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = mips_abi_choices
[i
].name
;
2652 /* The array we return must be NULL terminated. */
2653 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = NULL
;
2655 args
[MIPS_OPTION_ARG_ARCH
].name
= "ARCH";
2656 args
[MIPS_OPTION_ARG_ARCH
].values
2657 = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices
) + 1);
2658 for (i
= 0, j
= 0; i
< ARRAY_SIZE (mips_arch_choices
); i
++)
2659 if (*mips_arch_choices
[i
].name
!= '\0')
2660 args
[MIPS_OPTION_ARG_ARCH
].values
[j
++] = mips_arch_choices
[i
].name
;
2661 /* The array we return must be NULL terminated. */
2662 args
[MIPS_OPTION_ARG_ARCH
].values
[j
] = NULL
;
2664 /* The array we return must be NULL terminated. */
2665 args
[MIPS_OPTION_ARG_SIZE
].name
= NULL
;
2666 args
[MIPS_OPTION_ARG_SIZE
].values
= NULL
;
2668 opts_and_args
= XNEW (disasm_options_and_args_t
);
2669 opts_and_args
->args
= args
;
2671 opts
= &opts_and_args
->options
;
2672 opts
->name
= XNEWVEC (const char *, num_options
+ 1);
2673 opts
->description
= XNEWVEC (const char *, num_options
+ 1);
2674 opts
->arg
= XNEWVEC (const disasm_option_arg_t
*, num_options
+ 1);
2675 for (i
= 0; i
< num_options
; i
++)
2677 opts
->name
[i
] = mips_options
[i
].name
;
2678 opts
->description
[i
] = _(mips_options
[i
].description
);
2679 if (mips_options
[i
].arg
!= MIPS_OPTION_ARG_NONE
)
2680 opts
->arg
[i
] = &args
[mips_options
[i
].arg
];
2682 opts
->arg
[i
] = NULL
;
2684 /* The array we return must be NULL terminated. */
2685 opts
->name
[i
] = NULL
;
2686 opts
->description
[i
] = NULL
;
2687 opts
->arg
[i
] = NULL
;
2690 return opts_and_args
;
2694 print_mips_disassembler_options (FILE *stream
)
2696 const disasm_options_and_args_t
*opts_and_args
;
2697 const disasm_option_arg_t
*args
;
2698 const disasm_options_t
*opts
;
2703 opts_and_args
= disassembler_options_mips ();
2704 opts
= &opts_and_args
->options
;
2705 args
= opts_and_args
->args
;
2707 fprintf (stream
, _("\n\
2708 The following MIPS specific disassembler options are supported for use\n\
2709 with the -M switch (multiple options should be separated by commas):\n\n"));
2711 /* Compute the length of the longest option name. */
2712 for (i
= 0; opts
->name
[i
] != NULL
; i
++)
2714 size_t len
= strlen (opts
->name
[i
]);
2716 if (opts
->arg
[i
] != NULL
)
2717 len
+= strlen (opts
->arg
[i
]->name
);
2722 for (i
= 0, max_len
++; opts
->name
[i
] != NULL
; i
++)
2724 fprintf (stream
, " %s", opts
->name
[i
]);
2725 if (opts
->arg
[i
] != NULL
)
2726 fprintf (stream
, "%s", opts
->arg
[i
]->name
);
2727 if (opts
->description
[i
] != NULL
)
2729 size_t len
= strlen (opts
->name
[i
]);
2731 if (opts
->arg
[i
] != NULL
)
2732 len
+= strlen (opts
->arg
[i
]->name
);
2734 "%*c %s", (int) (max_len
- len
), ' ', opts
->description
[i
]);
2736 fprintf (stream
, _("\n"));
2739 for (i
= 0; args
[i
].name
!= NULL
; i
++)
2741 fprintf (stream
, _("\n\
2742 For the options above, the following values are supported for \"%s\":\n "),
2744 for (j
= 0; args
[i
].values
[j
] != NULL
; j
++)
2745 fprintf (stream
, " %s", args
[i
].values
[j
]);
2746 fprintf (stream
, _("\n"));
2749 fprintf (stream
, _("\n"));