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
23e69e47
RS
1075 case 's': /* cins32 and exts32 length-minus-one */
1076 case 'S': /* cins and exts length-minus-one field */
fc8c4fd1 1077 infprintf (is, "0x%x", GET_OP (l, CINSLM1));
bb35fb24
NC
1078 break;
1079
dd3cbb7e 1080 case 'Q': /* seqi/snei immediate field */
fc8c4fd1 1081 infprintf (is, "%d", GET_OP_S (l, SEQI));
dd3cbb7e
NC
1082 break;
1083
98675402 1084 case 'a': /* 8-bit signed offset in bit 6 */
fc8c4fd1 1085 infprintf (is, "%d", GET_OP_S (l, OFFSET_A));
98675402
RS
1086 break;
1087
1088 case 'b': /* 8-bit signed offset in bit 3 */
fc8c4fd1 1089 infprintf (is, "%d", GET_OP_S (l, OFFSET_B));
98675402
RS
1090 break;
1091
1092 case 'c': /* 9-bit signed offset in bit 6 */
c95354ed 1093 /* Left shift 4 bits to print the real offset. */
fc8c4fd1 1094 infprintf (is, "%d", GET_OP_S (l, OFFSET_C) << 4);
98675402
RS
1095 break;
1096
1097 case 'z':
fc8c4fd1 1098 infprintf (is, "%s", mips_gpr_names[GET_OP (l, RZ)]);
98675402
RS
1099 break;
1100
1101 case 'Z':
fc8c4fd1 1102 infprintf (is, "%s", mips_fpr_names[GET_OP (l, FZ)]);
98675402
RS
1103 break;
1104
27c5c572
RS
1105 case 'i': /* JALX destination */
1106 info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
1107 | (GET_OP (l, TARGET) << 2));
1108 /* For gdb disassembler, force odd address on jalx. */
1109 if (info->flavour == bfd_target_unknown_flavour)
1110 info->target |= 1;
1111 (*info->print_address_func) (info->target, info);
1112 break;
1113
7f3c4072
CM
1114 case 'j': /* 9-bit signed offset in bit 7. */
1115 infprintf (is, "%d", GET_OP_S (l, EVAOFFSET));
1116 break;
1117
794ac9d0
CD
1118 default:
1119 /* xgettext:c-format */
fc8c4fd1
MR
1120 infprintf (is,
1121 _("# internal error, "
1122 "undefined extension sequence (+%c)"),
1123 *d);
794ac9d0
CD
1124 return;
1125 }
1126 break;
1127
8b082fb1 1128 case '2':
fc8c4fd1 1129 infprintf (is, "0x%x", GET_OP (l, BP));
8b082fb1
TS
1130 break;
1131
fd25c5a9 1132 case '3':
fc8c4fd1 1133 infprintf (is, "0x%x", GET_OP (l, SA3));
fd25c5a9
CF
1134 break;
1135
1136 case '4':
fc8c4fd1 1137 infprintf (is, "0x%x", GET_OP (l, SA4));
fd25c5a9
CF
1138 break;
1139
1140 case '5':
fc8c4fd1 1141 infprintf (is, "0x%x", GET_OP (l, IMM8));
fd25c5a9
CF
1142 break;
1143
1144 case '6':
fc8c4fd1 1145 infprintf (is, "0x%x", GET_OP (l, RS));
fd25c5a9
CF
1146 break;
1147
1148 case '7':
fc8c4fd1 1149 infprintf (is, "$ac%d", GET_OP (l, DSPACC));
fd25c5a9
CF
1150 break;
1151
1152 case '8':
fc8c4fd1 1153 infprintf (is, "0x%x", GET_OP (l, WRDSP));
fd25c5a9
CF
1154 break;
1155
1156 case '9':
fc8c4fd1 1157 infprintf (is, "$ac%d", GET_OP (l, DSPACC_S));
fd25c5a9
CF
1158 break;
1159
1160 case '0': /* dsp 6-bit signed immediate in bit 20 */
fc8c4fd1 1161 infprintf (is, "%d", GET_OP_S (l, DSPSFT));
fd25c5a9
CF
1162 break;
1163
1164 case ':': /* dsp 7-bit signed immediate in bit 19 */
fc8c4fd1 1165 infprintf (is, "%d", GET_OP_S (l, DSPSFT_7));
fd25c5a9
CF
1166 break;
1167
dec0624d 1168 case '~':
fc8c4fd1 1169 infprintf (is, "%d", GET_OP_S (l, OFFSET12));
dec0624d
MR
1170 break;
1171
1172 case '\\':
fc8c4fd1 1173 infprintf (is, "0x%x", GET_OP (l, 3BITPOS));
dec0624d
MR
1174 break;
1175
fd25c5a9 1176 case '\'':
fc8c4fd1 1177 infprintf (is, "0x%x", GET_OP (l, RDDSP));
fd25c5a9
CF
1178 break;
1179
1180 case '@': /* dsp 10-bit signed immediate in bit 16 */
fc8c4fd1 1181 infprintf (is, "%d", GET_OP_S (l, IMM10));
fd25c5a9
CF
1182 break;
1183
61cc0267 1184 case '!':
fc8c4fd1 1185 infprintf (is, "%d", GET_OP (l, MT_U));
61cc0267
CF
1186 break;
1187
1188 case '$':
fc8c4fd1 1189 infprintf (is, "%d", GET_OP (l, MT_H));
61cc0267
CF
1190 break;
1191
1192 case '*':
fc8c4fd1 1193 infprintf (is, "$ac%d", GET_OP (l, MTACC_T));
61cc0267
CF
1194 break;
1195
1196 case '&':
fc8c4fd1 1197 infprintf (is, "$ac%d", GET_OP (l, MTACC_D));
61cc0267
CF
1198 break;
1199
1200 case 'g':
1201 /* Coprocessor register for CTTC1, MTTC2, MTHC2, CTTC2. */
fc8c4fd1 1202 infprintf (is, "$%d", GET_OP (l, RD));
61cc0267
CF
1203 break;
1204
794ac9d0
CD
1205 case 's':
1206 case 'b':
1207 case 'r':
1208 case 'v':
fc8c4fd1 1209 infprintf (is, "%s", mips_gpr_names[GET_OP (l, RS)]);
794ac9d0
CD
1210 break;
1211
1212 case 't':
1213 case 'w':
fc8c4fd1 1214 infprintf (is, "%s", mips_gpr_names[GET_OP (l, RT)]);
794ac9d0
CD
1215 break;
1216
1217 case 'i':
1218 case 'u':
fc8c4fd1 1219 infprintf (is, "0x%x", GET_OP (l, IMMEDIATE));
794ac9d0
CD
1220 break;
1221
1222 case 'j': /* Same as i, but sign-extended. */
1223 case 'o':
fc8c4fd1 1224 infprintf (is, "%d", GET_OP_S (l, DELTA));
794ac9d0
CD
1225 break;
1226
1227 case 'h':
fc8c4fd1 1228 infprintf (is, "0x%x", GET_OP (l, PREFX));
794ac9d0
CD
1229 break;
1230
1231 case 'k':
fc8c4fd1 1232 infprintf (is, "0x%x", GET_OP (l, CACHE));
794ac9d0
CD
1233 break;
1234
1235 case 'a':
1236 info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
fc8c4fd1 1237 | (GET_OP (l, TARGET) << 2));
794ac9d0
CD
1238 (*info->print_address_func) (info->target, info);
1239 break;
1240
1241 case 'p':
1242 /* Sign extend the displacement. */
fc8c4fd1 1243 info->target = (GET_OP_S (l, DELTA) << 2) + pc + INSNLEN;
794ac9d0
CD
1244 (*info->print_address_func) (info->target, info);
1245 break;
1246
1247 case 'd':
fc8c4fd1 1248 infprintf (is, "%s", mips_gpr_names[GET_OP (l, RD)]);
794ac9d0
CD
1249 break;
1250
1251 case 'U':
1252 {
1253 /* First check for both rd and rt being equal. */
314d60dd
ME
1254 unsigned int reg;
1255
1256 reg = GET_OP (l, RD);
fc8c4fd1
MR
1257 if (reg == GET_OP (l, RT))
1258 infprintf (is, "%s", mips_gpr_names[reg]);
794ac9d0
CD
1259 else
1260 {
1261 /* If one is zero use the other. */
1262 if (reg == 0)
fc8c4fd1
MR
1263 infprintf (is, "%s", mips_gpr_names[GET_OP (l, RT)]);
1264 else if (GET_OP (l, RT) == 0)
1265 infprintf (is, "%s", mips_gpr_names[reg]);
794ac9d0 1266 else /* Bogus, result depends on processor. */
fc8c4fd1
MR
1267 infprintf (is, "%s or %s",
1268 mips_gpr_names[reg],
1269 mips_gpr_names[GET_OP (l, RT)]);
794ac9d0
CD
1270 }
1271 }
1272 break;
1273
1274 case 'z':
fc8c4fd1 1275 infprintf (is, "%s", mips_gpr_names[0]);
794ac9d0
CD
1276 break;
1277
1278 case '<':
4dc48ef6 1279 case '1':
fc8c4fd1 1280 infprintf (is, "0x%x", GET_OP (l, SHAMT));
af7ee8bf 1281 break;
794ac9d0
CD
1282
1283 case 'c':
fc8c4fd1 1284 infprintf (is, "0x%x", GET_OP (l, CODE));
794ac9d0
CD
1285 break;
1286
1287 case 'q':
fc8c4fd1 1288 infprintf (is, "0x%x", GET_OP (l, CODE2));
af7ee8bf
CD
1289 break;
1290
1291 case 'C':
fc8c4fd1 1292 infprintf (is, "0x%x", GET_OP (l, COPZ));
794ac9d0
CD
1293 break;
1294
1295 case 'B':
fc8c4fd1 1296 infprintf (is, "0x%x", GET_OP (l, CODE20));
794ac9d0
CD
1297 break;
1298
1299 case 'J':
fc8c4fd1 1300 infprintf (is, "0x%x", GET_OP (l, CODE19));
794ac9d0
CD
1301 break;
1302
1303 case 'S':
1304 case 'V':
fc8c4fd1 1305 infprintf (is, "%s", mips_fpr_names[GET_OP (l, FS)]);
794ac9d0
CD
1306 break;
1307
1308 case 'T':
1309 case 'W':
fc8c4fd1 1310 infprintf (is, "%s", mips_fpr_names[GET_OP (l, FT)]);
af7ee8bf
CD
1311 break;
1312
bbcc0807 1313 case 'D':
fc8c4fd1 1314 infprintf (is, "%s", mips_fpr_names[GET_OP (l, FD)]);
794ac9d0
CD
1315 break;
1316
1317 case 'R':
fc8c4fd1 1318 infprintf (is, "%s", mips_fpr_names[GET_OP (l, FR)]);
794ac9d0
CD
1319 break;
1320
1321 case 'E':
fa7616a4
RS
1322 cpreg = GET_OP (l, RT);
1323 goto copro;
794ac9d0
CD
1324
1325 case 'G':
fa7616a4
RS
1326 cpreg = GET_OP (l, RD);
1327 copro:
794ac9d0
CD
1328 /* Coprocessor register for mtcN instructions, et al. Note
1329 that FPU (cp1) instructions disassemble this field using
1330 'S' format. Therefore, we only need to worry about cp0,
1331 cp2, and cp3. */
fa7616a4
RS
1332 if (opp->name[strlen (opp->name) - 1] == '0')
1333 {
1334 if (d[1] == ',' && d[2] == 'H')
1335 {
1336 const struct mips_cp0sel_name *n;
1337 unsigned int sel;
1338
1339 sel = GET_OP (l, SEL);
1340
1341 /* CP0 register including 'sel' code for mtcN (et al.), to be
1342 printed textually if known. If not known, print both
1343 CP0 register name and sel numerically since CP0 register
1344 with sel 0 may have a name unrelated to register being
1345 printed. */
1346 n = lookup_mips_cp0sel_name (mips_cp0sel_names,
1347 mips_cp0sel_names_len,
1348 cpreg, sel);
1349 if (n != NULL)
1350 infprintf (is, "%s", n->name);
1351 else
1352 infprintf (is, "$%d,%d", cpreg, sel);
1353 d += 2;
1354 }
1355 else
1356 infprintf (is, "%s", mips_cp0_names[cpreg]);
1357 }
794ac9d0 1358 else
fa7616a4 1359 infprintf (is, "$%d", cpreg);
794ac9d0
CD
1360 break;
1361
1362 case 'K':
fc8c4fd1 1363 infprintf (is, "%s", mips_hwr_names[GET_OP (l, RD)]);
794ac9d0
CD
1364 break;
1365
1366 case 'N':
fc8c4fd1
MR
1367 infprintf (is,
1368 (opp->pinfo & (FP_D | FP_S)) != 0 ? "$fcc%d" : "$cc%d",
1369 GET_OP (l, BCC));
794ac9d0
CD
1370 break;
1371
1372 case 'M':
fc8c4fd1 1373 infprintf (is, "$fcc%d", GET_OP (l, CCC));
794ac9d0
CD
1374 break;
1375
1376 case 'P':
fc8c4fd1 1377 infprintf (is, "%d", GET_OP (l, PERFREG));
794ac9d0
CD
1378 break;
1379
1380 case 'e':
fc8c4fd1 1381 infprintf (is, "%d", GET_OP (l, VECBYTE));
794ac9d0
CD
1382 break;
1383
1384 case '%':
fc8c4fd1 1385 infprintf (is, "%d", GET_OP (l, VECALIGN));
794ac9d0
CD
1386 break;
1387
1388 case 'H':
fc8c4fd1 1389 infprintf (is, "%d", GET_OP (l, SEL));
794ac9d0
CD
1390 break;
1391
1392 case 'O':
fc8c4fd1 1393 infprintf (is, "%d", GET_OP (l, ALN));
794ac9d0
CD
1394 break;
1395
1396 case 'Q':
bbcc0807 1397 {
fc8c4fd1 1398 unsigned int vsel = GET_OP (l, VSEL);
47b0e7ad 1399
794ac9d0
CD
1400 if ((vsel & 0x10) == 0)
1401 {
1402 int fmt;
47b0e7ad 1403
794ac9d0
CD
1404 vsel &= 0x0f;
1405 for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
1406 if ((vsel & 1) == 0)
1407 break;
fc8c4fd1 1408 infprintf (is, "$v%d[%d]", GET_OP (l, FT), vsel >> 1);
794ac9d0
CD
1409 }
1410 else if ((vsel & 0x08) == 0)
1411 {
fc8c4fd1 1412 infprintf (is, "$v%d", GET_OP (l, FT));
794ac9d0 1413 }
bbcc0807 1414 else
794ac9d0 1415 {
fc8c4fd1 1416 infprintf (is, "0x%x", GET_OP (l, FT));
794ac9d0 1417 }
bbcc0807 1418 }
794ac9d0
CD
1419 break;
1420
1421 case 'X':
fc8c4fd1 1422 infprintf (is, "$v%d", GET_OP (l, FD));
794ac9d0
CD
1423 break;
1424
1425 case 'Y':
fc8c4fd1 1426 infprintf (is, "$v%d", GET_OP (l, FS));
794ac9d0
CD
1427 break;
1428
1429 case 'Z':
fc8c4fd1 1430 infprintf (is, "$v%d", GET_OP (l, FT));
794ac9d0 1431 break;
bbcc0807 1432
af7ee8bf
CD
1433 default:
1434 /* xgettext:c-format */
fc8c4fd1 1435 infprintf (is, _("# internal error, undefined modifier (%c)"), *d);
794ac9d0 1436 return;
af7ee8bf 1437 }
252b5132
RH
1438 }
1439}
1440\f
252b5132
RH
1441/* Print the mips instruction at address MEMADDR in debugged memory,
1442 on using INFO. Returns length of the instruction, in bytes, which is
aa5f19f2 1443 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
252b5132
RH
1444 this is little-endian code. */
1445
1446static int
47b0e7ad 1447print_insn_mips (bfd_vma memaddr,
fc8c4fd1 1448 int word,
47b0e7ad 1449 struct disassemble_info *info)
252b5132 1450{
fc8c4fd1
MR
1451 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
1452 const fprintf_ftype infprintf = info->fprintf_func;
47b0e7ad 1453 const struct mips_opcode *op;
b34976b6 1454 static bfd_boolean init = 0;
fc8c4fd1 1455 void *is = info->stream;
252b5132
RH
1456
1457 /* Build a hash table to shorten the search time. */
1458 if (! init)
1459 {
1460 unsigned int i;
1461
1462 for (i = 0; i <= OP_MASK_OP; i++)
1463 {
1464 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
1465 {
986e18a5 1466 if (op->pinfo == INSN_MACRO
9e836e3d 1467 || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
252b5132 1468 continue;
fc8c4fd1 1469 if (i == GET_OP (op->match, OP))
252b5132
RH
1470 {
1471 mips_hash[i] = op;
1472 break;
1473 }
1474 }
7f6621cd 1475 }
252b5132
RH
1476
1477 init = 1;
1478 }
1479
aa5f19f2 1480 info->bytes_per_chunk = INSNLEN;
252b5132 1481 info->display_endian = info->endian;
9bb28706
CD
1482 info->insn_info_valid = 1;
1483 info->branch_delay_insns = 0;
def7143b 1484 info->data_size = 0;
9bb28706
CD
1485 info->insn_type = dis_nonbranch;
1486 info->target = 0;
1487 info->target2 = 0;
252b5132 1488
fc8c4fd1 1489 op = mips_hash[GET_OP (word, OP)];
252b5132
RH
1490 if (op != NULL)
1491 {
1492 for (; op < &mips_opcodes[NUMOPCODES]; op++)
1493 {
986e18a5 1494 if (op->pinfo != INSN_MACRO
9e836e3d 1495 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
986e18a5 1496 && (word & op->mask) == op->match)
252b5132 1497 {
47b0e7ad 1498 const char *d;
2bd7f1f3 1499
3396de36 1500 /* We always allow to disassemble the jalx instruction. */
d301a56b 1501 if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
3396de36 1502 && strcmp (op->name, "jalx"))
252b5132
RH
1503 continue;
1504
9bb28706
CD
1505 /* Figure out instruction type and branch delay information. */
1506 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
1507 {
c680e7f6
MR
1508 if ((op->pinfo & (INSN_WRITE_GPR_31
1509 | INSN_WRITE_GPR_D)) != 0)
9bb28706
CD
1510 info->insn_type = dis_jsr;
1511 else
1512 info->insn_type = dis_branch;
1513 info->branch_delay_insns = 1;
1514 }
1515 else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
1516 | INSN_COND_BRANCH_LIKELY)) != 0)
1517 {
c680e7f6 1518 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
9bb28706
CD
1519 info->insn_type = dis_condjsr;
1520 else
1521 info->insn_type = dis_condbranch;
1522 info->branch_delay_insns = 1;
1523 }
1524 else if ((op->pinfo & (INSN_STORE_MEMORY
1525 | INSN_LOAD_MEMORY_DELAY)) != 0)
1526 info->insn_type = dis_dref;
1527
fc8c4fd1 1528 infprintf (is, "%s", op->name);
252b5132
RH
1529
1530 d = op->args;
1531 if (d != NULL && *d != '\0')
1532 {
fc8c4fd1 1533 infprintf (is, "\t");
cc0ca239 1534 print_insn_args (d, word, memaddr, info, op);
252b5132
RH
1535 }
1536
aa5f19f2 1537 return INSNLEN;
252b5132
RH
1538 }
1539 }
1540 }
fc8c4fd1
MR
1541#undef GET_OP_S
1542#undef GET_OP
252b5132
RH
1543
1544 /* Handle undefined instructions. */
9bb28706 1545 info->insn_type = dis_noninsn;
fc8c4fd1 1546 infprintf (is, "0x%x", word);
aa5f19f2 1547 return INSNLEN;
252b5132 1548}
aa5f19f2 1549\f
252b5132
RH
1550/* Disassemble an operand for a mips16 instruction. */
1551
1552static void
47b0e7ad
NC
1553print_mips16_insn_arg (char type,
1554 const struct mips_opcode *op,
1555 int l,
1556 bfd_boolean use_extend,
1557 int extend,
1558 bfd_vma memaddr,
1559 struct disassemble_info *info)
252b5132 1560{
fc8c4fd1
MR
1561 const fprintf_ftype infprintf = info->fprintf_func;
1562 void *is = info->stream;
1563
1564#define GET_OP(insn, field) \
1565 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
1566#define GET_OP_S(insn, field) \
1567 ((GET_OP (insn, field) ^ ((MIPS16OP_MASK_##field >> 1) + 1)) \
1568 - ((MIPS16OP_MASK_##field >> 1) + 1))
252b5132
RH
1569 switch (type)
1570 {
1571 case ',':
1572 case '(':
1573 case ')':
fc8c4fd1 1574 infprintf (is, "%c", type);
252b5132
RH
1575 break;
1576
1577 case 'y':
1578 case 'w':
fc8c4fd1 1579 infprintf (is, "%s", mips16_reg_names (GET_OP (l, RY)));
252b5132
RH
1580 break;
1581
1582 case 'x':
1583 case 'v':
fc8c4fd1 1584 infprintf (is, "%s", mips16_reg_names (GET_OP (l, RX)));
252b5132
RH
1585 break;
1586
1587 case 'z':
fc8c4fd1 1588 infprintf (is, "%s", mips16_reg_names (GET_OP (l, RZ)));
252b5132
RH
1589 break;
1590
1591 case 'Z':
fc8c4fd1 1592 infprintf (is, "%s", mips16_reg_names (GET_OP (l, MOVE32Z)));
252b5132
RH
1593 break;
1594
1595 case '0':
fc8c4fd1 1596 infprintf (is, "%s", mips_gpr_names[0]);
252b5132
RH
1597 break;
1598
1599 case 'S':
fc8c4fd1 1600 infprintf (is, "%s", mips_gpr_names[29]);
252b5132
RH
1601 break;
1602
1603 case 'P':
fc8c4fd1 1604 infprintf (is, "$pc");
252b5132
RH
1605 break;
1606
1607 case 'R':
fc8c4fd1 1608 infprintf (is, "%s", mips_gpr_names[31]);
252b5132
RH
1609 break;
1610
1611 case 'X':
fc8c4fd1 1612 infprintf (is, "%s", mips_gpr_names[GET_OP (l, REGR32)]);
252b5132
RH
1613 break;
1614
1615 case 'Y':
fc8c4fd1 1616 infprintf (is, "%s", mips_gpr_names[MIPS16OP_EXTRACT_REG32R (l)]);
252b5132
RH
1617 break;
1618
1619 case '<':
1620 case '>':
1621 case '[':
1622 case ']':
1623 case '4':
1624 case '5':
1625 case 'H':
1626 case 'W':
1627 case 'D':
1628 case 'j':
1629 case '6':
1630 case '8':
1631 case 'V':
1632 case 'C':
1633 case 'U':
1634 case 'k':
1635 case 'K':
1636 case 'p':
1637 case 'q':
1638 case 'A':
1639 case 'B':
1640 case 'E':
1641 {
1642 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
1643
1644 shift = 0;
1645 signedp = 0;
1646 extbits = 16;
1647 pcrel = 0;
1648 extu = 0;
1649 branch = 0;
1650 switch (type)
1651 {
1652 case '<':
1653 nbits = 3;
fc8c4fd1 1654 immed = GET_OP (l, RZ);
252b5132
RH
1655 extbits = 5;
1656 extu = 1;
1657 break;
1658 case '>':
1659 nbits = 3;
fc8c4fd1 1660 immed = GET_OP (l, RX);
252b5132
RH
1661 extbits = 5;
1662 extu = 1;
1663 break;
1664 case '[':
1665 nbits = 3;
fc8c4fd1 1666 immed = GET_OP (l, RZ);
252b5132
RH
1667 extbits = 6;
1668 extu = 1;
1669 break;
1670 case ']':
1671 nbits = 3;
fc8c4fd1 1672 immed = GET_OP (l, RX);
252b5132
RH
1673 extbits = 6;
1674 extu = 1;
1675 break;
1676 case '4':
1677 nbits = 4;
fc8c4fd1 1678 immed = GET_OP (l, IMM4);
252b5132
RH
1679 signedp = 1;
1680 extbits = 15;
1681 break;
1682 case '5':
1683 nbits = 5;
fc8c4fd1 1684 immed = GET_OP (l, IMM5);
252b5132
RH
1685 info->insn_type = dis_dref;
1686 info->data_size = 1;
1687 break;
1688 case 'H':
1689 nbits = 5;
1690 shift = 1;
fc8c4fd1 1691 immed = GET_OP (l, IMM5);
252b5132
RH
1692 info->insn_type = dis_dref;
1693 info->data_size = 2;
1694 break;
1695 case 'W':
1696 nbits = 5;
1697 shift = 2;
fc8c4fd1 1698 immed = GET_OP (l, IMM5);
252b5132
RH
1699 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
1700 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
1701 {
1702 info->insn_type = dis_dref;
1703 info->data_size = 4;
1704 }
1705 break;
1706 case 'D':
1707 nbits = 5;
1708 shift = 3;
fc8c4fd1 1709 immed = GET_OP (l, IMM5);
252b5132
RH
1710 info->insn_type = dis_dref;
1711 info->data_size = 8;
1712 break;
1713 case 'j':
1714 nbits = 5;
fc8c4fd1 1715 immed = GET_OP (l, IMM5);
252b5132
RH
1716 signedp = 1;
1717 break;
1718 case '6':
1719 nbits = 6;
fc8c4fd1 1720 immed = GET_OP (l, IMM6);
252b5132
RH
1721 break;
1722 case '8':
1723 nbits = 8;
fc8c4fd1 1724 immed = GET_OP (l, IMM8);
252b5132
RH
1725 break;
1726 case 'V':
1727 nbits = 8;
1728 shift = 2;
fc8c4fd1 1729 immed = GET_OP (l, IMM8);
252b5132
RH
1730 /* FIXME: This might be lw, or it might be addiu to $sp or
1731 $pc. We assume it's load. */
1732 info->insn_type = dis_dref;
1733 info->data_size = 4;
1734 break;
1735 case 'C':
1736 nbits = 8;
1737 shift = 3;
fc8c4fd1 1738 immed = GET_OP (l, IMM8);
252b5132
RH
1739 info->insn_type = dis_dref;
1740 info->data_size = 8;
1741 break;
1742 case 'U':
1743 nbits = 8;
fc8c4fd1 1744 immed = GET_OP (l, IMM8);
252b5132
RH
1745 extu = 1;
1746 break;
1747 case 'k':
1748 nbits = 8;
fc8c4fd1 1749 immed = GET_OP (l, IMM8);
252b5132
RH
1750 signedp = 1;
1751 break;
1752 case 'K':
1753 nbits = 8;
1754 shift = 3;
fc8c4fd1 1755 immed = GET_OP (l, IMM8);
252b5132
RH
1756 signedp = 1;
1757 break;
1758 case 'p':
1759 nbits = 8;
fc8c4fd1 1760 immed = GET_OP (l, IMM8);
252b5132
RH
1761 signedp = 1;
1762 pcrel = 1;
1763 branch = 1;
252b5132
RH
1764 break;
1765 case 'q':
1766 nbits = 11;
fc8c4fd1 1767 immed = GET_OP (l, IMM11);
252b5132
RH
1768 signedp = 1;
1769 pcrel = 1;
1770 branch = 1;
252b5132
RH
1771 break;
1772 case 'A':
1773 nbits = 8;
1774 shift = 2;
fc8c4fd1 1775 immed = GET_OP (l, IMM8);
252b5132
RH
1776 pcrel = 1;
1777 /* FIXME: This can be lw or la. We assume it is lw. */
1778 info->insn_type = dis_dref;
1779 info->data_size = 4;
1780 break;
1781 case 'B':
1782 nbits = 5;
1783 shift = 3;
fc8c4fd1 1784 immed = GET_OP (l, IMM5);
252b5132
RH
1785 pcrel = 1;
1786 info->insn_type = dis_dref;
1787 info->data_size = 8;
1788 break;
1789 case 'E':
1790 nbits = 5;
1791 shift = 2;
fc8c4fd1 1792 immed = GET_OP (l, IMM5);
252b5132
RH
1793 pcrel = 1;
1794 break;
1795 default:
1796 abort ();
1797 }
1798
1799 if (! use_extend)
1800 {
1801 if (signedp && immed >= (1 << (nbits - 1)))
1802 immed -= 1 << nbits;
1803 immed <<= shift;
1804 if ((type == '<' || type == '>' || type == '[' || type == ']')
1805 && immed == 0)
1806 immed = 8;
1807 }
1808 else
1809 {
1810 if (extbits == 16)
1811 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1812 else if (extbits == 15)
1813 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1814 else
1815 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1816 immed &= (1 << extbits) - 1;
1817 if (! extu && immed >= (1 << (extbits - 1)))
1818 immed -= 1 << extbits;
1819 }
1820
1821 if (! pcrel)
fc8c4fd1 1822 infprintf (is, "%d", immed);
252b5132
RH
1823 else
1824 {
1825 bfd_vma baseaddr;
252b5132
RH
1826
1827 if (branch)
1828 {
1829 immed *= 2;
1830 baseaddr = memaddr + 2;
1831 }
1832 else if (use_extend)
1833 baseaddr = memaddr - 2;
1834 else
1835 {
1836 int status;
1837 bfd_byte buffer[2];
1838
1839 baseaddr = memaddr;
1840
1841 /* If this instruction is in the delay slot of a jr
1842 instruction, the base address is the address of the
1843 jr instruction. If it is in the delay slot of jalr
1844 instruction, the base address is the address of the
1845 jalr instruction. This test is unreliable: we have
1846 no way of knowing whether the previous word is
1847 instruction or data. */
1848 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
1849 info);
1850 if (status == 0
1851 && (((info->endian == BFD_ENDIAN_BIG
1852 ? bfd_getb16 (buffer)
1853 : bfd_getl16 (buffer))
1854 & 0xf800) == 0x1800))
1855 baseaddr = memaddr - 4;
1856 else
1857 {
1858 status = (*info->read_memory_func) (memaddr - 2, buffer,
1859 2, info);
1860 if (status == 0
1861 && (((info->endian == BFD_ENDIAN_BIG
1862 ? bfd_getb16 (buffer)
1863 : bfd_getl16 (buffer))
1864 & 0xf81f) == 0xe800))
1865 baseaddr = memaddr - 2;
1866 }
1867 }
9bb28706 1868 info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
022fac6d
TS
1869 if (pcrel && branch
1870 && info->flavour == bfd_target_unknown_flavour)
1871 /* For gdb disassembler, maintain odd address. */
1872 info->target |= 1;
9bb28706 1873 (*info->print_address_func) (info->target, info);
252b5132
RH
1874 }
1875 }
1876 break;
1877
1878 case 'a':
27c5c572 1879 case 'i':
022fac6d 1880 {
022fac6d
TS
1881 if (! use_extend)
1882 extend = 0;
1883 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
27c5c572 1884 if (type == 'a' && info->flavour == bfd_target_unknown_flavour)
022fac6d
TS
1885 /* For gdb disassembler, maintain odd address. */
1886 l |= 1;
1887 }
9bb28706
CD
1888 info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
1889 (*info->print_address_func) (info->target, info);
252b5132
RH
1890 break;
1891
1892 case 'l':
1893 case 'L':
1894 {
1895 int need_comma, amask, smask;
1896
1897 need_comma = 0;
1898
fc8c4fd1 1899 l = GET_OP (l, IMM6);
252b5132
RH
1900
1901 amask = (l >> 3) & 7;
1902
1903 if (amask > 0 && amask < 5)
1904 {
fc8c4fd1 1905 infprintf (is, "%s", mips_gpr_names[4]);
252b5132 1906 if (amask > 1)
fc8c4fd1 1907 infprintf (is, "-%s", mips_gpr_names[amask + 3]);
252b5132
RH
1908 need_comma = 1;
1909 }
1910
1911 smask = (l >> 1) & 3;
1912 if (smask == 3)
1913 {
fc8c4fd1 1914 infprintf (is, "%s??", need_comma ? "," : "");
252b5132
RH
1915 need_comma = 1;
1916 }
1917 else if (smask > 0)
1918 {
fc8c4fd1 1919 infprintf (is, "%s%s", need_comma ? "," : "", mips_gpr_names[16]);
252b5132 1920 if (smask > 1)
fc8c4fd1 1921 infprintf (is, "-%s", mips_gpr_names[smask + 15]);
252b5132
RH
1922 need_comma = 1;
1923 }
1924
1925 if (l & 1)
1926 {
fc8c4fd1 1927 infprintf (is, "%s%s", need_comma ? "," : "", mips_gpr_names[31]);
252b5132
RH
1928 need_comma = 1;
1929 }
1930
1931 if (amask == 5 || amask == 6)
1932 {
fc8c4fd1 1933 infprintf (is, "%s$f0", need_comma ? "," : "");
252b5132 1934 if (amask == 6)
fc8c4fd1 1935 infprintf (is, "-$f1");
252b5132
RH
1936 }
1937 }
1938 break;
1939
0499d65b
TS
1940 case 'm':
1941 case 'M':
1942 /* MIPS16e save/restore. */
1943 {
1944 int need_comma = 0;
1945 int amask, args, statics;
1946 int nsreg, smask;
1947 int framesz;
1948 int i, j;
1949
1950 l = l & 0x7f;
1951 if (use_extend)
1952 l |= extend << 16;
1953
1954 amask = (l >> 16) & 0xf;
1955 if (amask == MIPS16_ALL_ARGS)
1956 {
1957 args = 4;
1958 statics = 0;
1959 }
1960 else if (amask == MIPS16_ALL_STATICS)
1961 {
1962 args = 0;
1963 statics = 4;
1964 }
1965 else
1966 {
1967 args = amask >> 2;
1968 statics = amask & 3;
1969 }
1970
1971 if (args > 0) {
fc8c4fd1 1972 infprintf (is, "%s", mips_gpr_names[4]);
0499d65b 1973 if (args > 1)
fc8c4fd1 1974 infprintf (is, "-%s", mips_gpr_names[4 + args - 1]);
0499d65b
TS
1975 need_comma = 1;
1976 }
1977
1978 framesz = (((l >> 16) & 0xf0) | (l & 0x0f)) * 8;
1979 if (framesz == 0 && !use_extend)
1980 framesz = 128;
1981
fc8c4fd1 1982 infprintf (is, "%s%d", need_comma ? "," : "", framesz);
0499d65b
TS
1983
1984 if (l & 0x40) /* $ra */
fc8c4fd1 1985 infprintf (is, ",%s", mips_gpr_names[31]);
0499d65b
TS
1986
1987 nsreg = (l >> 24) & 0x7;
1988 smask = 0;
1989 if (l & 0x20) /* $s0 */
1990 smask |= 1 << 0;
1991 if (l & 0x10) /* $s1 */
1992 smask |= 1 << 1;
1993 if (nsreg > 0) /* $s2-$s8 */
1994 smask |= ((1 << nsreg) - 1) << 2;
1995
1996 /* Find first set static reg bit. */
1997 for (i = 0; i < 9; i++)
1998 {
1999 if (smask & (1 << i))
2000 {
fc8c4fd1 2001 infprintf (is, ",%s", mips_gpr_names[i == 8 ? 30 : (16 + i)]);
0499d65b
TS
2002 /* Skip over string of set bits. */
2003 for (j = i; smask & (2 << j); j++)
2004 continue;
2005 if (j > i)
fc8c4fd1 2006 infprintf (is, "-%s", mips_gpr_names[j == 8 ? 30 : (16 + j)]);
0499d65b
TS
2007 i = j + 1;
2008 }
2009 }
2010
2011 /* Statics $ax - $a3. */
2012 if (statics == 1)
fc8c4fd1 2013 infprintf (is, ",%s", mips_gpr_names[7]);
0499d65b 2014 else if (statics > 0)
fc8c4fd1
MR
2015 infprintf (is, ",%s-%s",
2016 mips_gpr_names[7 - statics + 1],
2017 mips_gpr_names[7]);
0499d65b
TS
2018 }
2019 break;
2020
252b5132 2021 default:
aa5f19f2 2022 /* xgettext:c-format */
fc8c4fd1
MR
2023 infprintf (is,
2024 _("# internal disassembler error, "
2025 "unrecognised modifier (%c)"),
2026 type);
252b5132
RH
2027 abort ();
2028 }
2029}
640c0ccd 2030
1bbce132
MR
2031
2032/* Check if the given address is the last word of a MIPS16 PLT entry.
2033 This word is data and depending on the value it may interfere with
2034 disassembly of further PLT entries. We make use of the fact PLT
2035 symbols are marked BSF_SYNTHETIC. */
2036static bfd_boolean
2037is_mips16_plt_tail (struct disassemble_info *info, bfd_vma addr)
2038{
2039 if (info->symbols
2040 && info->symbols[0]
2041 && (info->symbols[0]->flags & BSF_SYNTHETIC)
2042 && addr == bfd_asymbol_value (info->symbols[0]) + 12)
2043 return TRUE;
2044
2045 return FALSE;
2046}
2047
47b0e7ad
NC
2048/* Disassemble mips16 instructions. */
2049
2050static int
2051print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
2052{
fc8c4fd1 2053 const fprintf_ftype infprintf = info->fprintf_func;
47b0e7ad 2054 int status;
1bbce132 2055 bfd_byte buffer[4];
47b0e7ad
NC
2056 int length;
2057 int insn;
2058 bfd_boolean use_extend;
2059 int extend = 0;
2060 const struct mips_opcode *op, *opend;
fc8c4fd1 2061 void *is = info->stream;
47b0e7ad
NC
2062
2063 info->bytes_per_chunk = 2;
2064 info->display_endian = info->endian;
2065 info->insn_info_valid = 1;
2066 info->branch_delay_insns = 0;
2067 info->data_size = 0;
47b0e7ad
NC
2068 info->target = 0;
2069 info->target2 = 0;
2070
1bbce132
MR
2071 /* Decode PLT entry's GOT slot address word. */
2072 if (is_mips16_plt_tail (info, memaddr))
2073 {
2074 info->insn_type = dis_noninsn;
2075 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
2076 if (status == 0)
2077 {
2078 unsigned int gotslot;
2079
2080 if (info->endian == BFD_ENDIAN_BIG)
2081 gotslot = bfd_getb32 (buffer);
2082 else
2083 gotslot = bfd_getl32 (buffer);
2084 infprintf (is, ".word\t0x%x", gotslot);
2085
2086 return 4;
2087 }
2088 }
2089 else
2090 {
2091 info->insn_type = dis_nonbranch;
2092 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2093 }
47b0e7ad
NC
2094 if (status != 0)
2095 {
2096 (*info->memory_error_func) (status, memaddr, info);
2097 return -1;
2098 }
2099
2100 length = 2;
2101
2102 if (info->endian == BFD_ENDIAN_BIG)
2103 insn = bfd_getb16 (buffer);
2104 else
2105 insn = bfd_getl16 (buffer);
2106
2107 /* Handle the extend opcode specially. */
2108 use_extend = FALSE;
2109 if ((insn & 0xf800) == 0xf000)
2110 {
2111 use_extend = TRUE;
2112 extend = insn & 0x7ff;
2113
2114 memaddr += 2;
2115
2116 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2117 if (status != 0)
2118 {
fc8c4fd1 2119 infprintf (is, "extend 0x%x", (unsigned int) extend);
47b0e7ad
NC
2120 (*info->memory_error_func) (status, memaddr, info);
2121 return -1;
2122 }
2123
2124 if (info->endian == BFD_ENDIAN_BIG)
2125 insn = bfd_getb16 (buffer);
2126 else
2127 insn = bfd_getl16 (buffer);
2128
2129 /* Check for an extend opcode followed by an extend opcode. */
2130 if ((insn & 0xf800) == 0xf000)
2131 {
fc8c4fd1 2132 infprintf (is, "extend 0x%x", (unsigned int) extend);
47b0e7ad
NC
2133 info->insn_type = dis_noninsn;
2134 return length;
2135 }
2136
2137 length += 2;
2138 }
2139
2140 /* FIXME: Should probably use a hash table on the major opcode here. */
2141
2142 opend = mips16_opcodes + bfd_mips16_num_opcodes;
2143 for (op = mips16_opcodes; op < opend; op++)
2144 {
2145 if (op->pinfo != INSN_MACRO
2146 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
2147 && (insn & op->mask) == op->match)
2148 {
2149 const char *s;
2150
27c5c572 2151 if (op->args[0] == 'a' || op->args[0] == 'i')
47b0e7ad
NC
2152 {
2153 if (use_extend)
2154 {
fc8c4fd1 2155 infprintf (is, "extend 0x%x", (unsigned int) extend);
47b0e7ad
NC
2156 info->insn_type = dis_noninsn;
2157 return length - 2;
2158 }
2159
2160 use_extend = FALSE;
2161
2162 memaddr += 2;
2163
2164 status = (*info->read_memory_func) (memaddr, buffer, 2,
2165 info);
2166 if (status == 0)
2167 {
2168 use_extend = TRUE;
2169 if (info->endian == BFD_ENDIAN_BIG)
2170 extend = bfd_getb16 (buffer);
2171 else
2172 extend = bfd_getl16 (buffer);
2173 length += 2;
2174 }
2175 }
2176
fc8c4fd1 2177 infprintf (is, "%s", op->name);
47b0e7ad 2178 if (op->args[0] != '\0')
fc8c4fd1 2179 infprintf (is, "\t");
47b0e7ad
NC
2180
2181 for (s = op->args; *s != '\0'; s++)
2182 {
2183 if (*s == ','
2184 && s[1] == 'w'
fc8c4fd1 2185 && GET_OP (insn, RX) == GET_OP (insn, RY))
47b0e7ad
NC
2186 {
2187 /* Skip the register and the comma. */
2188 ++s;
2189 continue;
2190 }
2191 if (*s == ','
2192 && s[1] == 'v'
fc8c4fd1 2193 && GET_OP (insn, RZ) == GET_OP (insn, RX))
47b0e7ad
NC
2194 {
2195 /* Skip the register and the comma. */
2196 ++s;
2197 continue;
2198 }
2199 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
2200 info);
2201 }
2202
9a2c7088 2203 /* Figure out branch instruction type and delay slot information. */
47b0e7ad 2204 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
9a2c7088
MR
2205 info->branch_delay_insns = 1;
2206 if ((op->pinfo & (INSN_UNCOND_BRANCH_DELAY
2207 | MIPS16_INSN_UNCOND_BRANCH)) != 0)
47b0e7ad 2208 {
9a2c7088
MR
2209 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2210 info->insn_type = dis_jsr;
2211 else
47b0e7ad
NC
2212 info->insn_type = dis_branch;
2213 }
9a2c7088
MR
2214 else if ((op->pinfo & MIPS16_INSN_COND_BRANCH) != 0)
2215 info->insn_type = dis_condbranch;
47b0e7ad
NC
2216
2217 return length;
2218 }
2219 }
fc8c4fd1
MR
2220#undef GET_OP_S
2221#undef GET_OP
47b0e7ad
NC
2222
2223 if (use_extend)
fc8c4fd1
MR
2224 infprintf (is, "0x%x", extend | 0xf000);
2225 infprintf (is, "0x%x", insn);
47b0e7ad
NC
2226 info->insn_type = dis_noninsn;
2227
2228 return length;
2229}
2230
df58fc94
RS
2231/* Disassemble microMIPS instructions. */
2232
2233static int
2234print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
2235{
0c7533d3 2236 const fprintf_ftype infprintf = info->fprintf_func;
df58fc94
RS
2237 const struct mips_opcode *op, *opend;
2238 unsigned int lsb, msbd, msb;
2239 void *is = info->stream;
2240 unsigned int regno;
2241 bfd_byte buffer[2];
2242 int lastregno = 0;
2243 int higher;
2244 int length;
2245 int status;
2246 int delta;
2247 int immed;
2248 int insn;
2249
2250 lsb = 0;
2251
2252 info->bytes_per_chunk = 2;
2253 info->display_endian = info->endian;
2254 info->insn_info_valid = 1;
2255 info->branch_delay_insns = 0;
2256 info->data_size = 0;
2257 info->insn_type = dis_nonbranch;
2258 info->target = 0;
2259 info->target2 = 0;
2260
2261 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2262 if (status != 0)
2263 {
2264 (*info->memory_error_func) (status, memaddr, info);
2265 return -1;
2266 }
2267
2268 length = 2;
2269
2270 if (info->endian == BFD_ENDIAN_BIG)
2271 insn = bfd_getb16 (buffer);
2272 else
2273 insn = bfd_getl16 (buffer);
2274
2275 if ((insn & 0xfc00) == 0x7c00)
2276 {
2277 /* This is a 48-bit microMIPS instruction. */
2278 higher = insn;
2279
2280 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2281 if (status != 0)
2282 {
0c7533d3 2283 infprintf (is, "micromips 0x%x", higher);
df58fc94
RS
2284 (*info->memory_error_func) (status, memaddr + 2, info);
2285 return -1;
2286 }
2287 if (info->endian == BFD_ENDIAN_BIG)
2288 insn = bfd_getb16 (buffer);
2289 else
2290 insn = bfd_getl16 (buffer);
2291 higher = (higher << 16) | insn;
2292
2293 status = (*info->read_memory_func) (memaddr + 4, buffer, 2, info);
2294 if (status != 0)
2295 {
0c7533d3 2296 infprintf (is, "micromips 0x%x", higher);
df58fc94
RS
2297 (*info->memory_error_func) (status, memaddr + 4, info);
2298 return -1;
2299 }
2300 if (info->endian == BFD_ENDIAN_BIG)
2301 insn = bfd_getb16 (buffer);
2302 else
2303 insn = bfd_getl16 (buffer);
0c7533d3 2304 infprintf (is, "0x%x%04x (48-bit insn)", higher, insn);
df58fc94
RS
2305
2306 info->insn_type = dis_noninsn;
2307 return 6;
2308 }
2309 else if ((insn & 0x1c00) == 0x0000 || (insn & 0x1000) == 0x1000)
2310 {
2311 /* This is a 32-bit microMIPS instruction. */
2312 higher = insn;
2313
2314 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2315 if (status != 0)
2316 {
0c7533d3 2317 infprintf (is, "micromips 0x%x", higher);
df58fc94
RS
2318 (*info->memory_error_func) (status, memaddr + 2, info);
2319 return -1;
2320 }
2321
2322 if (info->endian == BFD_ENDIAN_BIG)
2323 insn = bfd_getb16 (buffer);
2324 else
2325 insn = bfd_getl16 (buffer);
2326
2327 insn = insn | (higher << 16);
2328
2329 length += 2;
2330 }
2331
2332 /* FIXME: Should probably use a hash table on the major opcode here. */
2333
2334#define GET_OP(insn, field) \
2335 (((insn) >> MICROMIPSOP_SH_##field) & MICROMIPSOP_MASK_##field)
fc8c4fd1
MR
2336#define GET_OP_S(insn, field) \
2337 ((GET_OP (insn, field) ^ ((MICROMIPSOP_MASK_##field >> 1) + 1)) \
2338 - ((MICROMIPSOP_MASK_##field >> 1) + 1))
df58fc94
RS
2339 opend = micromips_opcodes + bfd_micromips_num_opcodes;
2340 for (op = micromips_opcodes; op < opend; op++)
2341 {
2342 if (op->pinfo != INSN_MACRO
2343 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
2344 && (insn & op->mask) == op->match
2345 && ((length == 2 && (op->mask & 0xffff0000) == 0)
2346 || (length == 4 && (op->mask & 0xffff0000) != 0)))
2347 {
2348 const char *s;
2349
0c7533d3 2350 infprintf (is, "%s", op->name);
df58fc94 2351 if (op->args[0] != '\0')
0c7533d3 2352 infprintf (is, "\t");
df58fc94
RS
2353
2354 for (s = op->args; *s != '\0'; s++)
2355 {
2356 switch (*s)
2357 {
2358 case ',':
2359 case '(':
2360 case ')':
0c7533d3 2361 infprintf (is, "%c", *s);
df58fc94
RS
2362 break;
2363
2364 case '.':
fc8c4fd1 2365 infprintf (is, "%d", GET_OP_S (insn, OFFSET10));
df58fc94
RS
2366 break;
2367
2368 case '1':
d908c8af 2369 infprintf (is, "0x%x", GET_OP (insn, STYPE));
df58fc94
RS
2370 break;
2371
03f66e8a 2372 case '2':
48891606 2373 infprintf (is, "0x%x", GET_OP (insn, BP));
03f66e8a
MR
2374 break;
2375
2376 case '3':
48891606 2377 infprintf (is, "0x%x", GET_OP (insn, SA3));
03f66e8a
MR
2378 break;
2379
2380 case '4':
48891606 2381 infprintf (is, "0x%x", GET_OP (insn, SA4));
03f66e8a
MR
2382 break;
2383
2384 case '5':
48891606 2385 infprintf (is, "0x%x", GET_OP (insn, IMM8));
03f66e8a
MR
2386 break;
2387
2388 case '6':
48891606 2389 infprintf (is, "0x%x", GET_OP (insn, RS));
03f66e8a
MR
2390 break;
2391
2392 case '7':
48891606 2393 infprintf (is, "$ac%d", GET_OP (insn, DSPACC));
03f66e8a
MR
2394 break;
2395
2396 case '8':
48891606 2397 infprintf (is, "0x%x", GET_OP (insn, WRDSP));
03f66e8a
MR
2398 break;
2399
2400 case '0': /* DSP 6-bit signed immediate in bit 16. */
2401 delta = (GET_OP (insn, DSPSFT) ^ 0x20) - 0x20;
2402 infprintf (is, "%d", delta);
2403 break;
2404
df58fc94 2405 case '<':
d908c8af 2406 infprintf (is, "0x%x", GET_OP (insn, SHAMT));
df58fc94
RS
2407 break;
2408
dec0624d 2409 case '\\':
d908c8af 2410 infprintf (is, "0x%x", GET_OP (insn, 3BITPOS));
dec0624d
MR
2411 break;
2412
03f66e8a 2413 case '^':
48891606 2414 infprintf (is, "0x%x", GET_OP (insn, RD));
03f66e8a
MR
2415 break;
2416
df58fc94 2417 case '|':
d908c8af 2418 infprintf (is, "0x%x", GET_OP (insn, TRAP));
df58fc94
RS
2419 break;
2420
2421 case '~':
fc8c4fd1 2422 infprintf (is, "%d", GET_OP_S (insn, OFFSET12));
df58fc94
RS
2423 break;
2424
2425 case 'a':
27c5c572
RS
2426 info->target = (((memaddr + 4) & ~(bfd_vma) 0x07ffffff)
2427 | (GET_OP (insn, TARGET) << 1));
2428 /* For gdb disassembler, maintain odd address. */
2429 if (info->flavour == bfd_target_unknown_flavour)
df58fc94
RS
2430 info->target |= 1;
2431 (*info->print_address_func) (info->target, info);
2432 break;
2433
2434 case 'b':
2435 case 'r':
2436 case 's':
2437 case 'v':
0c7533d3 2438 infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RS)]);
df58fc94
RS
2439 break;
2440
2441 case 'c':
d908c8af 2442 infprintf (is, "0x%x", GET_OP (insn, CODE));
df58fc94
RS
2443 break;
2444
2445 case 'd':
0c7533d3 2446 infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RD)]);
df58fc94
RS
2447 break;
2448
2449 case 'h':
d908c8af 2450 infprintf (is, "0x%x", GET_OP (insn, PREFX));
df58fc94
RS
2451 break;
2452
2453 case 'i':
2454 case 'u':
d908c8af 2455 infprintf (is, "0x%x", GET_OP (insn, IMMEDIATE));
df58fc94
RS
2456 break;
2457
2458 case 'j': /* Same as i, but sign-extended. */
2459 case 'o':
fc8c4fd1 2460 infprintf (is, "%d", GET_OP_S (insn, DELTA));
df58fc94
RS
2461 break;
2462
2463 case 'k':
0c7533d3 2464 infprintf (is, "0x%x", GET_OP (insn, CACHE));
df58fc94
RS
2465 break;
2466
2467 case 'n':
2468 {
2469 int s_reg_encode;
2470
2471 immed = GET_OP (insn, RT);
2472 s_reg_encode = immed & 0xf;
2473 if (s_reg_encode != 0)
2474 {
2475 if (s_reg_encode == 1)
0c7533d3 2476 infprintf (is, "%s", mips_gpr_names[16]);
df58fc94 2477 else if (s_reg_encode < 9)
0c7533d3 2478 infprintf (is, "%s-%s",
df58fc94
RS
2479 mips_gpr_names[16],
2480 mips_gpr_names[15 + s_reg_encode]);
2481 else if (s_reg_encode == 9)
0c7533d3 2482 infprintf (is, "%s-%s,%s",
df58fc94
RS
2483 mips_gpr_names[16],
2484 mips_gpr_names[23],
2485 mips_gpr_names[30]);
2486 else
0c7533d3 2487 infprintf (is, "UNKNOWN");
df58fc94
RS
2488 }
2489
2490 if (immed & 0x10) /* For ra. */
2491 {
2492 if (s_reg_encode == 0)
0c7533d3 2493 infprintf (is, "%s", mips_gpr_names[31]);
df58fc94 2494 else
0c7533d3 2495 infprintf (is, ",%s", mips_gpr_names[31]);
df58fc94
RS
2496 }
2497 break;
2498 }
2499
2500 case 'p':
2501 /* Sign-extend the displacement. */
fc8c4fd1 2502 delta = GET_OP_S (insn, DELTA);
df58fc94
RS
2503 info->target = (delta << 1) + memaddr + length;
2504 (*info->print_address_func) (info->target, info);
2505 break;
2506
2507 case 'q':
d908c8af 2508 infprintf (is, "0x%x", GET_OP (insn, CODE2));
df58fc94
RS
2509 break;
2510
2511 case 't':
2512 case 'w':
0c7533d3 2513 infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RT)]);
df58fc94
RS
2514 break;
2515
2516 case 'y':
0c7533d3 2517 infprintf (is, "%s", mips_gpr_names[GET_OP (insn, RS3)]);
df58fc94
RS
2518 break;
2519
2520 case 'z':
0c7533d3 2521 infprintf (is, "%s", mips_gpr_names[0]);
df58fc94
RS
2522 break;
2523
03f66e8a
MR
2524 case '@': /* DSP 10-bit signed immediate in bit 16. */
2525 delta = (GET_OP (insn, IMM10) ^ 0x200) - 0x200;
2526 infprintf (is, "%d", delta);
2527 break;
2528
df58fc94 2529 case 'B':
d908c8af 2530 infprintf (is, "0x%x", GET_OP (insn, CODE10));
df58fc94
RS
2531 break;
2532
2533 case 'C':
d908c8af 2534 infprintf (is, "0x%x", GET_OP (insn, COPZ));
df58fc94
RS
2535 break;
2536
2537 case 'D':
0c7533d3 2538 infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FD)]);
df58fc94
RS
2539 break;
2540
2541 case 'E':
2542 /* Coprocessor register for lwcN instructions, et al.
2543
2544 Note that there is no load/store cp0 instructions, and
2545 that FPU (cp1) instructions disassemble this field using
2546 'T' format. Therefore, until we gain understanding of
2547 cp2 register names, we can simply print the register
2548 numbers. */
d908c8af 2549 infprintf (is, "$%d", GET_OP (insn, RT));
df58fc94
RS
2550 break;
2551
2552 case 'G':
2553 /* Coprocessor register for mtcN instructions, et al. Note
2554 that FPU (cp1) instructions disassemble this field using
2555 'S' format. Therefore, we only need to worry about cp0,
fa7616a4
RS
2556 cp2, and cp3. */
2557 if (op->name[strlen (op->name) - 1] == '0')
df58fc94 2558 {
fa7616a4
RS
2559 if (s[1] == ',' && s[2] == 'H')
2560 {
2561 const struct mips_cp0sel_name *n;
2562 unsigned int cp0reg, sel;
2563
2564 cp0reg = GET_OP (insn, RS);
2565 sel = GET_OP (insn, SEL);
2566
2567 /* CP0 register including 'sel' code for mtcN
2568 (et al.), to be printed textually if known.
2569 If not known, print both CP0 register name and
2570 sel numerically since CP0 register with sel 0 may
2571 have a name unrelated to register being
2572 printed. */
2573 n = lookup_mips_cp0sel_name (mips_cp0sel_names,
2574 mips_cp0sel_names_len,
2575 cp0reg, sel);
2576 if (n != NULL)
2577 infprintf (is, "%s", n->name);
2578 else
2579 infprintf (is, "$%d,%d", cp0reg, sel);
2580 s += 2;
2581 }
2582 else
2583 infprintf (is, "%s", mips_cp0_names[GET_OP (insn, RS)]);
df58fc94 2584 }
fa7616a4
RS
2585 else
2586 infprintf (is, "$%d", GET_OP (insn, RS));
df58fc94
RS
2587 break;
2588
2589 case 'H':
d908c8af 2590 infprintf (is, "%d", GET_OP (insn, SEL));
df58fc94
RS
2591 break;
2592
2593 case 'K':
0c7533d3 2594 infprintf (is, "%s", mips_hwr_names[GET_OP (insn, RS)]);
df58fc94
RS
2595 break;
2596
2597 case 'M':
d908c8af 2598 infprintf (is, "$fcc%d", GET_OP (insn, CCC));
df58fc94
RS
2599 break;
2600
2601 case 'N':
0c7533d3 2602 infprintf (is,
df58fc94 2603 (op->pinfo & (FP_D | FP_S)) != 0
d908c8af 2604 ? "$fcc%d" : "$cc%d",
df58fc94
RS
2605 GET_OP (insn, BCC));
2606 break;
2607
2608 case 'R':
0c7533d3 2609 infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FR)]);
df58fc94
RS
2610 break;
2611
2612 case 'S':
2613 case 'V':
0c7533d3 2614 infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FS)]);
df58fc94
RS
2615 break;
2616
2617 case 'T':
0c7533d3 2618 infprintf (is, "%s", mips_fpr_names[GET_OP (insn, FT)]);
df58fc94
RS
2619 break;
2620
2621 case '+':
2622 /* Extension character; switch for second char. */
2623 s++;
2624 switch (*s)
2625 {
2626 case 'A':
2627 lsb = GET_OP (insn, EXTLSB);
0c7533d3 2628 infprintf (is, "0x%x", lsb);
df58fc94
RS
2629 break;
2630
2631 case 'B':
2632 msb = GET_OP (insn, INSMSB);
0c7533d3 2633 infprintf (is, "0x%x", msb - lsb + 1);
df58fc94
RS
2634 break;
2635
2636 case 'C':
2637 case 'H':
2638 msbd = GET_OP (insn, EXTMSBD);
0c7533d3 2639 infprintf (is, "0x%x", msbd + 1);
df58fc94
RS
2640 break;
2641
df58fc94
RS
2642 case 'E':
2643 lsb = GET_OP (insn, EXTLSB) + 32;
0c7533d3 2644 infprintf (is, "0x%x", lsb);
df58fc94
RS
2645 break;
2646
2647 case 'F':
2648 msb = GET_OP (insn, INSMSB) + 32;
0c7533d3 2649 infprintf (is, "0x%x", msb - lsb + 1);
df58fc94
RS
2650 break;
2651
2652 case 'G':
2653 msbd = GET_OP (insn, EXTMSBD) + 32;
0c7533d3 2654 infprintf (is, "0x%x", msbd + 1);
df58fc94 2655 break;
7f3c4072 2656
27c5c572
RS
2657 case 'i':
2658 info->target = (((memaddr + 4) & ~(bfd_vma) 0x0fffffff)
2659 | (GET_OP (insn, TARGET) << 2));
2660 (*info->print_address_func) (info->target, info);
2661 break;
2662
7f3c4072
CM
2663 case 'j': /* 9-bit signed offset in bit 0. */
2664 delta = GET_OP_S (insn, EVAOFFSET);
2665 infprintf (is, "%d", delta);
2666 break;
df58fc94
RS
2667
2668 default:
2669 /* xgettext:c-format */
0c7533d3 2670 infprintf (is,
df58fc94
RS
2671 _("# internal disassembler error, "
2672 "unrecognized modifier (+%c)"),
2673 *s);
2674 abort ();
2675 }
2676 break;
2677
2678 case 'm':
2679 /* Extension character; switch for second char. */
2680 s++;
2681 switch (*s)
2682 {
2683 case 'a': /* global pointer. */
0c7533d3 2684 infprintf (is, "%s", mips_gpr_names[28]);
df58fc94
RS
2685 break;
2686
2687 case 'b':
2688 regno = micromips_to_32_reg_b_map[GET_OP (insn, MB)];
0c7533d3 2689 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2690 break;
2691
2692 case 'c':
2693 regno = micromips_to_32_reg_c_map[GET_OP (insn, MC)];
0c7533d3 2694 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2695 break;
2696
2697 case 'd':
2698 regno = micromips_to_32_reg_d_map[GET_OP (insn, MD)];
0c7533d3 2699 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2700 break;
2701
2702 case 'e':
2703 regno = micromips_to_32_reg_e_map[GET_OP (insn, ME)];
0c7533d3 2704 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2705 break;
2706
2707 case 'f':
2708 /* Save lastregno for "mt" to print out later. */
2709 lastregno = micromips_to_32_reg_f_map[GET_OP (insn, MF)];
0c7533d3 2710 infprintf (is, "%s", mips_gpr_names[lastregno]);
df58fc94
RS
2711 break;
2712
2713 case 'g':
2714 regno = micromips_to_32_reg_g_map[GET_OP (insn, MG)];
0c7533d3 2715 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2716 break;
2717
2718 case 'h':
e76ff5ab 2719 regno = micromips_to_32_reg_h_map1[GET_OP (insn, MH)];
0c7533d3 2720 infprintf (is, "%s", mips_gpr_names[regno]);
e76ff5ab
RS
2721 regno = micromips_to_32_reg_h_map2[GET_OP (insn, MH)];
2722 infprintf (is, ",%s", mips_gpr_names[regno]);
df58fc94
RS
2723 break;
2724
2725 case 'j':
0c7533d3 2726 infprintf (is, "%s", mips_gpr_names[GET_OP (insn, MJ)]);
df58fc94
RS
2727 break;
2728
2729 case 'l':
2730 regno = micromips_to_32_reg_l_map[GET_OP (insn, ML)];
0c7533d3 2731 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2732 break;
2733
2734 case 'm':
2735 regno = micromips_to_32_reg_m_map[GET_OP (insn, MM)];
0c7533d3 2736 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2737 break;
2738
2739 case 'n':
2740 regno = micromips_to_32_reg_n_map[GET_OP (insn, MN)];
0c7533d3 2741 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2742 break;
2743
2744 case 'p':
2745 /* Save lastregno for "mt" to print out later. */
2746 lastregno = GET_OP (insn, MP);
0c7533d3 2747 infprintf (is, "%s", mips_gpr_names[lastregno]);
df58fc94
RS
2748 break;
2749
2750 case 'q':
2751 regno = micromips_to_32_reg_q_map[GET_OP (insn, MQ)];
0c7533d3 2752 infprintf (is, "%s", mips_gpr_names[regno]);
df58fc94
RS
2753 break;
2754
2755 case 'r': /* program counter. */
0c7533d3 2756 infprintf (is, "$pc");
df58fc94
RS
2757 break;
2758
2759 case 's': /* stack pointer. */
2760 lastregno = 29;
0c7533d3 2761 infprintf (is, "%s", mips_gpr_names[29]);
df58fc94
RS
2762 break;
2763
2764 case 't':
0c7533d3 2765 infprintf (is, "%s", mips_gpr_names[lastregno]);
df58fc94
RS
2766 break;
2767
2768 case 'z': /* $0. */
0c7533d3 2769 infprintf (is, "%s", mips_gpr_names[0]);
df58fc94
RS
2770 break;
2771
2772 case 'A':
2773 /* Sign-extend the immediate. */
fc8c4fd1 2774 immed = GET_OP_S (insn, IMMA) << 2;
0c7533d3 2775 infprintf (is, "%d", immed);
df58fc94
RS
2776 break;
2777
2778 case 'B':
2779 immed = micromips_imm_b_map[GET_OP (insn, IMMB)];
0c7533d3 2780 infprintf (is, "%d", immed);
df58fc94
RS
2781 break;
2782
2783 case 'C':
2784 immed = micromips_imm_c_map[GET_OP (insn, IMMC)];
d908c8af 2785 infprintf (is, "0x%x", immed);
df58fc94
RS
2786 break;
2787
2788 case 'D':
2789 /* Sign-extend the displacement. */
fc8c4fd1 2790 delta = GET_OP_S (insn, IMMD);
df58fc94
RS
2791 info->target = (delta << 1) + memaddr + length;
2792 (*info->print_address_func) (info->target, info);
2793 break;
2794
2795 case 'E':
2796 /* Sign-extend the displacement. */
fc8c4fd1 2797 delta = GET_OP_S (insn, IMME);
df58fc94
RS
2798 info->target = (delta << 1) + memaddr + length;
2799 (*info->print_address_func) (info->target, info);
2800 break;
2801
2802 case 'F':
2803 immed = GET_OP (insn, IMMF);
0c7533d3 2804 infprintf (is, "0x%x", immed);
df58fc94
RS
2805 break;
2806
2807 case 'G':
2808 immed = (insn >> MICROMIPSOP_SH_IMMG) + 1;
2809 immed = (immed & MICROMIPSOP_MASK_IMMG) - 1;
0c7533d3 2810 infprintf (is, "%d", immed);
df58fc94
RS
2811 break;
2812
2813 case 'H':
2814 immed = GET_OP (insn, IMMH) << 1;
0c7533d3 2815 infprintf (is, "%d", immed);
df58fc94
RS
2816 break;
2817
2818 case 'I':
2819 immed = (insn >> MICROMIPSOP_SH_IMMI) + 1;
2820 immed = (immed & MICROMIPSOP_MASK_IMMI) - 1;
0c7533d3 2821 infprintf (is, "%d", immed);
df58fc94
RS
2822 break;
2823
2824 case 'J':
2825 immed = GET_OP (insn, IMMJ) << 2;
0c7533d3 2826 infprintf (is, "%d", immed);
df58fc94
RS
2827 break;
2828
2829 case 'L':
2830 immed = GET_OP (insn, IMML);
0c7533d3 2831 infprintf (is, "%d", immed);
df58fc94
RS
2832 break;
2833
2834 case 'M':
2835 immed = (insn >> MICROMIPSOP_SH_IMMM) - 1;
2836 immed = (immed & MICROMIPSOP_MASK_IMMM) + 1;
0c7533d3 2837 infprintf (is, "%d", immed);
df58fc94
RS
2838 break;
2839
2840 case 'N':
2841 immed = GET_OP (insn, IMMN);
2842 if (immed == 0)
0c7533d3 2843 infprintf (is, "%s,%s",
df58fc94
RS
2844 mips_gpr_names[16],
2845 mips_gpr_names[31]);
2846 else
0c7533d3 2847 infprintf (is, "%s-%s,%s",
df58fc94
RS
2848 mips_gpr_names[16],
2849 mips_gpr_names[16 + immed],
2850 mips_gpr_names[31]);
2851 break;
2852
2853 case 'O':
2854 immed = GET_OP (insn, IMMO);
0c7533d3 2855 infprintf (is, "0x%x", immed);
df58fc94
RS
2856 break;
2857
2858 case 'P':
2859 immed = GET_OP (insn, IMMP) << 2;
0c7533d3 2860 infprintf (is, "%d", immed);
df58fc94
RS
2861 break;
2862
2863 case 'Q':
2864 /* Sign-extend the immediate. */
fc8c4fd1 2865 immed = GET_OP_S (insn, IMMQ) << 2;
0c7533d3 2866 infprintf (is, "%d", immed);
df58fc94
RS
2867 break;
2868
2869 case 'U':
2870 immed = GET_OP (insn, IMMU) << 2;
0c7533d3 2871 infprintf (is, "%d", immed);
df58fc94
RS
2872 break;
2873
2874 case 'W':
2875 immed = GET_OP (insn, IMMW) << 2;
0c7533d3 2876 infprintf (is, "%d", immed);
df58fc94
RS
2877 break;
2878
2879 case 'X':
2880 /* Sign-extend the immediate. */
fc8c4fd1 2881 immed = GET_OP_S (insn, IMMX);
0c7533d3 2882 infprintf (is, "%d", immed);
df58fc94
RS
2883 break;
2884
2885 case 'Y':
2886 /* Sign-extend the immediate. */
fc8c4fd1
MR
2887 immed = GET_OP_S (insn, IMMY) << 2;
2888 if ((unsigned int) (immed + 8) < 16)
2889 immed ^= 0x400;
0c7533d3 2890 infprintf (is, "%d", immed);
df58fc94
RS
2891 break;
2892
2893 default:
2894 /* xgettext:c-format */
0c7533d3 2895 infprintf (is,
df58fc94
RS
2896 _("# internal disassembler error, "
2897 "unrecognized modifier (m%c)"),
2898 *s);
2899 abort ();
2900 }
2901 break;
2902
2903 default:
2904 /* xgettext:c-format */
0c7533d3 2905 infprintf (is,
df58fc94
RS
2906 _("# internal disassembler error, "
2907 "unrecognized modifier (%c)"),
2908 *s);
2909 abort ();
2910 }
2911 }
2912
2913 /* Figure out instruction type and branch delay information. */
2914 if ((op->pinfo
2915 & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY)) != 0)
2916 info->branch_delay_insns = 1;
2917 if (((op->pinfo & INSN_UNCOND_BRANCH_DELAY)
2918 | (op->pinfo2 & INSN2_UNCOND_BRANCH)) != 0)
2919 {
2920 if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_GPR_T)) != 0)
2921 info->insn_type = dis_jsr;
2922 else
2923 info->insn_type = dis_branch;
2924 }
2925 else if (((op->pinfo & INSN_COND_BRANCH_DELAY)
2926 | (op->pinfo2 & INSN2_COND_BRANCH)) != 0)
2927 {
2928 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2929 info->insn_type = dis_condjsr;
2930 else
2931 info->insn_type = dis_condbranch;
2932 }
2933 else if ((op->pinfo
2934 & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY_DELAY)) != 0)
2935 info->insn_type = dis_dref;
2936
2937 return length;
2938 }
2939 }
fc8c4fd1 2940#undef GET_OP_S
df58fc94
RS
2941#undef GET_OP
2942
0c7533d3 2943 infprintf (is, "0x%x", insn);
df58fc94
RS
2944 info->insn_type = dis_noninsn;
2945
2946 return length;
2947}
2948
2949/* Return 1 if a symbol associated with the location being disassembled
2950 indicates a compressed (MIPS16 or microMIPS) mode. We iterate over
2951 all the symbols at the address being considered assuming if at least
2952 one of them indicates code compression, then such code has been
2953 genuinely produced here (other symbols could have been derived from
2954 function symbols defined elsewhere or could define data). Otherwise,
2955 return 0. */
2956
2957static bfd_boolean
2958is_compressed_mode_p (struct disassemble_info *info)
2959{
df58fc94 2960 int i;
1bbce132
MR
2961 int l;
2962
2963 for (i = info->symtab_pos, l = i + info->num_symbols; i < l; i++)
2964 if (((info->symtab[i])->flags & BSF_SYNTHETIC) != 0
2965 && ((!micromips_ase
2966 && ELF_ST_IS_MIPS16 ((*info->symbols)->udata.i))
2967 || (micromips_ase
2968 && ELF_ST_IS_MICROMIPS ((*info->symbols)->udata.i))))
2969 return 1;
2970 else if (bfd_asymbol_flavour (info->symtab[i]) == bfd_target_elf_flavour
2971 && info->symtab[i]->section == info->section)
2972 {
2973 elf_symbol_type *symbol = (elf_symbol_type *) info->symtab[i];
2974 if ((!micromips_ase
2975 && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
2976 || (micromips_ase
2977 && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
2978 return 1;
2979 }
df58fc94
RS
2980
2981 return 0;
2982}
2983
47b0e7ad
NC
2984/* In an environment where we do not know the symbol type of the
2985 instruction we are forced to assume that the low order bit of the
2986 instructions' address may mark it as a mips16 instruction. If we
2987 are single stepping, or the pc is within the disassembled function,
2988 this works. Otherwise, we need a clue. Sometimes. */
2989
2990static int
2991_print_insn_mips (bfd_vma memaddr,
2992 struct disassemble_info *info,
2993 enum bfd_endian endianness)
2994{
df58fc94 2995 int (*print_insn_compr) (bfd_vma, struct disassemble_info *);
47b0e7ad
NC
2996 bfd_byte buffer[INSNLEN];
2997 int status;
2998
2999 set_default_mips_dis_options (info);
3000 parse_mips_dis_options (info->disassembler_options);
3001
df58fc94
RS
3002 if (info->mach == bfd_mach_mips16)
3003 return print_insn_mips16 (memaddr, info);
3004 if (info->mach == bfd_mach_mips_micromips)
3005 return print_insn_micromips (memaddr, info);
3006
3007 print_insn_compr = !micromips_ase ? print_insn_mips16 : print_insn_micromips;
3008
47b0e7ad 3009#if 1
df58fc94 3010 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
47b0e7ad
NC
3011 /* Only a few tools will work this way. */
3012 if (memaddr & 0x01)
df58fc94 3013 return print_insn_compr (memaddr, info);
47b0e7ad
NC
3014#endif
3015
3016#if SYMTAB_AVAILABLE
df58fc94
RS
3017 if (is_compressed_mode_p (info))
3018 return print_insn_compr (memaddr, info);
47b0e7ad
NC
3019#endif
3020
3021 status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
3022 if (status == 0)
3023 {
fc8c4fd1 3024 int insn;
47b0e7ad
NC
3025
3026 if (endianness == BFD_ENDIAN_BIG)
fc8c4fd1 3027 insn = bfd_getb32 (buffer);
47b0e7ad 3028 else
fc8c4fd1 3029 insn = bfd_getl32 (buffer);
47b0e7ad
NC
3030
3031 return print_insn_mips (memaddr, insn, info);
3032 }
3033 else
3034 {
3035 (*info->memory_error_func) (status, memaddr, info);
3036 return -1;
3037 }
3038}
3039
3040int
3041print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info)
3042{
3043 return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
3044}
3045
3046int
3047print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info)
3048{
3049 return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
3050}
3051\f
640c0ccd 3052void
47b0e7ad 3053print_mips_disassembler_options (FILE *stream)
640c0ccd 3054{
4a9a3c54 3055 unsigned int i;
640c0ccd
CD
3056
3057 fprintf (stream, _("\n\
3058The following MIPS specific disassembler options are supported for use\n\
3059with the -M switch (multiple options should be separated by commas):\n"));
3060
b015e599
AP
3061 fprintf (stream, _("\n\
3062 virt Recognize the virtualization ASE instructions.\n"));
3063
640c0ccd
CD
3064 fprintf (stream, _("\n\
3065 gpr-names=ABI Print GPR names according to specified ABI.\n\
3066 Default: based on binary being disassembled.\n"));
3067
3068 fprintf (stream, _("\n\
3069 fpr-names=ABI Print FPR names according to specified ABI.\n\
3070 Default: numeric.\n"));
3071
3072 fprintf (stream, _("\n\
3073 cp0-names=ARCH Print CP0 register names according to\n\
3074 specified architecture.\n\
3075 Default: based on binary being disassembled.\n"));
3076
af7ee8bf
CD
3077 fprintf (stream, _("\n\
3078 hwr-names=ARCH Print HWR names according to specified \n\
3079 architecture.\n\
3080 Default: based on binary being disassembled.\n"));
3081
640c0ccd
CD
3082 fprintf (stream, _("\n\
3083 reg-names=ABI Print GPR and FPR names according to\n\
3084 specified ABI.\n"));
3085
3086 fprintf (stream, _("\n\
af7ee8bf 3087 reg-names=ARCH Print CP0 register and HWR names according to\n\
640c0ccd
CD
3088 specified architecture.\n"));
3089
3090 fprintf (stream, _("\n\
3091 For the options above, the following values are supported for \"ABI\":\n\
3092 "));
4a9a3c54 3093 for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
640c0ccd
CD
3094 fprintf (stream, " %s", mips_abi_choices[i].name);
3095 fprintf (stream, _("\n"));
3096
3097 fprintf (stream, _("\n\
3098 For the options above, The following values are supported for \"ARCH\":\n\
3099 "));
4a9a3c54 3100 for (i = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
640c0ccd
CD
3101 if (*mips_arch_choices[i].name != '\0')
3102 fprintf (stream, " %s", mips_arch_choices[i].name);
3103 fprintf (stream, _("\n"));
3104
3105 fprintf (stream, _("\n"));
3106}
This page took 0.815395 seconds and 4 git commands to generate.