1 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
3 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2012
4 Free Software Foundation, Inc.
5 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
7 This file is part of the GNU opcodes library.
9 This library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
14 It is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
26 #include "libiberty.h"
27 #include "opcode/mips.h"
30 /* FIXME: These are needed to figure out if the code is mips16 or
31 not. The low bit of the address is often a good indicator. No
32 symbol table is available when this code runs out in an embedded
33 system as when it is used for disassembler support in a monitor. */
35 #if !defined(EMBEDDED_ENV)
36 #define SYMTAB_AVAILABLE 1
41 /* Mips instructions are at maximum this many bytes long. */
45 /* FIXME: These should be shared with gdb somehow. */
47 struct mips_cp0sel_name
51 const char * const name
;
54 /* The mips16 registers. */
55 static const unsigned int mips16_to_32_reg_map
[] =
57 16, 17, 2, 3, 4, 5, 6, 7
60 /* The microMIPS registers with type b. */
61 #define micromips_to_32_reg_b_map mips16_to_32_reg_map
63 /* The microMIPS registers with type c. */
64 #define micromips_to_32_reg_c_map mips16_to_32_reg_map
66 /* The microMIPS registers with type d. */
67 #define micromips_to_32_reg_d_map mips16_to_32_reg_map
69 /* The microMIPS registers with type e. */
70 #define micromips_to_32_reg_e_map mips16_to_32_reg_map
72 /* The microMIPS registers with type f. */
73 #define micromips_to_32_reg_f_map mips16_to_32_reg_map
75 /* The microMIPS registers with type g. */
76 #define micromips_to_32_reg_g_map mips16_to_32_reg_map
78 /* The microMIPS registers with type h. */
79 static const unsigned int micromips_to_32_reg_h_map
[] =
81 5, 5, 6, 4, 4, 4, 4, 4
84 /* The microMIPS registers with type i. */
85 static const unsigned int micromips_to_32_reg_i_map
[] =
87 6, 7, 7, 21, 22, 5, 6, 7
90 /* The microMIPS registers with type j: 32 registers. */
92 /* The microMIPS registers with type l. */
93 #define micromips_to_32_reg_l_map mips16_to_32_reg_map
95 /* The microMIPS registers with type m. */
96 static const unsigned int micromips_to_32_reg_m_map
[] =
98 0, 17, 2, 3, 16, 18, 19, 20
101 /* The microMIPS registers with type n. */
102 #define micromips_to_32_reg_n_map micromips_to_32_reg_m_map
104 /* The microMIPS registers with type p: 32 registers. */
106 /* The microMIPS registers with type q. */
107 static const unsigned int micromips_to_32_reg_q_map
[] =
109 0, 17, 2, 3, 4, 5, 6, 7
112 /* reg type s is $29. */
114 /* reg type t is the same as the last register. */
116 /* reg type y is $31. */
118 /* reg type z is $0. */
120 /* micromips imm B type. */
121 static const int micromips_imm_b_map
[8] =
123 1, 4, 8, 12, 16, 20, 24, -1
126 /* micromips imm C type. */
127 static const int micromips_imm_c_map
[16] =
129 128, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 255, 32768, 65535
132 /* micromips imm D type: (-512..511)<<1. */
133 /* micromips imm E type: (-64..63)<<1. */
134 /* micromips imm F type: (0..63). */
135 /* micromips imm G type: (-1..14). */
136 /* micromips imm H type: (0..15)<<1. */
137 /* micromips imm I type: (-1..126). */
138 /* micromips imm J type: (0..15)<<2. */
139 /* micromips imm L type: (0..15). */
140 /* micromips imm M type: (1..8). */
141 /* micromips imm W type: (0..63)<<2. */
142 /* micromips imm X type: (-8..7). */
143 /* micromips imm Y type: (-258..-3, 2..257)<<2. */
145 #define mips16_reg_names(rn) mips_gpr_names[mips16_to_32_reg_map[rn]]
148 static const char * const mips_gpr_names_numeric
[32] =
150 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
151 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
152 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
153 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
156 static const char * const mips_gpr_names_oldabi
[32] =
158 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
159 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
160 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
161 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
164 static const char * const mips_gpr_names_newabi
[32] =
166 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
167 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
168 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
169 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
172 static const char * const mips_fpr_names_numeric
[32] =
174 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
175 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
176 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
177 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
180 static const char * const mips_fpr_names_32
[32] =
182 "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
183 "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
184 "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f",
185 "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f"
188 static const char * const mips_fpr_names_n32
[32] =
190 "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3",
191 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
192 "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9",
193 "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13"
196 static const char * const mips_fpr_names_64
[32] =
198 "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
199 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
200 "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
201 "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
204 static const char * const mips_cp0_names_numeric
[32] =
206 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
207 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
208 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
209 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
212 static const char * const mips_cp0_names_r3000
[32] =
214 "c0_index", "c0_random", "c0_entrylo", "$3",
215 "c0_context", "$5", "$6", "$7",
216 "c0_badvaddr", "$9", "c0_entryhi", "$11",
217 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
218 "$16", "$17", "$18", "$19",
219 "$20", "$21", "$22", "$23",
220 "$24", "$25", "$26", "$27",
221 "$28", "$29", "$30", "$31",
224 static const char * const mips_cp0_names_r4000
[32] =
226 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
227 "c0_context", "c0_pagemask", "c0_wired", "$7",
228 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
229 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
230 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
231 "c0_xcontext", "$21", "$22", "$23",
232 "$24", "$25", "c0_ecc", "c0_cacheerr",
233 "c0_taglo", "c0_taghi", "c0_errorepc", "$31",
236 static const char * const mips_cp0_names_r5900
[32] =
238 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
239 "c0_context", "c0_pagemask", "c0_wired", "$7",
240 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
241 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
242 "c0_config", "$17", "$18", "$19",
243 "$20", "$21", "$22", "c0_badpaddr",
244 "c0_depc", "c0_perfcnt", "$26", "$27",
245 "c0_taglo", "c0_taghi", "c0_errorepc", "$31"
248 static const struct mips_cp0sel_name mips_cp0sel_names_mipsr5900
[] =
251 { 24, 3, "c0_iabm" },
253 { 24, 5, "c0_dabm" },
255 { 24, 7, "c0_dvbm" },
256 { 25, 1, "c0_perfcnt,1" },
257 { 25, 2, "c0_perfcnt,2" }
260 static const char * const mips_cp0_names_mips3264
[32] =
262 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
263 "c0_context", "c0_pagemask", "c0_wired", "$7",
264 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
265 "c0_status", "c0_cause", "c0_epc", "c0_prid",
266 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
267 "c0_xcontext", "$21", "$22", "c0_debug",
268 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
269 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
272 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264
[] =
274 { 16, 1, "c0_config1" },
275 { 16, 2, "c0_config2" },
276 { 16, 3, "c0_config3" },
277 { 18, 1, "c0_watchlo,1" },
278 { 18, 2, "c0_watchlo,2" },
279 { 18, 3, "c0_watchlo,3" },
280 { 18, 4, "c0_watchlo,4" },
281 { 18, 5, "c0_watchlo,5" },
282 { 18, 6, "c0_watchlo,6" },
283 { 18, 7, "c0_watchlo,7" },
284 { 19, 1, "c0_watchhi,1" },
285 { 19, 2, "c0_watchhi,2" },
286 { 19, 3, "c0_watchhi,3" },
287 { 19, 4, "c0_watchhi,4" },
288 { 19, 5, "c0_watchhi,5" },
289 { 19, 6, "c0_watchhi,6" },
290 { 19, 7, "c0_watchhi,7" },
291 { 25, 1, "c0_perfcnt,1" },
292 { 25, 2, "c0_perfcnt,2" },
293 { 25, 3, "c0_perfcnt,3" },
294 { 25, 4, "c0_perfcnt,4" },
295 { 25, 5, "c0_perfcnt,5" },
296 { 25, 6, "c0_perfcnt,6" },
297 { 25, 7, "c0_perfcnt,7" },
298 { 27, 1, "c0_cacheerr,1" },
299 { 27, 2, "c0_cacheerr,2" },
300 { 27, 3, "c0_cacheerr,3" },
301 { 28, 1, "c0_datalo" },
302 { 29, 1, "c0_datahi" }
305 static const char * const mips_cp0_names_mips3264r2
[32] =
307 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
308 "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
309 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
310 "c0_status", "c0_cause", "c0_epc", "c0_prid",
311 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
312 "c0_xcontext", "$21", "$22", "c0_debug",
313 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
314 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
317 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2
[] =
319 { 4, 1, "c0_contextconfig" },
320 { 0, 1, "c0_mvpcontrol" },
321 { 0, 2, "c0_mvpconf0" },
322 { 0, 3, "c0_mvpconf1" },
323 { 1, 1, "c0_vpecontrol" },
324 { 1, 2, "c0_vpeconf0" },
325 { 1, 3, "c0_vpeconf1" },
326 { 1, 4, "c0_yqmask" },
327 { 1, 5, "c0_vpeschedule" },
328 { 1, 6, "c0_vpeschefback" },
329 { 2, 1, "c0_tcstatus" },
330 { 2, 2, "c0_tcbind" },
331 { 2, 3, "c0_tcrestart" },
332 { 2, 4, "c0_tchalt" },
333 { 2, 5, "c0_tccontext" },
334 { 2, 6, "c0_tcschedule" },
335 { 2, 7, "c0_tcschefback" },
336 { 5, 1, "c0_pagegrain" },
337 { 6, 1, "c0_srsconf0" },
338 { 6, 2, "c0_srsconf1" },
339 { 6, 3, "c0_srsconf2" },
340 { 6, 4, "c0_srsconf3" },
341 { 6, 5, "c0_srsconf4" },
342 { 12, 1, "c0_intctl" },
343 { 12, 2, "c0_srsctl" },
344 { 12, 3, "c0_srsmap" },
345 { 15, 1, "c0_ebase" },
346 { 16, 1, "c0_config1" },
347 { 16, 2, "c0_config2" },
348 { 16, 3, "c0_config3" },
349 { 18, 1, "c0_watchlo,1" },
350 { 18, 2, "c0_watchlo,2" },
351 { 18, 3, "c0_watchlo,3" },
352 { 18, 4, "c0_watchlo,4" },
353 { 18, 5, "c0_watchlo,5" },
354 { 18, 6, "c0_watchlo,6" },
355 { 18, 7, "c0_watchlo,7" },
356 { 19, 1, "c0_watchhi,1" },
357 { 19, 2, "c0_watchhi,2" },
358 { 19, 3, "c0_watchhi,3" },
359 { 19, 4, "c0_watchhi,4" },
360 { 19, 5, "c0_watchhi,5" },
361 { 19, 6, "c0_watchhi,6" },
362 { 19, 7, "c0_watchhi,7" },
363 { 23, 1, "c0_tracecontrol" },
364 { 23, 2, "c0_tracecontrol2" },
365 { 23, 3, "c0_usertracedata" },
366 { 23, 4, "c0_tracebpc" },
367 { 25, 1, "c0_perfcnt,1" },
368 { 25, 2, "c0_perfcnt,2" },
369 { 25, 3, "c0_perfcnt,3" },
370 { 25, 4, "c0_perfcnt,4" },
371 { 25, 5, "c0_perfcnt,5" },
372 { 25, 6, "c0_perfcnt,6" },
373 { 25, 7, "c0_perfcnt,7" },
374 { 27, 1, "c0_cacheerr,1" },
375 { 27, 2, "c0_cacheerr,2" },
376 { 27, 3, "c0_cacheerr,3" },
377 { 28, 1, "c0_datalo" },
378 { 28, 2, "c0_taglo1" },
379 { 28, 3, "c0_datalo1" },
380 { 28, 4, "c0_taglo2" },
381 { 28, 5, "c0_datalo2" },
382 { 28, 6, "c0_taglo3" },
383 { 28, 7, "c0_datalo3" },
384 { 29, 1, "c0_datahi" },
385 { 29, 2, "c0_taghi1" },
386 { 29, 3, "c0_datahi1" },
387 { 29, 4, "c0_taghi2" },
388 { 29, 5, "c0_datahi2" },
389 { 29, 6, "c0_taghi3" },
390 { 29, 7, "c0_datahi3" },
393 /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
394 static const char * const mips_cp0_names_sb1
[32] =
396 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
397 "c0_context", "c0_pagemask", "c0_wired", "$7",
398 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
399 "c0_status", "c0_cause", "c0_epc", "c0_prid",
400 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
401 "c0_xcontext", "$21", "$22", "c0_debug",
402 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
403 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
406 static const struct mips_cp0sel_name mips_cp0sel_names_sb1
[] =
408 { 16, 1, "c0_config1" },
409 { 18, 1, "c0_watchlo,1" },
410 { 19, 1, "c0_watchhi,1" },
411 { 22, 0, "c0_perftrace" },
412 { 23, 3, "c0_edebug" },
413 { 25, 1, "c0_perfcnt,1" },
414 { 25, 2, "c0_perfcnt,2" },
415 { 25, 3, "c0_perfcnt,3" },
416 { 25, 4, "c0_perfcnt,4" },
417 { 25, 5, "c0_perfcnt,5" },
418 { 25, 6, "c0_perfcnt,6" },
419 { 25, 7, "c0_perfcnt,7" },
420 { 26, 1, "c0_buserr_pa" },
421 { 27, 1, "c0_cacheerr_d" },
422 { 27, 3, "c0_cacheerr_d_pa" },
423 { 28, 1, "c0_datalo_i" },
424 { 28, 2, "c0_taglo_d" },
425 { 28, 3, "c0_datalo_d" },
426 { 29, 1, "c0_datahi_i" },
427 { 29, 2, "c0_taghi_d" },
428 { 29, 3, "c0_datahi_d" },
431 /* Xlr cop0 register names. */
432 static const char * const mips_cp0_names_xlr
[32] = {
433 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
434 "c0_context", "c0_pagemask", "c0_wired", "$7",
435 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
436 "c0_status", "c0_cause", "c0_epc", "c0_prid",
437 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
438 "c0_xcontext", "$21", "$22", "c0_debug",
439 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
440 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
443 /* XLR's CP0 Select Registers. */
445 static const struct mips_cp0sel_name mips_cp0sel_names_xlr
[] = {
446 { 9, 6, "c0_extintreq" },
447 { 9, 7, "c0_extintmask" },
448 { 15, 1, "c0_ebase" },
449 { 16, 1, "c0_config1" },
450 { 16, 2, "c0_config2" },
451 { 16, 3, "c0_config3" },
452 { 16, 7, "c0_procid2" },
453 { 18, 1, "c0_watchlo,1" },
454 { 18, 2, "c0_watchlo,2" },
455 { 18, 3, "c0_watchlo,3" },
456 { 18, 4, "c0_watchlo,4" },
457 { 18, 5, "c0_watchlo,5" },
458 { 18, 6, "c0_watchlo,6" },
459 { 18, 7, "c0_watchlo,7" },
460 { 19, 1, "c0_watchhi,1" },
461 { 19, 2, "c0_watchhi,2" },
462 { 19, 3, "c0_watchhi,3" },
463 { 19, 4, "c0_watchhi,4" },
464 { 19, 5, "c0_watchhi,5" },
465 { 19, 6, "c0_watchhi,6" },
466 { 19, 7, "c0_watchhi,7" },
467 { 25, 1, "c0_perfcnt,1" },
468 { 25, 2, "c0_perfcnt,2" },
469 { 25, 3, "c0_perfcnt,3" },
470 { 25, 4, "c0_perfcnt,4" },
471 { 25, 5, "c0_perfcnt,5" },
472 { 25, 6, "c0_perfcnt,6" },
473 { 25, 7, "c0_perfcnt,7" },
474 { 27, 1, "c0_cacheerr,1" },
475 { 27, 2, "c0_cacheerr,2" },
476 { 27, 3, "c0_cacheerr,3" },
477 { 28, 1, "c0_datalo" },
478 { 29, 1, "c0_datahi" }
481 static const char * const mips_hwr_names_numeric
[32] =
483 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
484 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
485 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
486 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
489 static const char * const mips_hwr_names_mips3264r2
[32] =
491 "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
492 "$4", "$5", "$6", "$7",
493 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
494 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
495 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
498 struct mips_abi_choice
501 const char * const *gpr_names
;
502 const char * const *fpr_names
;
505 struct mips_abi_choice mips_abi_choices
[] =
507 { "numeric", mips_gpr_names_numeric
, mips_fpr_names_numeric
},
508 { "32", mips_gpr_names_oldabi
, mips_fpr_names_32
},
509 { "n32", mips_gpr_names_newabi
, mips_fpr_names_n32
},
510 { "64", mips_gpr_names_newabi
, mips_fpr_names_64
},
513 struct mips_arch_choice
517 unsigned long bfd_mach
;
520 const char * const *cp0_names
;
521 const struct mips_cp0sel_name
*cp0sel_names
;
522 unsigned int cp0sel_names_len
;
523 const char * const *hwr_names
;
526 const struct mips_arch_choice mips_arch_choices
[] =
528 { "numeric", 0, 0, 0, 0,
529 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
531 { "r3000", 1, bfd_mach_mips3000
, CPU_R3000
, ISA_MIPS1
,
532 mips_cp0_names_r3000
, NULL
, 0, mips_hwr_names_numeric
},
533 { "r3900", 1, bfd_mach_mips3900
, CPU_R3900
, ISA_MIPS1
,
534 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
535 { "r4000", 1, bfd_mach_mips4000
, CPU_R4000
, ISA_MIPS3
,
536 mips_cp0_names_r4000
, NULL
, 0, mips_hwr_names_numeric
},
537 { "r4010", 1, bfd_mach_mips4010
, CPU_R4010
, ISA_MIPS2
,
538 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
539 { "vr4100", 1, bfd_mach_mips4100
, CPU_VR4100
, ISA_MIPS3
,
540 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
541 { "vr4111", 1, bfd_mach_mips4111
, CPU_R4111
, ISA_MIPS3
,
542 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
543 { "vr4120", 1, bfd_mach_mips4120
, CPU_VR4120
, ISA_MIPS3
,
544 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
545 { "r4300", 1, bfd_mach_mips4300
, CPU_R4300
, ISA_MIPS3
,
546 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
547 { "r4400", 1, bfd_mach_mips4400
, CPU_R4400
, ISA_MIPS3
,
548 mips_cp0_names_r4000
, NULL
, 0, mips_hwr_names_numeric
},
549 { "r4600", 1, bfd_mach_mips4600
, CPU_R4600
, ISA_MIPS3
,
550 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
551 { "r4650", 1, bfd_mach_mips4650
, CPU_R4650
, ISA_MIPS3
,
552 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
553 { "r5000", 1, bfd_mach_mips5000
, CPU_R5000
, ISA_MIPS4
,
554 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
555 { "vr5400", 1, bfd_mach_mips5400
, CPU_VR5400
, ISA_MIPS4
,
556 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
557 { "vr5500", 1, bfd_mach_mips5500
, CPU_VR5500
, ISA_MIPS4
,
558 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
559 { "r5900", 1, bfd_mach_mips5900
, CPU_R5900
, ISA_MIPS3
,
560 mips_cp0_names_r5900
, NULL
, 0, mips_hwr_names_numeric
},
561 { "r6000", 1, bfd_mach_mips6000
, CPU_R6000
, ISA_MIPS2
,
562 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
563 { "rm7000", 1, bfd_mach_mips7000
, CPU_RM7000
, ISA_MIPS4
,
564 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
565 { "rm9000", 1, bfd_mach_mips7000
, CPU_RM7000
, ISA_MIPS4
,
566 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
567 { "r8000", 1, bfd_mach_mips8000
, CPU_R8000
, ISA_MIPS4
,
568 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
569 { "r10000", 1, bfd_mach_mips10000
, CPU_R10000
, ISA_MIPS4
,
570 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
571 { "r12000", 1, bfd_mach_mips12000
, CPU_R12000
, ISA_MIPS4
,
572 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
573 { "r14000", 1, bfd_mach_mips14000
, CPU_R14000
, ISA_MIPS4
,
574 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
575 { "r16000", 1, bfd_mach_mips16000
, CPU_R16000
, ISA_MIPS4
,
576 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
577 { "mips5", 1, bfd_mach_mips5
, CPU_MIPS5
, ISA_MIPS5
,
578 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
580 /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
581 Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
582 _MIPS32 Architecture For Programmers Volume I: Introduction to the
583 MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
585 { "mips32", 1, bfd_mach_mipsisa32
, CPU_MIPS32
,
586 ISA_MIPS32
| INSN_SMARTMIPS
,
587 mips_cp0_names_mips3264
,
588 mips_cp0sel_names_mips3264
, ARRAY_SIZE (mips_cp0sel_names_mips3264
),
589 mips_hwr_names_numeric
},
591 { "mips32r2", 1, bfd_mach_mipsisa32r2
, CPU_MIPS32R2
,
592 (ISA_MIPS32R2
| INSN_SMARTMIPS
| INSN_DSP
| INSN_DSPR2
593 | INSN_MIPS3D
| INSN_MT
| INSN_MCU
),
594 mips_cp0_names_mips3264r2
,
595 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
596 mips_hwr_names_mips3264r2
},
598 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
599 { "mips64", 1, bfd_mach_mipsisa64
, CPU_MIPS64
,
600 ISA_MIPS64
| INSN_MIPS3D
| INSN_MDMX
,
601 mips_cp0_names_mips3264
,
602 mips_cp0sel_names_mips3264
, ARRAY_SIZE (mips_cp0sel_names_mips3264
),
603 mips_hwr_names_numeric
},
605 { "mips64r2", 1, bfd_mach_mipsisa64r2
, CPU_MIPS64R2
,
606 (ISA_MIPS64R2
| INSN_MIPS3D
| INSN_DSP
| INSN_DSPR2
607 | INSN_DSP64
| INSN_MT
| INSN_MDMX
| INSN_MCU
),
608 mips_cp0_names_mips3264r2
,
609 mips_cp0sel_names_mips3264r2
, ARRAY_SIZE (mips_cp0sel_names_mips3264r2
),
610 mips_hwr_names_mips3264r2
},
612 { "sb1", 1, bfd_mach_mips_sb1
, CPU_SB1
,
613 ISA_MIPS64
| INSN_MIPS3D
| INSN_SB1
,
615 mips_cp0sel_names_sb1
, ARRAY_SIZE (mips_cp0sel_names_sb1
),
616 mips_hwr_names_numeric
},
618 { "loongson2e", 1, bfd_mach_mips_loongson_2e
, CPU_LOONGSON_2E
,
619 ISA_MIPS3
| INSN_LOONGSON_2E
, mips_cp0_names_numeric
,
620 NULL
, 0, mips_hwr_names_numeric
},
622 { "loongson2f", 1, bfd_mach_mips_loongson_2f
, CPU_LOONGSON_2F
,
623 ISA_MIPS3
| INSN_LOONGSON_2F
, mips_cp0_names_numeric
,
624 NULL
, 0, mips_hwr_names_numeric
},
626 { "loongson3a", 1, bfd_mach_mips_loongson_3a
, CPU_LOONGSON_3A
,
627 ISA_MIPS64
| INSN_LOONGSON_3A
, mips_cp0_names_numeric
,
628 NULL
, 0, mips_hwr_names_numeric
},
630 { "octeon", 1, bfd_mach_mips_octeon
, CPU_OCTEON
,
631 ISA_MIPS64R2
| INSN_OCTEON
, mips_cp0_names_numeric
, NULL
, 0,
632 mips_hwr_names_numeric
},
634 { "octeon+", 1, bfd_mach_mips_octeonp
, CPU_OCTEONP
,
635 ISA_MIPS64R2
| INSN_OCTEONP
, mips_cp0_names_numeric
,
636 NULL
, 0, mips_hwr_names_numeric
},
638 { "octeon2", 1, bfd_mach_mips_octeon2
, CPU_OCTEON2
,
639 ISA_MIPS64R2
| INSN_OCTEON2
, mips_cp0_names_numeric
,
640 NULL
, 0, mips_hwr_names_numeric
},
642 { "xlr", 1, bfd_mach_mips_xlr
, CPU_XLR
,
643 ISA_MIPS64
| INSN_XLR
,
645 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
646 mips_hwr_names_numeric
},
648 /* XLP is mostly like XLR, with the prominent exception it is being
650 { "xlp", 1, bfd_mach_mips_xlr
, CPU_XLR
,
651 ISA_MIPS64R2
| INSN_XLR
,
653 mips_cp0sel_names_xlr
, ARRAY_SIZE (mips_cp0sel_names_xlr
),
654 mips_hwr_names_numeric
},
656 /* This entry, mips16, is here only for ISA/processor selection; do
657 not print its name. */
658 { "", 1, bfd_mach_mips16
, CPU_MIPS16
, ISA_MIPS3
,
659 mips_cp0_names_numeric
, NULL
, 0, mips_hwr_names_numeric
},
662 /* ISA and processor type to disassemble for, and register names to use.
663 set_default_mips_dis_options and parse_mips_dis_options fill in these
665 static int mips_processor
;
667 static int micromips_ase
;
668 static const char * const *mips_gpr_names
;
669 static const char * const *mips_fpr_names
;
670 static const char * const *mips_cp0_names
;
671 static const struct mips_cp0sel_name
*mips_cp0sel_names
;
672 static int mips_cp0sel_names_len
;
673 static const char * const *mips_hwr_names
;
676 static int no_aliases
; /* If set disassemble as most general inst. */
678 static const struct mips_abi_choice
*
679 choose_abi_by_name (const char *name
, unsigned int namelen
)
681 const struct mips_abi_choice
*c
;
684 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_abi_choices
) && c
== NULL
; i
++)
685 if (strncmp (mips_abi_choices
[i
].name
, name
, namelen
) == 0
686 && strlen (mips_abi_choices
[i
].name
) == namelen
)
687 c
= &mips_abi_choices
[i
];
692 static const struct mips_arch_choice
*
693 choose_arch_by_name (const char *name
, unsigned int namelen
)
695 const struct mips_arch_choice
*c
= NULL
;
698 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
699 if (strncmp (mips_arch_choices
[i
].name
, name
, namelen
) == 0
700 && strlen (mips_arch_choices
[i
].name
) == namelen
)
701 c
= &mips_arch_choices
[i
];
706 static const struct mips_arch_choice
*
707 choose_arch_by_number (unsigned long mach
)
709 static unsigned long hint_bfd_mach
;
710 static const struct mips_arch_choice
*hint_arch_choice
;
711 const struct mips_arch_choice
*c
;
714 /* We optimize this because even if the user specifies no
715 flags, this will be done for every instruction! */
716 if (hint_bfd_mach
== mach
717 && hint_arch_choice
!= NULL
718 && hint_arch_choice
->bfd_mach
== hint_bfd_mach
)
719 return hint_arch_choice
;
721 for (i
= 0, c
= NULL
; i
< ARRAY_SIZE (mips_arch_choices
) && c
== NULL
; i
++)
723 if (mips_arch_choices
[i
].bfd_mach_valid
724 && mips_arch_choices
[i
].bfd_mach
== mach
)
726 c
= &mips_arch_choices
[i
];
727 hint_bfd_mach
= mach
;
728 hint_arch_choice
= c
;
734 /* Check if the object uses NewABI conventions. */
737 is_newabi (Elf_Internal_Ehdr
*header
)
739 /* There are no old-style ABIs which use 64-bit ELF. */
740 if (header
->e_ident
[EI_CLASS
] == ELFCLASS64
)
743 /* If a 32-bit ELF file, n32 is a new-style ABI. */
744 if ((header
->e_flags
& EF_MIPS_ABI2
) != 0)
750 /* Check if the object has microMIPS ASE code. */
753 is_micromips (Elf_Internal_Ehdr
*header
)
755 if ((header
->e_flags
& EF_MIPS_ARCH_ASE_MICROMIPS
) != 0)
762 set_default_mips_dis_options (struct disassemble_info
*info
)
764 const struct mips_arch_choice
*chosen_arch
;
766 /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
767 is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
768 CP0 register, and HWR names. */
769 mips_isa
= ISA_MIPS3
;
770 mips_processor
= CPU_R3000
;
772 mips_gpr_names
= mips_gpr_names_oldabi
;
773 mips_fpr_names
= mips_fpr_names_numeric
;
774 mips_cp0_names
= mips_cp0_names_numeric
;
775 mips_cp0sel_names
= NULL
;
776 mips_cp0sel_names_len
= 0;
777 mips_hwr_names
= mips_hwr_names_numeric
;
780 /* Update settings according to the ELF file header flags. */
781 if (info
->flavour
== bfd_target_elf_flavour
&& info
->section
!= NULL
)
783 Elf_Internal_Ehdr
*header
;
785 header
= elf_elfheader (info
->section
->owner
);
786 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
787 if (is_newabi (header
))
788 mips_gpr_names
= mips_gpr_names_newabi
;
789 /* If a microMIPS binary, then don't use MIPS16 bindings. */
790 micromips_ase
= is_micromips (header
);
793 /* Set ISA, architecture, and cp0 register names as best we can. */
794 #if ! SYMTAB_AVAILABLE
795 /* This is running out on a target machine, not in a host tool.
796 FIXME: Where does mips_target_info come from? */
797 target_processor
= mips_target_info
.processor
;
798 mips_isa
= mips_target_info
.isa
;
800 chosen_arch
= choose_arch_by_number (info
->mach
);
801 if (chosen_arch
!= NULL
)
803 mips_processor
= chosen_arch
->processor
;
804 mips_isa
= chosen_arch
->isa
;
805 mips_cp0_names
= chosen_arch
->cp0_names
;
806 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
807 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
808 mips_hwr_names
= chosen_arch
->hwr_names
;
814 parse_mips_dis_option (const char *option
, unsigned int len
)
816 unsigned int i
, optionlen
, vallen
;
818 const struct mips_abi_choice
*chosen_abi
;
819 const struct mips_arch_choice
*chosen_arch
;
821 /* Try to match options that are simple flags */
822 if (CONST_STRNEQ (option
, "no-aliases"))
828 /* Look for the = that delimits the end of the option name. */
829 for (i
= 0; i
< len
; i
++)
830 if (option
[i
] == '=')
833 if (i
== 0) /* Invalid option: no name before '='. */
835 if (i
== len
) /* Invalid option: no '='. */
837 if (i
== (len
- 1)) /* Invalid option: no value after '='. */
841 val
= option
+ (optionlen
+ 1);
842 vallen
= len
- (optionlen
+ 1);
844 if (strncmp ("gpr-names", option
, optionlen
) == 0
845 && strlen ("gpr-names") == optionlen
)
847 chosen_abi
= choose_abi_by_name (val
, vallen
);
848 if (chosen_abi
!= NULL
)
849 mips_gpr_names
= chosen_abi
->gpr_names
;
853 if (strncmp ("fpr-names", option
, optionlen
) == 0
854 && strlen ("fpr-names") == optionlen
)
856 chosen_abi
= choose_abi_by_name (val
, vallen
);
857 if (chosen_abi
!= NULL
)
858 mips_fpr_names
= chosen_abi
->fpr_names
;
862 if (strncmp ("cp0-names", option
, optionlen
) == 0
863 && strlen ("cp0-names") == optionlen
)
865 chosen_arch
= choose_arch_by_name (val
, vallen
);
866 if (chosen_arch
!= NULL
)
868 mips_cp0_names
= chosen_arch
->cp0_names
;
869 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
870 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
875 if (strncmp ("hwr-names", option
, optionlen
) == 0
876 && strlen ("hwr-names") == optionlen
)
878 chosen_arch
= choose_arch_by_name (val
, vallen
);
879 if (chosen_arch
!= NULL
)
880 mips_hwr_names
= chosen_arch
->hwr_names
;
884 if (strncmp ("reg-names", option
, optionlen
) == 0
885 && strlen ("reg-names") == optionlen
)
887 /* We check both ABI and ARCH here unconditionally, so
888 that "numeric" will do the desirable thing: select
889 numeric register names for all registers. Other than
890 that, a given name probably won't match both. */
891 chosen_abi
= choose_abi_by_name (val
, vallen
);
892 if (chosen_abi
!= NULL
)
894 mips_gpr_names
= chosen_abi
->gpr_names
;
895 mips_fpr_names
= chosen_abi
->fpr_names
;
897 chosen_arch
= choose_arch_by_name (val
, vallen
);
898 if (chosen_arch
!= NULL
)
900 mips_cp0_names
= chosen_arch
->cp0_names
;
901 mips_cp0sel_names
= chosen_arch
->cp0sel_names
;
902 mips_cp0sel_names_len
= chosen_arch
->cp0sel_names_len
;
903 mips_hwr_names
= chosen_arch
->hwr_names
;
908 /* Invalid option. */
912 parse_mips_dis_options (const char *options
)
914 const char *option_end
;
919 while (*options
!= '\0')
921 /* Skip empty options. */
928 /* We know that *options is neither NUL or a comma. */
929 option_end
= options
+ 1;
930 while (*option_end
!= ',' && *option_end
!= '\0')
933 parse_mips_dis_option (options
, option_end
- options
);
935 /* Go on to the next one. If option_end points to a comma, it
936 will be skipped above. */
937 options
= option_end
;
941 static const struct mips_cp0sel_name
*
942 lookup_mips_cp0sel_name (const struct mips_cp0sel_name
*names
,
949 for (i
= 0; i
< len
; i
++)
950 if (names
[i
].cp0reg
== cp0reg
&& names
[i
].sel
== sel
)
955 /* Print insn arguments for 32/64-bit code. */
958 print_insn_args (const char *d
,
961 struct disassemble_info
*info
,
962 const struct mips_opcode
*opp
)
964 const fprintf_ftype infprintf
= info
->fprintf_func
;
965 unsigned int lsb
, msb
, msbd
;
966 void *is
= info
->stream
;
971 #define GET_OP(insn, field) \
972 (((insn) >> OP_SH_##field) & OP_MASK_##field)
973 #define GET_OP_S(insn, field) \
974 ((GET_OP (insn, field) ^ ((OP_MASK_##field >> 1) + 1)) \
975 - ((OP_MASK_##field >> 1) + 1))
976 for (; *d
!= '\0'; d
++)
985 infprintf (is
, "%c", *d
);
989 /* Extension character; switch for second char. */
994 /* xgettext:c-format */
996 _("# internal error, "
997 "incomplete extension sequence (+)"));
1001 lsb
= GET_OP (l
, SHAMT
);
1002 infprintf (is
, "0x%x", lsb
);
1006 msb
= GET_OP (l
, INSMSB
);
1007 infprintf (is
, "0x%x", msb
- lsb
+ 1);
1011 infprintf (is
, "0x%x", GET_OP (l
, UDI1
));
1015 infprintf (is
, "0x%x", GET_OP (l
, UDI2
));
1019 infprintf (is
, "0x%x", GET_OP (l
, UDI3
));
1023 infprintf (is
, "0x%x", GET_OP (l
, UDI4
));
1028 msbd
= GET_OP (l
, EXTMSBD
);
1029 infprintf (is
, "0x%x", msbd
+ 1);
1034 const struct mips_cp0sel_name
*n
;
1035 unsigned int cp0reg
, sel
;
1037 cp0reg
= GET_OP (l
, RD
);
1038 sel
= GET_OP (l
, SEL
);
1040 /* CP0 register including 'sel' code for mtcN (et al.), to be
1041 printed textually if known. If not known, print both
1042 CP0 register name and sel numerically since CP0 register
1043 with sel 0 may have a name unrelated to register being
1045 n
= lookup_mips_cp0sel_name(mips_cp0sel_names
,
1046 mips_cp0sel_names_len
, cp0reg
, sel
);
1048 infprintf (is
, "%s", n
->name
);
1050 infprintf (is
, "$%d,%d", cp0reg
, sel
);
1055 lsb
= GET_OP (l
, SHAMT
) + 32;
1056 infprintf (is
, "0x%x", lsb
);
1060 msb
= GET_OP (l
, INSMSB
) + 32;
1061 infprintf (is
, "0x%x", msb
- lsb
+ 1);
1065 msbd
= GET_OP (l
, EXTMSBD
) + 32;
1066 infprintf (is
, "0x%x", msbd
+ 1);
1069 case 't': /* Coprocessor 0 reg name */
1070 infprintf (is
, "%s", mips_cp0_names
[GET_OP (l
, RT
)]);
1073 case 'T': /* Coprocessor 0 reg name */
1075 const struct mips_cp0sel_name
*n
;
1076 unsigned int cp0reg
, sel
;
1078 cp0reg
= GET_OP (l
, RT
);
1079 sel
= GET_OP (l
, SEL
);
1081 /* CP0 register including 'sel' code for mftc0, to be
1082 printed textually if known. If not known, print both
1083 CP0 register name and sel numerically since CP0 register
1084 with sel 0 may have a name unrelated to register being
1086 n
= lookup_mips_cp0sel_name(mips_cp0sel_names
,
1087 mips_cp0sel_names_len
, cp0reg
, sel
);
1089 infprintf (is
, "%s", n
->name
);
1091 infprintf (is
, "$%d,%d", cp0reg
, sel
);
1095 case 'x': /* bbit bit index */
1096 infprintf (is
, "0x%x", GET_OP (l
, BBITIND
));
1099 case 'p': /* cins, cins32, exts and exts32 position */
1100 infprintf (is
, "0x%x", GET_OP (l
, CINSPOS
));
1103 case 's': /* cins and exts length-minus-one */
1104 infprintf (is
, "0x%x", GET_OP (l
, CINSLM1
));
1107 case 'S': /* cins32 and exts32 length-minus-one field */
1108 infprintf (is
, "0x%x", GET_OP (l
, CINSLM1
));
1111 case 'Q': /* seqi/snei immediate field */
1112 infprintf (is
, "%d", GET_OP_S (l
, SEQI
));
1115 case 'a': /* 8-bit signed offset in bit 6 */
1116 infprintf (is
, "%d", GET_OP_S (l
, OFFSET_A
));
1119 case 'b': /* 8-bit signed offset in bit 3 */
1120 infprintf (is
, "%d", GET_OP_S (l
, OFFSET_B
));
1123 case 'c': /* 9-bit signed offset in bit 6 */
1124 /* Left shift 4 bits to print the real offset. */
1125 infprintf (is
, "%d", GET_OP_S (l
, OFFSET_C
) << 4);
1129 infprintf (is
, "%s", mips_gpr_names
[GET_OP (l
, RZ
)]);
1133 infprintf (is
, "%s", mips_fpr_names
[GET_OP (l
, FZ
)]);
1137 /* xgettext:c-format */
1139 _("# internal error, "
1140 "undefined extension sequence (+%c)"),
1147 infprintf (is
, "0x%x", GET_OP (l
, BP
));
1151 infprintf (is
, "0x%x", GET_OP (l
, SA3
));
1155 infprintf (is
, "0x%x", GET_OP (l
, SA4
));
1159 infprintf (is
, "0x%x", GET_OP (l
, IMM8
));
1163 infprintf (is
, "0x%x", GET_OP (l
, RS
));
1167 infprintf (is
, "$ac%d", GET_OP (l
, DSPACC
));
1171 infprintf (is
, "0x%x", GET_OP (l
, WRDSP
));
1175 infprintf (is
, "$ac%d", GET_OP (l
, DSPACC_S
));
1178 case '0': /* dsp 6-bit signed immediate in bit 20 */
1179 infprintf (is
, "%d", GET_OP_S (l
, DSPSFT
));
1182 case ':': /* dsp 7-bit signed immediate in bit 19 */
1183 infprintf (is
, "%d", GET_OP_S (l
, DSPSFT_7
));
1187 infprintf (is
, "%d", GET_OP_S (l
, OFFSET12
));
1191 infprintf (is
, "0x%x", GET_OP (l
, 3BITPOS
));
1195 infprintf (is
, "0x%x", GET_OP (l
, RDDSP
));
1198 case '@': /* dsp 10-bit signed immediate in bit 16 */
1199 infprintf (is
, "%d", GET_OP_S (l
, IMM10
));
1203 infprintf (is
, "%d", GET_OP (l
, MT_U
));
1207 infprintf (is
, "%d", GET_OP (l
, MT_H
));
1211 infprintf (is
, "$ac%d", GET_OP (l
, MTACC_T
));
1215 infprintf (is
, "$ac%d", GET_OP (l
, MTACC_D
));
1219 /* Coprocessor register for CTTC1, MTTC2, MTHC2, CTTC2. */
1220 infprintf (is
, "$%d", GET_OP (l
, RD
));
1227 infprintf (is
, "%s", mips_gpr_names
[GET_OP (l
, RS
)]);
1232 infprintf (is
, "%s", mips_gpr_names
[GET_OP (l
, RT
)]);
1237 infprintf (is
, "0x%x", GET_OP (l
, IMMEDIATE
));
1240 case 'j': /* Same as i, but sign-extended. */
1242 infprintf (is
, "%d", GET_OP_S (l
, DELTA
));
1246 infprintf (is
, "0x%x", GET_OP (l
, PREFX
));
1250 infprintf (is
, "0x%x", GET_OP (l
, CACHE
));
1254 info
->target
= (((pc
+ 4) & ~(bfd_vma
) 0x0fffffff)
1255 | (GET_OP (l
, TARGET
) << 2));
1256 /* For gdb disassembler, force odd address on jalx. */
1257 if (info
->flavour
== bfd_target_unknown_flavour
1258 && strcmp (opp
->name
, "jalx") == 0)
1260 (*info
->print_address_func
) (info
->target
, info
);
1264 /* Sign extend the displacement. */
1265 info
->target
= (GET_OP_S (l
, DELTA
) << 2) + pc
+ INSNLEN
;
1266 (*info
->print_address_func
) (info
->target
, info
);
1270 infprintf (is
, "%s", mips_gpr_names
[GET_OP (l
, RD
)]);
1275 /* First check for both rd and rt being equal. */
1278 reg
= GET_OP (l
, RD
);
1279 if (reg
== GET_OP (l
, RT
))
1280 infprintf (is
, "%s", mips_gpr_names
[reg
]);
1283 /* If one is zero use the other. */
1285 infprintf (is
, "%s", mips_gpr_names
[GET_OP (l
, RT
)]);
1286 else if (GET_OP (l
, RT
) == 0)
1287 infprintf (is
, "%s", mips_gpr_names
[reg
]);
1288 else /* Bogus, result depends on processor. */
1289 infprintf (is
, "%s or %s",
1290 mips_gpr_names
[reg
],
1291 mips_gpr_names
[GET_OP (l
, RT
)]);
1297 infprintf (is
, "%s", mips_gpr_names
[0]);
1302 infprintf (is
, "0x%x", GET_OP (l
, SHAMT
));
1306 infprintf (is
, "0x%x", GET_OP (l
, CODE
));
1310 infprintf (is
, "0x%x", GET_OP (l
, CODE2
));
1314 infprintf (is
, "0x%x", GET_OP (l
, COPZ
));
1318 infprintf (is
, "0x%x", GET_OP (l
, CODE20
));
1322 infprintf (is
, "0x%x", GET_OP (l
, CODE19
));
1327 infprintf (is
, "%s", mips_fpr_names
[GET_OP (l
, FS
)]);
1332 infprintf (is
, "%s", mips_fpr_names
[GET_OP (l
, FT
)]);
1336 infprintf (is
, "%s", mips_fpr_names
[GET_OP (l
, FD
)]);
1340 infprintf (is
, "%s", mips_fpr_names
[GET_OP (l
, FR
)]);
1344 /* Coprocessor register for lwcN instructions, et al.
1346 Note that there is no load/store cp0 instructions, and
1347 that FPU (cp1) instructions disassemble this field using
1348 'T' format. Therefore, until we gain understanding of
1349 cp2 register names, we can simply print the register
1351 infprintf (is
, "$%d", GET_OP (l
, RT
));
1355 /* Coprocessor register for mtcN instructions, et al. Note
1356 that FPU (cp1) instructions disassemble this field using
1357 'S' format. Therefore, we only need to worry about cp0,
1359 op
= GET_OP (l
, OP
);
1360 if (op
== OP_OP_COP0
)
1361 infprintf (is
, "%s", mips_cp0_names
[GET_OP (l
, RD
)]);
1363 infprintf (is
, "$%d", GET_OP (l
, RD
));
1367 infprintf (is
, "%s", mips_hwr_names
[GET_OP (l
, RD
)]);
1372 (opp
->pinfo
& (FP_D
| FP_S
)) != 0 ? "$fcc%d" : "$cc%d",
1377 infprintf (is
, "$fcc%d", GET_OP (l
, CCC
));
1381 infprintf (is
, "%d", GET_OP (l
, PERFREG
));
1385 infprintf (is
, "%d", GET_OP (l
, VECBYTE
));
1389 infprintf (is
, "%d", GET_OP (l
, VECALIGN
));
1393 infprintf (is
, "%d", GET_OP (l
, SEL
));
1397 infprintf (is
, "%d", GET_OP (l
, ALN
));
1402 unsigned int vsel
= GET_OP (l
, VSEL
);
1404 if ((vsel
& 0x10) == 0)
1409 for (fmt
= 0; fmt
< 3; fmt
++, vsel
>>= 1)
1410 if ((vsel
& 1) == 0)
1412 infprintf (is
, "$v%d[%d]", GET_OP (l
, FT
), vsel
>> 1);
1414 else if ((vsel
& 0x08) == 0)
1416 infprintf (is
, "$v%d", GET_OP (l
, FT
));
1420 infprintf (is
, "0x%x", GET_OP (l
, FT
));
1426 infprintf (is
, "$v%d", GET_OP (l
, FD
));
1430 infprintf (is
, "$v%d", GET_OP (l
, FS
));
1434 infprintf (is
, "$v%d", GET_OP (l
, FT
));
1438 /* xgettext:c-format */
1439 infprintf (is
, _("# internal error, undefined modifier (%c)"), *d
);
1445 /* Print the mips instruction at address MEMADDR in debugged memory,
1446 on using INFO. Returns length of the instruction, in bytes, which is
1447 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
1448 this is little-endian code. */
1451 print_insn_mips (bfd_vma memaddr
,
1453 struct disassemble_info
*info
)
1455 static const struct mips_opcode
*mips_hash
[OP_MASK_OP
+ 1];
1456 const fprintf_ftype infprintf
= info
->fprintf_func
;
1457 const struct mips_opcode
*op
;
1458 static bfd_boolean init
= 0;
1459 void *is
= info
->stream
;
1461 /* Build a hash table to shorten the search time. */
1466 for (i
= 0; i
<= OP_MASK_OP
; i
++)
1468 for (op
= mips_opcodes
; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1470 if (op
->pinfo
== INSN_MACRO
1471 || (no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
)))
1473 if (i
== GET_OP (op
->match
, OP
))
1484 info
->bytes_per_chunk
= INSNLEN
;
1485 info
->display_endian
= info
->endian
;
1486 info
->insn_info_valid
= 1;
1487 info
->branch_delay_insns
= 0;
1488 info
->data_size
= 0;
1489 info
->insn_type
= dis_nonbranch
;
1493 op
= mips_hash
[GET_OP (word
, OP
)];
1496 for (; op
< &mips_opcodes
[NUMOPCODES
]; op
++)
1498 if (op
->pinfo
!= INSN_MACRO
1499 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
1500 && (word
& op
->mask
) == op
->match
)
1504 /* We always allow to disassemble the jalx instruction. */
1505 if (!opcode_is_member (op
, mips_isa
, mips_processor
)
1506 && strcmp (op
->name
, "jalx"))
1509 /* Figure out instruction type and branch delay information. */
1510 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
1512 if ((op
->pinfo
& (INSN_WRITE_GPR_31
1513 | INSN_WRITE_GPR_D
)) != 0)
1514 info
->insn_type
= dis_jsr
;
1516 info
->insn_type
= dis_branch
;
1517 info
->branch_delay_insns
= 1;
1519 else if ((op
->pinfo
& (INSN_COND_BRANCH_DELAY
1520 | INSN_COND_BRANCH_LIKELY
)) != 0)
1522 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
1523 info
->insn_type
= dis_condjsr
;
1525 info
->insn_type
= dis_condbranch
;
1526 info
->branch_delay_insns
= 1;
1528 else if ((op
->pinfo
& (INSN_STORE_MEMORY
1529 | INSN_LOAD_MEMORY_DELAY
)) != 0)
1530 info
->insn_type
= dis_dref
;
1532 infprintf (is
, "%s", op
->name
);
1535 if (d
!= NULL
&& *d
!= '\0')
1537 infprintf (is
, "\t");
1538 print_insn_args (d
, word
, memaddr
, info
, op
);
1548 /* Handle undefined instructions. */
1549 info
->insn_type
= dis_noninsn
;
1550 infprintf (is
, "0x%x", word
);
1554 /* Disassemble an operand for a mips16 instruction. */
1557 print_mips16_insn_arg (char type
,
1558 const struct mips_opcode
*op
,
1560 bfd_boolean use_extend
,
1563 struct disassemble_info
*info
)
1565 const fprintf_ftype infprintf
= info
->fprintf_func
;
1566 void *is
= info
->stream
;
1568 #define GET_OP(insn, field) \
1569 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
1570 #define GET_OP_S(insn, field) \
1571 ((GET_OP (insn, field) ^ ((MIPS16OP_MASK_##field >> 1) + 1)) \
1572 - ((MIPS16OP_MASK_##field >> 1) + 1))
1578 infprintf (is
, "%c", type
);
1583 infprintf (is
, "%s", mips16_reg_names (GET_OP (l
, RY
)));
1588 infprintf (is
, "%s", mips16_reg_names (GET_OP (l
, RX
)));
1592 infprintf (is
, "%s", mips16_reg_names (GET_OP (l
, RZ
)));
1596 infprintf (is
, "%s", mips16_reg_names (GET_OP (l
, MOVE32Z
)));
1600 infprintf (is
, "%s", mips_gpr_names
[0]);
1604 infprintf (is
, "%s", mips_gpr_names
[29]);
1608 infprintf (is
, "$pc");
1612 infprintf (is
, "%s", mips_gpr_names
[31]);
1616 infprintf (is
, "%s", mips_gpr_names
[GET_OP (l
, REGR32
)]);
1620 infprintf (is
, "%s", mips_gpr_names
[MIPS16OP_EXTRACT_REG32R (l
)]);
1646 int immed
, nbits
, shift
, signedp
, extbits
, pcrel
, extu
, branch
;
1658 immed
= GET_OP (l
, RZ
);
1664 immed
= GET_OP (l
, RX
);
1670 immed
= GET_OP (l
, RZ
);
1676 immed
= GET_OP (l
, RX
);
1682 immed
= GET_OP (l
, IMM4
);
1688 immed
= GET_OP (l
, IMM5
);
1689 info
->insn_type
= dis_dref
;
1690 info
->data_size
= 1;
1695 immed
= GET_OP (l
, IMM5
);
1696 info
->insn_type
= dis_dref
;
1697 info
->data_size
= 2;
1702 immed
= GET_OP (l
, IMM5
);
1703 if ((op
->pinfo
& MIPS16_INSN_READ_PC
) == 0
1704 && (op
->pinfo
& MIPS16_INSN_READ_SP
) == 0)
1706 info
->insn_type
= dis_dref
;
1707 info
->data_size
= 4;
1713 immed
= GET_OP (l
, IMM5
);
1714 info
->insn_type
= dis_dref
;
1715 info
->data_size
= 8;
1719 immed
= GET_OP (l
, IMM5
);
1724 immed
= GET_OP (l
, IMM6
);
1728 immed
= GET_OP (l
, IMM8
);
1733 immed
= GET_OP (l
, IMM8
);
1734 /* FIXME: This might be lw, or it might be addiu to $sp or
1735 $pc. We assume it's load. */
1736 info
->insn_type
= dis_dref
;
1737 info
->data_size
= 4;
1742 immed
= GET_OP (l
, IMM8
);
1743 info
->insn_type
= dis_dref
;
1744 info
->data_size
= 8;
1748 immed
= GET_OP (l
, IMM8
);
1753 immed
= GET_OP (l
, IMM8
);
1759 immed
= GET_OP (l
, IMM8
);
1764 immed
= GET_OP (l
, IMM8
);
1771 immed
= GET_OP (l
, IMM11
);
1779 immed
= GET_OP (l
, IMM8
);
1781 /* FIXME: This can be lw or la. We assume it is lw. */
1782 info
->insn_type
= dis_dref
;
1783 info
->data_size
= 4;
1788 immed
= GET_OP (l
, IMM5
);
1790 info
->insn_type
= dis_dref
;
1791 info
->data_size
= 8;
1796 immed
= GET_OP (l
, IMM5
);
1805 if (signedp
&& immed
>= (1 << (nbits
- 1)))
1806 immed
-= 1 << nbits
;
1808 if ((type
== '<' || type
== '>' || type
== '[' || type
== ']')
1815 immed
|= ((extend
& 0x1f) << 11) | (extend
& 0x7e0);
1816 else if (extbits
== 15)
1817 immed
|= ((extend
& 0xf) << 11) | (extend
& 0x7f0);
1819 immed
= ((extend
>> 6) & 0x1f) | (extend
& 0x20);
1820 immed
&= (1 << extbits
) - 1;
1821 if (! extu
&& immed
>= (1 << (extbits
- 1)))
1822 immed
-= 1 << extbits
;
1826 infprintf (is
, "%d", immed
);
1834 baseaddr
= memaddr
+ 2;
1836 else if (use_extend
)
1837 baseaddr
= memaddr
- 2;
1845 /* If this instruction is in the delay slot of a jr
1846 instruction, the base address is the address of the
1847 jr instruction. If it is in the delay slot of jalr
1848 instruction, the base address is the address of the
1849 jalr instruction. This test is unreliable: we have
1850 no way of knowing whether the previous word is
1851 instruction or data. */
1852 status
= (*info
->read_memory_func
) (memaddr
- 4, buffer
, 2,
1855 && (((info
->endian
== BFD_ENDIAN_BIG
1856 ? bfd_getb16 (buffer
)
1857 : bfd_getl16 (buffer
))
1858 & 0xf800) == 0x1800))
1859 baseaddr
= memaddr
- 4;
1862 status
= (*info
->read_memory_func
) (memaddr
- 2, buffer
,
1865 && (((info
->endian
== BFD_ENDIAN_BIG
1866 ? bfd_getb16 (buffer
)
1867 : bfd_getl16 (buffer
))
1868 & 0xf81f) == 0xe800))
1869 baseaddr
= memaddr
- 2;
1872 info
->target
= (baseaddr
& ~((1 << shift
) - 1)) + immed
;
1874 && info
->flavour
== bfd_target_unknown_flavour
)
1875 /* For gdb disassembler, maintain odd address. */
1877 (*info
->print_address_func
) (info
->target
, info
);
1884 int jalx
= l
& 0x400;
1888 l
= ((l
& 0x1f) << 23) | ((l
& 0x3e0) << 13) | (extend
<< 2);
1889 if (!jalx
&& info
->flavour
== bfd_target_unknown_flavour
)
1890 /* For gdb disassembler, maintain odd address. */
1893 info
->target
= ((memaddr
+ 4) & ~(bfd_vma
) 0x0fffffff) | l
;
1894 (*info
->print_address_func
) (info
->target
, info
);
1900 int need_comma
, amask
, smask
;
1904 l
= GET_OP (l
, IMM6
);
1906 amask
= (l
>> 3) & 7;
1908 if (amask
> 0 && amask
< 5)
1910 infprintf (is
, "%s", mips_gpr_names
[4]);
1912 infprintf (is
, "-%s", mips_gpr_names
[amask
+ 3]);
1916 smask
= (l
>> 1) & 3;
1919 infprintf (is
, "%s??", need_comma
? "," : "");
1924 infprintf (is
, "%s%s", need_comma
? "," : "", mips_gpr_names
[16]);
1926 infprintf (is
, "-%s", mips_gpr_names
[smask
+ 15]);
1932 infprintf (is
, "%s%s", need_comma
? "," : "", mips_gpr_names
[31]);
1936 if (amask
== 5 || amask
== 6)
1938 infprintf (is
, "%s$f0", need_comma
? "," : "");
1940 infprintf (is
, "-$f1");
1947 /* MIPS16e save/restore. */
1950 int amask
, args
, statics
;
1959 amask
= (l
>> 16) & 0xf;
1960 if (amask
== MIPS16_ALL_ARGS
)
1965 else if (amask
== MIPS16_ALL_STATICS
)
1973 statics
= amask
& 3;
1977 infprintf (is
, "%s", mips_gpr_names
[4]);
1979 infprintf (is
, "-%s", mips_gpr_names
[4 + args
- 1]);
1983 framesz
= (((l
>> 16) & 0xf0) | (l
& 0x0f)) * 8;
1984 if (framesz
== 0 && !use_extend
)
1987 infprintf (is
, "%s%d", need_comma
? "," : "", framesz
);
1989 if (l
& 0x40) /* $ra */
1990 infprintf (is
, ",%s", mips_gpr_names
[31]);
1992 nsreg
= (l
>> 24) & 0x7;
1994 if (l
& 0x20) /* $s0 */
1996 if (l
& 0x10) /* $s1 */
1998 if (nsreg
> 0) /* $s2-$s8 */
1999 smask
|= ((1 << nsreg
) - 1) << 2;
2001 /* Find first set static reg bit. */
2002 for (i
= 0; i
< 9; i
++)
2004 if (smask
& (1 << i
))
2006 infprintf (is
, ",%s", mips_gpr_names
[i
== 8 ? 30 : (16 + i
)]);
2007 /* Skip over string of set bits. */
2008 for (j
= i
; smask
& (2 << j
); j
++)
2011 infprintf (is
, "-%s", mips_gpr_names
[j
== 8 ? 30 : (16 + j
)]);
2016 /* Statics $ax - $a3. */
2018 infprintf (is
, ",%s", mips_gpr_names
[7]);
2019 else if (statics
> 0)
2020 infprintf (is
, ",%s-%s",
2021 mips_gpr_names
[7 - statics
+ 1],
2027 /* xgettext:c-format */
2029 _("# internal disassembler error, "
2030 "unrecognised modifier (%c)"),
2036 /* Disassemble mips16 instructions. */
2039 print_insn_mips16 (bfd_vma memaddr
, struct disassemble_info
*info
)
2041 const fprintf_ftype infprintf
= info
->fprintf_func
;
2046 bfd_boolean use_extend
;
2048 const struct mips_opcode
*op
, *opend
;
2049 void *is
= info
->stream
;
2051 info
->bytes_per_chunk
= 2;
2052 info
->display_endian
= info
->endian
;
2053 info
->insn_info_valid
= 1;
2054 info
->branch_delay_insns
= 0;
2055 info
->data_size
= 0;
2056 info
->insn_type
= dis_nonbranch
;
2060 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2063 (*info
->memory_error_func
) (status
, memaddr
, info
);
2069 if (info
->endian
== BFD_ENDIAN_BIG
)
2070 insn
= bfd_getb16 (buffer
);
2072 insn
= bfd_getl16 (buffer
);
2074 /* Handle the extend opcode specially. */
2076 if ((insn
& 0xf800) == 0xf000)
2079 extend
= insn
& 0x7ff;
2083 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2086 infprintf (is
, "extend 0x%x", (unsigned int) extend
);
2087 (*info
->memory_error_func
) (status
, memaddr
, info
);
2091 if (info
->endian
== BFD_ENDIAN_BIG
)
2092 insn
= bfd_getb16 (buffer
);
2094 insn
= bfd_getl16 (buffer
);
2096 /* Check for an extend opcode followed by an extend opcode. */
2097 if ((insn
& 0xf800) == 0xf000)
2099 infprintf (is
, "extend 0x%x", (unsigned int) extend
);
2100 info
->insn_type
= dis_noninsn
;
2107 /* FIXME: Should probably use a hash table on the major opcode here. */
2109 opend
= mips16_opcodes
+ bfd_mips16_num_opcodes
;
2110 for (op
= mips16_opcodes
; op
< opend
; op
++)
2112 if (op
->pinfo
!= INSN_MACRO
2113 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
2114 && (insn
& op
->mask
) == op
->match
)
2118 if (strchr (op
->args
, 'a') != NULL
)
2122 infprintf (is
, "extend 0x%x", (unsigned int) extend
);
2123 info
->insn_type
= dis_noninsn
;
2131 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2,
2136 if (info
->endian
== BFD_ENDIAN_BIG
)
2137 extend
= bfd_getb16 (buffer
);
2139 extend
= bfd_getl16 (buffer
);
2144 infprintf (is
, "%s", op
->name
);
2145 if (op
->args
[0] != '\0')
2146 infprintf (is
, "\t");
2148 for (s
= op
->args
; *s
!= '\0'; s
++)
2152 && GET_OP (insn
, RX
) == GET_OP (insn
, RY
))
2154 /* Skip the register and the comma. */
2160 && GET_OP (insn
, RZ
) == GET_OP (insn
, RX
))
2162 /* Skip the register and the comma. */
2166 print_mips16_insn_arg (*s
, op
, insn
, use_extend
, extend
, memaddr
,
2170 /* Figure out branch instruction type and delay slot information. */
2171 if ((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
) != 0)
2172 info
->branch_delay_insns
= 1;
2173 if ((op
->pinfo
& (INSN_UNCOND_BRANCH_DELAY
2174 | MIPS16_INSN_UNCOND_BRANCH
)) != 0)
2176 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2177 info
->insn_type
= dis_jsr
;
2179 info
->insn_type
= dis_branch
;
2181 else if ((op
->pinfo
& MIPS16_INSN_COND_BRANCH
) != 0)
2182 info
->insn_type
= dis_condbranch
;
2191 infprintf (is
, "0x%x", extend
| 0xf000);
2192 infprintf (is
, "0x%x", insn
);
2193 info
->insn_type
= dis_noninsn
;
2198 /* Disassemble microMIPS instructions. */
2201 print_insn_micromips (bfd_vma memaddr
, struct disassemble_info
*info
)
2203 const fprintf_ftype infprintf
= info
->fprintf_func
;
2204 const struct mips_opcode
*op
, *opend
;
2205 unsigned int lsb
, msbd
, msb
;
2206 void *is
= info
->stream
;
2219 info
->bytes_per_chunk
= 2;
2220 info
->display_endian
= info
->endian
;
2221 info
->insn_info_valid
= 1;
2222 info
->branch_delay_insns
= 0;
2223 info
->data_size
= 0;
2224 info
->insn_type
= dis_nonbranch
;
2228 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 2, info
);
2231 (*info
->memory_error_func
) (status
, memaddr
, info
);
2237 if (info
->endian
== BFD_ENDIAN_BIG
)
2238 insn
= bfd_getb16 (buffer
);
2240 insn
= bfd_getl16 (buffer
);
2242 if ((insn
& 0xfc00) == 0x7c00)
2244 /* This is a 48-bit microMIPS instruction. */
2247 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2250 infprintf (is
, "micromips 0x%x", higher
);
2251 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
2254 if (info
->endian
== BFD_ENDIAN_BIG
)
2255 insn
= bfd_getb16 (buffer
);
2257 insn
= bfd_getl16 (buffer
);
2258 higher
= (higher
<< 16) | insn
;
2260 status
= (*info
->read_memory_func
) (memaddr
+ 4, buffer
, 2, info
);
2263 infprintf (is
, "micromips 0x%x", higher
);
2264 (*info
->memory_error_func
) (status
, memaddr
+ 4, info
);
2267 if (info
->endian
== BFD_ENDIAN_BIG
)
2268 insn
= bfd_getb16 (buffer
);
2270 insn
= bfd_getl16 (buffer
);
2271 infprintf (is
, "0x%x%04x (48-bit insn)", higher
, insn
);
2273 info
->insn_type
= dis_noninsn
;
2276 else if ((insn
& 0x1c00) == 0x0000 || (insn
& 0x1000) == 0x1000)
2278 /* This is a 32-bit microMIPS instruction. */
2281 status
= (*info
->read_memory_func
) (memaddr
+ 2, buffer
, 2, info
);
2284 infprintf (is
, "micromips 0x%x", higher
);
2285 (*info
->memory_error_func
) (status
, memaddr
+ 2, info
);
2289 if (info
->endian
== BFD_ENDIAN_BIG
)
2290 insn
= bfd_getb16 (buffer
);
2292 insn
= bfd_getl16 (buffer
);
2294 insn
= insn
| (higher
<< 16);
2299 /* FIXME: Should probably use a hash table on the major opcode here. */
2301 #define GET_OP(insn, field) \
2302 (((insn) >> MICROMIPSOP_SH_##field) & MICROMIPSOP_MASK_##field)
2303 #define GET_OP_S(insn, field) \
2304 ((GET_OP (insn, field) ^ ((MICROMIPSOP_MASK_##field >> 1) + 1)) \
2305 - ((MICROMIPSOP_MASK_##field >> 1) + 1))
2306 opend
= micromips_opcodes
+ bfd_micromips_num_opcodes
;
2307 for (op
= micromips_opcodes
; op
< opend
; op
++)
2309 if (op
->pinfo
!= INSN_MACRO
2310 && !(no_aliases
&& (op
->pinfo2
& INSN2_ALIAS
))
2311 && (insn
& op
->mask
) == op
->match
2312 && ((length
== 2 && (op
->mask
& 0xffff0000) == 0)
2313 || (length
== 4 && (op
->mask
& 0xffff0000) != 0)))
2317 infprintf (is
, "%s", op
->name
);
2318 if (op
->args
[0] != '\0')
2319 infprintf (is
, "\t");
2321 for (s
= op
->args
; *s
!= '\0'; s
++)
2328 infprintf (is
, "%c", *s
);
2332 infprintf (is
, "%d", GET_OP_S (insn
, OFFSET10
));
2336 infprintf (is
, "0x%x", GET_OP (insn
, STYPE
));
2340 infprintf (is
, "0x%x", GET_OP (insn
, BP
));
2344 infprintf (is
, "0x%x", GET_OP (insn
, SA3
));
2348 infprintf (is
, "0x%x", GET_OP (insn
, SA4
));
2352 infprintf (is
, "0x%x", GET_OP (insn
, IMM8
));
2356 infprintf (is
, "0x%x", GET_OP (insn
, RS
));
2360 infprintf (is
, "$ac%d", GET_OP (insn
, DSPACC
));
2364 infprintf (is
, "0x%x", GET_OP (insn
, WRDSP
));
2367 case '0': /* DSP 6-bit signed immediate in bit 16. */
2368 delta
= (GET_OP (insn
, DSPSFT
) ^ 0x20) - 0x20;
2369 infprintf (is
, "%d", delta
);
2373 infprintf (is
, "0x%x", GET_OP (insn
, SHAMT
));
2377 infprintf (is
, "0x%x", GET_OP (insn
, 3BITPOS
));
2381 infprintf (is
, "0x%x", GET_OP (insn
, RD
));
2385 infprintf (is
, "0x%x", GET_OP (insn
, TRAP
));
2389 infprintf (is
, "%d", GET_OP_S (insn
, OFFSET12
));
2393 if (strcmp (op
->name
, "jalx") == 0)
2394 info
->target
= (((memaddr
+ 4) & ~(bfd_vma
) 0x0fffffff)
2395 | (GET_OP (insn
, TARGET
) << 2));
2397 info
->target
= (((memaddr
+ 4) & ~(bfd_vma
) 0x07ffffff)
2398 | (GET_OP (insn
, TARGET
) << 1));
2399 /* For gdb disassembler, force odd address on jalx. */
2400 if (info
->flavour
== bfd_target_unknown_flavour
2401 && strcmp (op
->name
, "jalx") == 0)
2403 (*info
->print_address_func
) (info
->target
, info
);
2410 infprintf (is
, "%s", mips_gpr_names
[GET_OP (insn
, RS
)]);
2414 infprintf (is
, "0x%x", GET_OP (insn
, CODE
));
2418 infprintf (is
, "%s", mips_gpr_names
[GET_OP (insn
, RD
)]);
2422 infprintf (is
, "0x%x", GET_OP (insn
, PREFX
));
2427 infprintf (is
, "0x%x", GET_OP (insn
, IMMEDIATE
));
2430 case 'j': /* Same as i, but sign-extended. */
2432 infprintf (is
, "%d", GET_OP_S (insn
, DELTA
));
2436 infprintf (is
, "0x%x", GET_OP (insn
, CACHE
));
2443 immed
= GET_OP (insn
, RT
);
2444 s_reg_encode
= immed
& 0xf;
2445 if (s_reg_encode
!= 0)
2447 if (s_reg_encode
== 1)
2448 infprintf (is
, "%s", mips_gpr_names
[16]);
2449 else if (s_reg_encode
< 9)
2450 infprintf (is
, "%s-%s",
2452 mips_gpr_names
[15 + s_reg_encode
]);
2453 else if (s_reg_encode
== 9)
2454 infprintf (is
, "%s-%s,%s",
2457 mips_gpr_names
[30]);
2459 infprintf (is
, "UNKNOWN");
2462 if (immed
& 0x10) /* For ra. */
2464 if (s_reg_encode
== 0)
2465 infprintf (is
, "%s", mips_gpr_names
[31]);
2467 infprintf (is
, ",%s", mips_gpr_names
[31]);
2473 /* Sign-extend the displacement. */
2474 delta
= GET_OP_S (insn
, DELTA
);
2475 info
->target
= (delta
<< 1) + memaddr
+ length
;
2476 (*info
->print_address_func
) (info
->target
, info
);
2480 infprintf (is
, "0x%x", GET_OP (insn
, CODE2
));
2485 infprintf (is
, "%s", mips_gpr_names
[GET_OP (insn
, RT
)]);
2489 infprintf (is
, "%s", mips_gpr_names
[GET_OP (insn
, RS3
)]);
2493 infprintf (is
, "%s", mips_gpr_names
[0]);
2496 case '@': /* DSP 10-bit signed immediate in bit 16. */
2497 delta
= (GET_OP (insn
, IMM10
) ^ 0x200) - 0x200;
2498 infprintf (is
, "%d", delta
);
2502 infprintf (is
, "0x%x", GET_OP (insn
, CODE10
));
2506 infprintf (is
, "0x%x", GET_OP (insn
, COPZ
));
2510 infprintf (is
, "%s", mips_fpr_names
[GET_OP (insn
, FD
)]);
2514 /* Coprocessor register for lwcN instructions, et al.
2516 Note that there is no load/store cp0 instructions, and
2517 that FPU (cp1) instructions disassemble this field using
2518 'T' format. Therefore, until we gain understanding of
2519 cp2 register names, we can simply print the register
2521 infprintf (is
, "$%d", GET_OP (insn
, RT
));
2525 /* Coprocessor register for mtcN instructions, et al. Note
2526 that FPU (cp1) instructions disassemble this field using
2527 'S' format. Therefore, we only need to worry about cp0,
2529 The microMIPS encoding does not have a coprocessor
2530 identifier field as such, so we must work out the
2531 coprocessor number by looking at the opcode. */
2533 & ~((MICROMIPSOP_MASK_RT
<< MICROMIPSOP_SH_RT
)
2534 | (MICROMIPSOP_MASK_RS
<< MICROMIPSOP_SH_RS
)))
2536 case 0x000000fc: /* mfc0 */
2537 case 0x000002fc: /* mtc0 */
2538 case 0x580000fc: /* dmfc0 */
2539 case 0x580002fc: /* dmtc0 */
2540 infprintf (is
, "%s", mips_cp0_names
[GET_OP (insn
, RS
)]);
2543 infprintf (is
, "$%d", GET_OP (insn
, RS
));
2549 infprintf (is
, "%d", GET_OP (insn
, SEL
));
2553 infprintf (is
, "%s", mips_hwr_names
[GET_OP (insn
, RS
)]);
2557 infprintf (is
, "$fcc%d", GET_OP (insn
, CCC
));
2562 (op
->pinfo
& (FP_D
| FP_S
)) != 0
2563 ? "$fcc%d" : "$cc%d",
2564 GET_OP (insn
, BCC
));
2568 infprintf (is
, "%s", mips_fpr_names
[GET_OP (insn
, FR
)]);
2573 infprintf (is
, "%s", mips_fpr_names
[GET_OP (insn
, FS
)]);
2577 infprintf (is
, "%s", mips_fpr_names
[GET_OP (insn
, FT
)]);
2581 /* Extension character; switch for second char. */
2586 lsb
= GET_OP (insn
, EXTLSB
);
2587 infprintf (is
, "0x%x", lsb
);
2591 msb
= GET_OP (insn
, INSMSB
);
2592 infprintf (is
, "0x%x", msb
- lsb
+ 1);
2597 msbd
= GET_OP (insn
, EXTMSBD
);
2598 infprintf (is
, "0x%x", msbd
+ 1);
2603 const struct mips_cp0sel_name
*n
;
2604 unsigned int cp0reg
, sel
;
2606 cp0reg
= GET_OP (insn
, RS
);
2607 sel
= GET_OP (insn
, SEL
);
2609 /* CP0 register including 'sel' code for mtcN
2610 (et al.), to be printed textually if known.
2611 If not known, print both CP0 register name and
2612 sel numerically since CP0 register with sel 0 may
2613 have a name unrelated to register being printed. */
2614 n
= lookup_mips_cp0sel_name (mips_cp0sel_names
,
2615 mips_cp0sel_names_len
,
2618 infprintf (is
, "%s", n
->name
);
2620 infprintf (is
, "$%d,%d", cp0reg
, sel
);
2625 lsb
= GET_OP (insn
, EXTLSB
) + 32;
2626 infprintf (is
, "0x%x", lsb
);
2630 msb
= GET_OP (insn
, INSMSB
) + 32;
2631 infprintf (is
, "0x%x", msb
- lsb
+ 1);
2635 msbd
= GET_OP (insn
, EXTMSBD
) + 32;
2636 infprintf (is
, "0x%x", msbd
+ 1);
2640 /* xgettext:c-format */
2642 _("# internal disassembler error, "
2643 "unrecognized modifier (+%c)"),
2650 /* Extension character; switch for second char. */
2654 case 'a': /* global pointer. */
2655 infprintf (is
, "%s", mips_gpr_names
[28]);
2659 regno
= micromips_to_32_reg_b_map
[GET_OP (insn
, MB
)];
2660 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2664 regno
= micromips_to_32_reg_c_map
[GET_OP (insn
, MC
)];
2665 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2669 regno
= micromips_to_32_reg_d_map
[GET_OP (insn
, MD
)];
2670 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2674 regno
= micromips_to_32_reg_e_map
[GET_OP (insn
, ME
)];
2675 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2679 /* Save lastregno for "mt" to print out later. */
2680 lastregno
= micromips_to_32_reg_f_map
[GET_OP (insn
, MF
)];
2681 infprintf (is
, "%s", mips_gpr_names
[lastregno
]);
2685 regno
= micromips_to_32_reg_g_map
[GET_OP (insn
, MG
)];
2686 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2690 regno
= micromips_to_32_reg_h_map
[GET_OP (insn
, MH
)];
2691 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2695 regno
= micromips_to_32_reg_i_map
[GET_OP (insn
, MI
)];
2696 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2700 infprintf (is
, "%s", mips_gpr_names
[GET_OP (insn
, MJ
)]);
2704 regno
= micromips_to_32_reg_l_map
[GET_OP (insn
, ML
)];
2705 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2709 regno
= micromips_to_32_reg_m_map
[GET_OP (insn
, MM
)];
2710 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2714 regno
= micromips_to_32_reg_n_map
[GET_OP (insn
, MN
)];
2715 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2719 /* Save lastregno for "mt" to print out later. */
2720 lastregno
= GET_OP (insn
, MP
);
2721 infprintf (is
, "%s", mips_gpr_names
[lastregno
]);
2725 regno
= micromips_to_32_reg_q_map
[GET_OP (insn
, MQ
)];
2726 infprintf (is
, "%s", mips_gpr_names
[regno
]);
2729 case 'r': /* program counter. */
2730 infprintf (is
, "$pc");
2733 case 's': /* stack pointer. */
2735 infprintf (is
, "%s", mips_gpr_names
[29]);
2739 infprintf (is
, "%s", mips_gpr_names
[lastregno
]);
2743 infprintf (is
, "%s", mips_gpr_names
[0]);
2747 /* Sign-extend the immediate. */
2748 immed
= GET_OP_S (insn
, IMMA
) << 2;
2749 infprintf (is
, "%d", immed
);
2753 immed
= micromips_imm_b_map
[GET_OP (insn
, IMMB
)];
2754 infprintf (is
, "%d", immed
);
2758 immed
= micromips_imm_c_map
[GET_OP (insn
, IMMC
)];
2759 infprintf (is
, "0x%x", immed
);
2763 /* Sign-extend the displacement. */
2764 delta
= GET_OP_S (insn
, IMMD
);
2765 info
->target
= (delta
<< 1) + memaddr
+ length
;
2766 (*info
->print_address_func
) (info
->target
, info
);
2770 /* Sign-extend the displacement. */
2771 delta
= GET_OP_S (insn
, IMME
);
2772 info
->target
= (delta
<< 1) + memaddr
+ length
;
2773 (*info
->print_address_func
) (info
->target
, info
);
2777 immed
= GET_OP (insn
, IMMF
);
2778 infprintf (is
, "0x%x", immed
);
2782 immed
= (insn
>> MICROMIPSOP_SH_IMMG
) + 1;
2783 immed
= (immed
& MICROMIPSOP_MASK_IMMG
) - 1;
2784 infprintf (is
, "%d", immed
);
2788 immed
= GET_OP (insn
, IMMH
) << 1;
2789 infprintf (is
, "%d", immed
);
2793 immed
= (insn
>> MICROMIPSOP_SH_IMMI
) + 1;
2794 immed
= (immed
& MICROMIPSOP_MASK_IMMI
) - 1;
2795 infprintf (is
, "%d", immed
);
2799 immed
= GET_OP (insn
, IMMJ
) << 2;
2800 infprintf (is
, "%d", immed
);
2804 immed
= GET_OP (insn
, IMML
);
2805 infprintf (is
, "%d", immed
);
2809 immed
= (insn
>> MICROMIPSOP_SH_IMMM
) - 1;
2810 immed
= (immed
& MICROMIPSOP_MASK_IMMM
) + 1;
2811 infprintf (is
, "%d", immed
);
2815 immed
= GET_OP (insn
, IMMN
);
2817 infprintf (is
, "%s,%s",
2819 mips_gpr_names
[31]);
2821 infprintf (is
, "%s-%s,%s",
2823 mips_gpr_names
[16 + immed
],
2824 mips_gpr_names
[31]);
2828 immed
= GET_OP (insn
, IMMO
);
2829 infprintf (is
, "0x%x", immed
);
2833 immed
= GET_OP (insn
, IMMP
) << 2;
2834 infprintf (is
, "%d", immed
);
2838 /* Sign-extend the immediate. */
2839 immed
= GET_OP_S (insn
, IMMQ
) << 2;
2840 infprintf (is
, "%d", immed
);
2844 immed
= GET_OP (insn
, IMMU
) << 2;
2845 infprintf (is
, "%d", immed
);
2849 immed
= GET_OP (insn
, IMMW
) << 2;
2850 infprintf (is
, "%d", immed
);
2854 /* Sign-extend the immediate. */
2855 immed
= GET_OP_S (insn
, IMMX
);
2856 infprintf (is
, "%d", immed
);
2860 /* Sign-extend the immediate. */
2861 immed
= GET_OP_S (insn
, IMMY
) << 2;
2862 if ((unsigned int) (immed
+ 8) < 16)
2864 infprintf (is
, "%d", immed
);
2868 /* xgettext:c-format */
2870 _("# internal disassembler error, "
2871 "unrecognized modifier (m%c)"),
2878 /* xgettext:c-format */
2880 _("# internal disassembler error, "
2881 "unrecognized modifier (%c)"),
2887 /* Figure out instruction type and branch delay information. */
2889 & (INSN_UNCOND_BRANCH_DELAY
| INSN_COND_BRANCH_DELAY
)) != 0)
2890 info
->branch_delay_insns
= 1;
2891 if (((op
->pinfo
& INSN_UNCOND_BRANCH_DELAY
)
2892 | (op
->pinfo2
& INSN2_UNCOND_BRANCH
)) != 0)
2894 if ((op
->pinfo
& (INSN_WRITE_GPR_31
| INSN_WRITE_GPR_T
)) != 0)
2895 info
->insn_type
= dis_jsr
;
2897 info
->insn_type
= dis_branch
;
2899 else if (((op
->pinfo
& INSN_COND_BRANCH_DELAY
)
2900 | (op
->pinfo2
& INSN2_COND_BRANCH
)) != 0)
2902 if ((op
->pinfo
& INSN_WRITE_GPR_31
) != 0)
2903 info
->insn_type
= dis_condjsr
;
2905 info
->insn_type
= dis_condbranch
;
2908 & (INSN_STORE_MEMORY
| INSN_LOAD_MEMORY_DELAY
)) != 0)
2909 info
->insn_type
= dis_dref
;
2917 infprintf (is
, "0x%x", insn
);
2918 info
->insn_type
= dis_noninsn
;
2923 /* Return 1 if a symbol associated with the location being disassembled
2924 indicates a compressed (MIPS16 or microMIPS) mode. We iterate over
2925 all the symbols at the address being considered assuming if at least
2926 one of them indicates code compression, then such code has been
2927 genuinely produced here (other symbols could have been derived from
2928 function symbols defined elsewhere or could define data). Otherwise,
2932 is_compressed_mode_p (struct disassemble_info
*info
)
2934 elf_symbol_type
*symbol
;
2938 for (i
= 0; i
< info
->num_symbols
; i
++)
2940 pos
= info
->symtab_pos
+ i
;
2942 if (bfd_asymbol_flavour (info
->symtab
[pos
]) != bfd_target_elf_flavour
)
2945 if (info
->symtab
[pos
]->section
!= info
->section
)
2948 symbol
= (elf_symbol_type
*) info
->symtab
[pos
];
2950 && ELF_ST_IS_MIPS16 (symbol
->internal_elf_sym
.st_other
))
2952 && ELF_ST_IS_MICROMIPS (symbol
->internal_elf_sym
.st_other
)))
2959 /* In an environment where we do not know the symbol type of the
2960 instruction we are forced to assume that the low order bit of the
2961 instructions' address may mark it as a mips16 instruction. If we
2962 are single stepping, or the pc is within the disassembled function,
2963 this works. Otherwise, we need a clue. Sometimes. */
2966 _print_insn_mips (bfd_vma memaddr
,
2967 struct disassemble_info
*info
,
2968 enum bfd_endian endianness
)
2970 int (*print_insn_compr
) (bfd_vma
, struct disassemble_info
*);
2971 bfd_byte buffer
[INSNLEN
];
2974 set_default_mips_dis_options (info
);
2975 parse_mips_dis_options (info
->disassembler_options
);
2977 if (info
->mach
== bfd_mach_mips16
)
2978 return print_insn_mips16 (memaddr
, info
);
2979 if (info
->mach
== bfd_mach_mips_micromips
)
2980 return print_insn_micromips (memaddr
, info
);
2982 print_insn_compr
= !micromips_ase
? print_insn_mips16
: print_insn_micromips
;
2985 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
2986 /* Only a few tools will work this way. */
2988 return print_insn_compr (memaddr
, info
);
2991 #if SYMTAB_AVAILABLE
2992 if (is_compressed_mode_p (info
))
2993 return print_insn_compr (memaddr
, info
);
2996 status
= (*info
->read_memory_func
) (memaddr
, buffer
, INSNLEN
, info
);
3001 if (endianness
== BFD_ENDIAN_BIG
)
3002 insn
= bfd_getb32 (buffer
);
3004 insn
= bfd_getl32 (buffer
);
3006 return print_insn_mips (memaddr
, insn
, info
);
3010 (*info
->memory_error_func
) (status
, memaddr
, info
);
3016 print_insn_big_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
3018 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_BIG
);
3022 print_insn_little_mips (bfd_vma memaddr
, struct disassemble_info
*info
)
3024 return _print_insn_mips (memaddr
, info
, BFD_ENDIAN_LITTLE
);
3028 print_mips_disassembler_options (FILE *stream
)
3032 fprintf (stream
, _("\n\
3033 The following MIPS specific disassembler options are supported for use\n\
3034 with the -M switch (multiple options should be separated by commas):\n"));
3036 fprintf (stream
, _("\n\
3037 gpr-names=ABI Print GPR names according to specified ABI.\n\
3038 Default: based on binary being disassembled.\n"));
3040 fprintf (stream
, _("\n\
3041 fpr-names=ABI Print FPR names according to specified ABI.\n\
3042 Default: numeric.\n"));
3044 fprintf (stream
, _("\n\
3045 cp0-names=ARCH Print CP0 register names according to\n\
3046 specified architecture.\n\
3047 Default: based on binary being disassembled.\n"));
3049 fprintf (stream
, _("\n\
3050 hwr-names=ARCH Print HWR names according to specified \n\
3052 Default: based on binary being disassembled.\n"));
3054 fprintf (stream
, _("\n\
3055 reg-names=ABI Print GPR and FPR names according to\n\
3056 specified ABI.\n"));
3058 fprintf (stream
, _("\n\
3059 reg-names=ARCH Print CP0 register and HWR names according to\n\
3060 specified architecture.\n"));
3062 fprintf (stream
, _("\n\
3063 For the options above, the following values are supported for \"ABI\":\n\
3065 for (i
= 0; i
< ARRAY_SIZE (mips_abi_choices
); i
++)
3066 fprintf (stream
, " %s", mips_abi_choices
[i
].name
);
3067 fprintf (stream
, _("\n"));
3069 fprintf (stream
, _("\n\
3070 For the options above, The following values are supported for \"ARCH\":\n\
3072 for (i
= 0; i
< ARRAY_SIZE (mips_arch_choices
); i
++)
3073 if (*mips_arch_choices
[i
].name
!= '\0')
3074 fprintf (stream
, " %s", mips_arch_choices
[i
].name
);
3075 fprintf (stream
, _("\n"));
3077 fprintf (stream
, _("\n"));