2013-05-06 Sandra Loosemore <sandra@codesourcery.com>
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
252b5132 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
060d22b0 2 Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
8b99bf0b 3 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2012
73da6b6b 4 Free Software Foundation, Inc.
252b5132
RH
5 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
6
9b201bb5 7 This file is part of the GNU opcodes library.
252b5132 8
9b201bb5 9 This library is free software; you can redistribute it and/or modify
47b0e7ad 10 it under the terms of the GNU General Public License as published by
9b201bb5
NC
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
252b5132 13
9b201bb5
NC
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.
252b5132 18
47b0e7ad
NC
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. */
252b5132 23
252b5132
RH
24#include "sysdep.h"
25#include "dis-asm.h"
640c0ccd 26#include "libiberty.h"
252b5132
RH
27#include "opcode/mips.h"
28#include "opintl.h"
29
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
7f6621cd 33 system as when it is used for disassembler support in a monitor. */
252b5132
RH
34
35#if !defined(EMBEDDED_ENV)
36#define SYMTAB_AVAILABLE 1
37#include "elf-bfd.h"
38#include "elf/mips.h"
39#endif
40
aa5f19f2
NC
41/* Mips instructions are at maximum this many bytes long. */
42#define INSNLEN 4
43
252b5132 44\f
aa5f19f2 45/* FIXME: These should be shared with gdb somehow. */
252b5132 46
47b0e7ad
NC
47struct mips_cp0sel_name
48{
49 unsigned int cp0reg;
50 unsigned int sel;
51 const char * const name;
bbcc0807
CD
52};
53
654c225a
TS
54/* The mips16 registers. */
55static const unsigned int mips16_to_32_reg_map[] =
47b0e7ad 56{
654c225a 57 16, 17, 2, 3, 4, 5, 6, 7
252b5132 58};
fb48caed 59
df58fc94
RS
60/* The microMIPS registers with type b. */
61#define micromips_to_32_reg_b_map mips16_to_32_reg_map
62
63/* The microMIPS registers with type c. */
64#define micromips_to_32_reg_c_map mips16_to_32_reg_map
65
66/* The microMIPS registers with type d. */
67#define micromips_to_32_reg_d_map mips16_to_32_reg_map
68
69/* The microMIPS registers with type e. */
70#define micromips_to_32_reg_e_map mips16_to_32_reg_map
71
72/* The microMIPS registers with type f. */
73#define micromips_to_32_reg_f_map mips16_to_32_reg_map
74
75/* The microMIPS registers with type g. */
76#define micromips_to_32_reg_g_map mips16_to_32_reg_map
77
78/* The microMIPS registers with type h. */
79static const unsigned int micromips_to_32_reg_h_map[] =
80{
81 5, 5, 6, 4, 4, 4, 4, 4
82};
83
84/* The microMIPS registers with type i. */
85static const unsigned int micromips_to_32_reg_i_map[] =
86{
87 6, 7, 7, 21, 22, 5, 6, 7
88};
89
90/* The microMIPS registers with type j: 32 registers. */
91
92/* The microMIPS registers with type l. */
93#define micromips_to_32_reg_l_map mips16_to_32_reg_map
94
95/* The microMIPS registers with type m. */
96static const unsigned int micromips_to_32_reg_m_map[] =
97{
98 0, 17, 2, 3, 16, 18, 19, 20
99};
100
101/* The microMIPS registers with type n. */
102#define micromips_to_32_reg_n_map micromips_to_32_reg_m_map
103
104/* The microMIPS registers with type p: 32 registers. */
105
106/* The microMIPS registers with type q. */
107static const unsigned int micromips_to_32_reg_q_map[] =
108{
109 0, 17, 2, 3, 4, 5, 6, 7
110};
111
112/* reg type s is $29. */
113
114/* reg type t is the same as the last register. */
115
116/* reg type y is $31. */
117
118/* reg type z is $0. */
119
120/* micromips imm B type. */
121static const int micromips_imm_b_map[8] =
122{
123 1, 4, 8, 12, 16, 20, 24, -1
124};
125
126/* micromips imm C type. */
127static const int micromips_imm_c_map[16] =
128{
129 128, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 255, 32768, 65535
130};
131
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. */
144
654c225a
TS
145#define mips16_reg_names(rn) mips_gpr_names[mips16_to_32_reg_map[rn]]
146
147
47b0e7ad
NC
148static const char * const mips_gpr_names_numeric[32] =
149{
640c0ccd
CD
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"
aa5f19f2
NC
154};
155
47b0e7ad
NC
156static const char * const mips_gpr_names_oldabi[32] =
157{
640c0ccd
CD
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"
aa5f19f2
NC
162};
163
47b0e7ad
NC
164static const char * const mips_gpr_names_newabi[32] =
165{
640c0ccd 166 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
0b14f26e 167 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
640c0ccd
CD
168 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
169 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
170};
171
47b0e7ad
NC
172static const char * const mips_fpr_names_numeric[32] =
173{
640c0ccd
CD
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"
178};
179
47b0e7ad
NC
180static const char * const mips_fpr_names_32[32] =
181{
640c0ccd
CD
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"
186};
187
47b0e7ad
NC
188static const char * const mips_fpr_names_n32[32] =
189{
640c0ccd
CD
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"
194};
195
47b0e7ad
NC
196static const char * const mips_fpr_names_64[32] =
197{
640c0ccd
CD
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"
202};
203
47b0e7ad
NC
204static const char * const mips_cp0_names_numeric[32] =
205{
640c0ccd
CD
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"
210};
211
f409fd1e
MR
212static const char * const mips_cp0_names_r3000[32] =
213{
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",
222};
223
224static const char * const mips_cp0_names_r4000[32] =
225{
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",
234};
235
e407c74b
NC
236static const char * const mips_cp0_names_r5900[32] =
237{
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"
246};
247
248static const struct mips_cp0sel_name mips_cp0sel_names_mipsr5900[] =
249{
250 { 24, 2, "c0_iab" },
251 { 24, 3, "c0_iabm" },
252 { 24, 4, "c0_dab" },
253 { 24, 5, "c0_dabm" },
254 { 24, 6, "c0_dvb" },
255 { 24, 7, "c0_dvbm" },
256 { 25, 1, "c0_perfcnt,1" },
257 { 25, 2, "c0_perfcnt,2" }
258};
259
47b0e7ad
NC
260static const char * const mips_cp0_names_mips3264[32] =
261{
640c0ccd
CD
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",
270};
271
47b0e7ad
NC
272static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] =
273{
bbcc0807
CD
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" }
303};
304
47b0e7ad
NC
305static const char * const mips_cp0_names_mips3264r2[32] =
306{
af7ee8bf
CD
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",
315};
316
47b0e7ad
NC
317static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] =
318{
bbcc0807 319 { 4, 1, "c0_contextconfig" },
59c455b3
TS
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" },
bbcc0807 336 { 5, 1, "c0_pagegrain" },
59c455b3
TS
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" },
bbcc0807
CD
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" },
391};
392
640c0ccd 393/* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
47b0e7ad
NC
394static const char * const mips_cp0_names_sb1[32] =
395{
640c0ccd
CD
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",
404};
405
47b0e7ad
NC
406static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] =
407{
bbcc0807
CD
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" },
429};
430
52b6b6b9
JM
431/* Xlr cop0 register names. */
432static 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",
441};
442
443/* XLR's CP0 Select Registers. */
444
445static 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" }
479};
480
47b0e7ad
NC
481static const char * const mips_hwr_names_numeric[32] =
482{
af7ee8bf
CD
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"
487};
488
47b0e7ad
NC
489static const char * const mips_hwr_names_mips3264r2[32] =
490{
af7ee8bf
CD
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"
496};
497
47b0e7ad
NC
498struct mips_abi_choice
499{
500 const char * name;
640c0ccd
CD
501 const char * const *gpr_names;
502 const char * const *fpr_names;
503};
504
47b0e7ad
NC
505struct mips_abi_choice mips_abi_choices[] =
506{
640c0ccd
CD
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 },
511};
512
47b0e7ad
NC
513struct mips_arch_choice
514{
640c0ccd
CD
515 const char *name;
516 int bfd_mach_valid;
517 unsigned long bfd_mach;
518 int processor;
519 int isa;
520 const char * const *cp0_names;
bbcc0807
CD
521 const struct mips_cp0sel_name *cp0sel_names;
522 unsigned int cp0sel_names_len;
af7ee8bf 523 const char * const *hwr_names;
640c0ccd
CD
524};
525
47b0e7ad
NC
526const struct mips_arch_choice mips_arch_choices[] =
527{
640c0ccd 528 { "numeric", 0, 0, 0, 0,
bbcc0807
CD
529 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
530
640c0ccd 531 { "r3000", 1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1,
f409fd1e 532 mips_cp0_names_r3000, NULL, 0, mips_hwr_names_numeric },
640c0ccd 533 { "r3900", 1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1,
bbcc0807 534 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 535 { "r4000", 1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3,
f409fd1e 536 mips_cp0_names_r4000, NULL, 0, mips_hwr_names_numeric },
640c0ccd 537 { "r4010", 1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2,
bbcc0807 538 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 539 { "vr4100", 1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3,
bbcc0807 540 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 541 { "vr4111", 1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3,
bbcc0807 542 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 543 { "vr4120", 1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3,
bbcc0807 544 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 545 { "r4300", 1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3,
bbcc0807 546 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 547 { "r4400", 1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3,
f409fd1e 548 mips_cp0_names_r4000, NULL, 0, mips_hwr_names_numeric },
640c0ccd 549 { "r4600", 1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3,
bbcc0807 550 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 551 { "r4650", 1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3,
bbcc0807 552 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 553 { "r5000", 1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4,
bbcc0807 554 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 555 { "vr5400", 1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4,
bbcc0807 556 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 557 { "vr5500", 1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4,
bbcc0807 558 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
e407c74b
NC
559 { "r5900", 1, bfd_mach_mips5900, CPU_R5900, ISA_MIPS3,
560 mips_cp0_names_r5900, NULL, 0, mips_hwr_names_numeric },
640c0ccd 561 { "r6000", 1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2,
bbcc0807 562 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
5a7ea749
RS
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 },
640c0ccd 567 { "r8000", 1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4,
bbcc0807 568 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 569 { "r10000", 1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4,
bbcc0807 570 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 571 { "r12000", 1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4,
bbcc0807 572 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
3aa3176b
TS
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 },
640c0ccd 577 { "mips5", 1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5,
bbcc0807
CD
578 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
579
640c0ccd
CD
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),
584 page 1. */
585 { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32,
f79e2745 586 ISA_MIPS32 | INSN_SMARTMIPS,
bbcc0807
CD
587 mips_cp0_names_mips3264,
588 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
589 mips_hwr_names_numeric },
590
af7ee8bf 591 { "mips32r2", 1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
f79e2745 592 (ISA_MIPS32R2 | INSN_SMARTMIPS | INSN_DSP | INSN_DSPR2
dec0624d 593 | INSN_MIPS3D | INSN_MT | INSN_MCU),
bbcc0807
CD
594 mips_cp0_names_mips3264r2,
595 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
596 mips_hwr_names_mips3264r2 },
597
640c0ccd
CD
598 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
599 { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64,
f79e2745 600 ISA_MIPS64 | INSN_MIPS3D | INSN_MDMX,
bbcc0807
CD
601 mips_cp0_names_mips3264,
602 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
603 mips_hwr_names_numeric },
604
5f74bc13 605 { "mips64r2", 1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
f79e2745 606 (ISA_MIPS64R2 | INSN_MIPS3D | INSN_DSP | INSN_DSPR2
dec0624d 607 | INSN_DSP64 | INSN_MT | INSN_MDMX | INSN_MCU),
5f74bc13
CD
608 mips_cp0_names_mips3264r2,
609 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
610 mips_hwr_names_mips3264r2 },
611
640c0ccd
CD
612 { "sb1", 1, bfd_mach_mips_sb1, CPU_SB1,
613 ISA_MIPS64 | INSN_MIPS3D | INSN_SB1,
bbcc0807
CD
614 mips_cp0_names_sb1,
615 mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
616 mips_hwr_names_numeric },
640c0ccd 617
350cc38d
MS
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 },
621
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 },
625
fd503541
NC
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 },
629
57b592a3
AN
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 },
633
dd6a37e7 634 { "octeon+", 1, bfd_mach_mips_octeonp, CPU_OCTEONP,
432233b3
AP
635 ISA_MIPS64R2 | INSN_OCTEONP, mips_cp0_names_numeric,
636 NULL, 0, mips_hwr_names_numeric },
637
638 { "octeon2", 1, bfd_mach_mips_octeon2, CPU_OCTEON2,
639 ISA_MIPS64R2 | INSN_OCTEON2, mips_cp0_names_numeric,
dd6a37e7
AP
640 NULL, 0, mips_hwr_names_numeric },
641
52b6b6b9
JM
642 { "xlr", 1, bfd_mach_mips_xlr, CPU_XLR,
643 ISA_MIPS64 | INSN_XLR,
644 mips_cp0_names_xlr,
645 mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
646 mips_hwr_names_numeric },
647
55a36193
MK
648 /* XLP is mostly like XLR, with the prominent exception it is being
649 MIPS64R2. */
650 { "xlp", 1, bfd_mach_mips_xlr, CPU_XLR,
651 ISA_MIPS64R2 | INSN_XLR,
652 mips_cp0_names_xlr,
653 mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
654 mips_hwr_names_numeric },
655
640c0ccd
CD
656 /* This entry, mips16, is here only for ISA/processor selection; do
657 not print its name. */
f79e2745 658 { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3,
bbcc0807 659 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd
CD
660};
661
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
664 values. */
665static int mips_processor;
666static int mips_isa;
df58fc94 667static int micromips_ase;
640c0ccd
CD
668static const char * const *mips_gpr_names;
669static const char * const *mips_fpr_names;
670static const char * const *mips_cp0_names;
bbcc0807
CD
671static const struct mips_cp0sel_name *mips_cp0sel_names;
672static int mips_cp0sel_names_len;
af7ee8bf 673static const char * const *mips_hwr_names;
640c0ccd 674
986e18a5 675/* Other options */
47b0e7ad 676static int no_aliases; /* If set disassemble as most general inst. */
640c0ccd
CD
677\f
678static const struct mips_abi_choice *
47b0e7ad 679choose_abi_by_name (const char *name, unsigned int namelen)
640c0ccd
CD
680{
681 const struct mips_abi_choice *c;
682 unsigned int i;
683
684 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++)
47b0e7ad
NC
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];
688
640c0ccd
CD
689 return c;
690}
691
692static const struct mips_arch_choice *
47b0e7ad 693choose_arch_by_name (const char *name, unsigned int namelen)
640c0ccd
CD
694{
695 const struct mips_arch_choice *c = NULL;
696 unsigned int i;
697
698 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
47b0e7ad
NC
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];
702
640c0ccd
CD
703 return c;
704}
705
706static const struct mips_arch_choice *
47b0e7ad 707choose_arch_by_number (unsigned long mach)
640c0ccd
CD
708{
709 static unsigned long hint_bfd_mach;
710 static const struct mips_arch_choice *hint_arch_choice;
711 const struct mips_arch_choice *c;
712 unsigned int i;
713
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;
720
721 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
722 {
723 if (mips_arch_choices[i].bfd_mach_valid
724 && mips_arch_choices[i].bfd_mach == mach)
725 {
726 c = &mips_arch_choices[i];
727 hint_bfd_mach = mach;
728 hint_arch_choice = c;
729 }
730 }
731 return c;
732}
733
47b0e7ad
NC
734/* Check if the object uses NewABI conventions. */
735
736static int
737is_newabi (Elf_Internal_Ehdr *header)
738{
739 /* There are no old-style ABIs which use 64-bit ELF. */
740 if (header->e_ident[EI_CLASS] == ELFCLASS64)
741 return 1;
742
743 /* If a 32-bit ELF file, n32 is a new-style ABI. */
744 if ((header->e_flags & EF_MIPS_ABI2) != 0)
745 return 1;
746
747 return 0;
748}
749
df58fc94
RS
750/* Check if the object has microMIPS ASE code. */
751
752static int
753is_micromips (Elf_Internal_Ehdr *header)
754{
755 if ((header->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0)
756 return 1;
757
758 return 0;
759}
760
47b0e7ad
NC
761static void
762set_default_mips_dis_options (struct disassemble_info *info)
640c0ccd
CD
763{
764 const struct mips_arch_choice *chosen_arch;
765
df58fc94
RS
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. */
640c0ccd 769 mips_isa = ISA_MIPS3;
df58fc94
RS
770 mips_processor = CPU_R3000;
771 micromips_ase = 0;
640c0ccd
CD
772 mips_gpr_names = mips_gpr_names_oldabi;
773 mips_fpr_names = mips_fpr_names_numeric;
774 mips_cp0_names = mips_cp0_names_numeric;
bbcc0807
CD
775 mips_cp0sel_names = NULL;
776 mips_cp0sel_names_len = 0;
af7ee8bf 777 mips_hwr_names = mips_hwr_names_numeric;
986e18a5 778 no_aliases = 0;
640c0ccd 779
df58fc94 780 /* Update settings according to the ELF file header flags. */
fec06546 781 if (info->flavour == bfd_target_elf_flavour && info->section != NULL)
640c0ccd
CD
782 {
783 Elf_Internal_Ehdr *header;
784
fec06546 785 header = elf_elfheader (info->section->owner);
df58fc94 786 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
640c0ccd
CD
787 if (is_newabi (header))
788 mips_gpr_names = mips_gpr_names_newabi;
df58fc94
RS
789 /* If a microMIPS binary, then don't use MIPS16 bindings. */
790 micromips_ase = is_micromips (header);
640c0ccd
CD
791 }
792
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;
799#else
800 chosen_arch = choose_arch_by_number (info->mach);
801 if (chosen_arch != NULL)
802 {
803 mips_processor = chosen_arch->processor;
804 mips_isa = chosen_arch->isa;
bbcc0807
CD
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;
640c0ccd
CD
809 }
810#endif
811}
812
47b0e7ad
NC
813static void
814parse_mips_dis_option (const char *option, unsigned int len)
640c0ccd
CD
815{
816 unsigned int i, optionlen, vallen;
817 const char *val;
818 const struct mips_abi_choice *chosen_abi;
819 const struct mips_arch_choice *chosen_arch;
820
986e18a5 821 /* Try to match options that are simple flags */
0112cd26 822 if (CONST_STRNEQ (option, "no-aliases"))
986e18a5
FF
823 {
824 no_aliases = 1;
825 return;
826 }
827
640c0ccd
CD
828 /* Look for the = that delimits the end of the option name. */
829 for (i = 0; i < len; i++)
47b0e7ad
NC
830 if (option[i] == '=')
831 break;
832
640c0ccd
CD
833 if (i == 0) /* Invalid option: no name before '='. */
834 return;
835 if (i == len) /* Invalid option: no '='. */
836 return;
837 if (i == (len - 1)) /* Invalid option: no value after '='. */
838 return;
839
840 optionlen = i;
841 val = option + (optionlen + 1);
842 vallen = len - (optionlen + 1);
843
47b0e7ad
NC
844 if (strncmp ("gpr-names", option, optionlen) == 0
845 && strlen ("gpr-names") == optionlen)
640c0ccd
CD
846 {
847 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 848 if (chosen_abi != NULL)
640c0ccd
CD
849 mips_gpr_names = chosen_abi->gpr_names;
850 return;
851 }
852
47b0e7ad
NC
853 if (strncmp ("fpr-names", option, optionlen) == 0
854 && strlen ("fpr-names") == optionlen)
640c0ccd
CD
855 {
856 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 857 if (chosen_abi != NULL)
640c0ccd
CD
858 mips_fpr_names = chosen_abi->fpr_names;
859 return;
860 }
861
47b0e7ad
NC
862 if (strncmp ("cp0-names", option, optionlen) == 0
863 && strlen ("cp0-names") == optionlen)
640c0ccd
CD
864 {
865 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807
CD
866 if (chosen_arch != NULL)
867 {
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;
871 }
640c0ccd
CD
872 return;
873 }
874
47b0e7ad
NC
875 if (strncmp ("hwr-names", option, optionlen) == 0
876 && strlen ("hwr-names") == optionlen)
af7ee8bf
CD
877 {
878 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807 879 if (chosen_arch != NULL)
af7ee8bf
CD
880 mips_hwr_names = chosen_arch->hwr_names;
881 return;
882 }
883
47b0e7ad
NC
884 if (strncmp ("reg-names", option, optionlen) == 0
885 && strlen ("reg-names") == optionlen)
640c0ccd
CD
886 {
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)
893 {
bbcc0807
CD
894 mips_gpr_names = chosen_abi->gpr_names;
895 mips_fpr_names = chosen_abi->fpr_names;
640c0ccd
CD
896 }
897 chosen_arch = choose_arch_by_name (val, vallen);
898 if (chosen_arch != NULL)
899 {
bbcc0807
CD
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;
640c0ccd
CD
904 }
905 return;
906 }
907
908 /* Invalid option. */
909}
910
47b0e7ad
NC
911static void
912parse_mips_dis_options (const char *options)
640c0ccd
CD
913{
914 const char *option_end;
915
916 if (options == NULL)
917 return;
918
919 while (*options != '\0')
920 {
921 /* Skip empty options. */
922 if (*options == ',')
923 {
924 options++;
925 continue;
926 }
927
928 /* We know that *options is neither NUL or a comma. */
929 option_end = options + 1;
930 while (*option_end != ',' && *option_end != '\0')
931 option_end++;
932
933 parse_mips_dis_option (options, option_end - options);
934
935 /* Go on to the next one. If option_end points to a comma, it
936 will be skipped above. */
937 options = option_end;
938 }
939}
940
bbcc0807 941static const struct mips_cp0sel_name *
47b0e7ad
NC
942lookup_mips_cp0sel_name (const struct mips_cp0sel_name *names,
943 unsigned int len,
944 unsigned int cp0reg,
945 unsigned int sel)
bbcc0807
CD
946{
947 unsigned int i;
948
949 for (i = 0; i < len; i++)
950 if (names[i].cp0reg == cp0reg && names[i].sel == sel)
951 return &names[i];
952 return NULL;
953}
252b5132 954\f
7f6621cd 955/* Print insn arguments for 32/64-bit code. */
aa5f19f2 956
794ac9d0 957static void
47b0e7ad 958print_insn_args (const char *d,
fc8c4fd1 959 int l,
47b0e7ad 960 bfd_vma pc,
cc0ca239
TS
961 struct disassemble_info *info,
962 const struct mips_opcode *opp)
252b5132 963{
fc8c4fd1 964 const fprintf_ftype infprintf = info->fprintf_func;
440cc0bc 965 unsigned int lsb, msb, msbd;
fc8c4fd1
MR
966 void *is = info->stream;
967 int op;
440cc0bc
CD
968
969 lsb = 0;
252b5132 970
fc8c4fd1
MR
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))
794ac9d0 976 for (; *d != '\0'; d++)
252b5132 977 {
af7ee8bf
CD
978 switch (*d)
979 {
794ac9d0
CD
980 case ',':
981 case '(':
982 case ')':
983 case '[':
984 case ']':
fc8c4fd1 985 infprintf (is, "%c", *d);
794ac9d0
CD
986 break;
987
988 case '+':
989 /* Extension character; switch for second char. */
990 d++;
991 switch (*d)
992 {
993 case '\0':
994 /* xgettext:c-format */
fc8c4fd1
MR
995 infprintf (is,
996 _("# internal error, "
997 "incomplete extension sequence (+)"));
794ac9d0
CD
998 return;
999
1000 case 'A':
fc8c4fd1
MR
1001 lsb = GET_OP (l, SHAMT);
1002 infprintf (is, "0x%x", lsb);
794ac9d0
CD
1003 break;
1004
1005 case 'B':
fc8c4fd1
MR
1006 msb = GET_OP (l, INSMSB);
1007 infprintf (is, "0x%x", msb - lsb + 1);
794ac9d0
CD
1008 break;
1009
9bcd4f99 1010 case '1':
fc8c4fd1 1011 infprintf (is, "0x%x", GET_OP (l, UDI1));
9bcd4f99
TS
1012 break;
1013
1014 case '2':
fc8c4fd1 1015 infprintf (is, "0x%x", GET_OP (l, UDI2));
9bcd4f99
TS
1016 break;
1017
1018 case '3':
fc8c4fd1 1019 infprintf (is, "0x%x", GET_OP (l, UDI3));
9bcd4f99
TS
1020 break;
1021
1022 case '4':
fc8c4fd1 1023 infprintf (is, "0x%x", GET_OP (l, UDI4));
9bcd4f99
TS
1024 break;
1025
794ac9d0 1026 case 'C':
5f74bc13 1027 case 'H':
fc8c4fd1
MR
1028 msbd = GET_OP (l, EXTMSBD);
1029 infprintf (is, "0x%x", msbd + 1);
794ac9d0
CD
1030 break;
1031
1032 case 'D':
1033 {
1034 const struct mips_cp0sel_name *n;
1035 unsigned int cp0reg, sel;
1036
fc8c4fd1
MR
1037 cp0reg = GET_OP (l, RD);
1038 sel = GET_OP (l, SEL);
794ac9d0
CD
1039
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
1044 printed. */
1045 n = lookup_mips_cp0sel_name(mips_cp0sel_names,
1046 mips_cp0sel_names_len, cp0reg, sel);
1047 if (n != NULL)
fc8c4fd1 1048 infprintf (is, "%s", n->name);
794ac9d0 1049 else
fc8c4fd1 1050 infprintf (is, "$%d,%d", cp0reg, sel);
794ac9d0
CD
1051 break;
1052 }
1053
5f74bc13 1054 case 'E':
fc8c4fd1
MR
1055 lsb = GET_OP (l, SHAMT) + 32;
1056 infprintf (is, "0x%x", lsb);
5f74bc13
CD
1057 break;
1058
1059 case 'F':
fc8c4fd1
MR
1060 msb = GET_OP (l, INSMSB) + 32;
1061 infprintf (is, "0x%x", msb - lsb + 1);
5f74bc13
CD
1062 break;
1063
1064 case 'G':
fc8c4fd1
MR
1065 msbd = GET_OP (l, EXTMSBD) + 32;
1066 infprintf (is, "0x%x", msbd + 1);
5f74bc13
CD
1067 break;
1068
61cc0267 1069 case 't': /* Coprocessor 0 reg name */
fc8c4fd1 1070 infprintf (is, "%s", mips_cp0_names[GET_OP (l, RT)]);
61cc0267
CF
1071 break;
1072
1073 case 'T': /* Coprocessor 0 reg name */
1074 {
1075 const struct mips_cp0sel_name *n;
1076 unsigned int cp0reg, sel;
1077
fc8c4fd1
MR
1078 cp0reg = GET_OP (l, RT);
1079 sel = GET_OP (l, SEL);
61cc0267
CF
1080
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
1085 printed. */
1086 n = lookup_mips_cp0sel_name(mips_cp0sel_names,
1087 mips_cp0sel_names_len, cp0reg, sel);
1088 if (n != NULL)
fc8c4fd1 1089 infprintf (is, "%s", n->name);
61cc0267 1090 else
fc8c4fd1 1091 infprintf (is, "$%d,%d", cp0reg, sel);
61cc0267
CF
1092 break;
1093 }
1094
bb35fb24 1095 case 'x': /* bbit bit index */
fc8c4fd1 1096 infprintf (is, "0x%x", GET_OP (l, BBITIND));
bb35fb24
NC
1097 break;
1098
1099 case 'p': /* cins, cins32, exts and exts32 position */
fc8c4fd1 1100 infprintf (is, "0x%x", GET_OP (l, CINSPOS));
bb35fb24
NC
1101 break;
1102
1103 case 's': /* cins and exts length-minus-one */
fc8c4fd1 1104 infprintf (is, "0x%x", GET_OP (l, CINSLM1));
bb35fb24
NC
1105 break;
1106
1107 case 'S': /* cins32 and exts32 length-minus-one field */
fc8c4fd1 1108 infprintf (is, "0x%x", GET_OP (l, CINSLM1));
bb35fb24
NC
1109 break;
1110
dd3cbb7e 1111 case 'Q': /* seqi/snei immediate field */
fc8c4fd1 1112 infprintf (is, "%d", GET_OP_S (l, SEQI));
dd3cbb7e
NC
1113 break;
1114
98675402 1115 case 'a': /* 8-bit signed offset in bit 6 */
fc8c4fd1 1116 infprintf (is, "%d", GET_OP_S (l, OFFSET_A));
98675402
RS
1117 break;
1118
1119 case 'b': /* 8-bit signed offset in bit 3 */
fc8c4fd1 1120 infprintf (is, "%d", GET_OP_S (l, OFFSET_B));
98675402
RS
1121 break;
1122
1123 case 'c': /* 9-bit signed offset in bit 6 */
c95354ed 1124 /* Left shift 4 bits to print the real offset. */
fc8c4fd1 1125 infprintf (is, "%d", GET_OP_S (l, OFFSET_C) << 4);
98675402
RS
1126 break;
1127
1128 case 'z':
fc8c4fd1 1129 infprintf (is, "%s", mips_gpr_names[GET_OP (l, RZ)]);
98675402
RS
1130 break;
1131
1132 case 'Z':
fc8c4fd1 1133 infprintf (is, "%s", mips_fpr_names[GET_OP (l, FZ)]);
98675402
RS
1134 break;
1135
794ac9d0
CD
1136 default:
1137 /* xgettext:c-format */
fc8c4fd1
MR
1138 infprintf (is,
1139 _("# internal error, "
1140 "undefined extension sequence (+%c)"),
1141 *d);
794ac9d0
CD
1142 return;
1143 }
1144 break;
1145
8b082fb1 1146 case '2':
fc8c4fd1 1147 infprintf (is, "0x%x", GET_OP (l, BP));
8b082fb1
TS
1148 break;
1149
fd25c5a9 1150 case '3':
fc8c4fd1 1151 infprintf (is, "0x%x", GET_OP (l, SA3));
fd25c5a9
CF
1152 break;
1153
1154 case '4':
fc8c4fd1 1155 infprintf (is, "0x%x", GET_OP (l, SA4));
fd25c5a9
CF
1156 break;
1157
1158 case '5':
fc8c4fd1 1159 infprintf (is, "0x%x", GET_OP (l, IMM8));
fd25c5a9
CF
1160 break;
1161
1162 case '6':
fc8c4fd1 1163 infprintf (is, "0x%x", GET_OP (l, RS));
fd25c5a9
CF
1164 break;
1165
1166 case '7':
fc8c4fd1 1167 infprintf (is, "$ac%d", GET_OP (l, DSPACC));
fd25c5a9
CF
1168 break;
1169
1170 case '8':
fc8c4fd1 1171 infprintf (is, "0x%x", GET_OP (l, WRDSP));
fd25c5a9
CF
1172 break;
1173
1174 case '9':
fc8c4fd1 1175 infprintf (is, "$ac%d", GET_OP (l, DSPACC_S));
fd25c5a9
CF
1176 break;
1177
1178 case '0': /* dsp 6-bit signed immediate in bit 20 */
fc8c4fd1 1179 infprintf (is, "%d", GET_OP_S (l, DSPSFT));
fd25c5a9
CF
1180 break;
1181
1182 case ':': /* dsp 7-bit signed immediate in bit 19 */
fc8c4fd1 1183 infprintf (is, "%d", GET_OP_S (l, DSPSFT_7));
fd25c5a9
CF
1184 break;
1185
dec0624d 1186 case '~':
fc8c4fd1 1187 infprintf (is, "%d", GET_OP_S (l, OFFSET12));
dec0624d
MR
1188 break;
1189
1190 case '\\':
fc8c4fd1 1191 infprintf (is, "0x%x", GET_OP (l, 3BITPOS));
dec0624d
MR
1192 break;
1193
fd25c5a9 1194 case '\'':
fc8c4fd1 1195 infprintf (is, "0x%x", GET_OP (l, RDDSP));
fd25c5a9
CF
1196 break;
1197
1198 case '@': /* dsp 10-bit signed immediate in bit 16 */
fc8c4fd1 1199 infprintf (is, "%d", GET_OP_S (l, IMM10));
fd25c5a9
CF
1200 break;
1201
61cc0267 1202 case '!':
fc8c4fd1 1203 infprintf (is, "%d", GET_OP (l, MT_U));
61cc0267
CF
1204 break;
1205
1206 case '$':
fc8c4fd1 1207 infprintf (is, "%d", GET_OP (l, MT_H));
61cc0267
CF
1208 break;
1209
1210 case '*':
fc8c4fd1 1211 infprintf (is, "$ac%d", GET_OP (l, MTACC_T));
61cc0267
CF
1212 break;
1213
1214 case '&':
fc8c4fd1 1215 infprintf (is, "$ac%d", GET_OP (l, MTACC_D));
61cc0267
CF
1216 break;
1217
1218 case 'g':
1219 /* Coprocessor register for CTTC1, MTTC2, MTHC2, CTTC2. */
fc8c4fd1 1220 infprintf (is, "$%d", GET_OP (l, RD));
61cc0267
CF
1221 break;
1222
794ac9d0
CD
1223 case 's':
1224 case 'b':
1225 case 'r':
1226 case 'v':
fc8c4fd1 1227 infprintf (is, "%s", mips_gpr_names[GET_OP (l, RS)]);
794ac9d0
CD
1228 break;
1229
1230 case 't':
1231 case 'w':
fc8c4fd1 1232 infprintf (is, "%s", mips_gpr_names[GET_OP (l, RT)]);
794ac9d0
CD
1233 break;
1234
1235 case 'i':
1236 case 'u':
fc8c4fd1 1237 infprintf (is, "0x%x", GET_OP (l, IMMEDIATE));
794ac9d0
CD
1238 break;
1239
1240 case 'j': /* Same as i, but sign-extended. */
1241 case 'o':
fc8c4fd1 1242 infprintf (is, "%d", GET_OP_S (l, DELTA));
794ac9d0
CD
1243 break;
1244
1245 case 'h':
fc8c4fd1 1246 infprintf (is, "0x%x", GET_OP (l, PREFX));
794ac9d0
CD
1247 break;
1248
1249 case 'k':
fc8c4fd1 1250 infprintf (is, "0x%x", GET_OP (l, CACHE));
794ac9d0
CD
1251 break;
1252
1253 case 'a':
1254 info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
fc8c4fd1 1255 | (GET_OP (l, TARGET) << 2));
022fac6d
TS
1256 /* For gdb disassembler, force odd address on jalx. */
1257 if (info->flavour == bfd_target_unknown_flavour
1258 && strcmp (opp->name, "jalx") == 0)
1259 info->target |= 1;
794ac9d0
CD
1260 (*info->print_address_func) (info->target, info);
1261 break;
1262
1263 case 'p':
1264 /* Sign extend the displacement. */
fc8c4fd1 1265 info->target = (GET_OP_S (l, DELTA) << 2) + pc + INSNLEN;
794ac9d0
CD
1266 (*info->print_address_func) (info->target, info);
1267 break;
1268
1269 case 'd':
fc8c4fd1 1270 infprintf (is, "%s", mips_gpr_names[GET_OP (l, RD)]);
794ac9d0
CD
1271 break;
1272
1273 case 'U':
1274 {
1275 /* First check for both rd and rt being equal. */
314d60dd
ME
1276 unsigned int reg;
1277
1278 reg = GET_OP (l, RD);
fc8c4fd1
MR
1279 if (reg == GET_OP (l, RT))
1280 infprintf (is, "%s", mips_gpr_names[reg]);
794ac9d0
CD
1281 else
1282 {
1283 /* If one is zero use the other. */
1284 if (reg == 0)
fc8c4fd1
MR
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]);
794ac9d0 1288 else /* Bogus, result depends on processor. */
fc8c4fd1
MR
1289 infprintf (is, "%s or %s",
1290 mips_gpr_names[reg],
1291 mips_gpr_names[GET_OP (l, RT)]);
794ac9d0
CD
1292 }
1293 }
1294 break;
1295
1296 case 'z':
fc8c4fd1 1297 infprintf (is, "%s", mips_gpr_names[0]);
794ac9d0
CD
1298 break;
1299
1300 case '<':
4dc48ef6 1301 case '1':
fc8c4fd1 1302 infprintf (is, "0x%x", GET_OP (l, SHAMT));
af7ee8bf 1303 break;
794ac9d0
CD
1304
1305 case 'c':
fc8c4fd1 1306 infprintf (is, "0x%x", GET_OP (l, CODE));
794ac9d0
CD
1307 break;
1308
1309 case 'q':
fc8c4fd1 1310 infprintf (is, "0x%x", GET_OP (l, CODE2));
af7ee8bf
CD
1311 break;
1312
1313 case 'C':
fc8c4fd1 1314 infprintf (is, "0x%x", GET_OP (l, COPZ));
794ac9d0
CD
1315 break;
1316
1317 case 'B':
fc8c4fd1 1318 infprintf (is, "0x%x", GET_OP (l, CODE20));
794ac9d0
CD
1319 break;
1320
1321 case 'J':
fc8c4fd1 1322 infprintf (is, "0x%x", GET_OP (l, CODE19));
794ac9d0
CD
1323 break;
1324
1325 case 'S':
1326 case 'V':
fc8c4fd1 1327 infprintf (is, "%s", mips_fpr_names[GET_OP (l, FS)]);
794ac9d0
CD
1328 break;
1329
1330 case 'T':
1331 case 'W':
fc8c4fd1 1332 infprintf (is, "%s", mips_fpr_names[GET_OP (l, FT)]);
af7ee8bf
CD
1333 break;
1334
bbcc0807 1335 case 'D':
fc8c4fd1 1336 infprintf (is, "%s", mips_fpr_names[GET_OP (l, FD)]);
794ac9d0
CD
1337 break;
1338
1339 case 'R':
fc8c4fd1 1340 infprintf (is, "%s", mips_fpr_names[GET_OP (l, FR)]);
794ac9d0
CD
1341 break;
1342
1343 case 'E':
1344 /* Coprocessor register for lwcN instructions, et al.
1345
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
1350 numbers. */
fc8c4fd1 1351 infprintf (is, "$%d", GET_OP (l, RT));
794ac9d0
CD
1352 break;
1353
1354 case 'G':
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,
1358 cp2, and cp3. */
fc8c4fd1 1359 op = GET_OP (l, OP);
794ac9d0 1360 if (op == OP_OP_COP0)
fc8c4fd1 1361 infprintf (is, "%s", mips_cp0_names[GET_OP (l, RD)]);
794ac9d0 1362 else
fc8c4fd1 1363 infprintf (is, "$%d", GET_OP (l, RD));
794ac9d0
CD
1364 break;
1365
1366 case 'K':
fc8c4fd1 1367 infprintf (is, "%s", mips_hwr_names[GET_OP (l, RD)]);
794ac9d0
CD
1368 break;
1369
1370 case 'N':
fc8c4fd1
MR
1371 infprintf (is,
1372 (opp->pinfo & (FP_D | FP_S)) != 0 ? "$fcc%d" : "$cc%d",
1373 GET_OP (l, BCC));
794ac9d0
CD
1374 break;
1375
1376 case 'M':
fc8c4fd1 1377 infprintf (is, "$fcc%d", GET_OP (l, CCC));
794ac9d0
CD
1378 break;
1379
1380 case 'P':
fc8c4fd1 1381 infprintf (is, "%d", GET_OP (l, PERFREG));
794ac9d0
CD
1382 break;
1383
1384 case 'e':
fc8c4fd1 1385 infprintf (is, "%d", GET_OP (l, VECBYTE));
794ac9d0
CD
1386 break;
1387
1388 case '%':
fc8c4fd1 1389 infprintf (is, "%d", GET_OP (l, VECALIGN));
794ac9d0
CD
1390 break;
1391
1392 case 'H':
fc8c4fd1 1393 infprintf (is, "%d", GET_OP (l, SEL));
794ac9d0
CD
1394 break;
1395
1396 case 'O':
fc8c4fd1 1397 infprintf (is, "%d", GET_OP (l, ALN));
794ac9d0
CD
1398 break;
1399
1400 case 'Q':
bbcc0807 1401 {
fc8c4fd1 1402 unsigned int vsel = GET_OP (l, VSEL);
47b0e7ad 1403
794ac9d0
CD
1404 if ((vsel & 0x10) == 0)
1405 {
1406 int fmt;
47b0e7ad 1407
794ac9d0
CD
1408 vsel &= 0x0f;
1409 for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
1410 if ((vsel & 1) == 0)
1411 break;
fc8c4fd1 1412 infprintf (is, "$v%d[%d]", GET_OP (l, FT), vsel >> 1);
794ac9d0
CD
1413 }
1414 else if ((vsel & 0x08) == 0)
1415 {
fc8c4fd1 1416 infprintf (is, "$v%d", GET_OP (l, FT));
794ac9d0 1417 }
bbcc0807 1418 else
794ac9d0 1419 {
fc8c4fd1 1420 infprintf (is, "0x%x", GET_OP (l, FT));
794ac9d0 1421 }
bbcc0807 1422 }
794ac9d0
CD
1423 break;
1424
1425 case 'X':
fc8c4fd1 1426 infprintf (is, "$v%d", GET_OP (l, FD));
794ac9d0
CD
1427 break;
1428
1429 case 'Y':
fc8c4fd1 1430 infprintf (is, "$v%d", GET_OP (l, FS));
794ac9d0
CD
1431 break;
1432
1433 case 'Z':
fc8c4fd1 1434 infprintf (is, "$v%d", GET_OP (l, FT));
794ac9d0 1435 break;
bbcc0807 1436
af7ee8bf
CD
1437 default:
1438 /* xgettext:c-format */
fc8c4fd1 1439 infprintf (is, _("# internal error, undefined modifier (%c)"), *d);
794ac9d0 1440 return;
af7ee8bf 1441 }
252b5132
RH
1442 }
1443}
1444\f
252b5132
RH
1445/* Print the mips instruction at address MEMADDR in debugged memory,
1446 on using INFO. Returns length of the instruction, in bytes, which is
aa5f19f2 1447 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
252b5132
RH
1448 this is little-endian code. */
1449
1450static int
47b0e7ad 1451print_insn_mips (bfd_vma memaddr,
fc8c4fd1 1452 int word,
47b0e7ad 1453 struct disassemble_info *info)
252b5132 1454{
fc8c4fd1
MR
1455 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
1456 const fprintf_ftype infprintf = info->fprintf_func;
47b0e7ad 1457 const struct mips_opcode *op;
b34976b6 1458 static bfd_boolean init = 0;
fc8c4fd1 1459 void *is = info->stream;
252b5132
RH
1460
1461 /* Build a hash table to shorten the search time. */
1462 if (! init)
1463 {
1464 unsigned int i;
1465
1466 for (i = 0; i <= OP_MASK_OP; i++)
1467 {
1468 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
1469 {
986e18a5 1470 if (op->pinfo == INSN_MACRO
9e836e3d 1471 || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
252b5132 1472 continue;
fc8c4fd1 1473 if (i == GET_OP (op->match, OP))
252b5132
RH
1474 {
1475 mips_hash[i] = op;
1476 break;
1477 }
1478 }
7f6621cd 1479 }
252b5132
RH
1480
1481 init = 1;
1482 }
1483
aa5f19f2 1484 info->bytes_per_chunk = INSNLEN;
252b5132 1485 info->display_endian = info->endian;
9bb28706
CD
1486 info->insn_info_valid = 1;
1487 info->branch_delay_insns = 0;
def7143b 1488 info->data_size = 0;
9bb28706
CD
1489 info->insn_type = dis_nonbranch;
1490 info->target = 0;
1491 info->target2 = 0;
252b5132 1492
fc8c4fd1 1493 op = mips_hash[GET_OP (word, OP)];
252b5132
RH
1494 if (op != NULL)
1495 {
1496 for (; op < &mips_opcodes[NUMOPCODES]; op++)
1497 {
986e18a5 1498 if (op->pinfo != INSN_MACRO
9e836e3d 1499 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
986e18a5 1500 && (word & op->mask) == op->match)
252b5132 1501 {
47b0e7ad 1502 const char *d;
2bd7f1f3 1503
3396de36 1504 /* We always allow to disassemble the jalx instruction. */
35d0a169 1505 if (!opcode_is_member (op, mips_isa, mips_processor)
3396de36 1506 && strcmp (op->name, "jalx"))
252b5132
RH
1507 continue;
1508
9bb28706
CD
1509 /* Figure out instruction type and branch delay information. */
1510 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
1511 {
c680e7f6
MR
1512 if ((op->pinfo & (INSN_WRITE_GPR_31
1513 | INSN_WRITE_GPR_D)) != 0)
9bb28706
CD
1514 info->insn_type = dis_jsr;
1515 else
1516 info->insn_type = dis_branch;
1517 info->branch_delay_insns = 1;
1518 }
1519 else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
1520 | INSN_COND_BRANCH_LIKELY)) != 0)
1521 {
c680e7f6 1522 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
9bb28706
CD
1523 info->insn_type = dis_condjsr;
1524 else
1525 info->insn_type = dis_condbranch;
1526 info->branch_delay_insns = 1;
1527 }
1528 else if ((op->pinfo & (INSN_STORE_MEMORY
1529 | INSN_LOAD_MEMORY_DELAY)) != 0)
1530 info->insn_type = dis_dref;
1531
fc8c4fd1 1532 infprintf (is, "%s", op->name);
252b5132
RH
1533
1534 d = op->args;
1535 if (d != NULL && *d != '\0')
1536 {
fc8c4fd1 1537 infprintf (is, "\t");
cc0ca239 1538 print_insn_args (d, word, memaddr, info, op);
252b5132
RH
1539 }
1540
aa5f19f2 1541 return INSNLEN;
252b5132
RH
1542 }
1543 }
1544 }
fc8c4fd1
MR
1545#undef GET_OP_S
1546#undef GET_OP
252b5132
RH
1547
1548 /* Handle undefined instructions. */
9bb28706 1549 info->insn_type = dis_noninsn;
fc8c4fd1 1550 infprintf (is, "0x%x", word);
aa5f19f2 1551 return INSNLEN;
252b5132 1552}
aa5f19f2 1553\f
252b5132
RH
1554/* Disassemble an operand for a mips16 instruction. */
1555
1556static void
47b0e7ad
NC
1557print_mips16_insn_arg (char type,
1558 const struct mips_opcode *op,
1559 int l,
1560 bfd_boolean use_extend,
1561 int extend,
1562 bfd_vma memaddr,
1563 struct disassemble_info *info)
252b5132 1564{
fc8c4fd1
MR
1565 const fprintf_ftype infprintf = info->fprintf_func;
1566 void *is = info->stream;
1567
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))
252b5132
RH
1573 switch (type)
1574 {
1575 case ',':
1576 case '(':
1577 case ')':
fc8c4fd1 1578 infprintf (is, "%c", type);
252b5132
RH
1579 break;
1580
1581 case 'y':
1582 case 'w':
fc8c4fd1 1583 infprintf (is, "%s", mips16_reg_names (GET_OP (l, RY)));
252b5132
RH
1584 break;
1585
1586 case 'x':
1587 case 'v':
fc8c4fd1 1588 infprintf (is, "%s", mips16_reg_names (GET_OP (l, RX)));
252b5132
RH
1589 break;
1590
1591 case 'z':
fc8c4fd1 1592 infprintf (is, "%s", mips16_reg_names (GET_OP (l, RZ)));
252b5132
RH
1593 break;
1594
1595 case 'Z':
fc8c4fd1 1596 infprintf (is, "%s", mips16_reg_names (GET_OP (l, MOVE32Z)));
252b5132
RH
1597 break;
1598
1599 case '0':
fc8c4fd1 1600 infprintf (is, "%s", mips_gpr_names[0]);
252b5132
RH
1601 break;
1602
1603 case 'S':
fc8c4fd1 1604 infprintf (is, "%s", mips_gpr_names[29]);
252b5132
RH
1605 break;
1606
1607 case 'P':
fc8c4fd1 1608 infprintf (is, "$pc");
252b5132
RH
1609 break;
1610
1611 case 'R':
fc8c4fd1 1612 infprintf (is, "%s", mips_gpr_names[31]);
252b5132
RH
1613 break;
1614
1615 case 'X':
fc8c4fd1 1616 infprintf (is, "%s", mips_gpr_names[GET_OP (l, REGR32)]);
252b5132
RH
1617 break;
1618
1619 case 'Y':
fc8c4fd1 1620 infprintf (is, "%s", mips_gpr_names[MIPS16OP_EXTRACT_REG32R (l)]);
252b5132
RH
1621 break;
1622
1623 case '<':
1624 case '>':
1625 case '[':
1626 case ']':
1627 case '4':
1628 case '5':
1629 case 'H':
1630 case 'W':
1631 case 'D':
1632 case 'j':
1633 case '6':
1634 case '8':
1635 case 'V':
1636 case 'C':
1637 case 'U':
1638 case 'k':
1639 case 'K':
1640 case 'p':
1641 case 'q':
1642 case 'A':
1643 case 'B':
1644 case 'E':
1645 {
1646 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
1647
1648 shift = 0;
1649 signedp = 0;
1650 extbits = 16;
1651 pcrel = 0;
1652 extu = 0;
1653 branch = 0;
1654 switch (type)
1655 {
1656 case '<':
1657 nbits = 3;
fc8c4fd1 1658 immed = GET_OP (l, RZ);
252b5132
RH
1659 extbits = 5;
1660 extu = 1;
1661 break;
1662 case '>':
1663 nbits = 3;
fc8c4fd1 1664 immed = GET_OP (l, RX);
252b5132
RH
1665 extbits = 5;
1666 extu = 1;
1667 break;
1668 case '[':
1669 nbits = 3;
fc8c4fd1 1670 immed = GET_OP (l, RZ);
252b5132
RH
1671 extbits = 6;
1672 extu = 1;
1673 break;
1674 case ']':
1675 nbits = 3;
fc8c4fd1 1676 immed = GET_OP (l, RX);
252b5132
RH
1677 extbits = 6;
1678 extu = 1;
1679 break;
1680 case '4':
1681 nbits = 4;
fc8c4fd1 1682 immed = GET_OP (l, IMM4);
252b5132
RH
1683 signedp = 1;
1684 extbits = 15;
1685 break;
1686 case '5':
1687 nbits = 5;
fc8c4fd1 1688 immed = GET_OP (l, IMM5);
252b5132
RH
1689 info->insn_type = dis_dref;
1690 info->data_size = 1;
1691 break;
1692 case 'H':
1693 nbits = 5;
1694 shift = 1;
fc8c4fd1 1695 immed = GET_OP (l, IMM5);
252b5132
RH
1696 info->insn_type = dis_dref;
1697 info->data_size = 2;
1698 break;
1699 case 'W':
1700 nbits = 5;
1701 shift = 2;
fc8c4fd1 1702 immed = GET_OP (l, IMM5);
252b5132
RH
1703 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
1704 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
1705 {
1706 info->insn_type = dis_dref;
1707 info->data_size = 4;
1708 }
1709 break;
1710 case 'D':
1711 nbits = 5;
1712 shift = 3;
fc8c4fd1 1713 immed = GET_OP (l, IMM5);
252b5132
RH
1714 info->insn_type = dis_dref;
1715 info->data_size = 8;
1716 break;
1717 case 'j':
1718 nbits = 5;
fc8c4fd1 1719 immed = GET_OP (l, IMM5);
252b5132
RH
1720 signedp = 1;
1721 break;
1722 case '6':
1723 nbits = 6;
fc8c4fd1 1724 immed = GET_OP (l, IMM6);
252b5132
RH
1725 break;
1726 case '8':
1727 nbits = 8;
fc8c4fd1 1728 immed = GET_OP (l, IMM8);
252b5132
RH
1729 break;
1730 case 'V':
1731 nbits = 8;
1732 shift = 2;
fc8c4fd1 1733 immed = GET_OP (l, IMM8);
252b5132
RH
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;
1738 break;
1739 case 'C':
1740 nbits = 8;
1741 shift = 3;
fc8c4fd1 1742 immed = GET_OP (l, IMM8);
252b5132
RH
1743 info->insn_type = dis_dref;
1744 info->data_size = 8;
1745 break;
1746 case 'U':
1747 nbits = 8;
fc8c4fd1 1748 immed = GET_OP (l, IMM8);
252b5132
RH
1749 extu = 1;
1750 break;
1751 case 'k':
1752 nbits = 8;
fc8c4fd1 1753 immed = GET_OP (l, IMM8);
252b5132
RH
1754 signedp = 1;
1755 break;
1756 case 'K':
1757 nbits = 8;
1758 shift = 3;
fc8c4fd1 1759 immed = GET_OP (l, IMM8);
252b5132
RH
1760 signedp = 1;
1761 break;
1762 case 'p':
1763 nbits = 8;
fc8c4fd1 1764 immed = GET_OP (l, IMM8);
252b5132
RH
1765 signedp = 1;
1766 pcrel = 1;
1767 branch = 1;
252b5132
RH
1768 break;
1769 case 'q':
1770 nbits = 11;
fc8c4fd1 1771 immed = GET_OP (l, IMM11);
252b5132
RH
1772 signedp = 1;
1773 pcrel = 1;
1774 branch = 1;
252b5132
RH
1775 break;
1776 case 'A':
1777 nbits = 8;
1778 shift = 2;
fc8c4fd1 1779 immed = GET_OP (l, IMM8);
252b5132
RH
1780 pcrel = 1;
1781 /* FIXME: This can be lw or la. We assume it is lw. */
1782 info->insn_type = dis_dref;
1783 info->data_size = 4;
1784 break;
1785 case 'B':
1786 nbits = 5;
1787 shift = 3;
fc8c4fd1 1788 immed = GET_OP (l, IMM5);
252b5132
RH
1789 pcrel = 1;
1790 info->insn_type = dis_dref;
1791 info->data_size = 8;
1792 break;
1793 case 'E':
1794 nbits = 5;
1795 shift = 2;
fc8c4fd1 1796 immed = GET_OP (l, IMM5);
252b5132
RH
1797 pcrel = 1;
1798 break;
1799 default:
1800 abort ();
1801 }
1802
1803 if (! use_extend)
1804 {
1805 if (signedp && immed >= (1 << (nbits - 1)))
1806 immed -= 1 << nbits;
1807 immed <<= shift;
1808 if ((type == '<' || type == '>' || type == '[' || type == ']')
1809 && immed == 0)
1810 immed = 8;
1811 }
1812 else
1813 {
1814 if (extbits == 16)
1815 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1816 else if (extbits == 15)
1817 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1818 else
1819 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1820 immed &= (1 << extbits) - 1;
1821 if (! extu && immed >= (1 << (extbits - 1)))
1822 immed -= 1 << extbits;
1823 }
1824
1825 if (! pcrel)
fc8c4fd1 1826 infprintf (is, "%d", immed);
252b5132
RH
1827 else
1828 {
1829 bfd_vma baseaddr;
252b5132
RH
1830
1831 if (branch)
1832 {
1833 immed *= 2;
1834 baseaddr = memaddr + 2;
1835 }
1836 else if (use_extend)
1837 baseaddr = memaddr - 2;
1838 else
1839 {
1840 int status;
1841 bfd_byte buffer[2];
1842
1843 baseaddr = memaddr;
1844
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,
1853 info);
1854 if (status == 0
1855 && (((info->endian == BFD_ENDIAN_BIG
1856 ? bfd_getb16 (buffer)
1857 : bfd_getl16 (buffer))
1858 & 0xf800) == 0x1800))
1859 baseaddr = memaddr - 4;
1860 else
1861 {
1862 status = (*info->read_memory_func) (memaddr - 2, buffer,
1863 2, info);
1864 if (status == 0
1865 && (((info->endian == BFD_ENDIAN_BIG
1866 ? bfd_getb16 (buffer)
1867 : bfd_getl16 (buffer))
1868 & 0xf81f) == 0xe800))
1869 baseaddr = memaddr - 2;
1870 }
1871 }
9bb28706 1872 info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
022fac6d
TS
1873 if (pcrel && branch
1874 && info->flavour == bfd_target_unknown_flavour)
1875 /* For gdb disassembler, maintain odd address. */
1876 info->target |= 1;
9bb28706 1877 (*info->print_address_func) (info->target, info);
252b5132
RH
1878 }
1879 }
1880 break;
1881
1882 case 'a':
022fac6d
TS
1883 {
1884 int jalx = l & 0x400;
1885
1886 if (! use_extend)
1887 extend = 0;
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. */
1891 l |= 1;
1892 }
9bb28706
CD
1893 info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
1894 (*info->print_address_func) (info->target, info);
252b5132
RH
1895 break;
1896
1897 case 'l':
1898 case 'L':
1899 {
1900 int need_comma, amask, smask;
1901
1902 need_comma = 0;
1903
fc8c4fd1 1904 l = GET_OP (l, IMM6);
252b5132
RH
1905
1906 amask = (l >> 3) & 7;
1907
1908 if (amask > 0 && amask < 5)
1909 {
fc8c4fd1 1910 infprintf (is, "%s", mips_gpr_names[4]);
252b5132 1911 if (amask > 1)
fc8c4fd1 1912 infprintf (is, "-%s", mips_gpr_names[amask + 3]);
252b5132
RH
1913 need_comma = 1;
1914 }
1915
1916 smask = (l >> 1) & 3;
1917 if (smask == 3)
1918 {
fc8c4fd1 1919 infprintf (is, "%s??", need_comma ? "," : "");
252b5132
RH
1920 need_comma = 1;
1921 }
1922 else if (smask > 0)
1923 {
fc8c4fd1 1924 infprintf (is, "%s%s", need_comma ? "," : "", mips_gpr_names[16]);
252b5132 1925 if (smask > 1)
fc8c4fd1 1926 infprintf (is, "-%s", mips_gpr_names[smask + 15]);
252b5132
RH
1927 need_comma = 1;
1928 }
1929
1930 if (l & 1)
1931 {
fc8c4fd1 1932 infprintf (is, "%s%s", need_comma ? "," : "", mips_gpr_names[31]);
252b5132
RH
1933 need_comma = 1;
1934 }
1935
1936 if (amask == 5 || amask == 6)
1937 {
fc8c4fd1 1938 infprintf (is, "%s$f0", need_comma ? "," : "");
252b5132 1939 if (amask == 6)
fc8c4fd1 1940 infprintf (is, "-$f1");
252b5132
RH
1941 }
1942 }
1943 break;
1944
0499d65b
TS
1945 case 'm':
1946 case 'M':
1947 /* MIPS16e save/restore. */
1948 {
1949 int need_comma = 0;
1950 int amask, args, statics;
1951 int nsreg, smask;
1952 int framesz;
1953 int i, j;
1954
1955 l = l & 0x7f;
1956 if (use_extend)
1957 l |= extend << 16;
1958
1959 amask = (l >> 16) & 0xf;
1960 if (amask == MIPS16_ALL_ARGS)
1961 {
1962 args = 4;
1963 statics = 0;
1964 }
1965 else if (amask == MIPS16_ALL_STATICS)
1966 {
1967 args = 0;
1968 statics = 4;
1969 }
1970 else
1971 {
1972 args = amask >> 2;
1973 statics = amask & 3;
1974 }
1975
1976 if (args > 0) {
fc8c4fd1 1977 infprintf (is, "%s", mips_gpr_names[4]);
0499d65b 1978 if (args > 1)
fc8c4fd1 1979 infprintf (is, "-%s", mips_gpr_names[4 + args - 1]);
0499d65b
TS
1980 need_comma = 1;
1981 }
1982
1983 framesz = (((l >> 16) & 0xf0) | (l & 0x0f)) * 8;
1984 if (framesz == 0 && !use_extend)
1985 framesz = 128;
1986
fc8c4fd1 1987 infprintf (is, "%s%d", need_comma ? "," : "", framesz);
0499d65b
TS
1988
1989 if (l & 0x40) /* $ra */
fc8c4fd1 1990 infprintf (is, ",%s", mips_gpr_names[31]);
0499d65b
TS
1991
1992 nsreg = (l >> 24) & 0x7;
1993 smask = 0;
1994 if (l & 0x20) /* $s0 */
1995 smask |= 1 << 0;
1996 if (l & 0x10) /* $s1 */
1997 smask |= 1 << 1;
1998 if (nsreg > 0) /* $s2-$s8 */
1999 smask |= ((1 << nsreg) - 1) << 2;
2000
2001 /* Find first set static reg bit. */
2002 for (i = 0; i < 9; i++)
2003 {
2004 if (smask & (1 << i))
2005 {
fc8c4fd1 2006 infprintf (is, ",%s", mips_gpr_names[i == 8 ? 30 : (16 + i)]);
0499d65b
TS
2007 /* Skip over string of set bits. */
2008 for (j = i; smask & (2 << j); j++)
2009 continue;
2010 if (j > i)
fc8c4fd1 2011 infprintf (is, "-%s", mips_gpr_names[j == 8 ? 30 : (16 + j)]);
0499d65b
TS
2012 i = j + 1;
2013 }
2014 }
2015
2016 /* Statics $ax - $a3. */
2017 if (statics == 1)
fc8c4fd1 2018 infprintf (is, ",%s", mips_gpr_names[7]);
0499d65b 2019 else if (statics > 0)
fc8c4fd1
MR
2020 infprintf (is, ",%s-%s",
2021 mips_gpr_names[7 - statics + 1],
2022 mips_gpr_names[7]);
0499d65b
TS
2023 }
2024 break;
2025
252b5132 2026 default:
aa5f19f2 2027 /* xgettext:c-format */
fc8c4fd1
MR
2028 infprintf (is,
2029 _("# internal disassembler error, "
2030 "unrecognised modifier (%c)"),
2031 type);
252b5132
RH
2032 abort ();
2033 }
2034}
640c0ccd 2035
47b0e7ad
NC
2036/* Disassemble mips16 instructions. */
2037
2038static int
2039print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
2040{
fc8c4fd1 2041 const fprintf_ftype infprintf = info->fprintf_func;
47b0e7ad
NC
2042 int status;
2043 bfd_byte buffer[2];
2044 int length;
2045 int insn;
2046 bfd_boolean use_extend;
2047 int extend = 0;
2048 const struct mips_opcode *op, *opend;
fc8c4fd1 2049 void *is = info->stream;
47b0e7ad
NC
2050
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;
2057 info->target = 0;
2058 info->target2 = 0;
2059
2060 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2061 if (status != 0)
2062 {
2063 (*info->memory_error_func) (status, memaddr, info);
2064 return -1;
2065 }
2066
2067 length = 2;
2068
2069 if (info->endian == BFD_ENDIAN_BIG)
2070 insn = bfd_getb16 (buffer);
2071 else
2072 insn = bfd_getl16 (buffer);
2073
2074 /* Handle the extend opcode specially. */
2075 use_extend = FALSE;
2076 if ((insn & 0xf800) == 0xf000)
2077 {
2078 use_extend = TRUE;
2079 extend = insn & 0x7ff;
2080
2081 memaddr += 2;
2082
2083 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2084 if (status != 0)
2085 {
fc8c4fd1 2086 infprintf (is, "extend 0x%x", (unsigned int) extend);
47b0e7ad
NC
2087 (*info->memory_error_func) (status, memaddr, info);
2088 return -1;
2089 }
2090
2091 if (info->endian == BFD_ENDIAN_BIG)
2092 insn = bfd_getb16 (buffer);
2093 else
2094 insn = bfd_getl16 (buffer);
2095
2096 /* Check for an extend opcode followed by an extend opcode. */
2097 if ((insn & 0xf800) == 0xf000)
2098 {
fc8c4fd1 2099 infprintf (is, "extend 0x%x", (unsigned int) extend);
47b0e7ad
NC
2100 info->insn_type = dis_noninsn;
2101 return length;
2102 }
2103
2104 length += 2;
2105 }
2106
2107 /* FIXME: Should probably use a hash table on the major opcode here. */
2108
2109 opend = mips16_opcodes + bfd_mips16_num_opcodes;
2110 for (op = mips16_opcodes; op < opend; op++)
2111 {
2112 if (op->pinfo != INSN_MACRO
2113 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
2114 && (insn & op->mask) == op->match)
2115 {
2116 const char *s;
2117
2118 if (strchr (op->args, 'a') != NULL)
2119 {
2120 if (use_extend)
2121 {
fc8c4fd1 2122 infprintf (is, "extend 0x%x", (unsigned int) extend);
47b0e7ad
NC
2123 info->insn_type = dis_noninsn;
2124 return length - 2;
2125 }
2126
2127 use_extend = FALSE;
2128
2129 memaddr += 2;
2130
2131 status = (*info->read_memory_func) (memaddr, buffer, 2,
2132 info);
2133 if (status == 0)
2134 {
2135 use_extend = TRUE;
2136 if (info->endian == BFD_ENDIAN_BIG)
2137 extend = bfd_getb16 (buffer);
2138 else
2139 extend = bfd_getl16 (buffer);
2140 length += 2;
2141 }
2142 }
2143
fc8c4fd1 2144 infprintf (is, "%s", op->name);
47b0e7ad 2145 if (op->args[0] != '\0')
fc8c4fd1 2146 infprintf (is, "\t");
47b0e7ad
NC
2147
2148 for (s = op->args; *s != '\0'; s++)
2149 {
2150 if (*s == ','
2151 && s[1] == 'w'
fc8c4fd1 2152 && GET_OP (insn, RX) == GET_OP (insn, RY))
47b0e7ad
NC
2153 {
2154 /* Skip the register and the comma. */
2155 ++s;
2156 continue;
2157 }
2158 if (*s == ','
2159 && s[1] == 'v'
fc8c4fd1 2160 && GET_OP (insn, RZ) == GET_OP (insn, RX))
47b0e7ad
NC
2161 {
2162 /* Skip the register and the comma. */
2163 ++s;
2164 continue;
2165 }
2166 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
2167 info);
2168 }
2169
9a2c7088 2170 /* Figure out branch instruction type and delay slot information. */
47b0e7ad 2171 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
9a2c7088
MR
2172 info->branch_delay_insns = 1;
2173 if ((op->pinfo & (INSN_UNCOND_BRANCH_DELAY
2174 | MIPS16_INSN_UNCOND_BRANCH)) != 0)
47b0e7ad 2175 {
9a2c7088
MR
2176 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2177 info->insn_type = dis_jsr;
2178 else
47b0e7ad
NC
2179 info->insn_type = dis_branch;
2180 }
9a2c7088
MR
2181 else if ((op->pinfo & MIPS16_INSN_COND_BRANCH) != 0)
2182 info->insn_type = dis_condbranch;
47b0e7ad
NC
2183
2184 return length;
2185 }
2186 }
fc8c4fd1
MR
2187#undef GET_OP_S
2188#undef GET_OP
47b0e7ad
NC
2189
2190 if (use_extend)
fc8c4fd1
MR
2191 infprintf (is, "0x%x", extend | 0xf000);
2192 infprintf (is, "0x%x", insn);
47b0e7ad
NC
2193 info->insn_type = dis_noninsn;
2194
2195 return length;
2196}
2197
df58fc94
RS
2198/* Disassemble microMIPS instructions. */
2199
2200static int
2201print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
2202{
0c7533d3 2203 const fprintf_ftype infprintf = info->fprintf_func;
df58fc94
RS
2204 const struct mips_opcode *op, *opend;
2205 unsigned int lsb, msbd, msb;
2206 void *is = info->stream;
2207 unsigned int regno;
2208 bfd_byte buffer[2];
2209 int lastregno = 0;
2210 int higher;
2211 int length;
2212 int status;
2213 int delta;
2214 int immed;
2215 int insn;
2216
2217 lsb = 0;
2218
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;
2225 info->target = 0;
2226 info->target2 = 0;
2227
2228 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2229 if (status != 0)
2230 {
2231 (*info->memory_error_func) (status, memaddr, info);
2232 return -1;
2233 }
2234
2235 length = 2;
2236
2237 if (info->endian == BFD_ENDIAN_BIG)
2238 insn = bfd_getb16 (buffer);
2239 else
2240 insn = bfd_getl16 (buffer);
2241
2242 if ((insn & 0xfc00) == 0x7c00)
2243 {
2244 /* This is a 48-bit microMIPS instruction. */
2245 higher = insn;
2246
2247 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2248 if (status != 0)
2249 {
0c7533d3 2250 infprintf (is, "micromips 0x%x", higher);
df58fc94
RS
2251 (*info->memory_error_func) (status, memaddr + 2, info);
2252 return -1;
2253 }
2254 if (info->endian == BFD_ENDIAN_BIG)
2255 insn = bfd_getb16 (buffer);
2256 else
2257 insn = bfd_getl16 (buffer);
2258 higher = (higher << 16) | insn;
2259
2260 status = (*info->read_memory_func) (memaddr + 4, buffer, 2, info);
2261 if (status != 0)
2262 {
0c7533d3 2263 infprintf (is, "micromips 0x%x", higher);
df58fc94
RS
2264 (*info->memory_error_func) (status, memaddr + 4, info);
2265 return -1;
2266 }
2267 if (info->endian == BFD_ENDIAN_BIG)
2268 insn = bfd_getb16 (buffer);
2269 else
2270 insn = bfd_getl16 (buffer);
0c7533d3 2271 infprintf (is, "0x%x%04x (48-bit insn)", higher, insn);
df58fc94
RS
2272
2273 info->insn_type = dis_noninsn;
2274 return 6;
2275 }
2276 else if ((insn & 0x1c00) == 0x0000 || (insn & 0x1000) == 0x1000)
2277 {
2278 /* This is a 32-bit microMIPS instruction. */
2279 higher = insn;
2280
2281 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2282 if (status != 0)
2283 {
0c7533d3 2284 infprintf (is, "micromips 0x%x", higher);
df58fc94
RS
2285 (*info->memory_error_func) (status, memaddr + 2, info);
2286 return -1;
2287 }
2288
2289 if (info->endian == BFD_ENDIAN_BIG)
2290 insn = bfd_getb16 (buffer);
2291 else
2292 insn = bfd_getl16 (buffer);
2293
2294 insn = insn | (higher << 16);
2295
2296 length += 2;
2297 }
2298
2299 /* FIXME: Should probably use a hash table on the major opcode here. */
2300
2301#define GET_OP(insn, field) \
2302 (((insn) >> MICROMIPSOP_SH_##field) & MICROMIPSOP_MASK_##field)
fc8c4fd1
MR
2303#define GET_OP_S(insn, field) \
2304 ((GET_OP (insn, field) ^ ((MICROMIPSOP_MASK_##field >> 1) + 1)) \
2305 - ((MICROMIPSOP_MASK_##field >> 1) + 1))
df58fc94
RS
2306 opend = micromips_opcodes + bfd_micromips_num_opcodes;
2307 for (op = micromips_opcodes; op < opend; op++)
2308 {
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)))
2314 {
2315 const char *s;
2316
0c7533d3 2317 infprintf (is, "%s", op->name);
df58fc94 2318 if (op->args[0] != '\0')
0c7533d3 2319 infprintf (is, "\t");
df58fc94
RS
2320
2321 for (s = op->args; *s != '\0'; s++)
2322 {
2323 switch (*s)
2324 {
2325 case ',':
2326 case '(':
2327 case ')':
0c7533d3 2328 infprintf (is, "%c", *s);
df58fc94
RS
2329 break;
2330
2331 case '.':
fc8c4fd1 2332 infprintf (is, "%d", GET_OP_S (insn, OFFSET10));
df58fc94
RS
2333 break;
2334
2335 case '1':
d908c8af 2336 infprintf (is, "0x%x", GET_OP (insn, STYPE));
df58fc94
RS
2337 break;
2338
03f66e8a 2339 case '2':
48891606 2340 infprintf (is, "0x%x", GET_OP (insn, BP));
03f66e8a
MR
2341 break;
2342
2343 case '3':
48891606 2344 infprintf (is, "0x%x", GET_OP (insn, SA3));
03f66e8a
MR
2345 break;
2346
2347 case '4':
48891606 2348 infprintf (is, "0x%x", GET_OP (insn, SA4));
03f66e8a
MR
2349 break;
2350
2351 case '5':
48891606 2352 infprintf (is, "0x%x", GET_OP (insn, IMM8));
03f66e8a
MR
2353 break;
2354
2355 case '6':
48891606 2356 infprintf (is, "0x%x", GET_OP (insn, RS));
03f66e8a
MR
2357 break;
2358
2359 case '7':
48891606 2360 infprintf (is, "$ac%d", GET_OP (insn, DSPACC));
03f66e8a
MR
2361 break;
2362
2363 case '8':
48891606 2364 infprintf (is, "0x%x", GET_OP (insn, WRDSP));
03f66e8a
MR
2365 break;
2366
2367 case '0': /* DSP 6-bit signed immediate in bit 16. */
2368 delta = (GET_OP (insn, DSPSFT) ^ 0x20) - 0x20;
2369 infprintf (is, "%d", delta);
2370 break;
2371
df58fc94 2372 case '<':
d908c8af 2373 infprintf (is, "0x%x", GET_OP (insn, SHAMT));
df58fc94
RS
2374 break;
2375
dec0624d 2376 case '\\':
d908c8af 2377 infprintf (is, "0x%x", GET_OP (insn, 3BITPOS));
dec0624d
MR
2378 break;
2379
03f66e8a 2380 case '^':
48891606 2381 infprintf (is, "0x%x", GET_OP (insn, RD));
03f66e8a
MR
2382 break;
2383
df58fc94 2384 case '|':
d908c8af 2385 infprintf (is, "0x%x", GET_OP (insn, TRAP));
df58fc94
RS
2386 break;
2387
2388 case '~':
fc8c4fd1 2389 infprintf (is, "%d", GET_OP_S (insn, OFFSET12));
df58fc94
RS
2390 break;
2391
2392 case 'a':
2393 if (strcmp (op->name, "jalx") == 0)
2394 info->target = (((memaddr + 4) & ~(bfd_vma) 0x0fffffff)
2395 | (GET_OP (insn, TARGET) << 2));
2396 else
2397 info->target = (((memaddr + 4) & ~(bfd_vma) 0x07ffffff)
fc8c4fd1 2398 | (GET_OP (insn, TARGET) << 1));
df58fc94
RS
2399 /* For gdb disassembler, force odd address on jalx. */
2400 if (info->flavour == bfd_target_unknown_flavour
2401 && strcmp (op->name, "jalx") == 0)
2402 info->target |= 1;
2403 (*info->print_address_func) (info->target, info);
2404 break;
2405
2406 case 'b':
2407 case 'r':
2408 case 's':
2409 case 'v':
0c7533d3 2410 infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RS)]);
df58fc94
RS
2411 break;
2412
2413 case 'c':
d908c8af 2414 infprintf (is, "0x%x", GET_OP (insn, CODE));
df58fc94
RS
2415 break;
2416
2417 case 'd':
0c7533d3 2418 infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RD)]);
df58fc94
RS
2419 break;
2420
2421 case 'h':
d908c8af 2422 infprintf (is, "0x%x", GET_OP (insn, PREFX));
df58fc94
RS
2423 break;
2424
2425 case 'i':
2426 case 'u':
d908c8af 2427 infprintf (is, "0x%x", GET_OP (insn, IMMEDIATE));
df58fc94
RS
2428 break;
2429
2430 case 'j': /* Same as i, but sign-extended. */
2431 case 'o':
fc8c4fd1 2432 infprintf (is, "%d", GET_OP_S (insn, DELTA));
df58fc94
RS
2433 break;
2434
2435 case 'k':
0c7533d3 2436 infprintf (is, "0x%x", GET_OP (insn, CACHE));
df58fc94
RS
2437 break;
2438
2439 case 'n':
2440 {
2441 int s_reg_encode;
2442
2443 immed = GET_OP (insn, RT);
2444 s_reg_encode = immed & 0xf;
2445 if (s_reg_encode != 0)
2446 {
2447 if (s_reg_encode == 1)
0c7533d3 2448 infprintf (is, "%s", mips_gpr_names[16]);
df58fc94 2449 else if (s_reg_encode < 9)
0c7533d3 2450 infprintf (is, "%s-%s",
df58fc94
RS
2451 mips_gpr_names[16],
2452 mips_gpr_names[15 + s_reg_encode]);
2453 else if (s_reg_encode == 9)
0c7533d3 2454 infprintf (is, "%s-%s,%s",
df58fc94
RS
2455 mips_gpr_names[16],
2456 mips_gpr_names[23],
2457 mips_gpr_names[30]);
2458 else
0c7533d3 2459 infprintf (is, "UNKNOWN");
df58fc94
RS
2460 }
2461
2462 if (immed & 0x10) /* For ra. */
2463 {
2464 if (s_reg_encode == 0)
0c7533d3 2465 infprintf (is, "%s", mips_gpr_names[31]);
df58fc94 2466 else
0c7533d3 2467 infprintf (is, ",%s", mips_gpr_names[31]);
df58fc94
RS
2468 }
2469 break;
2470 }
2471
2472 case 'p':
2473 /* Sign-extend the displacement. */
fc8c4fd1 2474 delta = GET_OP_S (insn, DELTA);
df58fc94
RS
2475 info->target = (delta << 1) + memaddr + length;
2476 (*info->print_address_func) (info->target, info);
2477 break;
2478
2479 case 'q':
d908c8af 2480 infprintf (is, "0x%x", GET_OP (insn, CODE2));
df58fc94
RS
2481 break;
2482
2483 case 't':
2484 case 'w':
0c7533d3 2485 infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RT)]);
df58fc94
RS
2486 break;
2487
2488 case 'y':
0c7533d3 2489 infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RS3)]);
df58fc94
RS
2490 break;
2491
2492 case 'z':
0c7533d3 2493 infprintf (is, "%s", mips_gpr_names[0]);
df58fc94
RS
2494 break;
2495
03f66e8a
MR
2496 case '@': /* DSP 10-bit signed immediate in bit 16. */
2497 delta = (GET_OP (insn, IMM10) ^ 0x200) - 0x200;
2498 infprintf (is, "%d", delta);
2499 break;
2500
df58fc94 2501 case 'B':
d908c8af 2502 infprintf (is, "0x%x", GET_OP (insn, CODE10));
df58fc94
RS
2503 break;
2504
2505 case 'C':
d908c8af 2506 infprintf (is, "0x%x", GET_OP (insn, COPZ));
df58fc94
RS
2507 break;
2508
2509 case 'D':
0c7533d3 2510 infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FD)]);
df58fc94
RS
2511 break;
2512
2513 case 'E':
2514 /* Coprocessor register for lwcN instructions, et al.
2515
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
2520 numbers. */
d908c8af 2521 infprintf (is, "$%d", GET_OP (insn, RT));
df58fc94
RS
2522 break;
2523
2524 case 'G':
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,
2528 cp2, and cp3.
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. */
2532 switch (insn
2533 & ~((MICROMIPSOP_MASK_RT << MICROMIPSOP_SH_RT)
2534 | (MICROMIPSOP_MASK_RS << MICROMIPSOP_SH_RS)))
2535 {
2536 case 0x000000fc: /* mfc0 */
2537 case 0x000002fc: /* mtc0 */
2538 case 0x580000fc: /* dmfc0 */
2539 case 0x580002fc: /* dmtc0 */
0c7533d3 2540 infprintf (is, "%s", mips_cp0_names[GET_OP (insn, RS)]);
df58fc94
RS
2541 break;
2542 default:
d908c8af 2543 infprintf (is, "$%d", GET_OP (insn, RS));
df58fc94
RS
2544 break;
2545 }
2546 break;
2547
2548 case 'H':
d908c8af 2549 infprintf (is, "%d", GET_OP (insn, SEL));
df58fc94
RS
2550 break;
2551
2552 case 'K':
0c7533d3 2553 infprintf (is, "%s", mips_hwr_names[GET_OP (insn, RS)]);
df58fc94
RS
2554 break;
2555
2556 case 'M':
d908c8af 2557 infprintf (is, "$fcc%d", GET_OP (insn, CCC));
df58fc94
RS
2558 break;
2559
2560 case 'N':
0c7533d3 2561 infprintf (is,
df58fc94 2562 (op->pinfo & (FP_D | FP_S)) != 0
d908c8af 2563 ? "$fcc%d" : "$cc%d",
df58fc94
RS
2564 GET_OP (insn, BCC));
2565 break;
2566
2567 case 'R':
0c7533d3 2568 infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FR)]);
df58fc94
RS
2569 break;
2570
2571 case 'S':
2572 case 'V':
0c7533d3 2573 infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FS)]);
df58fc94
RS
2574 break;
2575
2576 case 'T':
0c7533d3 2577 infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FT)]);
df58fc94
RS
2578 break;
2579
2580 case '+':
2581 /* Extension character; switch for second char. */
2582 s++;
2583 switch (*s)
2584 {
2585 case 'A':
2586 lsb = GET_OP (insn, EXTLSB);
0c7533d3 2587 infprintf (is, "0x%x", lsb);
df58fc94
RS
2588 break;
2589
2590 case 'B':
2591 msb = GET_OP (insn, INSMSB);
0c7533d3 2592 infprintf (is, "0x%x", msb - lsb + 1);
df58fc94
RS
2593 break;
2594
2595 case 'C':
2596 case 'H':
2597 msbd = GET_OP (insn, EXTMSBD);
0c7533d3 2598 infprintf (is, "0x%x", msbd + 1);
df58fc94
RS
2599 break;
2600
2601 case 'D':
2602 {
2603 const struct mips_cp0sel_name *n;
2604 unsigned int cp0reg, sel;
2605
2606 cp0reg = GET_OP (insn, RS);
2607 sel = GET_OP (insn, SEL);
2608
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,
2616 cp0reg, sel);
2617 if (n != NULL)
0c7533d3 2618 infprintf (is, "%s", n->name);
df58fc94 2619 else
0c7533d3 2620 infprintf (is, "$%d,%d", cp0reg, sel);
df58fc94
RS
2621 break;
2622 }
2623
2624 case 'E':
2625 lsb = GET_OP (insn, EXTLSB) + 32;
0c7533d3 2626 infprintf (is, "0x%x", lsb);
df58fc94
RS
2627 break;
2628
2629 case 'F':
2630 msb = GET_OP (insn, INSMSB) + 32;
0c7533d3 2631 infprintf (is, "0x%x", msb - lsb + 1);
df58fc94
RS
2632 break;
2633
2634 case 'G':
2635 msbd = GET_OP (insn, EXTMSBD) + 32;
0c7533d3 2636 infprintf (is, "0x%x", msbd + 1);
df58fc94
RS
2637 break;
2638
2639 default:
2640 /* xgettext:c-format */
0c7533d3 2641 infprintf (is,
df58fc94
RS
2642 _("# internal disassembler error, "
2643 "unrecognized modifier (+%c)"),
2644 *s);
2645 abort ();
2646 }
2647 break;
2648
2649 case 'm':
2650 /* Extension character; switch for second char. */
2651 s++;
2652 switch (*s)
2653 {
2654 case 'a': /* global pointer. */
0c7533d3 2655 infprintf (is, "%s", mips_gpr_names[28]);
df58fc94
RS
2656 break;
2657
2658 case 'b':
2659 regno = micromips_to_32_reg_b_map[GET_OP (insn, MB)];
0c7533d3 2660 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2661 break;
2662
2663 case 'c':
2664 regno = micromips_to_32_reg_c_map[GET_OP (insn, MC)];
0c7533d3 2665 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2666 break;
2667
2668 case 'd':
2669 regno = micromips_to_32_reg_d_map[GET_OP (insn, MD)];
0c7533d3 2670 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2671 break;
2672
2673 case 'e':
2674 regno = micromips_to_32_reg_e_map[GET_OP (insn, ME)];
0c7533d3 2675 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2676 break;
2677
2678 case 'f':
2679 /* Save lastregno for "mt" to print out later. */
2680 lastregno = micromips_to_32_reg_f_map[GET_OP (insn, MF)];
0c7533d3 2681 infprintf (is, "%s", mips_gpr_names[lastregno]);
df58fc94
RS
2682 break;
2683
2684 case 'g':
2685 regno = micromips_to_32_reg_g_map[GET_OP (insn, MG)];
0c7533d3 2686 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2687 break;
2688
2689 case 'h':
2690 regno = micromips_to_32_reg_h_map[GET_OP (insn, MH)];
0c7533d3 2691 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2692 break;
2693
2694 case 'i':
2695 regno = micromips_to_32_reg_i_map[GET_OP (insn, MI)];
0c7533d3 2696 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2697 break;
2698
2699 case 'j':
0c7533d3 2700 infprintf (is, "%s", mips_gpr_names[GET_OP (insn, MJ)]);
df58fc94
RS
2701 break;
2702
2703 case 'l':
2704 regno = micromips_to_32_reg_l_map[GET_OP (insn, ML)];
0c7533d3 2705 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2706 break;
2707
2708 case 'm':
2709 regno = micromips_to_32_reg_m_map[GET_OP (insn, MM)];
0c7533d3 2710 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2711 break;
2712
2713 case 'n':
2714 regno = micromips_to_32_reg_n_map[GET_OP (insn, MN)];
0c7533d3 2715 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2716 break;
2717
2718 case 'p':
2719 /* Save lastregno for "mt" to print out later. */
2720 lastregno = GET_OP (insn, MP);
0c7533d3 2721 infprintf (is, "%s", mips_gpr_names[lastregno]);
df58fc94
RS
2722 break;
2723
2724 case 'q':
2725 regno = micromips_to_32_reg_q_map[GET_OP (insn, MQ)];
0c7533d3 2726 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2727 break;
2728
2729 case 'r': /* program counter. */
0c7533d3 2730 infprintf (is, "$pc");
df58fc94
RS
2731 break;
2732
2733 case 's': /* stack pointer. */
2734 lastregno = 29;
0c7533d3 2735 infprintf (is, "%s", mips_gpr_names[29]);
df58fc94
RS
2736 break;
2737
2738 case 't':
0c7533d3 2739 infprintf (is, "%s", mips_gpr_names[lastregno]);
df58fc94
RS
2740 break;
2741
2742 case 'z': /* $0. */
0c7533d3 2743 infprintf (is, "%s", mips_gpr_names[0]);
df58fc94
RS
2744 break;
2745
2746 case 'A':
2747 /* Sign-extend the immediate. */
fc8c4fd1 2748 immed = GET_OP_S (insn, IMMA) << 2;
0c7533d3 2749 infprintf (is, "%d", immed);
df58fc94
RS
2750 break;
2751
2752 case 'B':
2753 immed = micromips_imm_b_map[GET_OP (insn, IMMB)];
0c7533d3 2754 infprintf (is, "%d", immed);
df58fc94
RS
2755 break;
2756
2757 case 'C':
2758 immed = micromips_imm_c_map[GET_OP (insn, IMMC)];
d908c8af 2759 infprintf (is, "0x%x", immed);
df58fc94
RS
2760 break;
2761
2762 case 'D':
2763 /* Sign-extend the displacement. */
fc8c4fd1 2764 delta = GET_OP_S (insn, IMMD);
df58fc94
RS
2765 info->target = (delta << 1) + memaddr + length;
2766 (*info->print_address_func) (info->target, info);
2767 break;
2768
2769 case 'E':
2770 /* Sign-extend the displacement. */
fc8c4fd1 2771 delta = GET_OP_S (insn, IMME);
df58fc94
RS
2772 info->target = (delta << 1) + memaddr + length;
2773 (*info->print_address_func) (info->target, info);
2774 break;
2775
2776 case 'F':
2777 immed = GET_OP (insn, IMMF);
0c7533d3 2778 infprintf (is, "0x%x", immed);
df58fc94
RS
2779 break;
2780
2781 case 'G':
2782 immed = (insn >> MICROMIPSOP_SH_IMMG) + 1;
2783 immed = (immed & MICROMIPSOP_MASK_IMMG) - 1;
0c7533d3 2784 infprintf (is, "%d", immed);
df58fc94
RS
2785 break;
2786
2787 case 'H':
2788 immed = GET_OP (insn, IMMH) << 1;
0c7533d3 2789 infprintf (is, "%d", immed);
df58fc94
RS
2790 break;
2791
2792 case 'I':
2793 immed = (insn >> MICROMIPSOP_SH_IMMI) + 1;
2794 immed = (immed & MICROMIPSOP_MASK_IMMI) - 1;
0c7533d3 2795 infprintf (is, "%d", immed);
df58fc94
RS
2796 break;
2797
2798 case 'J':
2799 immed = GET_OP (insn, IMMJ) << 2;
0c7533d3 2800 infprintf (is, "%d", immed);
df58fc94
RS
2801 break;
2802
2803 case 'L':
2804 immed = GET_OP (insn, IMML);
0c7533d3 2805 infprintf (is, "%d", immed);
df58fc94
RS
2806 break;
2807
2808 case 'M':
2809 immed = (insn >> MICROMIPSOP_SH_IMMM) - 1;
2810 immed = (immed & MICROMIPSOP_MASK_IMMM) + 1;
0c7533d3 2811 infprintf (is, "%d", immed);
df58fc94
RS
2812 break;
2813
2814 case 'N':
2815 immed = GET_OP (insn, IMMN);
2816 if (immed == 0)
0c7533d3 2817 infprintf (is, "%s,%s",
df58fc94
RS
2818 mips_gpr_names[16],
2819 mips_gpr_names[31]);
2820 else
0c7533d3 2821 infprintf (is, "%s-%s,%s",
df58fc94
RS
2822 mips_gpr_names[16],
2823 mips_gpr_names[16 + immed],
2824 mips_gpr_names[31]);
2825 break;
2826
2827 case 'O':
2828 immed = GET_OP (insn, IMMO);
0c7533d3 2829 infprintf (is, "0x%x", immed);
df58fc94
RS
2830 break;
2831
2832 case 'P':
2833 immed = GET_OP (insn, IMMP) << 2;
0c7533d3 2834 infprintf (is, "%d", immed);
df58fc94
RS
2835 break;
2836
2837 case 'Q':
2838 /* Sign-extend the immediate. */
fc8c4fd1 2839 immed = GET_OP_S (insn, IMMQ) << 2;
0c7533d3 2840 infprintf (is, "%d", immed);
df58fc94
RS
2841 break;
2842
2843 case 'U':
2844 immed = GET_OP (insn, IMMU) << 2;
0c7533d3 2845 infprintf (is, "%d", immed);
df58fc94
RS
2846 break;
2847
2848 case 'W':
2849 immed = GET_OP (insn, IMMW) << 2;
0c7533d3 2850 infprintf (is, "%d", immed);
df58fc94
RS
2851 break;
2852
2853 case 'X':
2854 /* Sign-extend the immediate. */
fc8c4fd1 2855 immed = GET_OP_S (insn, IMMX);
0c7533d3 2856 infprintf (is, "%d", immed);
df58fc94
RS
2857 break;
2858
2859 case 'Y':
2860 /* Sign-extend the immediate. */
fc8c4fd1
MR
2861 immed = GET_OP_S (insn, IMMY) << 2;
2862 if ((unsigned int) (immed + 8) < 16)
2863 immed ^= 0x400;
0c7533d3 2864 infprintf (is, "%d", immed);
df58fc94
RS
2865 break;
2866
2867 default:
2868 /* xgettext:c-format */
0c7533d3 2869 infprintf (is,
df58fc94
RS
2870 _("# internal disassembler error, "
2871 "unrecognized modifier (m%c)"),
2872 *s);
2873 abort ();
2874 }
2875 break;
2876
2877 default:
2878 /* xgettext:c-format */
0c7533d3 2879 infprintf (is,
df58fc94
RS
2880 _("# internal disassembler error, "
2881 "unrecognized modifier (%c)"),
2882 *s);
2883 abort ();
2884 }
2885 }
2886
2887 /* Figure out instruction type and branch delay information. */
2888 if ((op->pinfo
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)
2893 {
2894 if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_GPR_T)) != 0)
2895 info->insn_type = dis_jsr;
2896 else
2897 info->insn_type = dis_branch;
2898 }
2899 else if (((op->pinfo & INSN_COND_BRANCH_DELAY)
2900 | (op->pinfo2 & INSN2_COND_BRANCH)) != 0)
2901 {
2902 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2903 info->insn_type = dis_condjsr;
2904 else
2905 info->insn_type = dis_condbranch;
2906 }
2907 else if ((op->pinfo
2908 & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY_DELAY)) != 0)
2909 info->insn_type = dis_dref;
2910
2911 return length;
2912 }
2913 }
fc8c4fd1 2914#undef GET_OP_S
df58fc94
RS
2915#undef GET_OP
2916
0c7533d3 2917 infprintf (is, "0x%x", insn);
df58fc94
RS
2918 info->insn_type = dis_noninsn;
2919
2920 return length;
2921}
2922
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,
2929 return 0. */
2930
2931static bfd_boolean
2932is_compressed_mode_p (struct disassemble_info *info)
2933{
2934 elf_symbol_type *symbol;
2935 int pos;
2936 int i;
2937
2938 for (i = 0; i < info->num_symbols; i++)
2939 {
2940 pos = info->symtab_pos + i;
2941
2942 if (bfd_asymbol_flavour (info->symtab[pos]) != bfd_target_elf_flavour)
2943 continue;
2944
5417f71e
MR
2945 if (info->symtab[pos]->section != info->section)
2946 continue;
2947
df58fc94
RS
2948 symbol = (elf_symbol_type *) info->symtab[pos];
2949 if ((!micromips_ase
2950 && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
2951 || (micromips_ase
2952 && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
2953 return 1;
2954 }
2955
2956 return 0;
2957}
2958
47b0e7ad
NC
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. */
2964
2965static int
2966_print_insn_mips (bfd_vma memaddr,
2967 struct disassemble_info *info,
2968 enum bfd_endian endianness)
2969{
df58fc94 2970 int (*print_insn_compr) (bfd_vma, struct disassemble_info *);
47b0e7ad
NC
2971 bfd_byte buffer[INSNLEN];
2972 int status;
2973
2974 set_default_mips_dis_options (info);
2975 parse_mips_dis_options (info->disassembler_options);
2976
df58fc94
RS
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);
2981
2982 print_insn_compr = !micromips_ase ? print_insn_mips16 : print_insn_micromips;
2983
47b0e7ad 2984#if 1
df58fc94 2985 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
47b0e7ad
NC
2986 /* Only a few tools will work this way. */
2987 if (memaddr & 0x01)
df58fc94 2988 return print_insn_compr (memaddr, info);
47b0e7ad
NC
2989#endif
2990
2991#if SYMTAB_AVAILABLE
df58fc94
RS
2992 if (is_compressed_mode_p (info))
2993 return print_insn_compr (memaddr, info);
47b0e7ad
NC
2994#endif
2995
2996 status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
2997 if (status == 0)
2998 {
fc8c4fd1 2999 int insn;
47b0e7ad
NC
3000
3001 if (endianness == BFD_ENDIAN_BIG)
fc8c4fd1 3002 insn = bfd_getb32 (buffer);
47b0e7ad 3003 else
fc8c4fd1 3004 insn = bfd_getl32 (buffer);
47b0e7ad
NC
3005
3006 return print_insn_mips (memaddr, insn, info);
3007 }
3008 else
3009 {
3010 (*info->memory_error_func) (status, memaddr, info);
3011 return -1;
3012 }
3013}
3014
3015int
3016print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info)
3017{
3018 return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
3019}
3020
3021int
3022print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info)
3023{
3024 return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
3025}
3026\f
640c0ccd 3027void
47b0e7ad 3028print_mips_disassembler_options (FILE *stream)
640c0ccd 3029{
4a9a3c54 3030 unsigned int i;
640c0ccd
CD
3031
3032 fprintf (stream, _("\n\
3033The following MIPS specific disassembler options are supported for use\n\
3034with the -M switch (multiple options should be separated by commas):\n"));
3035
3036 fprintf (stream, _("\n\
3037 gpr-names=ABI Print GPR names according to specified ABI.\n\
3038 Default: based on binary being disassembled.\n"));
3039
3040 fprintf (stream, _("\n\
3041 fpr-names=ABI Print FPR names according to specified ABI.\n\
3042 Default: numeric.\n"));
3043
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"));
3048
af7ee8bf
CD
3049 fprintf (stream, _("\n\
3050 hwr-names=ARCH Print HWR names according to specified \n\
3051 architecture.\n\
3052 Default: based on binary being disassembled.\n"));
3053
640c0ccd
CD
3054 fprintf (stream, _("\n\
3055 reg-names=ABI Print GPR and FPR names according to\n\
3056 specified ABI.\n"));
3057
3058 fprintf (stream, _("\n\
af7ee8bf 3059 reg-names=ARCH Print CP0 register and HWR names according to\n\
640c0ccd
CD
3060 specified architecture.\n"));
3061
3062 fprintf (stream, _("\n\
3063 For the options above, the following values are supported for \"ABI\":\n\
3064 "));
4a9a3c54 3065 for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
640c0ccd
CD
3066 fprintf (stream, " %s", mips_abi_choices[i].name);
3067 fprintf (stream, _("\n"));
3068
3069 fprintf (stream, _("\n\
3070 For the options above, The following values are supported for \"ARCH\":\n\
3071 "));
4a9a3c54 3072 for (i = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
640c0ccd
CD
3073 if (*mips_arch_choices[i].name != '\0')
3074 fprintf (stream, " %s", mips_arch_choices[i].name);
3075 fprintf (stream, _("\n"));
3076
3077 fprintf (stream, _("\n"));
3078}
This page took 1.0057 seconds and 4 git commands to generate.