1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 Copyright (C) 1989-2018 Free Software Foundation, Inc.
3 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
5 This file is part of the GNU opcodes library.
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
23 #include "disassemble.h"
24 #include "libiberty.h"
25 #include "opcode/mips.h"
28 /* FIXME: These are needed to figure out if the code is mips16 or
29 not. The low bit of the address is often a good indicator. No
30 symbol table is available when this code runs out in an embedded
31 system as when it is used for disassembler support in a monitor. */
33 #if !defined(EMBEDDED_ENV)
34 #define SYMTAB_AVAILABLE 1
39 /* Mips instructions are at maximum this many bytes long. */
43 /* FIXME: These should be shared with gdb somehow. */
45 struct mips_cp0sel_name
49 const char * const name
;
52 static const char * const mips_gpr_names_numeric
[32] =
54 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
55 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
56 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
57 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
60 static const char * const mips_gpr_names_oldabi
[32] =
62 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
63 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
64 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
65 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
68 static const char * const mips_gpr_names_newabi
[32] =
70 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
71 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
72 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
73 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
76 static const char * const mips_fpr_names_numeric
[32] =
78 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
79 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
80 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
81 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
84 static const char * const mips_fpr_names_32
[32] =
86 "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
87 "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
88 "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f",
89 "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f"
92 static const char * const mips_fpr_names_n32
[32] =
94 "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3",
95 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
96 "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9",
97 "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13"
100 static const char * const mips_fpr_names_64
[32] =
102 "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
103 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
104 "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
105 "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
108 static const char * const mips_cp0_names_numeric
[32] =
110 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
111 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
112 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
113 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
116 static const char * const mips_cp1_names_numeric
[32] =
118 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
119 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
120 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
121 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
124 static const char * const mips_cp0_names_r3000
[32] =
126 "c0_index", "c0_random", "c0_entrylo", "$3",
127 "c0_context", "$5", "$6", "$7",
128 "c0_badvaddr", "$9", "c0_entryhi", "$11",
129 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
130 "$16", "$17", "$18", "$19",
131 "$20", "$21", "$22", "$23",
132 "$24", "$25", "$26", "$27",
133 "$28", "$29", "$30", "$31",
136 static const char * const mips_cp0_names_r4000
[32] =
138 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
139 "c0_context", "c0_pagemask", "c0_wired", "$7",
140 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
141 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
142 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
143 "c0_xcontext", "$21", "$22", "$23",
144 "$24", "$25", "c0_ecc", "c0_cacheerr",
145 "c0_taglo", "c0_taghi", "c0_errorepc", "$31",
148 static const char * const mips_cp0_names_r5900
[32] =
150 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
151 "c0_context", "c0_pagemask", "c0_wired", "$7",
152 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
153 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
154 "c0_config", "$17", "$18", "$19",
155 "$20", "$21", "$22", "c0_badpaddr",
156 "c0_depc", "c0_perfcnt", "$26", "$27",
157 "c0_taglo", "c0_taghi", "c0_errorepc", "$31"
160 static const char * const mips_cp0_names_mips3264
[32] =
162 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
163 "c0_context", "c0_pagemask", "c0_wired", "$7",
164 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
165 "c0_status", "c0_cause", "c0_epc", "c0_prid",
166 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
167 "c0_xcontext", "$21", "$22", "c0_debug",
168 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
169 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
172 static const char * const mips_cp1_names_mips3264
[32] =
174 "c1_fir", "c1_ufr", "$2", "$3",
175 "c1_unfr", "$5", "$6", "$7",
176 "$8", "$9", "$10", "$11",
177 "$12", "$13", "$14", "$15",
178 "$16", "$17", "$18", "$19",
179 "$20", "$21", "$22", "$23",
180 "$24", "c1_fccr", "c1_fexr", "$27",
181 "c1_fenr", "$29", "$30", "c1_fcsr"
184 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264
[] =
186 { 16, 1, "c0_config1" },
187 { 16, 2, "c0_config2" },
188 { 16, 3, "c0_config3" },
189 { 18, 1, "c0_watchlo,1" },
190 { 18, 2, "c0_watchlo,2" },
191 { 18, 3, "c0_watchlo,3" },
192 { 18, 4, "c0_watchlo,4" },
193 { 18, 5, "c0_watchlo,5" },
194 { 18, 6, "c0_watchlo,6" },
195 { 18, 7, "c0_watchlo,7" },
196 { 19, 1, "c0_watchhi,1" },
197 { 19, 2, "c0_watchhi,2" },
198 { 19, 3, "c0_watchhi,3" },
199 { 19, 4, "c0_watchhi,4" },
200 { 19, 5, "c0_watchhi,5" },
201 { 19, 6, "c0_watchhi,6" },
202 { 19, 7, "c0_watchhi,7" },
203 { 25, 1, "c0_perfcnt,1" },
204 { 25, 2, "c0_perfcnt,2" },
205 { 25, 3, "c0_perfcnt,3" },
206 { 25, 4, "c0_perfcnt,4" },
207 { 25, 5, "c0_perfcnt,5" },
208 { 25, 6, "c0_perfcnt,6" },
209 { 25, 7, "c0_perfcnt,7" },
210 { 27, 1, "c0_cacheerr,1" },
211 { 27, 2, "c0_cacheerr,2" },
212 { 27, 3, "c0_cacheerr,3" },
213 { 28, 1, "c0_datalo" },
214 { 29, 1, "c0_datahi" }
217 static const char * const mips_cp0_names_mips3264r2
[32] =
219 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
220 "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
221 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
222 "c0_status", "c0_cause", "c0_epc", "c0_prid",
223 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
224 "c0_xcontext", "$21", "$22", "c0_debug",
225 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
226 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
229 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2
[] =
231 { 4, 1, "c0_contextconfig" },
232 { 0, 1, "c0_mvpcontrol" },
233 { 0, 2, "c0_mvpconf0" },
234 { 0, 3, "c0_mvpconf1" },
235 { 1, 1, "c0_vpecontrol" },
236 { 1, 2, "c0_vpeconf0" },
237 { 1, 3, "c0_vpeconf1" },
238 { 1, 4, "c0_yqmask" },
239 { 1, 5, "c0_vpeschedule" },
240 { 1, 6, "c0_vpeschefback" },
241 { 2, 1, "c0_tcstatus" },
242 { 2, 2, "c0_tcbind" },
243 { 2, 3, "c0_tcrestart" },
244 { 2, 4, "c0_tchalt" },
245 { 2, 5, "c0_tccontext" },
246 { 2, 6, "c0_tcschedule" },
247 { 2, 7, "c0_tcschefback" },
248 { 5, 1, "c0_pagegrain" },
249 { 6, 1, "c0_srsconf0" },
250 { 6, 2, "c0_srsconf1" },
251 { 6, 3, "c0_srsconf2" },
252 { 6, 4, "c0_srsconf3" },
253 { 6, 5, "c0_srsconf4" },
254 { 12, 1, "c0_intctl" },
255 { 12, 2, "c0_srsctl" },
256 { 12, 3, "c0_srsmap" },
257 { 15, 1, "c0_ebase" },
258 { 16, 1, "c0_config1" },
259 { 16, 2, "c0_config2" },
260 { 16, 3, "c0_config3" },
261 { 18, 1, "c0_watchlo,1" },
262 { 18, 2, "c0_watchlo,2" },
263 { 18, 3, "c0_watchlo,3" },
264 { 18, 4, "c0_watchlo,4" },
265 { 18, 5, "c0_watchlo,5" },
266 { 18, 6, "c0_watchlo,6" },
267 { 18, 7, "c0_watchlo,7" },
268 { 19, 1, "c0_watchhi,1" },
269 { 19, 2, "c0_watchhi,2" },
270 { 19, 3, "c0_watchhi,3" },
271 { 19, 4, "c0_watchhi,4" },
272 { 19, 5, "c0_watchhi,5" },
273 { 19, 6, "c0_watchhi,6" },
274 { 19, 7, "c0_watchhi,7" },
275 { 23, 1, "c0_tracecontrol" },
276 { 23, 2, "c0_tracecontrol2" },
277 { 23, 3, "c0_usertracedata" },
278 { 23, 4, "c0_tracebpc" },
279 { 25, 1, "c0_perfcnt,1" },
280 { 25, 2, "c0_perfcnt,2" },
281 { 25, 3, "c0_perfcnt,3" },
282 { 25, 4, "c0_perfcnt,4" },
283 { 25, 5, "c0_perfcnt,5" },
284 { 25, 6, "c0_perfcnt,6" },
285 { 25, 7, "c0_perfcnt,7" },
286 { 27, 1, "c0_cacheerr,1" },
287 { 27, 2, "c0_cacheerr,2" },
288 { 27, 3, "c0_cacheerr,3" },
289 { 28, 1, "c0_datalo" },
290 { 28, 2, "c0_taglo1" },
291 { 28, 3, "c0_datalo1" },
292 { 28, 4, "c0_taglo2" },
293 { 28, 5, "c0_datalo2" },
294 { 28, 6, "c0_taglo3" },
295 { 28, 7, "c0_datalo3" },
296 { 29, 1, "c0_datahi" },
297 { 29, 2, "c0_taghi1" },
298 { 29, 3, "c0_datahi1" },
299 { 29, 4, "c0_taghi2" },
300 { 29, 5, "c0_datahi2" },
301 { 29, 6, "c0_taghi3" },
302 { 29, 7, "c0_datahi3" },
305 /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
306 static const char * const mips_cp0_names_sb1
[32] =
308 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
309 "c0_context", "c0_pagemask", "c0_wired", "$7",
310 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
311 "c0_status", "c0_cause", "c0_epc", "c0_prid",
312 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
313 "c0_xcontext", "$21", "$22", "c0_debug",
314 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
315 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
318 static const struct mips_cp0sel_name mips_cp0sel_names_sb1
[] =
320 { 16, 1, "c0_config1" },
321 { 18, 1, "c0_watchlo,1" },
322 { 19, 1, "c0_watchhi,1" },
323 { 22, 0, "c0_perftrace" },
324 { 23, 3, "c0_edebug" },
325 { 25, 1, "c0_perfcnt,1" },
326 { 25, 2, "c0_perfcnt,2" },
327 { 25, 3, "c0_perfcnt,3" },
328 { 25, 4, "c0_perfcnt,4" },
329 { 25, 5, "c0_perfcnt,5" },
330 { 25, 6, "c0_perfcnt,6" },
331 { 25, 7, "c0_perfcnt,7" },
332 { 26, 1, "c0_buserr_pa" },
333 { 27, 1, "c0_cacheerr_d" },
334 { 27, 3, "c0_cacheerr_d_pa" },
335 { 28, 1, "c0_datalo_i" },
336 { 28, 2, "c0_taglo_d" },
337 { 28, 3, "c0_datalo_d" },
338 { 29, 1, "c0_datahi_i" },
339 { 29, 2, "c0_taghi_d" },
340 { 29, 3, "c0_datahi_d" },
343 /* Xlr cop0 register names. */
344 static const char * const mips_cp0_names_xlr
[32] = {
345 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
346 "c0_context", "c0_pagemask", "c0_wired", "$7",
347 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
348 "c0_status", "c0_cause", "c0_epc", "c0_prid",
349 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
350 "c0_xcontext", "$21", "$22", "c0_debug",
351 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
352 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
355 /* XLR's CP0 Select Registers. */
357 static const struct mips_cp0sel_name mips_cp0sel_names_xlr
[] = {
358 { 9, 6, "c0_extintreq" },
359 { 9, 7, "c0_extintmask" },
360 { 15, 1, "c0_ebase" },
361 { 16, 1, "c0_config1" },
362 { 16, 2, "c0_config2" },
363 { 16, 3, "c0_config3" },
364 { 16, 7, "c0_procid2" },
365 { 18, 1, "c0_watchlo,1" },
366 { 18, 2, "c0_watchlo,2" },
367 { 18, 3, "c0_watchlo,3" },
368 { 18, 4, "c0_watchlo,4" },
369 { 18, 5, "c0_watchlo,5" },
370 { 18, 6, "c0_watchlo,6" },
371 { 18, 7, "c0_watchlo,7" },
372 { 19, 1, "c0_watchhi,1" },
373 { 19, 2, "c0_watchhi,2" },
374 { 19, 3, "c0_watchhi,3" },
375 { 19, 4, "c0_watchhi,4" },
376 { 19, 5, "c0_watchhi,5" },
377 { 19, 6, "c0_watchhi,6" },
378 { 19, 7, "c0_watchhi,7" },
379 { 25, 1, "c0_perfcnt,1" },
380 { 25, 2, "c0_perfcnt,2" },
381 { 25, 3, "c0_perfcnt,3" },
382 { 25, 4, "c0_perfcnt,4" },
383 { 25, 5, "c0_perfcnt,5" },
384 { 25, 6, "c0_perfcnt,6" },
385 { 25, 7, "c0_perfcnt,7" },
386 { 27, 1, "c0_cacheerr,1" },
387 { 27, 2, "c0_cacheerr,2" },
388 { 27, 3, "c0_cacheerr,3" },
389 { 28, 1, "c0_datalo" },
390 { 29, 1, "c0_datahi" }
393 static const char * const mips_hwr_names_numeric
[32] =
395 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
396 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
397 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
398 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
401 static const char * const mips_hwr_names_mips3264r2
[32] =
403 "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
404 "$4", "$5", "$6", "$7",
405 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
406 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
407 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
410 static const char * const msa_control_names
[32] =
412 "msa_ir", "msa_csr", "msa_access", "msa_save",
413 "msa_modify", "msa_request", "msa_map", "msa_unmap",
414 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
415 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
416 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
419 struct mips_abi_choice
422 const char * const *gpr_names
;
423 const char * const *fpr_names
;
426 struct mips_abi_choice mips_abi_choices
[] =
428 { "numeric", mips_gpr_names_numeric
, mips_fpr_names_numeric
},
429 { "32", mips_gpr_names_oldabi
, mips_fpr_names_32
},
430 { "n32", mips_gpr_names_newabi
, mips_fpr_names_n32
},
431 { "64", mips_gpr_names_newabi
, mips_fpr_names_64
},
434 struct mips_arch_choice
438 unsigned long bfd_mach
;
442 const char * const *cp0_names
;
443 const struct mips_cp0sel_name
*cp0sel_names
;
444 unsigned int cp0sel_names_len
;
445 const char * const *cp1_names
;
446 const char * const *hwr_names
;
449 const struct mips_arch_choice mips_arch_choices
[] =
451 { "numeric", 0, 0, 0, 0, 0,
452 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
453 mips_hwr_names_numeric
},
455 { "r3000", 1, bfd_mach_mips3000
, CPU_R3000
, ISA_MIPS1
, 0,
456 mips_cp0_names_r3000
, NULL
, 0, mips_cp1_names_numeric
,
457 mips_hwr_names_numeric
},
458 { "r3900", 1, bfd_mach_mips3900
, CPU_R3900
, ISA_MIPS1
, 0,
459 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
460 mips_hwr_names_numeric
},
461 { "r4000", 1, bfd_mach_mips4000
, CPU_R4000
, ISA_MIPS3
, 0,
462 mips_cp0_names_r4000
, NULL
, 0, mips_cp1_names_numeric
,
463 mips_hwr_names_numeric
},
464 { "r4010", 1, bfd_mach_mips4010
, CPU_R4010
, ISA_MIPS2
, 0,
465 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
466 mips_hwr_names_numeric
},
467 { "vr4100", 1, bfd_mach_mips4100
, CPU_VR4100
, ISA_MIPS3
, 0,
468 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
469 mips_hwr_names_numeric
},
470 { "vr4111", 1, bfd_mach_mips4111
, CPU_R4111
, ISA_MIPS3
, 0,
471 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
472 mips_hwr_names_numeric
},
473 { "vr4120", 1, bfd_mach_mips4120
, CPU_VR4120
, ISA_MIPS3
, 0,
474 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
475 mips_hwr_names_numeric
},
476 { "r4300", 1, bfd_mach_mips4300
, CPU_R4300
, ISA_MIPS3
, 0,
477 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
478 mips_hwr_names_numeric
},
479 { "r4400", 1, bfd_mach_mips4400
, CPU_R4400
, ISA_MIPS3
, 0,
480 mips_cp0_names_r4000
, NULL
, 0, mips_cp1_names_numeric
,
481 mips_hwr_names_numeric
},
482 { "r4600", 1, bfd_mach_mips4600
, CPU_R4600
, ISA_MIPS3
, 0,
483 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
484 mips_hwr_names_numeric
},
485 { "r4650", 1, bfd_mach_mips4650
, CPU_R4650
, ISA_MIPS3
, 0,
486 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
487 mips_hwr_names_numeric
},
488 { "r5000", 1, bfd_mach_mips5000
, CPU_R5000
, ISA_MIPS4
, 0,
489 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
490 mips_hwr_names_numeric
},
491 { "vr5400", 1, bfd_mach_mips5400
, CPU_VR5400
, ISA_MIPS4
, 0,
492 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
493 mips_hwr_names_numeric
},
494 { "vr5500", 1, bfd_mach_mips5500
, CPU_VR5500
, ISA_MIPS4
, 0,
495 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
496 mips_hwr_names_numeric
},
497 { "r5900", 1, bfd_mach_mips5900
, CPU_R5900
, ISA_MIPS3
, 0,
498 mips_cp0_names_r5900
, NULL
, 0, mips_cp1_names_numeric
,
499 mips_hwr_names_numeric
},
500 { "r6000", 1, bfd_mach_mips6000
, CPU_R6000
, ISA_MIPS2
, 0,
501 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
502 mips_hwr_names_numeric
},
503 { "rm7000", 1, bfd_mach_mips7000
, CPU_RM7000
, ISA_MIPS4
, 0,
504 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
505 mips_hwr_names_numeric
},
506 { "rm9000", 1, bfd_mach_mips7000
, CPU_RM7000
, ISA_MIPS4
, 0,
507 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
508 mips_hwr_names_numeric
},
509 { "r8000", 1, bfd_mach_mips8000
, CPU_R8000
, ISA_MIPS4
, 0,
510 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
511 mips_hwr_names_numeric
},
512 { "r10000", 1, bfd_mach_mips10000
, CPU_R10000
, ISA_MIPS4
, 0,
513 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
514 mips_hwr_names_numeric
},
515 { "r12000", 1, bfd_mach_mips12000
, CPU_R12000
, ISA_MIPS4
, 0,
516 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
517 mips_hwr_names_numeric
},
518 { "r14000", 1, bfd_mach_mips14000
, CPU_R14000
, ISA_MIPS4
, 0,
519 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
520 mips_hwr_names_numeric
},
521 { "r16000", 1, bfd_mach_mips16000
, CPU_R16000
, ISA_MIPS4
, 0,
522 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
523 mips_hwr_names_numeric
},
524 { "mips5", 1, bfd_mach_mips5
, CPU_MIPS5
, ISA_MIPS5
, 0,
525 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
526 mips_hwr_names_numeric
},
528 /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
529 Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
530 _MIPS32 Architecture For Programmers Volume I: Introduction to the
531 MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
533 { "mips32", 1, bfd_mach_mipsisa32
, CPU_MIPS32
,
534 ISA_MIPS32
, ASE_SMARTMIPS
,
535 mips_cp0_names_mips3264
,
536 mips_cp0sel_names_mips3264
, ARRAY_SIZE (mips_cp0sel_names_mips3264
),
537 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
539 { "mips32r2", 1, bfd_mach_mipsisa32r2
, CPU_MIPS32R2
,
541 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
542 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
543 mips_cp0_names_mips3264r2
,
544 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
545 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
547 { "mips32r3", 1, bfd_mach_mipsisa32r3
, CPU_MIPS32R3
,
549 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
550 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
551 mips_cp0_names_mips3264r2
,
552 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
553 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
555 { "mips32r5", 1, bfd_mach_mipsisa32r5
, CPU_MIPS32R5
,
557 (ASE_SMARTMIPS
| ASE_DSP
| ASE_DSPR2
| ASE_EVA
| ASE_MIPS3D
558 | ASE_MT
| ASE_MCU
| ASE_VIRT
| ASE_MSA
| ASE_XPA
),
559 mips_cp0_names_mips3264r2
,
560 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
561 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
563 { "mips32r6", 1, bfd_mach_mipsisa32r6
, CPU_MIPS32R6
,
565 (ASE_EVA
| ASE_MSA
| ASE_VIRT
| ASE_XPA
| ASE_MCU
| ASE_MT
| ASE_DSP
566 | ASE_DSPR2
| ASE_DSPR3
| ASE_CRC
| ASE_GINV
),
567 mips_cp0_names_mips3264r2
,
568 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
569 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
571 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
572 { "mips64", 1, bfd_mach_mipsisa64
, CPU_MIPS64
,
573 ISA_MIPS64
, ASE_MIPS3D
| ASE_MDMX
,
574 mips_cp0_names_mips3264
,
575 mips_cp0sel_names_mips3264
, ARRAY_SIZE (mips_cp0sel_names_mips3264
),
576 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
578 { "mips64r2", 1, bfd_mach_mipsisa64r2
, CPU_MIPS64R2
,
580 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
581 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
582 mips_cp0_names_mips3264r2
,
583 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
584 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
586 { "mips64r3", 1, bfd_mach_mipsisa64r3
, CPU_MIPS64R3
,
588 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
589 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
590 mips_cp0_names_mips3264r2
,
591 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
592 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
594 { "mips64r5", 1, bfd_mach_mipsisa64r5
, CPU_MIPS64R5
,
596 (ASE_MIPS3D
| ASE_DSP
| ASE_DSPR2
| ASE_DSP64
| ASE_EVA
| ASE_MT
597 | ASE_MCU
| ASE_VIRT
| ASE_VIRT64
| ASE_MSA
| ASE_MSA64
| ASE_XPA
),
598 mips_cp0_names_mips3264r2
,
599 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
600 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
602 { "mips64r6", 1, bfd_mach_mipsisa64r6
, CPU_MIPS64R6
,
604 (ASE_EVA
| ASE_MSA
| ASE_MSA64
| ASE_XPA
| ASE_VIRT
| ASE_VIRT64
605 | ASE_MCU
| ASE_MT
| ASE_DSP
| ASE_DSPR2
| ASE_DSPR3
| ASE_CRC
606 | ASE_CRC64
| ASE_GINV
),
607 mips_cp0_names_mips3264r2
,
608 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
609 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
611 { "interaptiv-mr2", 1, bfd_mach_mips_interaptiv_mr2
, CPU_INTERAPTIV_MR2
,
613 ASE_MT
| ASE_EVA
| ASE_DSP
| ASE_DSPR2
| ASE_MIPS16E2
| ASE_MIPS16E2_MT
,
614 mips_cp0_names_mips3264r2
,
615 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
616 mips_cp1_names_mips3264
, mips_hwr_names_mips3264r2
},
618 { "sb1", 1, bfd_mach_mips_sb1
, CPU_SB1
,
619 ISA_MIPS64
| INSN_SB1
, ASE_MIPS3D
,
621 mips_cp0sel_names_sb1
, ARRAY_SIZE (mips_cp0sel_names_sb1
),
622 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
624 { "loongson2e", 1, bfd_mach_mips_loongson_2e
, CPU_LOONGSON_2E
,
625 ISA_MIPS3
| INSN_LOONGSON_2E
, 0, mips_cp0_names_numeric
,
626 NULL
, 0, mips_cp1_names_numeric
, mips_hwr_names_numeric
},
628 { "loongson2f", 1, bfd_mach_mips_loongson_2f
, CPU_LOONGSON_2F
,
629 ISA_MIPS3
| INSN_LOONGSON_2F
, ASE_LOONGSON_MMI
, mips_cp0_names_numeric
,
630 NULL
, 0, mips_cp1_names_numeric
, mips_hwr_names_numeric
},
632 { "loongson3a", 1, bfd_mach_mips_loongson_3a
, CPU_LOONGSON_3A
,
633 ISA_MIPS64R2
, ASE_LOONGSON_MMI
| ASE_LOONGSON_CAM
| ASE_LOONGSON_EXT
,
634 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_mips3264
,
635 mips_hwr_names_numeric
},
637 { "octeon", 1, bfd_mach_mips_octeon
, CPU_OCTEON
,
638 ISA_MIPS64R2
| INSN_OCTEON
, 0, mips_cp0_names_numeric
, NULL
, 0,
639 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
641 { "octeon+", 1, bfd_mach_mips_octeonp
, CPU_OCTEONP
,
642 ISA_MIPS64R2
| INSN_OCTEONP
, 0, mips_cp0_names_numeric
,
643 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
645 { "octeon2", 1, bfd_mach_mips_octeon2
, CPU_OCTEON2
,
646 ISA_MIPS64R2
| INSN_OCTEON2
, 0, mips_cp0_names_numeric
,
647 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
649 { "octeon3", 1, bfd_mach_mips_octeon3
, CPU_OCTEON3
,
650 ISA_MIPS64R5
| INSN_OCTEON3
, ASE_VIRT
| ASE_VIRT64
,
651 mips_cp0_names_numeric
,
652 NULL
, 0, mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
654 { "xlr", 1, bfd_mach_mips_xlr
, CPU_XLR
,
655 ISA_MIPS64
| INSN_XLR
, 0,
657 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
658 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
660 /* XLP is mostly like XLR, with the prominent exception it is being
662 { "xlp", 1, bfd_mach_mips_xlr
, CPU_XLR
,
663 ISA_MIPS64R2
| INSN_XLR
, 0,
665 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
666 mips_cp1_names_mips3264
, mips_hwr_names_numeric
},
668 /* This entry, mips16, is here only for ISA/processor selection; do
669 not print its name. */
670 { "", 1, bfd_mach_mips16
, CPU_MIPS16
, ISA_MIPS64
,
671 ASE_MIPS16E2
| ASE_MIPS16E2_MT
,
672 mips_cp0_names_numeric
, NULL
, 0, mips_cp1_names_numeric
,
673 mips_hwr_names_numeric
},
676 /* ISA and processor type to disassemble for, and register names to use.
677 set_default_mips_dis_options and parse_mips_dis_options fill in these
679 static int mips_processor
;
682 static int micromips_ase
;
683 static const char * const *mips_gpr_names
;
684 static const char * const *mips_fpr_names
;
685 static const char * const *mips_cp0_names
;
686 static const struct mips_cp0sel_name
*mips_cp0sel_names
;
687 static int mips_cp0sel_names_len
;
688 static const char * const *mips_cp1_names
;
689 static const char * const *mips_hwr_names
;
692 static int no_aliases
; /* If set disassemble as most general inst. */
694 static const struct mips_abi_choice
*
695 choose_abi_by_name (const char *name
, unsigned int namelen
)
697 const struct mips_abi_choice
*c
;
700 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_abi_choices
) && c
== NULL
; i
++)
701 if (strncmp (mips_abi_choices
[i
].name
, name
, namelen
) == 0
702 && strlen (mips_abi_choices
[i
].name
) == namelen
)
703 c
= &mips_abi_choices
[i
];
708 static const struct mips_arch_choice
*
709 choose_arch_by_name (const char *name
, unsigned int namelen
)
711 const struct mips_arch_choice
*c
= NULL
;
714 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
715 if (strncmp (mips_arch_choices
[i
].name
, name
, namelen
) == 0
716 && strlen (mips_arch_choices
[i
].name
) == namelen
)
717 c
= &mips_arch_choices
[i
];
722 static const struct mips_arch_choice
*
723 choose_arch_by_number (unsigned long mach
)
725 static unsigned long hint_bfd_mach
;
726 static const struct mips_arch_choice
*hint_arch_choice
;
727 const struct mips_arch_choice
*c
;
730 /* We optimize this because even if the user specifies no
731 flags, this will be done for every instruction! */
732 if (hint_bfd_mach
== mach
733 && hint_arch_choice
!= NULL
734 && hint_arch_choice
->bfd_mach
== hint_bfd_mach
)
735 return hint_arch_choice
;
737 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
739 if (mips_arch_choices
[i
].bfd_mach_valid
740 && mips_arch_choices
[i
].bfd_mach
== mach
)
742 c
= &mips_arch_choices
[i
];
743 hint_bfd_mach
= mach
;
744 hint_arch_choice
= c
;
750 /* Check if the object uses NewABI conventions. */
753 is_newabi (Elf_Internal_Ehdr
*header
)
755 /* There are no old-style ABIs which use 64-bit ELF. */
756 if (header
->e_ident
[EI_CLASS
] == ELFCLASS64
)
759 /* If a 32-bit ELF file, n32 is a new-style ABI. */
760 if ((header
->e_flags
& EF_MIPS_ABI2
) != 0)
766 /* Check if the object has microMIPS ASE code. */
769 is_micromips (Elf_Internal_Ehdr
*header
)
771 if ((header
->e_flags
& EF_MIPS_ARCH_ASE_MICROMIPS
) != 0)
777 /* Convert ASE flags from .MIPS.abiflags to internal values. */
780 mips_convert_abiflags_ases (unsigned long afl_ases
)
782 unsigned long opcode_ases
= 0;
784 if (afl_ases
& AFL_ASE_DSP
)
785 opcode_ases
|= ASE_DSP
;
786 if (afl_ases
& AFL_ASE_DSPR2
)
787 opcode_ases
|= ASE_DSPR2
;
788 if (afl_ases
& AFL_ASE_EVA
)
789 opcode_ases
|= ASE_EVA
;
790 if (afl_ases
& AFL_ASE_MCU
)
791 opcode_ases
|= ASE_MCU
;
792 if (afl_ases
& AFL_ASE_MDMX
)
793 opcode_ases
|= ASE_MDMX
;
794 if (afl_ases
& AFL_ASE_MIPS3D
)
795 opcode_ases
|= ASE_MIPS3D
;
796 if (afl_ases
& AFL_ASE_MT
)
797 opcode_ases
|= ASE_MT
;
798 if (afl_ases
& AFL_ASE_SMARTMIPS
)
799 opcode_ases
|= ASE_SMARTMIPS
;
800 if (afl_ases
& AFL_ASE_VIRT
)
801 opcode_ases
|= ASE_VIRT
;
802 if (afl_ases
& AFL_ASE_MSA
)
803 opcode_ases
|= ASE_MSA
;
804 if (afl_ases
& AFL_ASE_XPA
)
805 opcode_ases
|= ASE_XPA
;
806 if (afl_ases
& AFL_ASE_DSPR3
)
807 opcode_ases
|= ASE_DSPR3
;
808 if (afl_ases
& AFL_ASE_MIPS16E2
)
809 opcode_ases
|= ASE_MIPS16E2
;
813 /* Calculate combination ASE flags from regular ASE flags. */
816 mips_calculate_combination_ases (unsigned long opcode_ases
)
818 unsigned long combination_ases
= 0;
820 if ((opcode_ases
& (ASE_XPA
| ASE_VIRT
)) == (ASE_XPA
| ASE_VIRT
))
821 combination_ases
|= ASE_XPA_VIRT
;
822 if ((opcode_ases
& (ASE_MIPS16E2
| ASE_MT
)) == (ASE_MIPS16E2
| ASE_MT
))
823 combination_ases
|= ASE_MIPS16E2_MT
;
824 return combination_ases
;
828 set_default_mips_dis_options (struct disassemble_info
*info
)
830 const struct mips_arch_choice
*chosen_arch
;
832 /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
833 is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
834 CP0 register, and HWR names. */
835 mips_isa
= ISA_MIPS3
;
836 mips_processor
= CPU_R3000
;
839 mips_gpr_names
= mips_gpr_names_oldabi
;
840 mips_fpr_names
= mips_fpr_names_numeric
;
841 mips_cp0_names
= mips_cp0_names_numeric
;
842 mips_cp0sel_names
= NULL
;
843 mips_cp0sel_names_len
= 0;
844 mips_cp1_names
= mips_cp1_names_numeric
;
845 mips_hwr_names
= mips_hwr_names_numeric
;
848 /* Set ISA, architecture, and cp0 register names as best we can. */
849 #if ! SYMTAB_AVAILABLE
850 /* This is running out on a target machine, not in a host tool.
851 FIXME: Where does mips_target_info come from? */
852 target_processor
= mips_target_info
.processor
;
853 mips_isa
= mips_target_info
.isa
;
854 mips_ase
= mips_target_info
.ase
;
856 chosen_arch
= choose_arch_by_number (info
->mach
);
857 if (chosen_arch
!= NULL
)
859 mips_processor
= chosen_arch
->processor
;
860 mips_isa
= chosen_arch
->isa
;
861 mips_ase
= chosen_arch
->ase
;
862 mips_cp0_names
= chosen_arch
->cp0_names
;
863 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
864 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
865 mips_cp1_names
= chosen_arch
->cp1_names
;
866 mips_hwr_names
= chosen_arch
->hwr_names
;
869 /* Update settings according to the ELF file header flags. */
870 if (info
->flavour
== bfd_target_elf_flavour
&& info
->section
!= NULL
)
872 struct bfd
*abfd
= info
->section
->owner
;
873 Elf_Internal_Ehdr
*header
= elf_elfheader (abfd
);
874 Elf_Internal_ABIFlags_v0
*abiflags
= NULL
;
876 /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
877 because we won't then have a MIPS/ELF BFD, however we need
878 to guard against a link error in a `--enable-targets=...'
879 configuration with a 32-bit host where the MIPS target is
880 a secondary, or with MIPS/ECOFF configurations. */
881 #ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
882 abiflags
= bfd_mips_elf_get_abiflags (abfd
);
884 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
885 if (is_newabi (header
))
886 mips_gpr_names
= mips_gpr_names_newabi
;
887 /* If a microMIPS binary, then don't use MIPS16 bindings. */
888 micromips_ase
= is_micromips (header
);
889 /* OR in any extra ASE flags set in ELF file structures. */
891 mips_ase
|= mips_convert_abiflags_ases (abiflags
->ases
);
892 else if (header
->e_flags
& EF_MIPS_ARCH_ASE_MDMX
)
893 mips_ase
|= ASE_MDMX
;
896 mips_ase
|= mips_calculate_combination_ases (mips_ase
);
899 /* Parse an ASE disassembler option and set the corresponding global
900 ASE flag(s). Return TRUE if successful, FALSE otherwise. */
903 parse_mips_ase_option (const char *option
)
905 if (CONST_STRNEQ (option
, "msa"))
908 if ((mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R2
909 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R3
910 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R5
911 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
)
912 mips_ase
|= ASE_MSA64
;
916 if (CONST_STRNEQ (option
, "virt"))
918 mips_ase
|= ASE_VIRT
;
919 if (mips_isa
& ISA_MIPS64R2
920 || mips_isa
& ISA_MIPS64R3
921 || mips_isa
& ISA_MIPS64R5
922 || mips_isa
& ISA_MIPS64R6
)
923 mips_ase
|= ASE_VIRT64
;
927 if (CONST_STRNEQ (option
, "xpa"))
933 if (CONST_STRNEQ (option
, "ginv"))
935 mips_ase
|= ASE_GINV
;
939 if (CONST_STRNEQ (option
, "loongson-mmi"))
941 mips_ase
|= ASE_LOONGSON_MMI
;
945 if (CONST_STRNEQ (option
, "loongson-cam"))
947 mips_ase
|= ASE_LOONGSON_CAM
;
951 /* Put here for match ext2 frist */
952 if (CONST_STRNEQ (option
, "loongson-ext2"))
954 mips_ase
|= ASE_LOONGSON_EXT2
;
958 if (CONST_STRNEQ (option
, "loongson-ext"))
960 mips_ase
|= ASE_LOONGSON_EXT
;
968 parse_mips_dis_option (const char *option
, unsigned int len
)
970 unsigned int i
, optionlen
, vallen
;
972 const struct mips_abi_choice
*chosen_abi
;
973 const struct mips_arch_choice
*chosen_arch
;
975 /* Try to match options that are simple flags */
976 if (CONST_STRNEQ (option
, "no-aliases"))
982 if (parse_mips_ase_option (option
))
984 mips_ase
|= mips_calculate_combination_ases (mips_ase
);
988 /* Look for the = that delimits the end of the option name. */
989 for (i
= 0; i
< len
; i
++)
990 if (option
[i
] == '=')
993 if (i
== 0) /* Invalid option: no name before '='. */
995 if (i
== len
) /* Invalid option: no '='. */
997 if (i
== (len
- 1)) /* Invalid option: no value after '='. */
1001 val
= option
+ (optionlen
+ 1);
1002 vallen
= len
- (optionlen
+ 1);
1004 if (strncmp ("gpr-names", option
, optionlen
) == 0
1005 && strlen ("gpr-names") == optionlen
)
1007 chosen_abi
= choose_abi_by_name (val
, vallen
);
1008 if (chosen_abi
!= NULL
)
1009 mips_gpr_names
= chosen_abi
->gpr_names
;
1013 if (strncmp ("fpr-names", option
, optionlen
) == 0
1014 && strlen ("fpr-names") == optionlen
)
1016 chosen_abi
= choose_abi_by_name (val
, vallen
);
1017 if (chosen_abi
!= NULL
)
1018 mips_fpr_names
= chosen_abi
->fpr_names
;
1022 if (strncmp ("cp0-names", option
, optionlen
) == 0
1023 && strlen ("cp0-names") == optionlen
)
1025 chosen_arch
= choose_arch_by_name (val
, vallen
);
1026 if (chosen_arch
!= NULL
)
1028 mips_cp0_names
= chosen_arch
->cp0_names
;
1029 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1030 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1035 if (strncmp ("cp1-names", option
, optionlen
) == 0
1036 && strlen ("cp1-names") == optionlen
)
1038 chosen_arch
= choose_arch_by_name (val
, vallen
);
1039 if (chosen_arch
!= NULL
)
1040 mips_cp1_names
= chosen_arch
->cp1_names
;
1044 if (strncmp ("hwr-names", option
, optionlen
) == 0
1045 && strlen ("hwr-names") == optionlen
)
1047 chosen_arch
= choose_arch_by_name (val
, vallen
);
1048 if (chosen_arch
!= NULL
)
1049 mips_hwr_names
= chosen_arch
->hwr_names
;
1053 if (strncmp ("reg-names", option
, optionlen
) == 0
1054 && strlen ("reg-names") == optionlen
)
1056 /* We check both ABI and ARCH here unconditionally, so
1057 that "numeric" will do the desirable thing: select
1058 numeric register names for all registers. Other than
1059 that, a given name probably won't match both. */
1060 chosen_abi
= choose_abi_by_name (val
, vallen
);
1061 if (chosen_abi
!= NULL
)
1063 mips_gpr_names
= chosen_abi
->gpr_names
;
1064 mips_fpr_names
= chosen_abi
->fpr_names
;
1066 chosen_arch
= choose_arch_by_name (val
, vallen
);
1067 if (chosen_arch
!= NULL
)
1069 mips_cp0_names
= chosen_arch
->cp0_names
;
1070 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
1071 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
1072 mips_cp1_names
= chosen_arch
->cp1_names
;
1073 mips_hwr_names
= chosen_arch
->hwr_names
;
1078 /* Invalid option. */
1082 parse_mips_dis_options (const char *options
)
1084 const char *option_end
;
1086 if (options
== NULL
)
1089 while (*options
!= '\0')
1091 /* Skip empty options. */
1092 if (*options
== ',')
1098 /* We know that *options is neither NUL or a comma. */
1099 option_end
= options
+ 1;
1100 while (*option_end
!= ',' && *option_end
!= '\0')
1103 parse_mips_dis_option (options
, option_end
- options
);
1105 /* Go on to the next one. If option_end points to a comma, it
1106 will be skipped above. */
1107 options
= option_end
;
1111 static const struct mips_cp0sel_name
*
1112 lookup_mips_cp0sel_name (const struct mips_cp0sel_name
*names
,
1114 unsigned int cp0reg
,
1119 for (i
= 0; i
< len
; i
++)
1120 if (names
[i
].cp0reg
== cp0reg
&& names
[i
].sel
== sel
)
1125 /* Print register REGNO, of type TYPE, for instruction OPCODE. */
1128 print_reg (struct disassemble_info
*info
, const struct mips_opcode
*opcode
,
1129 enum mips_reg_operand_type type
, int regno
)
1134 info
->fprintf_func (info
->stream
, "%s", mips_gpr_names
[regno
]);
1138 info
->fprintf_func (info
->stream
, "%s", mips_fpr_names
[regno
]);
1142 if (opcode
->pinfo
& (FP_D
| FP_S
))
1143 info
->fprintf_func (info
->stream
, "$fcc%d", regno
);
1145 info
->fprintf_func (info
->stream
, "$cc%d", regno
);
1149 if (opcode
->membership
& INSN_5400
)
1150 info
->fprintf_func (info
->stream
, "$f%d", regno
);
1152 info
->fprintf_func (info
->stream
, "$v%d", regno
);
1156 info
->fprintf_func (info
->stream
, "$ac%d", regno
);
1160 if (opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1161 info
->fprintf_func (info
->stream
, "%s", mips_cp0_names
[regno
]);
1162 else if (opcode
->name
[strlen (opcode
->name
) - 1] == '1')
1163 info
->fprintf_func (info
->stream
, "%s", mips_cp1_names
[regno
]);
1165 info
->fprintf_func (info
->stream
, "$%d", regno
);
1169 info
->fprintf_func (info
->stream
, "%s", mips_hwr_names
[regno
]);
1173 info
->fprintf_func (info
->stream
, "$vf%d", regno
);
1177 info
->fprintf_func (info
->stream
, "$vi%d", regno
);
1180 case OP_REG_R5900_I
:
1181 info
->fprintf_func (info
->stream
, "$I");
1184 case OP_REG_R5900_Q
:
1185 info
->fprintf_func (info
->stream
, "$Q");
1188 case OP_REG_R5900_R
:
1189 info
->fprintf_func (info
->stream
, "$R");
1192 case OP_REG_R5900_ACC
:
1193 info
->fprintf_func (info
->stream
, "$ACC");
1197 info
->fprintf_func (info
->stream
, "$w%d", regno
);
1200 case OP_REG_MSA_CTRL
:
1201 info
->fprintf_func (info
->stream
, "%s", msa_control_names
[regno
]);
1207 /* Used to track the state carried over from previous operands in
1209 struct mips_print_arg_state
{
1210 /* The value of the last OP_INT seen. We only use this for OP_MSB,
1211 where the value is known to be unsigned and small. */
1212 unsigned int last_int
;
1214 /* The type and number of the last OP_REG seen. We only use this for
1215 OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1216 enum mips_reg_operand_type last_reg_type
;
1217 unsigned int last_regno
;
1218 unsigned int dest_regno
;
1219 unsigned int seen_dest
;
1222 /* Initialize STATE for the start of an instruction. */
1225 init_print_arg_state (struct mips_print_arg_state
*state
)
1227 memset (state
, 0, sizeof (*state
));
1230 /* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1231 whose value is given by UVAL. */
1234 print_vu0_channel (struct disassemble_info
*info
,
1235 const struct mips_operand
*operand
, unsigned int uval
)
1237 if (operand
->size
== 4)
1238 info
->fprintf_func (info
->stream
, "%s%s%s%s",
1239 uval
& 8 ? "x" : "",
1240 uval
& 4 ? "y" : "",
1241 uval
& 2 ? "z" : "",
1242 uval
& 1 ? "w" : "");
1243 else if (operand
->size
== 2)
1244 info
->fprintf_func (info
->stream
, "%c", "xyzw"[uval
]);
1249 /* Record information about a register operand. */
1252 mips_seen_register (struct mips_print_arg_state
*state
,
1254 enum mips_reg_operand_type reg_type
)
1256 state
->last_reg_type
= reg_type
;
1257 state
->last_regno
= regno
;
1259 if (!state
->seen_dest
)
1261 state
->seen_dest
= 1;
1262 state
->dest_regno
= regno
;
1266 /* Print SAVE/RESTORE instruction operands according to the argument
1267 register mask AMASK, the number of static registers saved NSREG,
1268 the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1269 and the frame size FRAME_SIZE. */
1272 mips_print_save_restore (struct disassemble_info
*info
, unsigned int amask
,
1273 unsigned int nsreg
, unsigned int ra
,
1274 unsigned int s0
, unsigned int s1
,
1275 unsigned int frame_size
)
1277 const fprintf_ftype infprintf
= info
->fprintf_func
;
1278 unsigned int nargs
, nstatics
, smask
, i
, j
;
1279 void *is
= info
->stream
;
1282 if (amask
== MIPS_SVRS_ALL_ARGS
)
1287 else if (amask
== MIPS_SVRS_ALL_STATICS
)
1295 nstatics
= amask
& 3;
1301 infprintf (is
, "%s", mips_gpr_names
[4]);
1303 infprintf (is
, "-%s", mips_gpr_names
[4 + nargs
- 1]);
1307 infprintf (is
, "%s%d", sep
, frame_size
);
1310 infprintf (is
, ",%s", mips_gpr_names
[31]);
1317 if (nsreg
> 0) /* $s2-$s8 */
1318 smask
|= ((1 << nsreg
) - 1) << 2;
1320 for (i
= 0; i
< 9; i
++)
1321 if (smask
& (1 << i
))
1323 infprintf (is
, ",%s", mips_gpr_names
[i
== 8 ? 30 : (16 + i
)]);
1324 /* Skip over string of set bits. */
1325 for (j
= i
; smask
& (2 << j
); j
++)
1328 infprintf (is
, "-%s", mips_gpr_names
[j
== 8 ? 30 : (16 + j
)]);
1331 /* Statics $ax - $a3. */
1333 infprintf (is
, ",%s", mips_gpr_names
[7]);
1334 else if (nstatics
> 0)
1335 infprintf (is
, ",%s-%s",
1336 mips_gpr_names
[7 - nstatics
+ 1],
1341 /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1342 UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1343 the base address for OP_PCREL operands. */
1346 print_insn_arg (struct disassemble_info
*info
,
1347 struct mips_print_arg_state
*state
,
1348 const struct mips_opcode
*opcode
,
1349 const struct mips_operand
*operand
,
1353 const fprintf_ftype infprintf
= info
->fprintf_func
;
1354 void *is
= info
->stream
;
1356 switch (operand
->type
)
1360 const struct mips_int_operand
*int_op
;
1362 int_op
= (const struct mips_int_operand
*) operand
;
1363 uval
= mips_decode_int_operand (int_op
, uval
);
1364 state
->last_int
= uval
;
1365 if (int_op
->print_hex
)
1366 infprintf (is
, "0x%x", uval
);
1368 infprintf (is
, "%d", uval
);
1374 const struct mips_mapped_int_operand
*mint_op
;
1376 mint_op
= (const struct mips_mapped_int_operand
*) operand
;
1377 uval
= mint_op
->int_map
[uval
];
1378 state
->last_int
= uval
;
1379 if (mint_op
->print_hex
)
1380 infprintf (is
, "0x%x", uval
);
1382 infprintf (is
, "%d", uval
);
1388 const struct mips_msb_operand
*msb_op
;
1390 msb_op
= (const struct mips_msb_operand
*) operand
;
1391 uval
+= msb_op
->bias
;
1392 if (msb_op
->add_lsb
)
1393 uval
-= state
->last_int
;
1394 infprintf (is
, "0x%x", uval
);
1399 case OP_OPTIONAL_REG
:
1401 const struct mips_reg_operand
*reg_op
;
1403 reg_op
= (const struct mips_reg_operand
*) operand
;
1404 uval
= mips_decode_reg_operand (reg_op
, uval
);
1405 print_reg (info
, opcode
, reg_op
->reg_type
, uval
);
1407 mips_seen_register (state
, uval
, reg_op
->reg_type
);
1413 const struct mips_reg_pair_operand
*pair_op
;
1415 pair_op
= (const struct mips_reg_pair_operand
*) operand
;
1416 print_reg (info
, opcode
, pair_op
->reg_type
,
1417 pair_op
->reg1_map
[uval
]);
1418 infprintf (is
, ",");
1419 print_reg (info
, opcode
, pair_op
->reg_type
,
1420 pair_op
->reg2_map
[uval
]);
1426 const struct mips_pcrel_operand
*pcrel_op
;
1428 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1429 info
->target
= mips_decode_pcrel_operand (pcrel_op
, base_pc
, uval
);
1431 /* For jumps and branches clear the ISA bit except for
1432 the GDB disassembler. */
1433 if (pcrel_op
->include_isa_bit
1434 && info
->flavour
!= bfd_target_unknown_flavour
)
1437 (*info
->print_address_func
) (info
->target
, info
);
1442 infprintf (is
, "%d", uval
);
1445 case OP_ADDIUSP_INT
:
1449 sval
= mips_signed_operand (operand
, uval
) * 4;
1450 if (sval
>= -8 && sval
< 8)
1452 infprintf (is
, "%d", sval
);
1456 case OP_CLO_CLZ_DEST
:
1458 unsigned int reg1
, reg2
;
1462 /* If one is zero use the other. */
1463 if (reg1
== reg2
|| reg2
== 0)
1464 infprintf (is
, "%s", mips_gpr_names
[reg1
]);
1466 infprintf (is
, "%s", mips_gpr_names
[reg2
]);
1468 /* Bogus, result depends on processor. */
1469 infprintf (is
, "%s or %s", mips_gpr_names
[reg1
],
1470 mips_gpr_names
[reg2
]);
1476 case OP_NON_ZERO_REG
:
1478 print_reg (info
, opcode
, OP_REG_GP
, uval
& 31);
1479 mips_seen_register (state
, uval
, OP_REG_GP
);
1483 case OP_LWM_SWM_LIST
:
1484 if (operand
->size
== 2)
1487 infprintf (is
, "%s,%s",
1489 mips_gpr_names
[31]);
1491 infprintf (is
, "%s-%s,%s",
1493 mips_gpr_names
[16 + uval
],
1494 mips_gpr_names
[31]);
1500 s_reg_encode
= uval
& 0xf;
1501 if (s_reg_encode
!= 0)
1503 if (s_reg_encode
== 1)
1504 infprintf (is
, "%s", mips_gpr_names
[16]);
1505 else if (s_reg_encode
< 9)
1506 infprintf (is
, "%s-%s",
1508 mips_gpr_names
[15 + s_reg_encode
]);
1509 else if (s_reg_encode
== 9)
1510 infprintf (is
, "%s-%s,%s",
1513 mips_gpr_names
[30]);
1515 infprintf (is
, "UNKNOWN");
1518 if (uval
& 0x10) /* For ra. */
1520 if (s_reg_encode
== 0)
1521 infprintf (is
, "%s", mips_gpr_names
[31]);
1523 infprintf (is
, ",%s", mips_gpr_names
[31]);
1528 case OP_ENTRY_EXIT_LIST
:
1531 unsigned int amask
, smask
;
1534 amask
= (uval
>> 3) & 7;
1535 if (amask
> 0 && amask
< 5)
1537 infprintf (is
, "%s", mips_gpr_names
[4]);
1539 infprintf (is
, "-%s", mips_gpr_names
[amask
+ 3]);
1543 smask
= (uval
>> 1) & 3;
1546 infprintf (is
, "%s??", sep
);
1551 infprintf (is
, "%s%s", sep
, mips_gpr_names
[16]);
1553 infprintf (is
, "-%s", mips_gpr_names
[smask
+ 15]);
1559 infprintf (is
, "%s%s", sep
, mips_gpr_names
[31]);
1563 if (amask
== 5 || amask
== 6)
1565 infprintf (is
, "%s%s", sep
, mips_fpr_names
[0]);
1567 infprintf (is
, "-%s", mips_fpr_names
[1]);
1572 case OP_SAVE_RESTORE_LIST
:
1573 /* Should be handled by the caller due to complex behavior. */
1576 case OP_MDMX_IMM_REG
:
1582 if ((vsel
& 0x10) == 0)
1587 for (fmt
= 0; fmt
< 3; fmt
++, vsel
>>= 1)
1588 if ((vsel
& 1) == 0)
1590 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1591 infprintf (is
, "[%d]", vsel
>> 1);
1593 else if ((vsel
& 0x08) == 0)
1594 print_reg (info
, opcode
, OP_REG_VEC
, uval
);
1596 infprintf (is
, "0x%x", uval
);
1600 case OP_REPEAT_PREV_REG
:
1601 print_reg (info
, opcode
, state
->last_reg_type
, state
->last_regno
);
1604 case OP_REPEAT_DEST_REG
:
1605 print_reg (info
, opcode
, state
->last_reg_type
, state
->dest_regno
);
1609 infprintf (is
, "$pc");
1613 print_reg (info
, opcode
, OP_REG_GP
, 28);
1617 case OP_VU0_MATCH_SUFFIX
:
1618 print_vu0_channel (info
, operand
, uval
);
1622 infprintf (is
, "[%d]", uval
);
1626 infprintf (is
, "[");
1627 print_reg (info
, opcode
, OP_REG_GP
, uval
);
1628 infprintf (is
, "]");
1633 /* Validate the arguments for INSN, which is described by OPCODE.
1634 Use DECODE_OPERAND to get the encoding of each operand. */
1637 validate_insn_args (const struct mips_opcode
*opcode
,
1638 const struct mips_operand
*(*decode_operand
) (const char *),
1641 struct mips_print_arg_state state
;
1642 const struct mips_operand
*operand
;
1646 init_print_arg_state (&state
);
1647 for (s
= opcode
->args
; *s
; ++s
)
1661 operand
= decode_operand (s
);
1665 uval
= mips_extract_operand (operand
, insn
);
1666 switch (operand
->type
)
1669 case OP_OPTIONAL_REG
:
1671 const struct mips_reg_operand
*reg_op
;
1673 reg_op
= (const struct mips_reg_operand
*) operand
;
1674 uval
= mips_decode_reg_operand (reg_op
, uval
);
1675 mips_seen_register (&state
, uval
, reg_op
->reg_type
);
1681 unsigned int reg1
, reg2
;
1686 if (reg1
!= reg2
|| reg1
== 0)
1693 const struct mips_check_prev_operand
*prev_op
;
1695 prev_op
= (const struct mips_check_prev_operand
*) operand
;
1697 if (!prev_op
->zero_ok
&& uval
== 0)
1700 if (((prev_op
->less_than_ok
&& uval
< state
.last_regno
)
1701 || (prev_op
->greater_than_ok
&& uval
> state
.last_regno
)
1702 || (prev_op
->equal_ok
&& uval
== state
.last_regno
)))
1708 case OP_NON_ZERO_REG
:
1721 case OP_ADDIUSP_INT
:
1722 case OP_CLO_CLZ_DEST
:
1723 case OP_LWM_SWM_LIST
:
1724 case OP_ENTRY_EXIT_LIST
:
1725 case OP_MDMX_IMM_REG
:
1726 case OP_REPEAT_PREV_REG
:
1727 case OP_REPEAT_DEST_REG
:
1731 case OP_VU0_MATCH_SUFFIX
:
1734 case OP_SAVE_RESTORE_LIST
:
1738 if (*s
== 'm' || *s
== '+' || *s
== '-')
1745 /* Print the arguments for INSN, which is described by OPCODE.
1746 Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
1747 as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1748 operand is for a branch or jump. */
1751 print_insn_args (struct disassemble_info
*info
,
1752 const struct mips_opcode
*opcode
,
1753 const struct mips_operand
*(*decode_operand
) (const char *),
1754 unsigned int insn
, bfd_vma insn_pc
, unsigned int length
)
1756 const fprintf_ftype infprintf
= info
->fprintf_func
;
1757 void *is
= info
->stream
;
1758 struct mips_print_arg_state state
;
1759 const struct mips_operand
*operand
;
1762 init_print_arg_state (&state
);
1763 for (s
= opcode
->args
; *s
; ++s
)
1770 infprintf (is
, "%c", *s
);
1775 infprintf (is
, "%c%c", *s
, *s
);
1779 operand
= decode_operand (s
);
1782 /* xgettext:c-format */
1784 _("# internal error, undefined operand in `%s %s'"),
1785 opcode
->name
, opcode
->args
);
1789 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
1791 /* Handle this case here because of the complex behavior. */
1792 unsigned int amask
= (insn
>> 15) & 0xf;
1793 unsigned int nsreg
= (insn
>> 23) & 0x7;
1794 unsigned int ra
= insn
& 0x1000; /* $ra */
1795 unsigned int s0
= insn
& 0x800; /* $s0 */
1796 unsigned int s1
= insn
& 0x400; /* $s1 */
1797 unsigned int frame_size
= (((insn
>> 15) & 0xf0)
1798 | ((insn
>> 6) & 0x0f)) * 8;
1799 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
,
1802 else if (operand
->type
== OP_REG
1805 && opcode
->name
[strlen (opcode
->name
) - 1] == '0')
1807 /* Coprocessor register 0 with sel field. */
1808 const struct mips_cp0sel_name
*n
;
1809 unsigned int reg
, sel
;
1811 reg
= mips_extract_operand (operand
, insn
);
1813 operand
= decode_operand (s
);
1814 sel
= mips_extract_operand (operand
, insn
);
1816 /* CP0 register including 'sel' code for mftc0, to be
1817 printed textually if known. If not known, print both
1818 CP0 register name and sel numerically since CP0 register
1819 with sel 0 may have a name unrelated to register being
1821 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
1822 mips_cp0sel_names_len
,
1825 infprintf (is
, "%s", n
->name
);
1827 infprintf (is
, "$%d,%d", reg
, sel
);
1831 bfd_vma base_pc
= insn_pc
;
1833 /* Adjust the PC relative base so that branch/jump insns use
1834 the following PC as the base but genuinely PC relative
1835 operands use the current PC. */
1836 if (operand
->type
== OP_PCREL
)
1838 const struct mips_pcrel_operand
*pcrel_op
;
1840 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
1841 /* The include_isa_bit flag is sufficient to distinguish
1842 branch/jump from other PC relative operands. */
1843 if (pcrel_op
->include_isa_bit
)
1847 print_insn_arg (info
, &state
, opcode
, operand
, base_pc
,
1848 mips_extract_operand (operand
, insn
));
1850 if (*s
== 'm' || *s
== '+' || *s
== '-')
1857 /* Print the mips instruction at address MEMADDR in debugged memory,
1858 on using INFO. Returns length of the instruction, in bytes, which is
1859 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
1860 this is little-endian code. */
1863 print_insn_mips (bfd_vma memaddr
,
1865 struct disassemble_info
*info
)
1867 #define GET_OP(insn, field) \
1868 (((insn) >> OP_SH_##field) & OP_MASK_##field)
1869 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
1870 const fprintf_ftype infprintf
= info
->fprintf_func
;
1871 const struct mips_opcode
*op
;
1872 static bfd_boolean init
= 0;
1873 void *is
= info
->stream
;
1875 /* Build a hash table to shorten the search time. */
1880 for (i
= 0; i
<= OP_MASK_OP
; i
++)
1882 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1884 if (op
->pinfo
== INSN_MACRO
1885 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
1887 if (i
== GET_OP (op
->match
, OP
))
1898 info
->bytes_per_chunk
= INSNLEN
;
1899 info
->display_endian
= info
->endian
;
1900 info
->insn_info_valid
= 1;
1901 info
->branch_delay_insns
= 0;
1902 info
->data_size
= 0;
1903 info
->insn_type
= dis_nonbranch
;
1907 op
= mips_hash
[GET_OP (word
, OP
)];
1910 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1912 if (op
->pinfo
!= INSN_MACRO
1913 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
1914 && (word
& op
->mask
) == op
->match
)
1916 /* We always disassemble the jalx instruction, except for MIPS r6. */
1917 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
)
1918 && (strcmp (op
->name
, "jalx")
1919 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS32R6
1920 || (mips_isa
& INSN_ISA_MASK
) == ISA_MIPS64R6
))
1923 /* Figure out instruction type and branch delay information. */
1924 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
1926 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
1927 info
->insn_type
= dis_jsr
;
1929 info
->insn_type
= dis_branch
;
1930 info
->branch_delay_insns
= 1;
1932 else if ((op
->pinfo
& (INSN_COND_BRANCH_DELAY
1933 | INSN_COND_BRANCH_LIKELY
)) != 0)
1935 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
1936 info
->insn_type
= dis_condjsr
;
1938 info
->insn_type
= dis_condbranch
;
1939 info
->branch_delay_insns
= 1;
1941 else if ((op
->pinfo
& (INSN_STORE_MEMORY
1942 | INSN_LOAD_MEMORY
)) != 0)
1943 info
->insn_type
= dis_dref
;
1945 if (!validate_insn_args (op
, decode_mips_operand
, word
))
1948 infprintf (is
, "%s", op
->name
);
1949 if (op
->pinfo2
& INSN2_VU0_CHANNEL_SUFFIX
)
1953 infprintf (is
, ".");
1954 uval
= mips_extract_operand (&mips_vu0_channel_mask
, word
);
1955 print_vu0_channel (info
, &mips_vu0_channel_mask
, uval
);
1960 infprintf (is
, "\t");
1961 print_insn_args (info
, op
, decode_mips_operand
, word
,
1971 /* Handle undefined instructions. */
1972 info
->insn_type
= dis_noninsn
;
1973 infprintf (is
, "0x%x", word
);
1977 /* Disassemble an operand for a mips16 instruction. */
1980 print_mips16_insn_arg (struct disassemble_info
*info
,
1981 struct mips_print_arg_state
*state
,
1982 const struct mips_opcode
*opcode
,
1983 char type
, bfd_vma memaddr
,
1984 unsigned insn
, bfd_boolean use_extend
,
1985 unsigned extend
, bfd_boolean is_offset
)
1987 const fprintf_ftype infprintf
= info
->fprintf_func
;
1988 void *is
= info
->stream
;
1989 const struct mips_operand
*operand
, *ext_operand
;
1990 unsigned short ext_size
;
2002 infprintf (is
, "%c", type
);
2006 operand
= decode_mips16_operand (type
, FALSE
);
2009 /* xgettext:c-format */
2010 infprintf (is
, _("# internal error, undefined operand in `%s %s'"),
2011 opcode
->name
, opcode
->args
);
2015 if (operand
->type
== OP_SAVE_RESTORE_LIST
)
2017 /* Handle this case here because of the complex interaction
2018 with the EXTEND opcode. */
2019 unsigned int amask
= extend
& 0xf;
2020 unsigned int nsreg
= (extend
>> 8) & 0x7;
2021 unsigned int ra
= insn
& 0x40; /* $ra */
2022 unsigned int s0
= insn
& 0x20; /* $s0 */
2023 unsigned int s1
= insn
& 0x10; /* $s1 */
2024 unsigned int frame_size
= ((extend
& 0xf0) | (insn
& 0x0f)) * 8;
2025 if (frame_size
== 0 && !use_extend
)
2027 mips_print_save_restore (info
, amask
, nsreg
, ra
, s0
, s1
, frame_size
);
2031 if (is_offset
&& operand
->type
== OP_INT
)
2033 const struct mips_int_operand
*int_op
;
2035 int_op
= (const struct mips_int_operand
*) operand
;
2036 info
->insn_type
= dis_dref
;
2037 info
->data_size
= 1 << int_op
->shift
;
2043 ext_operand
= decode_mips16_operand (type
, TRUE
);
2044 if (ext_operand
!= operand
2045 || (operand
->type
== OP_INT
&& operand
->lsb
== 0
2046 && mips_opcode_32bit_p (opcode
)))
2048 ext_size
= ext_operand
->size
;
2049 operand
= ext_operand
;
2052 if (operand
->size
== 26)
2053 uval
= ((extend
& 0x1f) << 21) | ((extend
& 0x3e0) << 11) | insn
;
2054 else if (ext_size
== 16 || ext_size
== 9)
2055 uval
= ((extend
& 0x1f) << 11) | (extend
& 0x7e0) | (insn
& 0x1f);
2056 else if (ext_size
== 15)
2057 uval
= ((extend
& 0xf) << 11) | (extend
& 0x7f0) | (insn
& 0xf);
2058 else if (ext_size
== 6)
2059 uval
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
2061 uval
= mips_extract_operand (operand
, (extend
<< 16) | insn
);
2063 uval
&= (1U << ext_size
) - 1;
2065 baseaddr
= memaddr
+ 2;
2066 if (operand
->type
== OP_PCREL
)
2068 const struct mips_pcrel_operand
*pcrel_op
;
2070 pcrel_op
= (const struct mips_pcrel_operand
*) operand
;
2071 if (!pcrel_op
->include_isa_bit
&& use_extend
)
2072 baseaddr
= memaddr
- 2;
2073 else if (!pcrel_op
->include_isa_bit
)
2077 /* If this instruction is in the delay slot of a JAL/JALX
2078 instruction, the base address is the address of the
2079 JAL/JALX instruction. If it is in the delay slot of
2080 a JR/JALR instruction, the base address is the address
2081 of the JR/JALR instruction. This test is unreliable:
2082 we have no way of knowing whether the previous word is
2083 instruction or data. */
2084 if (info
->read_memory_func (memaddr
- 4, buffer
, 2, info
) == 0
2085 && (((info
->endian
== BFD_ENDIAN_BIG
2086 ? bfd_getb16 (buffer
)
2087 : bfd_getl16 (buffer
))
2088 & 0xf800) == 0x1800))
2089 baseaddr
= memaddr
- 4;
2090 else if (info
->read_memory_func (memaddr
- 2, buffer
, 2,
2092 && (((info
->endian
== BFD_ENDIAN_BIG
2093 ? bfd_getb16 (buffer
)
2094 : bfd_getl16 (buffer
))
2095 & 0xf89f) == 0xe800)
2096 && (((info
->endian
== BFD_ENDIAN_BIG
2097 ? bfd_getb16 (buffer
)
2098 : bfd_getl16 (buffer
))
2099 & 0x0060) != 0x0060))
2100 baseaddr
= memaddr
- 2;
2106 print_insn_arg (info
, state
, opcode
, operand
, baseaddr
+ 1, uval
);
2112 /* Check if the given address is the last word of a MIPS16 PLT entry.
2113 This word is data and depending on the value it may interfere with
2114 disassembly of further PLT entries. We make use of the fact PLT
2115 symbols are marked BSF_SYNTHETIC. */
2117 is_mips16_plt_tail (struct disassemble_info
*info
, bfd_vma addr
)
2121 && (info
->symbols
[0]->flags
& BSF_SYNTHETIC
)
2122 && addr
== bfd_asymbol_value (info
->symbols
[0]) + 12)
2128 /* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2137 /* Disassemble mips16 instructions. */
2140 print_insn_mips16 (bfd_vma memaddr
, struct disassemble_info
*info
)
2142 const fprintf_ftype infprintf
= info
->fprintf_func
;
2145 const struct mips_opcode
*op
, *opend
;
2146 struct mips_print_arg_state state
;
2147 void *is
= info
->stream
;
2148 bfd_boolean have_second
;
2149 bfd_boolean extend_only
;
2150 unsigned int second
;
2154 info
->bytes_per_chunk
= 2;
2155 info
->display_endian
= info
->endian
;
2156 info
->insn_info_valid
= 1;
2157 info
->branch_delay_insns
= 0;
2158 info
->data_size
= 0;
2162 #define GET_OP(insn, field) \
2163 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
2164 /* Decode PLT entry's GOT slot address word. */
2165 if (is_mips16_plt_tail (info
, memaddr
))
2167 info
->insn_type
= dis_noninsn
;
2168 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
2171 unsigned int gotslot
;
2173 if (info
->endian
== BFD_ENDIAN_BIG
)
2174 gotslot
= bfd_getb32 (buffer
);
2176 gotslot
= bfd_getl32 (buffer
);
2177 infprintf (is
, ".word\t0x%x", gotslot
);
2184 info
->insn_type
= dis_nonbranch
;
2185 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2189 (*info
->memory_error_func
) (status
, memaddr
, info
);
2193 extend_only
= FALSE
;
2195 if (info
->endian
== BFD_ENDIAN_BIG
)
2196 first
= bfd_getb16 (buffer
);
2198 first
= bfd_getl16 (buffer
);
2200 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2204 if (info
->endian
== BFD_ENDIAN_BIG
)
2205 second
= bfd_getb16 (buffer
);
2207 second
= bfd_getl16 (buffer
);
2208 full
= (first
<< 16) | second
;
2212 have_second
= FALSE
;
2217 /* FIXME: Should probably use a hash table on the major opcode here. */
2219 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
2220 for (op
= mips16_opcodes
; op
< opend
; op
++)
2222 enum match_kind match
;
2224 if (!opcode_is_member (op
, mips_isa
, mips_ase
, mips_processor
))
2227 if (op
->pinfo
== INSN_MACRO
2228 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
2230 else if (mips_opcode_32bit_p (op
))
2233 && (full
& op
->mask
) == op
->match
)
2238 else if ((first
& op
->mask
) == op
->match
)
2240 match
= MATCH_SHORT
;
2244 else if ((first
& 0xf800) == 0xf000
2247 && (second
& op
->mask
) == op
->match
)
2249 if (op
->pinfo2
& INSN2_SHORT_ONLY
)
2260 if (match
!= MATCH_NONE
)
2264 infprintf (is
, "%s", op
->name
);
2265 if (op
->args
[0] != '\0')
2266 infprintf (is
, "\t");
2268 init_print_arg_state (&state
);
2269 for (s
= op
->args
; *s
!= '\0'; s
++)
2273 && GET_OP (full
, RX
) == GET_OP (full
, RY
))
2275 /* Skip the register and the comma. */
2281 && GET_OP (full
, RZ
) == GET_OP (full
, RX
))
2283 /* Skip the register and the comma. */
2290 && op
->name
[strlen (op
->name
) - 1] == '0')
2292 /* Coprocessor register 0 with sel field. */
2293 const struct mips_cp0sel_name
*n
;
2294 const struct mips_operand
*operand
;
2295 unsigned int reg
, sel
;
2297 operand
= decode_mips16_operand (*s
, TRUE
);
2298 reg
= mips_extract_operand (operand
, (first
<< 16) | second
);
2300 operand
= decode_mips16_operand (*s
, TRUE
);
2301 sel
= mips_extract_operand (operand
, (first
<< 16) | second
);
2303 /* CP0 register including 'sel' code for mftc0, to be
2304 printed textually if known. If not known, print both
2305 CP0 register name and sel numerically since CP0 register
2306 with sel 0 may have a name unrelated to register being
2308 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
2309 mips_cp0sel_names_len
,
2312 infprintf (is
, "%s", n
->name
);
2314 infprintf (is
, "$%d,%d", reg
, sel
);
2320 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
+ 2,
2321 second
, TRUE
, first
, s
[1] == '(');
2324 print_mips16_insn_arg (info
, &state
, op
, *s
, memaddr
,
2325 first
, FALSE
, 0, s
[1] == '(');
2327 case MATCH_NONE
: /* Stop the compiler complaining. */
2332 /* Figure out branch instruction type and delay slot information. */
2333 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
2334 info
->branch_delay_insns
= 1;
2335 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0
2336 || (op
->pinfo2
& INSN2_UNCOND_BRANCH
) != 0)
2338 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2339 info
->insn_type
= dis_jsr
;
2341 info
->insn_type
= dis_branch
;
2343 else if ((op
->pinfo2
& INSN2_COND_BRANCH
) != 0)
2344 info
->insn_type
= dis_condbranch
;
2346 return match
== MATCH_FULL
? 4 : 2;
2351 infprintf (is
, "0x%x", first
);
2352 info
->insn_type
= dis_noninsn
;
2357 /* Disassemble microMIPS instructions. */
2360 print_insn_micromips (bfd_vma memaddr
, struct disassemble_info
*info
)
2362 const fprintf_ftype infprintf
= info
->fprintf_func
;
2363 const struct mips_opcode
*op
, *opend
;
2364 void *is
= info
->stream
;
2366 unsigned int higher
;
2367 unsigned int length
;
2371 info
->bytes_per_chunk
= 2;
2372 info
->display_endian
= info
->endian
;
2373 info
->insn_info_valid
= 1;
2374 info
->branch_delay_insns
= 0;
2375 info
->data_size
= 0;
2376 info
->insn_type
= dis_nonbranch
;
2380 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2383 (*info
->memory_error_func
) (status
, memaddr
, info
);
2389 if (info
->endian
== BFD_ENDIAN_BIG
)
2390 insn
= bfd_getb16 (buffer
);
2392 insn
= bfd_getl16 (buffer
);
2394 if ((insn
& 0x1c00) == 0x0000 || (insn
& 0x1000) == 0x1000)
2396 /* This is a 32-bit microMIPS instruction. */
2399 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2402 infprintf (is
, "micromips 0x%x", higher
);
2403 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
2407 if (info
->endian
== BFD_ENDIAN_BIG
)
2408 insn
= bfd_getb16 (buffer
);
2410 insn
= bfd_getl16 (buffer
);
2412 insn
= insn
| (higher
<< 16);
2417 /* FIXME: Should probably use a hash table on the major opcode here. */
2419 opend
= micromips_opcodes
+ bfd_micromips_num_opcodes
;
2420 for (op
= micromips_opcodes
; op
< opend
; op
++)
2422 if (op
->pinfo
!= INSN_MACRO
2423 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
2424 && (insn
& op
->mask
) == op
->match
2425 && ((length
== 2 && (op
->mask
& 0xffff0000) == 0)
2426 || (length
== 4 && (op
->mask
& 0xffff0000) != 0)))
2428 if (!validate_insn_args (op
, decode_micromips_operand
, insn
))
2431 infprintf (is
, "%s", op
->name
);
2435 infprintf (is
, "\t");
2436 print_insn_args (info
, op
, decode_micromips_operand
, insn
,
2437 memaddr
+ 1, length
);
2440 /* Figure out instruction type and branch delay information. */
2442 & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
)) != 0)
2443 info
->branch_delay_insns
= 1;
2444 if (((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
2445 | (op
->pinfo2
& INSN2_UNCOND_BRANCH
)) != 0)
2447 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_1
)) != 0)
2448 info
->insn_type
= dis_jsr
;
2450 info
->insn_type
= dis_branch
;
2452 else if (((op
->pinfo
& INSN_COND_BRANCH_DELAY
)
2453 | (op
->pinfo2
& INSN2_COND_BRANCH
)) != 0)
2455 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2456 info
->insn_type
= dis_condjsr
;
2458 info
->insn_type
= dis_condbranch
;
2461 & (INSN_STORE_MEMORY
| INSN_LOAD_MEMORY
)) != 0)
2462 info
->insn_type
= dis_dref
;
2468 infprintf (is
, "0x%x", insn
);
2469 info
->insn_type
= dis_noninsn
;
2474 /* Return 1 if a symbol associated with the location being disassembled
2475 indicates a compressed mode, either MIPS16 or microMIPS, according to
2476 MICROMIPS_P. We iterate over all the symbols at the address being
2477 considered assuming if at least one of them indicates code compression,
2478 then such code has been genuinely produced here (other symbols could
2479 have been derived from function symbols defined elsewhere or could
2480 define data). Otherwise, return 0. */
2483 is_compressed_mode_p (struct disassemble_info
*info
, bfd_boolean micromips_p
)
2488 for (i
= info
->symtab_pos
, l
= i
+ info
->num_symbols
; i
< l
; i
++)
2489 if (((info
->symtab
[i
])->flags
& BSF_SYNTHETIC
) != 0
2491 && ELF_ST_IS_MIPS16 ((*info
->symbols
)->udata
.i
))
2493 && ELF_ST_IS_MICROMIPS ((*info
->symbols
)->udata
.i
))))
2495 else if (bfd_asymbol_flavour (info
->symtab
[i
]) == bfd_target_elf_flavour
2496 && info
->symtab
[i
]->section
== info
->section
)
2498 elf_symbol_type
*symbol
= (elf_symbol_type
*) info
->symtab
[i
];
2500 && ELF_ST_IS_MIPS16 (symbol
->internal_elf_sym
.st_other
))
2502 && ELF_ST_IS_MICROMIPS (symbol
->internal_elf_sym
.st_other
)))
2509 /* In an environment where we do not know the symbol type of the
2510 instruction we are forced to assume that the low order bit of the
2511 instructions' address may mark it as a mips16 instruction. If we
2512 are single stepping, or the pc is within the disassembled function,
2513 this works. Otherwise, we need a clue. Sometimes. */
2516 _print_insn_mips (bfd_vma memaddr
,
2517 struct disassemble_info
*info
,
2518 enum bfd_endian endianness
)
2520 bfd_byte buffer
[INSNLEN
];
2523 set_default_mips_dis_options (info
);
2524 parse_mips_dis_options (info
->disassembler_options
);
2526 if (info
->mach
== bfd_mach_mips16
)
2527 return print_insn_mips16 (memaddr
, info
);
2528 if (info
->mach
== bfd_mach_mips_micromips
)
2529 return print_insn_micromips (memaddr
, info
);
2532 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
2533 /* Only a few tools will work this way. */
2537 return print_insn_micromips (memaddr
, info
);
2539 return print_insn_mips16 (memaddr
, info
);
2543 #if SYMTAB_AVAILABLE
2544 if (is_compressed_mode_p (info
, TRUE
))
2545 return print_insn_micromips (memaddr
, info
);
2546 if (is_compressed_mode_p (info
, FALSE
))
2547 return print_insn_mips16 (memaddr
, info
);
2550 status
= (*info
->read_memory_func
) (memaddr
, buffer
, INSNLEN
, info
);
2555 if (endianness
== BFD_ENDIAN_BIG
)
2556 insn
= bfd_getb32 (buffer
);
2558 insn
= bfd_getl32 (buffer
);
2560 return print_insn_mips (memaddr
, insn
, info
);
2564 (*info
->memory_error_func
) (status
, memaddr
, info
);
2570 print_insn_big_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2572 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_BIG
);
2576 print_insn_little_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
2578 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_LITTLE
);
2581 /* Indices into option argument vector for options accepting an argument.
2582 Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2585 MIPS_OPTION_ARG_NONE
= -1,
2586 MIPS_OPTION_ARG_ABI
,
2587 MIPS_OPTION_ARG_ARCH
,
2588 MIPS_OPTION_ARG_SIZE
2589 } mips_option_arg_t
;
2591 /* Valid MIPS disassembler options. */
2595 const char *description
;
2596 mips_option_arg_t arg
;
2599 { "no-aliases", N_("Use canonical instruction forms.\n"),
2600 MIPS_OPTION_ARG_NONE
},
2601 { "msa", N_("Recognize MSA instructions.\n"),
2602 MIPS_OPTION_ARG_NONE
},
2603 { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2604 MIPS_OPTION_ARG_NONE
},
2605 { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2607 MIPS_OPTION_ARG_NONE
},
2608 { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2610 MIPS_OPTION_ARG_NONE
},
2612 N_("Recognize the Loongson MultiMedia extensions "
2613 "Instructions (MMI) ASE instructions.\n"),
2614 MIPS_OPTION_ARG_NONE
},
2616 N_("Recognize the Loongson Content Address Memory (CAM) "
2617 " instructions.\n"),
2618 MIPS_OPTION_ARG_NONE
},
2620 N_("Recognize the Loongson EXTensions (EXT) "
2621 " instructions.\n"),
2622 MIPS_OPTION_ARG_NONE
},
2624 N_("Recognize the Loongson EXTensions R2 (EXT2) "
2625 " instructions.\n"),
2626 MIPS_OPTION_ARG_NONE
},
2627 { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2628 Default: based on binary being disassembled.\n"),
2629 MIPS_OPTION_ARG_ABI
},
2630 { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2631 Default: numeric.\n"),
2632 MIPS_OPTION_ARG_ABI
},
2633 { "cp0-names=", N_("Print CP0 register names according to specified "
2635 Default: based on binary being disassembled.\n"),
2636 MIPS_OPTION_ARG_ARCH
},
2637 { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2638 Default: based on binary being disassembled.\n"),
2639 MIPS_OPTION_ARG_ARCH
},
2640 { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2641 MIPS_OPTION_ARG_ABI
},
2642 { "reg-names=", N_("Print CP0 register and HWR names according to "
2645 MIPS_OPTION_ARG_ARCH
}
2648 /* Build the structure representing valid MIPS disassembler options.
2649 This is done dynamically for maintenance ease purpose; a static
2650 initializer would be unreadable. */
2652 const disasm_options_and_args_t
*
2653 disassembler_options_mips (void)
2655 static disasm_options_and_args_t
*opts_and_args
;
2657 if (opts_and_args
== NULL
)
2659 size_t num_options
= ARRAY_SIZE (mips_options
);
2660 size_t num_args
= MIPS_OPTION_ARG_SIZE
;
2661 disasm_option_arg_t
*args
;
2662 disasm_options_t
*opts
;
2666 args
= XNEWVEC (disasm_option_arg_t
, num_args
+ 1);
2668 args
[MIPS_OPTION_ARG_ABI
].name
= "ABI";
2669 args
[MIPS_OPTION_ARG_ABI
].values
2670 = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices
) + 1);
2671 for (i
= 0; i
< ARRAY_SIZE (mips_abi_choices
); i
++)
2672 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = mips_abi_choices
[i
].name
;
2673 /* The array we return must be NULL terminated. */
2674 args
[MIPS_OPTION_ARG_ABI
].values
[i
] = NULL
;
2676 args
[MIPS_OPTION_ARG_ARCH
].name
= "ARCH";
2677 args
[MIPS_OPTION_ARG_ARCH
].values
2678 = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices
) + 1);
2679 for (i
= 0, j
= 0; i
< ARRAY_SIZE (mips_arch_choices
); i
++)
2680 if (*mips_arch_choices
[i
].name
!= '\0')
2681 args
[MIPS_OPTION_ARG_ARCH
].values
[j
++] = mips_arch_choices
[i
].name
;
2682 /* The array we return must be NULL terminated. */
2683 args
[MIPS_OPTION_ARG_ARCH
].values
[j
] = NULL
;
2685 /* The array we return must be NULL terminated. */
2686 args
[MIPS_OPTION_ARG_SIZE
].name
= NULL
;
2687 args
[MIPS_OPTION_ARG_SIZE
].values
= NULL
;
2689 opts_and_args
= XNEW (disasm_options_and_args_t
);
2690 opts_and_args
->args
= args
;
2692 opts
= &opts_and_args
->options
;
2693 opts
->name
= XNEWVEC (const char *, num_options
+ 1);
2694 opts
->description
= XNEWVEC (const char *, num_options
+ 1);
2695 opts
->arg
= XNEWVEC (const disasm_option_arg_t
*, num_options
+ 1);
2696 for (i
= 0; i
< num_options
; i
++)
2698 opts
->name
[i
] = mips_options
[i
].name
;
2699 opts
->description
[i
] = _(mips_options
[i
].description
);
2700 if (mips_options
[i
].arg
!= MIPS_OPTION_ARG_NONE
)
2701 opts
->arg
[i
] = &args
[mips_options
[i
].arg
];
2703 opts
->arg
[i
] = NULL
;
2705 /* The array we return must be NULL terminated. */
2706 opts
->name
[i
] = NULL
;
2707 opts
->description
[i
] = NULL
;
2708 opts
->arg
[i
] = NULL
;
2711 return opts_and_args
;
2715 print_mips_disassembler_options (FILE *stream
)
2717 const disasm_options_and_args_t
*opts_and_args
;
2718 const disasm_option_arg_t
*args
;
2719 const disasm_options_t
*opts
;
2724 opts_and_args
= disassembler_options_mips ();
2725 opts
= &opts_and_args
->options
;
2726 args
= opts_and_args
->args
;
2728 fprintf (stream
, _("\n\
2729 The following MIPS specific disassembler options are supported for use\n\
2730 with the -M switch (multiple options should be separated by commas):\n\n"));
2732 /* Compute the length of the longest option name. */
2733 for (i
= 0; opts
->name
[i
] != NULL
; i
++)
2735 size_t len
= strlen (opts
->name
[i
]);
2737 if (opts
->arg
[i
] != NULL
)
2738 len
+= strlen (opts
->arg
[i
]->name
);
2743 for (i
= 0, max_len
++; opts
->name
[i
] != NULL
; i
++)
2745 fprintf (stream
, " %s", opts
->name
[i
]);
2746 if (opts
->arg
[i
] != NULL
)
2747 fprintf (stream
, "%s", opts
->arg
[i
]->name
);
2748 if (opts
->description
[i
] != NULL
)
2750 size_t len
= strlen (opts
->name
[i
]);
2752 if (opts
->arg
[i
] != NULL
)
2753 len
+= strlen (opts
->arg
[i
]->name
);
2755 "%*c %s", (int) (max_len
- len
), ' ', opts
->description
[i
]);
2757 fprintf (stream
, _("\n"));
2760 for (i
= 0; args
[i
].name
!= NULL
; i
++)
2762 fprintf (stream
, _("\n\
2763 For the options above, the following values are supported for \"%s\":\n "),
2765 for (j
= 0; args
[i
].values
[j
] != NULL
; j
++)
2766 fprintf (stream
, " %s", args
[i
].values
[j
]);
2767 fprintf (stream
, _("\n"));
2770 fprintf (stream
, _("\n"));