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