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