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