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