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
, mips_cp0_names_numeric
,
634 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
636 { "octeon", 1, bfd_mach_mips_octeon
, CPU_OCTEON
,
637 ISA_MIPS64R2
| INSN_OCTEON
, 0, mips_cp0_names_numeric
, NULL
, 0,
638 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
640 { "octeon+", 1, bfd_mach_mips_octeonp
, CPU_OCTEONP
,
641 ISA_MIPS64R2
| INSN_OCTEONP
, 0, mips_cp0_names_numeric
,
642 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
644 { "octeon2", 1, bfd_mach_mips_octeon2
, CPU_OCTEON2
,
645 ISA_MIPS64R2
| INSN_OCTEON2
, 0, mips_cp0_names_numeric
,
646 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
648 { "octeon3", 1, bfd_mach_mips_octeon3
, CPU_OCTEON3
,
649 ISA_MIPS64R5
| INSN_OCTEON3
, ASE_VIRT
| ASE_VIRT64
,
650 mips_cp0_names_numeric
,
651 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
653 { "xlr", 1, bfd_mach_mips_xlr
, CPU_XLR
,
654 ISA_MIPS64
| INSN_XLR
, 0,
656 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
657 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
659 /* XLP is mostly like XLR, with the prominent exception it is being
661 { "xlp", 1, bfd_mach_mips_xlr
, CPU_XLR
,
662 ISA_MIPS64R2
| INSN_XLR
, 0,
664 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
665 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
667 /* This entry, mips16, is here only for ISA/processor selection; do
668 not print its name. */
669 { "", 1, bfd_mach_mips16
, CPU_MIPS16
, ISA_MIPS64
,
670 ASE_MIPS16E2
| ASE_MIPS16E2_MT
,
671 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
672 mips_hwr_names_numeric
},
675 /* ISA and processor type to disassemble for, and register names to use.
676 set_default_mips_dis_options and parse_mips_dis_options fill in these
678 static int mips_processor
;
681 static int micromips_ase
;
682 static const char * const *mips_gpr_names
;
683 static const char * const *mips_fpr_names
;
684 static const char * const *mips_cp0_names
;
685 static const struct mips_cp0sel_name
*mips_cp0sel_names
;
686 static int mips_cp0sel_names_len
;
687 static const char * const *mips_cp1_names
;
688 static const char * const *mips_hwr_names
;
691 static int no_aliases
; /* If set disassemble as most general inst. */
693 static const struct mips_abi_choice
*
694 choose_abi_by_name (const char *name
, unsigned int namelen
)
696 const struct mips_abi_choice
*c
;
699 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_abi_choices
) && c
== NULL
; i
++)
700 if (strncmp (mips_abi_choices
[i
].name
, name
, namelen
) == 0
701 && strlen (mips_abi_choices
[i
].name
) == namelen
)
702 c
= &mips_abi_choices
[i
];
707 static const struct mips_arch_choice
*
708 choose_arch_by_name (const char *name
, unsigned int namelen
)
710 const struct mips_arch_choice
*c
= NULL
;
713 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
714 if (strncmp (mips_arch_choices
[i
].name
, name
, namelen
) == 0
715 && strlen (mips_arch_choices
[i
].name
) == namelen
)
716 c
= &mips_arch_choices
[i
];
721 static const struct mips_arch_choice
*
722 choose_arch_by_number (unsigned long mach
)
724 static unsigned long hint_bfd_mach
;
725 static const struct mips_arch_choice
*hint_arch_choice
;
726 const struct mips_arch_choice
*c
;
729 /* We optimize this because even if the user specifies no
730 flags, this will be done for every instruction! */
731 if (hint_bfd_mach
== mach
732 && hint_arch_choice
!= NULL
733 && hint_arch_choice
->bfd_mach
== hint_bfd_mach
)
734 return hint_arch_choice
;
736 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
738 if (mips_arch_choices
[i
].bfd_mach_valid
739 && mips_arch_choices
[i
].bfd_mach
== mach
)
741 c
= &mips_arch_choices
[i
];
742 hint_bfd_mach
= mach
;
743 hint_arch_choice
= c
;
749 /* Check if the object uses NewABI conventions. */
752 is_newabi (Elf_Internal_Ehdr
*header
)
754 /* There are no old-style ABIs which use 64-bit ELF. */
755 if (header
->e_ident
[EI_CLASS
] == ELFCLASS64
)
758 /* If a 32-bit ELF file, n32 is a new-style ABI. */
759 if ((header
->e_flags
& EF_MIPS_ABI2
) != 0)
765 /* Check if the object has microMIPS ASE code. */
768 is_micromips (Elf_Internal_Ehdr
*header
)
770 if ((header
->e_flags
& EF_MIPS_ARCH_ASE_MICROMIPS
) != 0)
776 /* Convert ASE flags from .MIPS.abiflags to internal values. */
779 mips_convert_abiflags_ases (unsigned long afl_ases
)
781 unsigned long opcode_ases
= 0;
783 if (afl_ases
& AFL_ASE_DSP
)
784 opcode_ases
|= ASE_DSP
;
785 if (afl_ases
& AFL_ASE_DSPR2
)
786 opcode_ases
|= ASE_DSPR2
;
787 if (afl_ases
& AFL_ASE_EVA
)
788 opcode_ases
|= ASE_EVA
;
789 if (afl_ases
& AFL_ASE_MCU
)
790 opcode_ases
|= ASE_MCU
;
791 if (afl_ases
& AFL_ASE_MDMX
)
792 opcode_ases
|= ASE_MDMX
;
793 if (afl_ases
& AFL_ASE_MIPS3D
)
794 opcode_ases
|= ASE_MIPS3D
;
795 if (afl_ases
& AFL_ASE_MT
)
796 opcode_ases
|= ASE_MT
;
797 if (afl_ases
& AFL_ASE_SMARTMIPS
)
798 opcode_ases
|= ASE_SMARTMIPS
;
799 if (afl_ases
& AFL_ASE_VIRT
)
800 opcode_ases
|= ASE_VIRT
;
801 if (afl_ases
& AFL_ASE_MSA
)
802 opcode_ases
|= ASE_MSA
;
803 if (afl_ases
& AFL_ASE_XPA
)
804 opcode_ases
|= ASE_XPA
;
805 if (afl_ases
& AFL_ASE_DSPR3
)
806 opcode_ases
|= ASE_DSPR3
;
807 if (afl_ases
& AFL_ASE_MIPS16E2
)
808 opcode_ases
|= ASE_MIPS16E2
;
812 /* Calculate combination ASE flags from regular ASE flags. */
815 mips_calculate_combination_ases (unsigned long opcode_ases
)
817 unsigned long combination_ases
= 0;
819 if ((opcode_ases
& (ASE_XPA
| ASE_VIRT
)) == (ASE_XPA
| ASE_VIRT
))
820 combination_ases
|= ASE_XPA_VIRT
;
821 if ((opcode_ases
& (ASE_MIPS16E2
| ASE_MT
)) == (ASE_MIPS16E2
| ASE_MT
))
822 combination_ases
|= ASE_MIPS16E2_MT
;
823 return combination_ases
;
827 set_default_mips_dis_options (struct disassemble_info
*info
)
829 const struct mips_arch_choice
*chosen_arch
;
831 /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
832 is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
833 CP0 register, and HWR names. */
834 mips_isa
= ISA_MIPS3
;
835 mips_processor
= CPU_R3000
;
838 mips_gpr_names
= mips_gpr_names_oldabi
;
839 mips_fpr_names
= mips_fpr_names_numeric
;
840 mips_cp0_names
= mips_cp0_names_numeric
;
841 mips_cp0sel_names
= NULL
;
842 mips_cp0sel_names_len
= 0;
843 mips_cp1_names
= mips_cp1_names_numeric
;
844 mips_hwr_names
= mips_hwr_names_numeric
;
847 /* Set ISA, architecture, and cp0 register names as best we can. */
848 #if ! SYMTAB_AVAILABLE
849 /* This is running out on a target machine, not in a host tool.
850 FIXME: Where does mips_target_info come from? */
851 target_processor
= mips_target_info
.processor
;
852 mips_isa
= mips_target_info
.isa
;
853 mips_ase
= mips_target_info
.ase
;
855 chosen_arch
= choose_arch_by_number (info
->mach
);
856 if (chosen_arch
!= NULL
)
858 mips_processor
= chosen_arch
->processor
;
859 mips_isa
= chosen_arch
->isa
;
860 mips_ase
= chosen_arch
->ase
;
861 mips_cp0_names
= chosen_arch
->cp0_names
;
862 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
863 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
864 mips_cp1_names
= chosen_arch
->cp1_names
;
865 mips_hwr_names
= chosen_arch
->hwr_names
;
868 /* Update settings according to the ELF file header flags. */
869 if (info
->flavour
== bfd_target_elf_flavour
&& info
->section
!= NULL
)
871 struct bfd
*abfd
= info
->section
->owner
;
872 Elf_Internal_Ehdr
*header
= elf_elfheader (abfd
);
873 Elf_Internal_ABIFlags_v0
*abiflags
= NULL
;
875 /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
876 because we won't then have a MIPS/ELF BFD, however we need
877 to guard against a link error in a `--enable-targets=...'
878 configuration with a 32-bit host where the MIPS target is
879 a secondary, or with MIPS/ECOFF configurations. */
880 #ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
881 abiflags
= bfd_mips_elf_get_abiflags (abfd
);
883 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
884 if (is_newabi (header
))
885 mips_gpr_names
= mips_gpr_names_newabi
;
886 /* If a microMIPS binary, then don't use MIPS16 bindings. */
887 micromips_ase
= is_micromips (header
);
888 /* OR in any extra ASE flags set in ELF file structures. */
890 mips_ase
|= mips_convert_abiflags_ases (abiflags
->ases
);
891 else if (header
->e_flags
& EF_MIPS_ARCH_ASE_MDMX
)
892 mips_ase
|= ASE_MDMX
;
895 mips_ase
|= mips_calculate_combination_ases (mips_ase
);
898 /* Parse an ASE disassembler option and set the corresponding global
899 ASE flag(s). Return TRUE if successful, FALSE otherwise. */
902 parse_mips_ase_option (const char *option
)
904 if (CONST_STRNEQ (option
, "msa"))
907 if ((mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R2
908 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R3
909 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R5
910 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
)
911 mips_ase
|= ASE_MSA64
;
915 if (CONST_STRNEQ (option
, "virt"))
917 mips_ase
|= ASE_VIRT
;
918 if (mips_isa
& ISA_MIPS64R2
919 || mips_isa
& ISA_MIPS64R3
920 || mips_isa
& ISA_MIPS64R5
921 || mips_isa
& ISA_MIPS64R6
)
922 mips_ase
|= ASE_VIRT64
;
926 if (CONST_STRNEQ (option
, "xpa"))
932 if (CONST_STRNEQ (option
, "ginv"))
934 mips_ase
|= ASE_GINV
;
938 if (CONST_STRNEQ (option
, "loongson-mmi"))
940 mips_ase
|= ASE_LOONGSON_MMI
;
948 parse_mips_dis_option (const char *option
, unsigned int len
)
950 unsigned int i
, optionlen
, vallen
;
952 const struct mips_abi_choice
*chosen_abi
;
953 const struct mips_arch_choice
*chosen_arch
;
955 /* Try to match options that are simple flags */
956 if (CONST_STRNEQ (option
, "no-aliases"))
962 if (parse_mips_ase_option (option
))
964 mips_ase
|= mips_calculate_combination_ases (mips_ase
);
968 /* Look for the = that delimits the end of the option name. */
969 for (i
= 0; i
< len
; i
++)
970 if (option
[i
] == '=')
973 if (i
== 0) /* Invalid option: no name before '='. */
975 if (i
== len
) /* Invalid option: no '='. */
977 if (i
== (len
- 1)) /* Invalid option: no value after '='. */
981 val
= option
+ (optionlen
+ 1);
982 vallen
= len
- (optionlen
+ 1);
984 if (strncmp ("gpr-names", option
, optionlen
) == 0
985 && strlen ("gpr-names") == optionlen
)
987 chosen_abi
= choose_abi_by_name (val
, vallen
);
988 if (chosen_abi
!= NULL
)
989 mips_gpr_names
= chosen_abi
->gpr_names
;
993 if (strncmp ("fpr-names", option
, optionlen
) == 0
994 && strlen ("fpr-names") == optionlen
)
996 chosen_abi
= choose_abi_by_name (val
, vallen
);
997 if (chosen_abi
!= NULL
)
998 mips_fpr_names
= chosen_abi
->fpr_names
;
1002 if (strncmp ("cp0-names", option
, optionlen
) == 0
1003 && strlen ("cp0-names") == optionlen
)
1005 chosen_arch
= choose_arch_by_name (val
, vallen
);
1006 if (chosen_arch
!= NULL
)
1008 mips_cp0_names
= chosen_arch
->cp0_names
;
1009 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1010 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1015 if (strncmp ("cp1-names", option
, optionlen
) == 0
1016 && strlen ("cp1-names") == optionlen
)
1018 chosen_arch
= choose_arch_by_name (val
, vallen
);
1019 if (chosen_arch
!= NULL
)
1020 mips_cp1_names
= chosen_arch
->cp1_names
;
1024 if (strncmp ("hwr-names", option
, optionlen
) == 0
1025 && strlen ("hwr-names") == optionlen
)
1027 chosen_arch
= choose_arch_by_name (val
, vallen
);
1028 if (chosen_arch
!= NULL
)
1029 mips_hwr_names
= chosen_arch
->hwr_names
;
1033 if (strncmp ("reg-names", option
, optionlen
) == 0
1034 && strlen ("reg-names") == optionlen
)
1036 /* We check both ABI and ARCH here unconditionally, so
1037 that "numeric" will do the desirable thing: select
1038 numeric register names for all registers. Other than
1039 that, a given name probably won't match both. */
1040 chosen_abi
= choose_abi_by_name (val
, vallen
);
1041 if (chosen_abi
!= NULL
)
1043 mips_gpr_names
= chosen_abi
->gpr_names
;
1044 mips_fpr_names
= chosen_abi
->fpr_names
;
1046 chosen_arch
= choose_arch_by_name (val
, vallen
);
1047 if (chosen_arch
!= NULL
)
1049 mips_cp0_names
= chosen_arch
->cp0_names
;
1050 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1051 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1052 mips_cp1_names
= chosen_arch
->cp1_names
;
1053 mips_hwr_names
= chosen_arch
->hwr_names
;
1058 /* Invalid option. */
1062 parse_mips_dis_options (const char *options
)
1064 const char *option_end
;
1066 if (options
== NULL
)
1069 while (*options
!= '\0')
1071 /* Skip empty options. */
1072 if (*options
== ',')
1078 /* We know that *options is neither NUL or a comma. */
1079 option_end
= options
+ 1;
1080 while (*option_end
!= ',' && *option_end
!= '\0')
1083 parse_mips_dis_option (options
, option_end
- options
);
1085 /* Go on to the next one. If option_end points to a comma, it
1086 will be skipped above. */
1087 options
= option_end
;
1091 static const struct mips_cp0sel_name
*
1092 lookup_mips_cp0sel_name (const struct mips_cp0sel_name
*names
,
1094 unsigned int cp0reg
,
1099 for (i
= 0; i
< len
; i
++)
1100 if (names
[i
].cp0reg
== cp0reg
&& names
[i
].sel
== sel
)
1105 /* Print register REGNO, of type TYPE, for instruction OPCODE. */
1108 print_reg (struct disassemble_info
*info
, const struct mips_opcode
*opcode
,
1109 enum mips_reg_operand_type type
, int regno
)
1114 info
->fprintf_func (info
->stream
, "%s", mips_gpr_names
[regno
]);
1118 info
->fprintf_func (info
->stream
, "%s", mips_fpr_names
[regno
]);
1122 if (opcode
->pinfo
& (FP_D
| FP_S
))
1123 info
->fprintf_func (info
->stream
, "$fcc%d", regno
);
1125 info
->fprintf_func (info
->stream
, "$cc%d", regno
);
1129 if (opcode
->membership
& INSN_5400
)
1130 info
->fprintf_func (info
->stream
, "$f%d", regno
);
1132 info
->fprintf_func (info
->stream
, "$v%d", regno
);
1136 info
->fprintf_func (info
->stream
, "$ac%d", regno
);
1140 if (opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1141 info
->fprintf_func (info
->stream
, "%s", mips_cp0_names
[regno
]);
1142 else if (opcode
->name
[strlen (opcode
->name
) - 1] == '1')
1143 info
->fprintf_func (info
->stream
, "%s", mips_cp1_names
[regno
]);
1145 info
->fprintf_func (info
->stream
, "$%d", regno
);
1149 info
->fprintf_func (info
->stream
, "%s", mips_hwr_names
[regno
]);
1153 info
->fprintf_func (info
->stream
, "$vf%d", regno
);
1157 info
->fprintf_func (info
->stream
, "$vi%d", regno
);
1160 case OP_REG_R5900_I
:
1161 info
->fprintf_func (info
->stream
, "$I");
1164 case OP_REG_R5900_Q
:
1165 info
->fprintf_func (info
->stream
, "$Q");
1168 case OP_REG_R5900_R
:
1169 info
->fprintf_func (info
->stream
, "$R");
1172 case OP_REG_R5900_ACC
:
1173 info
->fprintf_func (info
->stream
, "$ACC");
1177 info
->fprintf_func (info
->stream
, "$w%d", regno
);
1180 case OP_REG_MSA_CTRL
:
1181 info
->fprintf_func (info
->stream
, "%s", msa_control_names
[regno
]);
1187 /* Used to track the state carried over from previous operands in
1189 struct mips_print_arg_state
{
1190 /* The value of the last OP_INT seen. We only use this for OP_MSB,
1191 where the value is known to be unsigned and small. */
1192 unsigned int last_int
;
1194 /* The type and number of the last OP_REG seen. We only use this for
1195 OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1196 enum mips_reg_operand_type last_reg_type
;
1197 unsigned int last_regno
;
1198 unsigned int dest_regno
;
1199 unsigned int seen_dest
;
1202 /* Initialize STATE for the start of an instruction. */
1205 init_print_arg_state (struct mips_print_arg_state
*state
)
1207 memset (state
, 0, sizeof (*state
));
1210 /* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1211 whose value is given by UVAL. */
1214 print_vu0_channel (struct disassemble_info
*info
,
1215 const struct mips_operand
*operand
, unsigned int uval
)
1217 if (operand
->size
== 4)
1218 info
->fprintf_func (info
->stream
, "%s%s%s%s",
1219 uval
& 8 ? "x" : "",
1220 uval
& 4 ? "y" : "",
1221 uval
& 2 ? "z" : "",
1222 uval
& 1 ? "w" : "");
1223 else if (operand
->size
== 2)
1224 info
->fprintf_func (info
->stream
, "%c", "xyzw"[uval
]);
1229 /* Record information about a register operand. */
1232 mips_seen_register (struct mips_print_arg_state
*state
,
1234 enum mips_reg_operand_type reg_type
)
1236 state
->last_reg_type
= reg_type
;
1237 state
->last_regno
= regno
;
1239 if (!state
->seen_dest
)
1241 state
->seen_dest
= 1;
1242 state
->dest_regno
= regno
;
1246 /* Print SAVE/RESTORE instruction operands according to the argument
1247 register mask AMASK, the number of static registers saved NSREG,
1248 the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1249 and the frame size FRAME_SIZE. */
1252 mips_print_save_restore (struct disassemble_info
*info
, unsigned int amask
,
1253 unsigned int nsreg
, unsigned int ra
,
1254 unsigned int s0
, unsigned int s1
,
1255 unsigned int frame_size
)
1257 const fprintf_ftype infprintf
= info
->fprintf_func
;
1258 unsigned int nargs
, nstatics
, smask
, i
, j
;
1259 void *is
= info
->stream
;
1262 if (amask
== MIPS_SVRS_ALL_ARGS
)
1267 else if (amask
== MIPS_SVRS_ALL_STATICS
)
1275 nstatics
= amask
& 3;
1281 infprintf (is
, "%s", mips_gpr_names
[4]);
1283 infprintf (is
, "-%s", mips_gpr_names
[4 + nargs
- 1]);
1287 infprintf (is
, "%s%d", sep
, frame_size
);
1290 infprintf (is
, ",%s", mips_gpr_names
[31]);
1297 if (nsreg
> 0) /* $s2-$s8 */
1298 smask
|= ((1 << nsreg
) - 1) << 2;
1300 for (i
= 0; i
< 9; i
++)
1301 if (smask
& (1 << i
))
1303 infprintf (is
, ",%s", mips_gpr_names
[i
== 8 ? 30 : (16 + i
)]);
1304 /* Skip over string of set bits. */
1305 for (j
= i
; smask
& (2 << j
); j
++)
1308 infprintf (is
, "-%s", mips_gpr_names
[j
== 8 ? 30 : (16 + j
)]);
1311 /* Statics $ax - $a3. */
1313 infprintf (is
, ",%s", mips_gpr_names
[7]);
1314 else if (nstatics
> 0)
1315 infprintf (is
, ",%s-%s",
1316 mips_gpr_names
[7 - nstatics
+ 1],
1321 /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1322 UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1323 the base address for OP_PCREL operands. */
1326 print_insn_arg (struct disassemble_info
*info
,
1327 struct mips_print_arg_state
*state
,
1328 const struct mips_opcode
*opcode
,
1329 const struct mips_operand
*operand
,
1333 const fprintf_ftype infprintf
= info
->fprintf_func
;
1334 void *is
= info
->stream
;
1336 switch (operand
->type
)
1340 const struct mips_int_operand
*int_op
;
1342 int_op
= (const struct mips_int_operand
*) operand
;
1343 uval
= mips_decode_int_operand (int_op
, uval
);
1344 state
->last_int
= uval
;
1345 if (int_op
->print_hex
)
1346 infprintf (is
, "0x%x", uval
);
1348 infprintf (is
, "%d", uval
);
1354 const struct mips_mapped_int_operand
*mint_op
;
1356 mint_op
= (const struct mips_mapped_int_operand
*) operand
;
1357 uval
= mint_op
->int_map
[uval
];
1358 state
->last_int
= uval
;
1359 if (mint_op
->print_hex
)
1360 infprintf (is
, "0x%x", uval
);
1362 infprintf (is
, "%d", uval
);
1368 const struct mips_msb_operand
*msb_op
;
1370 msb_op
= (const struct mips_msb_operand
*) operand
;
1371 uval
+= msb_op
->bias
;
1372 if (msb_op
->add_lsb
)
1373 uval
-= state
->last_int
;
1374 infprintf (is
, "0x%x", uval
);
1379 case OP_OPTIONAL_REG
:
1381 const struct mips_reg_operand
*reg_op
;
1383 reg_op
= (const struct mips_reg_operand
*) operand
;
1384 uval
= mips_decode_reg_operand (reg_op
, uval
);
1385 print_reg (info
, opcode
, reg_op
->reg_type
, uval
);
1387 mips_seen_register (state
, uval
, reg_op
->reg_type
);
1393 const struct mips_reg_pair_operand
*pair_op
;
1395 pair_op
= (const struct mips_reg_pair_operand
*) operand
;
1396 print_reg (info
, opcode
, pair_op
->reg_type
,
1397 pair_op
->reg1_map
[uval
]);
1398 infprintf (is
, ",");
1399 print_reg (info
, opcode
, pair_op
->reg_type
,
1400 pair_op
->reg2_map
[uval
]);
1406 const struct mips_pcrel_operand
*pcrel_op
;
1408 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1409 info
->target
= mips_decode_pcrel_operand (pcrel_op
, base_pc
, uval
);
1411 /* For jumps and branches clear the ISA bit except for
1412 the GDB disassembler. */
1413 if (pcrel_op
->include_isa_bit
1414 && info
->flavour
!= bfd_target_unknown_flavour
)
1417 (*info
->print_address_func
) (info
->target
, info
);
1422 infprintf (is
, "%d", uval
);
1425 case OP_ADDIUSP_INT
:
1429 sval
= mips_signed_operand (operand
, uval
) * 4;
1430 if (sval
>= -8 && sval
< 8)
1432 infprintf (is
, "%d", sval
);
1436 case OP_CLO_CLZ_DEST
:
1438 unsigned int reg1
, reg2
;
1442 /* If one is zero use the other. */
1443 if (reg1
== reg2
|| reg2
== 0)
1444 infprintf (is
, "%s", mips_gpr_names
[reg1
]);
1446 infprintf (is
, "%s", mips_gpr_names
[reg2
]);
1448 /* Bogus, result depends on processor. */
1449 infprintf (is
, "%s or %s", mips_gpr_names
[reg1
],
1450 mips_gpr_names
[reg2
]);
1456 case OP_NON_ZERO_REG
:
1458 print_reg (info
, opcode
, OP_REG_GP
, uval
& 31);
1459 mips_seen_register (state
, uval
, OP_REG_GP
);
1463 case OP_LWM_SWM_LIST
:
1464 if (operand
->size
== 2)
1467 infprintf (is
, "%s,%s",
1469 mips_gpr_names
[31]);
1471 infprintf (is
, "%s-%s,%s",
1473 mips_gpr_names
[16 + uval
],
1474 mips_gpr_names
[31]);
1480 s_reg_encode
= uval
& 0xf;
1481 if (s_reg_encode
!= 0)
1483 if (s_reg_encode
== 1)
1484 infprintf (is
, "%s", mips_gpr_names
[16]);
1485 else if (s_reg_encode
< 9)
1486 infprintf (is
, "%s-%s",
1488 mips_gpr_names
[15 + s_reg_encode
]);
1489 else if (s_reg_encode
== 9)
1490 infprintf (is
, "%s-%s,%s",
1493 mips_gpr_names
[30]);
1495 infprintf (is
, "UNKNOWN");
1498 if (uval
& 0x10) /* For ra. */
1500 if (s_reg_encode
== 0)
1501 infprintf (is
, "%s", mips_gpr_names
[31]);
1503 infprintf (is
, ",%s", mips_gpr_names
[31]);
1508 case OP_ENTRY_EXIT_LIST
:
1511 unsigned int amask
, smask
;
1514 amask
= (uval
>> 3) & 7;
1515 if (amask
> 0 && amask
< 5)
1517 infprintf (is
, "%s", mips_gpr_names
[4]);
1519 infprintf (is
, "-%s", mips_gpr_names
[amask
+ 3]);
1523 smask
= (uval
>> 1) & 3;
1526 infprintf (is
, "%s??", sep
);
1531 infprintf (is
, "%s%s", sep
, mips_gpr_names
[16]);
1533 infprintf (is
, "-%s", mips_gpr_names
[smask
+ 15]);
1539 infprintf (is
, "%s%s", sep
, mips_gpr_names
[31]);
1543 if (amask
== 5 || amask
== 6)
1545 infprintf (is
, "%s%s", sep
, mips_fpr_names
[0]);
1547 infprintf (is
, "-%s", mips_fpr_names
[1]);
1552 case OP_SAVE_RESTORE_LIST
:
1553 /* Should be handled by the caller due to complex behavior. */
1556 case OP_MDMX_IMM_REG
:
1562 if ((vsel
& 0x10) == 0)
1567 for (fmt
= 0; fmt
< 3; fmt
++, vsel
>>= 1)
1568 if ((vsel
& 1) == 0)
1570 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1571 infprintf (is
, "[%d]", vsel
>> 1);
1573 else if ((vsel
& 0x08) == 0)
1574 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1576 infprintf (is
, "0x%x", uval
);
1580 case OP_REPEAT_PREV_REG
:
1581 print_reg (info
, opcode
, state
->last_reg_type
, state
->last_regno
);
1584 case OP_REPEAT_DEST_REG
:
1585 print_reg (info
, opcode
, state
->last_reg_type
, state
->dest_regno
);
1589 infprintf (is
, "$pc");
1593 print_reg (info
, opcode
, OP_REG_GP
, 28);
1597 case OP_VU0_MATCH_SUFFIX
:
1598 print_vu0_channel (info
, operand
, uval
);
1602 infprintf (is
, "[%d]", uval
);
1606 infprintf (is
, "[");
1607 print_reg (info
, opcode
, OP_REG_GP
, uval
);
1608 infprintf (is
, "]");
1613 /* Validate the arguments for INSN, which is described by OPCODE.
1614 Use DECODE_OPERAND to get the encoding of each operand. */
1617 validate_insn_args (const struct mips_opcode
*opcode
,
1618 const struct mips_operand
*(*decode_operand
) (const char *),
1621 struct mips_print_arg_state state
;
1622 const struct mips_operand
*operand
;
1626 init_print_arg_state (&state
);
1627 for (s
= opcode
->args
; *s
; ++s
)
1641 operand
= decode_operand (s
);
1645 uval
= mips_extract_operand (operand
, insn
);
1646 switch (operand
->type
)
1649 case OP_OPTIONAL_REG
:
1651 const struct mips_reg_operand
*reg_op
;
1653 reg_op
= (const struct mips_reg_operand
*) operand
;
1654 uval
= mips_decode_reg_operand (reg_op
, uval
);
1655 mips_seen_register (&state
, uval
, reg_op
->reg_type
);
1661 unsigned int reg1
, reg2
;
1666 if (reg1
!= reg2
|| reg1
== 0)
1673 const struct mips_check_prev_operand
*prev_op
;
1675 prev_op
= (const struct mips_check_prev_operand
*) operand
;
1677 if (!prev_op
->zero_ok
&& uval
== 0)
1680 if (((prev_op
->less_than_ok
&& uval
< state
.last_regno
)
1681 || (prev_op
->greater_than_ok
&& uval
> state
.last_regno
)
1682 || (prev_op
->equal_ok
&& uval
== state
.last_regno
)))
1688 case OP_NON_ZERO_REG
:
1701 case OP_ADDIUSP_INT
:
1702 case OP_CLO_CLZ_DEST
:
1703 case OP_LWM_SWM_LIST
:
1704 case OP_ENTRY_EXIT_LIST
:
1705 case OP_MDMX_IMM_REG
:
1706 case OP_REPEAT_PREV_REG
:
1707 case OP_REPEAT_DEST_REG
:
1711 case OP_VU0_MATCH_SUFFIX
:
1714 case OP_SAVE_RESTORE_LIST
:
1718 if (*s
== 'm' || *s
== '+' || *s
== '-')
1725 /* Print the arguments for INSN, which is described by OPCODE.
1726 Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
1727 as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1728 operand is for a branch or jump. */
1731 print_insn_args (struct disassemble_info
*info
,
1732 const struct mips_opcode
*opcode
,
1733 const struct mips_operand
*(*decode_operand
) (const char *),
1734 unsigned int insn
, bfd_vma insn_pc
, unsigned int length
)
1736 const fprintf_ftype infprintf
= info
->fprintf_func
;
1737 void *is
= info
->stream
;
1738 struct mips_print_arg_state state
;
1739 const struct mips_operand
*operand
;
1742 init_print_arg_state (&state
);
1743 for (s
= opcode
->args
; *s
; ++s
)
1750 infprintf (is
, "%c", *s
);
1755 infprintf (is
, "%c%c", *s
, *s
);
1759 operand
= decode_operand (s
);
1762 /* xgettext:c-format */
1764 _("# internal error, undefined operand in `%s %s'"),
1765 opcode
->name
, opcode
->args
);
1769 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
1771 /* Handle this case here because of the complex behavior. */
1772 unsigned int amask
= (insn
>> 15) & 0xf;
1773 unsigned int nsreg
= (insn
>> 23) & 0x7;
1774 unsigned int ra
= insn
& 0x1000; /* $ra */
1775 unsigned int s0
= insn
& 0x800; /* $s0 */
1776 unsigned int s1
= insn
& 0x400; /* $s1 */
1777 unsigned int frame_size
= (((insn
>> 15) & 0xf0)
1778 | ((insn
>> 6) & 0x0f)) * 8;
1779 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
,
1782 else if (operand
->type
== OP_REG
1785 && opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1787 /* Coprocessor register 0 with sel field. */
1788 const struct mips_cp0sel_name
*n
;
1789 unsigned int reg
, sel
;
1791 reg
= mips_extract_operand (operand
, insn
);
1793 operand
= decode_operand (s
);
1794 sel
= mips_extract_operand (operand
, insn
);
1796 /* CP0 register including 'sel' code for mftc0, to be
1797 printed textually if known. If not known, print both
1798 CP0 register name and sel numerically since CP0 register
1799 with sel 0 may have a name unrelated to register being
1801 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
1802 mips_cp0sel_names_len
,
1805 infprintf (is
, "%s", n
->name
);
1807 infprintf (is
, "$%d,%d", reg
, sel
);
1811 bfd_vma base_pc
= insn_pc
;
1813 /* Adjust the PC relative base so that branch/jump insns use
1814 the following PC as the base but genuinely PC relative
1815 operands use the current PC. */
1816 if (operand
->type
== OP_PCREL
)
1818 const struct mips_pcrel_operand
*pcrel_op
;
1820 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1821 /* The include_isa_bit flag is sufficient to distinguish
1822 branch/jump from other PC relative operands. */
1823 if (pcrel_op
->include_isa_bit
)
1827 print_insn_arg (info
, &state
, opcode
, operand
, base_pc
,
1828 mips_extract_operand (operand
, insn
));
1830 if (*s
== 'm' || *s
== '+' || *s
== '-')
1837 /* Print the mips instruction at address MEMADDR in debugged memory,
1838 on using INFO. Returns length of the instruction, in bytes, which is
1839 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
1840 this is little-endian code. */
1843 print_insn_mips (bfd_vma memaddr
,
1845 struct disassemble_info
*info
)
1847 #define GET_OP(insn, field) \
1848 (((insn) >> OP_SH_##field) & OP_MASK_##field)
1849 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
1850 const fprintf_ftype infprintf
= info
->fprintf_func
;
1851 const struct mips_opcode
*op
;
1852 static bfd_boolean init
= 0;
1853 void *is
= info
->stream
;
1855 /* Build a hash table to shorten the search time. */
1860 for (i
= 0; i
<= OP_MASK_OP
; i
++)
1862 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1864 if (op
->pinfo
== INSN_MACRO
1865 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
1867 if (i
== GET_OP (op
->match
, OP
))
1878 info
->bytes_per_chunk
= INSNLEN
;
1879 info
->display_endian
= info
->endian
;
1880 info
->insn_info_valid
= 1;
1881 info
->branch_delay_insns
= 0;
1882 info
->data_size
= 0;
1883 info
->insn_type
= dis_nonbranch
;
1887 op
= mips_hash
[GET_OP (word
, OP
)];
1890 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1892 if (op
->pinfo
!= INSN_MACRO
1893 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
1894 && (word
& op
->mask
) == op
->match
)
1896 /* We always disassemble the jalx instruction, except for MIPS r6. */
1897 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
)
1898 && (strcmp (op
->name
, "jalx")
1899 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS32R6
1900 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
))
1903 /* Figure out instruction type and branch delay information. */
1904 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
1906 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
1907 info
->insn_type
= dis_jsr
;
1909 info
->insn_type
= dis_branch
;
1910 info
->branch_delay_insns
= 1;
1912 else if ((op
->pinfo
& (INSN_COND_BRANCH_DELAY
1913 | INSN_COND_BRANCH_LIKELY
)) != 0)
1915 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
1916 info
->insn_type
= dis_condjsr
;
1918 info
->insn_type
= dis_condbranch
;
1919 info
->branch_delay_insns
= 1;
1921 else if ((op
->pinfo
& (INSN_STORE_MEMORY
1922 | INSN_LOAD_MEMORY
)) != 0)
1923 info
->insn_type
= dis_dref
;
1925 if (!validate_insn_args (op
, decode_mips_operand
, word
))
1928 infprintf (is
, "%s", op
->name
);
1929 if (op
->pinfo2
& INSN2_VU0_CHANNEL_SUFFIX
)
1933 infprintf (is
, ".");
1934 uval
= mips_extract_operand (&mips_vu0_channel_mask
, word
);
1935 print_vu0_channel (info
, &mips_vu0_channel_mask
, uval
);
1940 infprintf (is
, "\t");
1941 print_insn_args (info
, op
, decode_mips_operand
, word
,
1951 /* Handle undefined instructions. */
1952 info
->insn_type
= dis_noninsn
;
1953 infprintf (is
, "0x%x", word
);
1957 /* Disassemble an operand for a mips16 instruction. */
1960 print_mips16_insn_arg (struct disassemble_info
*info
,
1961 struct mips_print_arg_state
*state
,
1962 const struct mips_opcode
*opcode
,
1963 char type
, bfd_vma memaddr
,
1964 unsigned insn
, bfd_boolean use_extend
,
1965 unsigned extend
, bfd_boolean is_offset
)
1967 const fprintf_ftype infprintf
= info
->fprintf_func
;
1968 void *is
= info
->stream
;
1969 const struct mips_operand
*operand
, *ext_operand
;
1970 unsigned short ext_size
;
1982 infprintf (is
, "%c", type
);
1986 operand
= decode_mips16_operand (type
, FALSE
);
1989 /* xgettext:c-format */
1990 infprintf (is
, _("# internal error, undefined operand in `%s %s'"),
1991 opcode
->name
, opcode
->args
);
1995 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
1997 /* Handle this case here because of the complex interaction
1998 with the EXTEND opcode. */
1999 unsigned int amask
= extend
& 0xf;
2000 unsigned int nsreg
= (extend
>> 8) & 0x7;
2001 unsigned int ra
= insn
& 0x40; /* $ra */
2002 unsigned int s0
= insn
& 0x20; /* $s0 */
2003 unsigned int s1
= insn
& 0x10; /* $s1 */
2004 unsigned int frame_size
= ((extend
& 0xf0) | (insn
& 0x0f)) * 8;
2005 if (frame_size
== 0 && !use_extend
)
2007 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
, frame_size
);
2011 if (is_offset
&& operand
->type
== OP_INT
)
2013 const struct mips_int_operand
*int_op
;
2015 int_op
= (const struct mips_int_operand
*) operand
;
2016 info
->insn_type
= dis_dref
;
2017 info
->data_size
= 1 << int_op
->shift
;
2023 ext_operand
= decode_mips16_operand (type
, TRUE
);
2024 if (ext_operand
!= operand
2025 || (operand
->type
== OP_INT
&& operand
->lsb
== 0
2026 && mips_opcode_32bit_p (opcode
)))
2028 ext_size
= ext_operand
->size
;
2029 operand
= ext_operand
;
2032 if (operand
->size
== 26)
2033 uval
= ((extend
& 0x1f) << 21) | ((extend
& 0x3e0) << 11) | insn
;
2034 else if (ext_size
== 16 || ext_size
== 9)
2035 uval
= ((extend
& 0x1f) << 11) | (extend
& 0x7e0) | (insn
& 0x1f);
2036 else if (ext_size
== 15)
2037 uval
= ((extend
& 0xf) << 11) | (extend
& 0x7f0) | (insn
& 0xf);
2038 else if (ext_size
== 6)
2039 uval
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
2041 uval
= mips_extract_operand (operand
, (extend
<< 16) | insn
);
2043 uval
&= (1U << ext_size
) - 1;
2045 baseaddr
= memaddr
+ 2;
2046 if (operand
->type
== OP_PCREL
)
2048 const struct mips_pcrel_operand
*pcrel_op
;
2050 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
2051 if (!pcrel_op
->include_isa_bit
&& use_extend
)
2052 baseaddr
= memaddr
- 2;
2053 else if (!pcrel_op
->include_isa_bit
)
2057 /* If this instruction is in the delay slot of a JAL/JALX
2058 instruction, the base address is the address of the
2059 JAL/JALX instruction. If it is in the delay slot of
2060 a JR/JALR instruction, the base address is the address
2061 of the JR/JALR instruction. This test is unreliable:
2062 we have no way of knowing whether the previous word is
2063 instruction or data. */
2064 if (info
->read_memory_func (memaddr
- 4, buffer
, 2, info
) == 0
2065 && (((info
->endian
== BFD_ENDIAN_BIG
2066 ? bfd_getb16 (buffer
)
2067 : bfd_getl16 (buffer
))
2068 & 0xf800) == 0x1800))
2069 baseaddr
= memaddr
- 4;
2070 else if (info
->read_memory_func (memaddr
- 2, buffer
, 2,
2072 && (((info
->endian
== BFD_ENDIAN_BIG
2073 ? bfd_getb16 (buffer
)
2074 : bfd_getl16 (buffer
))
2075 & 0xf89f) == 0xe800)
2076 && (((info
->endian
== BFD_ENDIAN_BIG
2077 ? bfd_getb16 (buffer
)
2078 : bfd_getl16 (buffer
))
2079 & 0x0060) != 0x0060))
2080 baseaddr
= memaddr
- 2;
2086 print_insn_arg (info
, state
, opcode
, operand
, baseaddr
+ 1, uval
);
2092 /* Check if the given address is the last word of a MIPS16 PLT entry.
2093 This word is data and depending on the value it may interfere with
2094 disassembly of further PLT entries. We make use of the fact PLT
2095 symbols are marked BSF_SYNTHETIC. */
2097 is_mips16_plt_tail (struct disassemble_info
*info
, bfd_vma addr
)
2101 && (info
->symbols
[0]->flags
& BSF_SYNTHETIC
)
2102 && addr
== bfd_asymbol_value (info
->symbols
[0]) + 12)
2108 /* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2117 /* Disassemble mips16 instructions. */
2120 print_insn_mips16 (bfd_vma memaddr
, struct disassemble_info
*info
)
2122 const fprintf_ftype infprintf
= info
->fprintf_func
;
2125 const struct mips_opcode
*op
, *opend
;
2126 struct mips_print_arg_state state
;
2127 void *is
= info
->stream
;
2128 bfd_boolean have_second
;
2129 bfd_boolean extend_only
;
2130 unsigned int second
;
2134 info
->bytes_per_chunk
= 2;
2135 info
->display_endian
= info
->endian
;
2136 info
->insn_info_valid
= 1;
2137 info
->branch_delay_insns
= 0;
2138 info
->data_size
= 0;
2142 #define GET_OP(insn, field) \
2143 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
2144 /* Decode PLT entry's GOT slot address word. */
2145 if (is_mips16_plt_tail (info
, memaddr
))
2147 info
->insn_type
= dis_noninsn
;
2148 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
2151 unsigned int gotslot
;
2153 if (info
->endian
== BFD_ENDIAN_BIG
)
2154 gotslot
= bfd_getb32 (buffer
);
2156 gotslot
= bfd_getl32 (buffer
);
2157 infprintf (is
, ".word\t0x%x", gotslot
);
2164 info
->insn_type
= dis_nonbranch
;
2165 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2169 (*info
->memory_error_func
) (status
, memaddr
, info
);
2173 extend_only
= FALSE
;
2175 if (info
->endian
== BFD_ENDIAN_BIG
)
2176 first
= bfd_getb16 (buffer
);
2178 first
= bfd_getl16 (buffer
);
2180 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2184 if (info
->endian
== BFD_ENDIAN_BIG
)
2185 second
= bfd_getb16 (buffer
);
2187 second
= bfd_getl16 (buffer
);
2188 full
= (first
<< 16) | second
;
2192 have_second
= FALSE
;
2197 /* FIXME: Should probably use a hash table on the major opcode here. */
2199 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
2200 for (op
= mips16_opcodes
; op
< opend
; op
++)
2202 enum match_kind match
;
2204 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
))
2207 if (op
->pinfo
== INSN_MACRO
2208 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
2210 else if (mips_opcode_32bit_p (op
))
2213 && (full
& op
->mask
) == op
->match
)
2218 else if ((first
& op
->mask
) == op
->match
)
2220 match
= MATCH_SHORT
;
2224 else if ((first
& 0xf800) == 0xf000
2227 && (second
& op
->mask
) == op
->match
)
2229 if (op
->pinfo2
& INSN2_SHORT_ONLY
)
2240 if (match
!= MATCH_NONE
)
2244 infprintf (is
, "%s", op
->name
);
2245 if (op
->args
[0] != '\0')
2246 infprintf (is
, "\t");
2248 init_print_arg_state (&state
);
2249 for (s
= op
->args
; *s
!= '\0'; s
++)
2253 && GET_OP (full
, RX
) == GET_OP (full
, RY
))
2255 /* Skip the register and the comma. */
2261 && GET_OP (full
, RZ
) == GET_OP (full
, RX
))
2263 /* Skip the register and the comma. */
2270 && op
->name
[strlen (op
->name
) - 1] == '0')
2272 /* Coprocessor register 0 with sel field. */
2273 const struct mips_cp0sel_name
*n
;
2274 const struct mips_operand
*operand
;
2275 unsigned int reg
, sel
;
2277 operand
= decode_mips16_operand (*s
, TRUE
);
2278 reg
= mips_extract_operand (operand
, (first
<< 16) | second
);
2280 operand
= decode_mips16_operand (*s
, TRUE
);
2281 sel
= mips_extract_operand (operand
, (first
<< 16) | second
);
2283 /* CP0 register including 'sel' code for mftc0, to be
2284 printed textually if known. If not known, print both
2285 CP0 register name and sel numerically since CP0 register
2286 with sel 0 may have a name unrelated to register being
2288 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
2289 mips_cp0sel_names_len
,
2292 infprintf (is
, "%s", n
->name
);
2294 infprintf (is
, "$%d,%d", reg
, sel
);
2300 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
+ 2,
2301 second
, TRUE
, first
, s
[1] == '(');
2304 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
,
2305 first
, FALSE
, 0, s
[1] == '(');
2307 case MATCH_NONE
: /* Stop the compiler complaining. */
2312 /* Figure out branch instruction type and delay slot information. */
2313 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
2314 info
->branch_delay_insns
= 1;
2315 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0
2316 || (op
->pinfo2
& INSN2_UNCOND_BRANCH
) != 0)
2318 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2319 info
->insn_type
= dis_jsr
;
2321 info
->insn_type
= dis_branch
;
2323 else if ((op
->pinfo2
& INSN2_COND_BRANCH
) != 0)
2324 info
->insn_type
= dis_condbranch
;
2326 return match
== MATCH_FULL
? 4 : 2;
2331 infprintf (is
, "0x%x", first
);
2332 info
->insn_type
= dis_noninsn
;
2337 /* Disassemble microMIPS instructions. */
2340 print_insn_micromips (bfd_vma memaddr
, struct disassemble_info
*info
)
2342 const fprintf_ftype infprintf
= info
->fprintf_func
;
2343 const struct mips_opcode
*op
, *opend
;
2344 void *is
= info
->stream
;
2346 unsigned int higher
;
2347 unsigned int length
;
2351 info
->bytes_per_chunk
= 2;
2352 info
->display_endian
= info
->endian
;
2353 info
->insn_info_valid
= 1;
2354 info
->branch_delay_insns
= 0;
2355 info
->data_size
= 0;
2356 info
->insn_type
= dis_nonbranch
;
2360 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2363 (*info
->memory_error_func
) (status
, memaddr
, info
);
2369 if (info
->endian
== BFD_ENDIAN_BIG
)
2370 insn
= bfd_getb16 (buffer
);
2372 insn
= bfd_getl16 (buffer
);
2374 if ((insn
& 0x1c00) == 0x0000 || (insn
& 0x1000) == 0x1000)
2376 /* This is a 32-bit microMIPS instruction. */
2379 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2382 infprintf (is
, "micromips 0x%x", higher
);
2383 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
2387 if (info
->endian
== BFD_ENDIAN_BIG
)
2388 insn
= bfd_getb16 (buffer
);
2390 insn
= bfd_getl16 (buffer
);
2392 insn
= insn
| (higher
<< 16);
2397 /* FIXME: Should probably use a hash table on the major opcode here. */
2399 opend
= micromips_opcodes
+ bfd_micromips_num_opcodes
;
2400 for (op
= micromips_opcodes
; op
< opend
; op
++)
2402 if (op
->pinfo
!= INSN_MACRO
2403 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
2404 && (insn
& op
->mask
) == op
->match
2405 && ((length
== 2 && (op
->mask
& 0xffff0000) == 0)
2406 || (length
== 4 && (op
->mask
& 0xffff0000) != 0)))
2408 if (!validate_insn_args (op
, decode_micromips_operand
, insn
))
2411 infprintf (is
, "%s", op
->name
);
2415 infprintf (is
, "\t");
2416 print_insn_args (info
, op
, decode_micromips_operand
, insn
,
2417 memaddr
+ 1, length
);
2420 /* Figure out instruction type and branch delay information. */
2422 & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
)) != 0)
2423 info
->branch_delay_insns
= 1;
2424 if (((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
2425 | (op
->pinfo2
& INSN2_UNCOND_BRANCH
)) != 0)
2427 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
2428 info
->insn_type
= dis_jsr
;
2430 info
->insn_type
= dis_branch
;
2432 else if (((op
->pinfo
& INSN_COND_BRANCH_DELAY
)
2433 | (op
->pinfo2
& INSN2_COND_BRANCH
)) != 0)
2435 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2436 info
->insn_type
= dis_condjsr
;
2438 info
->insn_type
= dis_condbranch
;
2441 & (INSN_STORE_MEMORY
| INSN_LOAD_MEMORY
)) != 0)
2442 info
->insn_type
= dis_dref
;
2448 infprintf (is
, "0x%x", insn
);
2449 info
->insn_type
= dis_noninsn
;
2454 /* Return 1 if a symbol associated with the location being disassembled
2455 indicates a compressed mode, either MIPS16 or microMIPS, according to
2456 MICROMIPS_P. We iterate over all the symbols at the address being
2457 considered assuming if at least one of them indicates code compression,
2458 then such code has been genuinely produced here (other symbols could
2459 have been derived from function symbols defined elsewhere or could
2460 define data). Otherwise, return 0. */
2463 is_compressed_mode_p (struct disassemble_info
*info
, bfd_boolean micromips_p
)
2468 for (i
= info
->symtab_pos
, l
= i
+ info
->num_symbols
; i
< l
; i
++)
2469 if (((info
->symtab
[i
])->flags
& BSF_SYNTHETIC
) != 0
2471 && ELF_ST_IS_MIPS16 ((*info
->symbols
)->udata
.i
))
2473 && ELF_ST_IS_MICROMIPS ((*info
->symbols
)->udata
.i
))))
2475 else if (bfd_asymbol_flavour (info
->symtab
[i
]) == bfd_target_elf_flavour
2476 && info
->symtab
[i
]->section
== info
->section
)
2478 elf_symbol_type
*symbol
= (elf_symbol_type
*) info
->symtab
[i
];
2480 && ELF_ST_IS_MIPS16 (symbol
->internal_elf_sym
.st_other
))
2482 && ELF_ST_IS_MICROMIPS (symbol
->internal_elf_sym
.st_other
)))
2489 /* In an environment where we do not know the symbol type of the
2490 instruction we are forced to assume that the low order bit of the
2491 instructions' address may mark it as a mips16 instruction. If we
2492 are single stepping, or the pc is within the disassembled function,
2493 this works. Otherwise, we need a clue. Sometimes. */
2496 _print_insn_mips (bfd_vma memaddr
,
2497 struct disassemble_info
*info
,
2498 enum bfd_endian endianness
)
2500 bfd_byte buffer
[INSNLEN
];
2503 set_default_mips_dis_options (info
);
2504 parse_mips_dis_options (info
->disassembler_options
);
2506 if (info
->mach
== bfd_mach_mips16
)
2507 return print_insn_mips16 (memaddr
, info
);
2508 if (info
->mach
== bfd_mach_mips_micromips
)
2509 return print_insn_micromips (memaddr
, info
);
2512 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
2513 /* Only a few tools will work this way. */
2517 return print_insn_micromips (memaddr
, info
);
2519 return print_insn_mips16 (memaddr
, info
);
2523 #if SYMTAB_AVAILABLE
2524 if (is_compressed_mode_p (info
, TRUE
))
2525 return print_insn_micromips (memaddr
, info
);
2526 if (is_compressed_mode_p (info
, FALSE
))
2527 return print_insn_mips16 (memaddr
, info
);
2530 status
= (*info
->read_memory_func
) (memaddr
, buffer
, INSNLEN
, info
);
2535 if (endianness
== BFD_ENDIAN_BIG
)
2536 insn
= bfd_getb32 (buffer
);
2538 insn
= bfd_getl32 (buffer
);
2540 return print_insn_mips (memaddr
, insn
, info
);
2544 (*info
->memory_error_func
) (status
, memaddr
, info
);
2550 print_insn_big_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2552 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_BIG
);
2556 print_insn_little_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2558 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_LITTLE
);
2561 /* Indices into option argument vector for options accepting an argument.
2562 Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2565 MIPS_OPTION_ARG_NONE
= -1,
2566 MIPS_OPTION_ARG_ABI
,
2567 MIPS_OPTION_ARG_ARCH
,
2568 MIPS_OPTION_ARG_SIZE
2569 } mips_option_arg_t
;
2571 /* Valid MIPS disassembler options. */
2575 const char *description
;
2576 mips_option_arg_t arg
;
2579 { "no-aliases", N_("Use canonical instruction forms.\n"),
2580 MIPS_OPTION_ARG_NONE
},
2581 { "msa", N_("Recognize MSA instructions.\n"),
2582 MIPS_OPTION_ARG_NONE
},
2583 { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2584 MIPS_OPTION_ARG_NONE
},
2585 { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2587 MIPS_OPTION_ARG_NONE
},
2588 { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2590 MIPS_OPTION_ARG_NONE
},
2592 N_("Recognize the Loongson MultiMedia extensions "
2593 "Instructions (MMI) ASE instructions.\n"),
2594 MIPS_OPTION_ARG_NONE
},
2595 { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2596 Default: based on binary being disassembled.\n"),
2597 MIPS_OPTION_ARG_ABI
},
2598 { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2599 Default: numeric.\n"),
2600 MIPS_OPTION_ARG_ABI
},
2601 { "cp0-names=", N_("Print CP0 register names according to specified "
2603 Default: based on binary being disassembled.\n"),
2604 MIPS_OPTION_ARG_ARCH
},
2605 { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2606 Default: based on binary being disassembled.\n"),
2607 MIPS_OPTION_ARG_ARCH
},
2608 { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2609 MIPS_OPTION_ARG_ABI
},
2610 { "reg-names=", N_("Print CP0 register and HWR names according to "
2613 MIPS_OPTION_ARG_ARCH
}
2616 /* Build the structure representing valid MIPS disassembler options.
2617 This is done dynamically for maintenance ease purpose; a static
2618 initializer would be unreadable. */
2620 const disasm_options_and_args_t
*
2621 disassembler_options_mips (void)
2623 static disasm_options_and_args_t
*opts_and_args
;
2625 if (opts_and_args
== NULL
)
2627 size_t num_options
= ARRAY_SIZE (mips_options
);
2628 size_t num_args
= MIPS_OPTION_ARG_SIZE
;
2629 disasm_option_arg_t
*args
;
2630 disasm_options_t
*opts
;
2634 args
= XNEWVEC (disasm_option_arg_t
, num_args
+ 1);
2636 args
[MIPS_OPTION_ARG_ABI
].name
= "ABI";
2637 args
[MIPS_OPTION_ARG_ABI
].values
2638 = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices
) + 1);
2639 for (i
= 0; i
< ARRAY_SIZE (mips_abi_choices
); i
++)
2640 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = mips_abi_choices
[i
].name
;
2641 /* The array we return must be NULL terminated. */
2642 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = NULL
;
2644 args
[MIPS_OPTION_ARG_ARCH
].name
= "ARCH";
2645 args
[MIPS_OPTION_ARG_ARCH
].values
2646 = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices
) + 1);
2647 for (i
= 0, j
= 0; i
< ARRAY_SIZE (mips_arch_choices
); i
++)
2648 if (*mips_arch_choices
[i
].name
!= '\0')
2649 args
[MIPS_OPTION_ARG_ARCH
].values
[j
++] = mips_arch_choices
[i
].name
;
2650 /* The array we return must be NULL terminated. */
2651 args
[MIPS_OPTION_ARG_ARCH
].values
[j
] = NULL
;
2653 /* The array we return must be NULL terminated. */
2654 args
[MIPS_OPTION_ARG_SIZE
].name
= NULL
;
2655 args
[MIPS_OPTION_ARG_SIZE
].values
= NULL
;
2657 opts_and_args
= XNEW (disasm_options_and_args_t
);
2658 opts_and_args
->args
= args
;
2660 opts
= &opts_and_args
->options
;
2661 opts
->name
= XNEWVEC (const char *, num_options
+ 1);
2662 opts
->description
= XNEWVEC (const char *, num_options
+ 1);
2663 opts
->arg
= XNEWVEC (const disasm_option_arg_t
*, num_options
+ 1);
2664 for (i
= 0; i
< num_options
; i
++)
2666 opts
->name
[i
] = mips_options
[i
].name
;
2667 opts
->description
[i
] = _(mips_options
[i
].description
);
2668 if (mips_options
[i
].arg
!= MIPS_OPTION_ARG_NONE
)
2669 opts
->arg
[i
] = &args
[mips_options
[i
].arg
];
2671 opts
->arg
[i
] = NULL
;
2673 /* The array we return must be NULL terminated. */
2674 opts
->name
[i
] = NULL
;
2675 opts
->description
[i
] = NULL
;
2676 opts
->arg
[i
] = NULL
;
2679 return opts_and_args
;
2683 print_mips_disassembler_options (FILE *stream
)
2685 const disasm_options_and_args_t
*opts_and_args
;
2686 const disasm_option_arg_t
*args
;
2687 const disasm_options_t
*opts
;
2692 opts_and_args
= disassembler_options_mips ();
2693 opts
= &opts_and_args
->options
;
2694 args
= opts_and_args
->args
;
2696 fprintf (stream
, _("\n\
2697 The following MIPS specific disassembler options are supported for use\n\
2698 with the -M switch (multiple options should be separated by commas):\n\n"));
2700 /* Compute the length of the longest option name. */
2701 for (i
= 0; opts
->name
[i
] != NULL
; i
++)
2703 size_t len
= strlen (opts
->name
[i
]);
2705 if (opts
->arg
[i
] != NULL
)
2706 len
+= strlen (opts
->arg
[i
]->name
);
2711 for (i
= 0, max_len
++; opts
->name
[i
] != NULL
; i
++)
2713 fprintf (stream
, " %s", opts
->name
[i
]);
2714 if (opts
->arg
[i
] != NULL
)
2715 fprintf (stream
, "%s", opts
->arg
[i
]->name
);
2716 if (opts
->description
[i
] != NULL
)
2718 size_t len
= strlen (opts
->name
[i
]);
2720 if (opts
->arg
[i
] != NULL
)
2721 len
+= strlen (opts
->arg
[i
]->name
);
2723 "%*c %s", (int) (max_len
- len
), ' ', opts
->description
[i
]);
2725 fprintf (stream
, _("\n"));
2728 for (i
= 0; args
[i
].name
!= NULL
; i
++)
2730 fprintf (stream
, _("\n\
2731 For the options above, the following values are supported for \"%s\":\n "),
2733 for (j
= 0; args
[i
].values
[j
] != NULL
; j
++)
2734 fprintf (stream
, " %s", args
[i
].values
[j
]);
2735 fprintf (stream
, _("\n"));
2738 fprintf (stream
, _("\n"));