]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/mips-dis.c
opcodes/
[thirdparty/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
252b5132 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
060d22b0 2 Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
8b99bf0b 3 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2012
73da6b6b 4 Free Software Foundation, Inc.
252b5132
RH
5 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
6
9b201bb5 7 This file is part of the GNU opcodes library.
252b5132 8
9b201bb5 9 This library is free software; you can redistribute it and/or modify
47b0e7ad 10 it under the terms of the GNU General Public License as published by
9b201bb5
NC
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
252b5132 13
9b201bb5
NC
14 It is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
252b5132 18
47b0e7ad
NC
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
252b5132 23
252b5132
RH
24#include "sysdep.h"
25#include "dis-asm.h"
640c0ccd 26#include "libiberty.h"
252b5132
RH
27#include "opcode/mips.h"
28#include "opintl.h"
29
30/* FIXME: These are needed to figure out if the code is mips16 or
31 not. The low bit of the address is often a good indicator. No
32 symbol table is available when this code runs out in an embedded
7f6621cd 33 system as when it is used for disassembler support in a monitor. */
252b5132
RH
34
35#if !defined(EMBEDDED_ENV)
36#define SYMTAB_AVAILABLE 1
37#include "elf-bfd.h"
38#include "elf/mips.h"
39#endif
40
aa5f19f2
NC
41/* Mips instructions are at maximum this many bytes long. */
42#define INSNLEN 4
43
252b5132 44\f
aa5f19f2 45/* FIXME: These should be shared with gdb somehow. */
252b5132 46
47b0e7ad
NC
47struct mips_cp0sel_name
48{
49 unsigned int cp0reg;
50 unsigned int sel;
51 const char * const name;
bbcc0807
CD
52};
53
47b0e7ad
NC
54static const char * const mips_gpr_names_numeric[32] =
55{
640c0ccd
CD
56 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
57 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
58 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
59 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
aa5f19f2
NC
60};
61
47b0e7ad
NC
62static const char * const mips_gpr_names_oldabi[32] =
63{
640c0ccd
CD
64 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
65 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
66 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
67 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
aa5f19f2
NC
68};
69
47b0e7ad
NC
70static const char * const mips_gpr_names_newabi[32] =
71{
640c0ccd 72 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
0b14f26e 73 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
640c0ccd
CD
74 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
75 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
76};
77
47b0e7ad
NC
78static const char * const mips_fpr_names_numeric[32] =
79{
640c0ccd
CD
80 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
81 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
82 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
83 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
84};
85
47b0e7ad
NC
86static const char * const mips_fpr_names_32[32] =
87{
640c0ccd
CD
88 "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
89 "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
90 "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f",
91 "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f"
92};
93
47b0e7ad
NC
94static const char * const mips_fpr_names_n32[32] =
95{
640c0ccd
CD
96 "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3",
97 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
98 "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9",
99 "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13"
100};
101
47b0e7ad
NC
102static const char * const mips_fpr_names_64[32] =
103{
640c0ccd
CD
104 "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
105 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
106 "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
107 "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
108};
109
47b0e7ad
NC
110static const char * const mips_cp0_names_numeric[32] =
111{
640c0ccd
CD
112 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
113 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
114 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
115 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
116};
117
dc76d757
AB
118static const char * const mips_cp1_names_numeric[32] =
119{
120 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
121 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
122 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
123 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
124};
125
f409fd1e
MR
126static const char * const mips_cp0_names_r3000[32] =
127{
128 "c0_index", "c0_random", "c0_entrylo", "$3",
129 "c0_context", "$5", "$6", "$7",
130 "c0_badvaddr", "$9", "c0_entryhi", "$11",
131 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
132 "$16", "$17", "$18", "$19",
133 "$20", "$21", "$22", "$23",
134 "$24", "$25", "$26", "$27",
135 "$28", "$29", "$30", "$31",
136};
137
138static const char * const mips_cp0_names_r4000[32] =
139{
140 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
141 "c0_context", "c0_pagemask", "c0_wired", "$7",
142 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
143 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
144 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
145 "c0_xcontext", "$21", "$22", "$23",
146 "$24", "$25", "c0_ecc", "c0_cacheerr",
147 "c0_taglo", "c0_taghi", "c0_errorepc", "$31",
148};
149
e407c74b
NC
150static const char * const mips_cp0_names_r5900[32] =
151{
152 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
153 "c0_context", "c0_pagemask", "c0_wired", "$7",
154 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
155 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
156 "c0_config", "$17", "$18", "$19",
157 "$20", "$21", "$22", "c0_badpaddr",
158 "c0_depc", "c0_perfcnt", "$26", "$27",
159 "c0_taglo", "c0_taghi", "c0_errorepc", "$31"
160};
161
162static const struct mips_cp0sel_name mips_cp0sel_names_mipsr5900[] =
163{
164 { 24, 2, "c0_iab" },
165 { 24, 3, "c0_iabm" },
166 { 24, 4, "c0_dab" },
167 { 24, 5, "c0_dabm" },
168 { 24, 6, "c0_dvb" },
169 { 24, 7, "c0_dvbm" },
170 { 25, 1, "c0_perfcnt,1" },
171 { 25, 2, "c0_perfcnt,2" }
172};
173
47b0e7ad
NC
174static const char * const mips_cp0_names_mips3264[32] =
175{
640c0ccd
CD
176 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
177 "c0_context", "c0_pagemask", "c0_wired", "$7",
178 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
179 "c0_status", "c0_cause", "c0_epc", "c0_prid",
180 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
181 "c0_xcontext", "$21", "$22", "c0_debug",
182 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
183 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
184};
185
dc76d757
AB
186static const char * const mips_cp1_names_mips3264[32] =
187{
188 "c1_fir", "c1_ufr", "$2", "$3",
189 "c1_unfr", "$5", "$6", "$7",
190 "$8", "$9", "$10", "$11",
191 "$12", "$13", "$14", "$15",
192 "$16", "$17", "$18", "$19",
193 "$20", "$21", "$22", "$23",
194 "$24", "c1_fccr", "c1_fexr", "$27",
195 "c1_fenr", "$29", "$30", "c1_fcsr"
196};
197
47b0e7ad
NC
198static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] =
199{
bbcc0807
CD
200 { 16, 1, "c0_config1" },
201 { 16, 2, "c0_config2" },
202 { 16, 3, "c0_config3" },
203 { 18, 1, "c0_watchlo,1" },
204 { 18, 2, "c0_watchlo,2" },
205 { 18, 3, "c0_watchlo,3" },
206 { 18, 4, "c0_watchlo,4" },
207 { 18, 5, "c0_watchlo,5" },
208 { 18, 6, "c0_watchlo,6" },
209 { 18, 7, "c0_watchlo,7" },
210 { 19, 1, "c0_watchhi,1" },
211 { 19, 2, "c0_watchhi,2" },
212 { 19, 3, "c0_watchhi,3" },
213 { 19, 4, "c0_watchhi,4" },
214 { 19, 5, "c0_watchhi,5" },
215 { 19, 6, "c0_watchhi,6" },
216 { 19, 7, "c0_watchhi,7" },
217 { 25, 1, "c0_perfcnt,1" },
218 { 25, 2, "c0_perfcnt,2" },
219 { 25, 3, "c0_perfcnt,3" },
220 { 25, 4, "c0_perfcnt,4" },
221 { 25, 5, "c0_perfcnt,5" },
222 { 25, 6, "c0_perfcnt,6" },
223 { 25, 7, "c0_perfcnt,7" },
224 { 27, 1, "c0_cacheerr,1" },
225 { 27, 2, "c0_cacheerr,2" },
226 { 27, 3, "c0_cacheerr,3" },
227 { 28, 1, "c0_datalo" },
228 { 29, 1, "c0_datahi" }
229};
230
47b0e7ad
NC
231static const char * const mips_cp0_names_mips3264r2[32] =
232{
af7ee8bf
CD
233 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
234 "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
235 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
236 "c0_status", "c0_cause", "c0_epc", "c0_prid",
237 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
238 "c0_xcontext", "$21", "$22", "c0_debug",
239 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
240 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
241};
242
47b0e7ad
NC
243static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] =
244{
bbcc0807 245 { 4, 1, "c0_contextconfig" },
59c455b3
TS
246 { 0, 1, "c0_mvpcontrol" },
247 { 0, 2, "c0_mvpconf0" },
248 { 0, 3, "c0_mvpconf1" },
249 { 1, 1, "c0_vpecontrol" },
250 { 1, 2, "c0_vpeconf0" },
251 { 1, 3, "c0_vpeconf1" },
252 { 1, 4, "c0_yqmask" },
253 { 1, 5, "c0_vpeschedule" },
254 { 1, 6, "c0_vpeschefback" },
255 { 2, 1, "c0_tcstatus" },
256 { 2, 2, "c0_tcbind" },
257 { 2, 3, "c0_tcrestart" },
258 { 2, 4, "c0_tchalt" },
259 { 2, 5, "c0_tccontext" },
260 { 2, 6, "c0_tcschedule" },
261 { 2, 7, "c0_tcschefback" },
bbcc0807 262 { 5, 1, "c0_pagegrain" },
59c455b3
TS
263 { 6, 1, "c0_srsconf0" },
264 { 6, 2, "c0_srsconf1" },
265 { 6, 3, "c0_srsconf2" },
266 { 6, 4, "c0_srsconf3" },
267 { 6, 5, "c0_srsconf4" },
bbcc0807
CD
268 { 12, 1, "c0_intctl" },
269 { 12, 2, "c0_srsctl" },
270 { 12, 3, "c0_srsmap" },
271 { 15, 1, "c0_ebase" },
272 { 16, 1, "c0_config1" },
273 { 16, 2, "c0_config2" },
274 { 16, 3, "c0_config3" },
275 { 18, 1, "c0_watchlo,1" },
276 { 18, 2, "c0_watchlo,2" },
277 { 18, 3, "c0_watchlo,3" },
278 { 18, 4, "c0_watchlo,4" },
279 { 18, 5, "c0_watchlo,5" },
280 { 18, 6, "c0_watchlo,6" },
281 { 18, 7, "c0_watchlo,7" },
282 { 19, 1, "c0_watchhi,1" },
283 { 19, 2, "c0_watchhi,2" },
284 { 19, 3, "c0_watchhi,3" },
285 { 19, 4, "c0_watchhi,4" },
286 { 19, 5, "c0_watchhi,5" },
287 { 19, 6, "c0_watchhi,6" },
288 { 19, 7, "c0_watchhi,7" },
289 { 23, 1, "c0_tracecontrol" },
290 { 23, 2, "c0_tracecontrol2" },
291 { 23, 3, "c0_usertracedata" },
292 { 23, 4, "c0_tracebpc" },
293 { 25, 1, "c0_perfcnt,1" },
294 { 25, 2, "c0_perfcnt,2" },
295 { 25, 3, "c0_perfcnt,3" },
296 { 25, 4, "c0_perfcnt,4" },
297 { 25, 5, "c0_perfcnt,5" },
298 { 25, 6, "c0_perfcnt,6" },
299 { 25, 7, "c0_perfcnt,7" },
300 { 27, 1, "c0_cacheerr,1" },
301 { 27, 2, "c0_cacheerr,2" },
302 { 27, 3, "c0_cacheerr,3" },
303 { 28, 1, "c0_datalo" },
304 { 28, 2, "c0_taglo1" },
305 { 28, 3, "c0_datalo1" },
306 { 28, 4, "c0_taglo2" },
307 { 28, 5, "c0_datalo2" },
308 { 28, 6, "c0_taglo3" },
309 { 28, 7, "c0_datalo3" },
310 { 29, 1, "c0_datahi" },
311 { 29, 2, "c0_taghi1" },
312 { 29, 3, "c0_datahi1" },
313 { 29, 4, "c0_taghi2" },
314 { 29, 5, "c0_datahi2" },
315 { 29, 6, "c0_taghi3" },
316 { 29, 7, "c0_datahi3" },
317};
318
640c0ccd 319/* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
47b0e7ad
NC
320static const char * const mips_cp0_names_sb1[32] =
321{
640c0ccd
CD
322 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
323 "c0_context", "c0_pagemask", "c0_wired", "$7",
324 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
325 "c0_status", "c0_cause", "c0_epc", "c0_prid",
326 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
327 "c0_xcontext", "$21", "$22", "c0_debug",
328 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
329 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
330};
331
47b0e7ad
NC
332static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] =
333{
bbcc0807
CD
334 { 16, 1, "c0_config1" },
335 { 18, 1, "c0_watchlo,1" },
336 { 19, 1, "c0_watchhi,1" },
337 { 22, 0, "c0_perftrace" },
338 { 23, 3, "c0_edebug" },
339 { 25, 1, "c0_perfcnt,1" },
340 { 25, 2, "c0_perfcnt,2" },
341 { 25, 3, "c0_perfcnt,3" },
342 { 25, 4, "c0_perfcnt,4" },
343 { 25, 5, "c0_perfcnt,5" },
344 { 25, 6, "c0_perfcnt,6" },
345 { 25, 7, "c0_perfcnt,7" },
346 { 26, 1, "c0_buserr_pa" },
347 { 27, 1, "c0_cacheerr_d" },
348 { 27, 3, "c0_cacheerr_d_pa" },
349 { 28, 1, "c0_datalo_i" },
350 { 28, 2, "c0_taglo_d" },
351 { 28, 3, "c0_datalo_d" },
352 { 29, 1, "c0_datahi_i" },
353 { 29, 2, "c0_taghi_d" },
354 { 29, 3, "c0_datahi_d" },
355};
356
52b6b6b9
JM
357/* Xlr cop0 register names. */
358static const char * const mips_cp0_names_xlr[32] = {
359 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
360 "c0_context", "c0_pagemask", "c0_wired", "$7",
361 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
362 "c0_status", "c0_cause", "c0_epc", "c0_prid",
363 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
364 "c0_xcontext", "$21", "$22", "c0_debug",
365 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
366 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
367};
368
369/* XLR's CP0 Select Registers. */
370
371static const struct mips_cp0sel_name mips_cp0sel_names_xlr[] = {
372 { 9, 6, "c0_extintreq" },
373 { 9, 7, "c0_extintmask" },
374 { 15, 1, "c0_ebase" },
375 { 16, 1, "c0_config1" },
376 { 16, 2, "c0_config2" },
377 { 16, 3, "c0_config3" },
378 { 16, 7, "c0_procid2" },
379 { 18, 1, "c0_watchlo,1" },
380 { 18, 2, "c0_watchlo,2" },
381 { 18, 3, "c0_watchlo,3" },
382 { 18, 4, "c0_watchlo,4" },
383 { 18, 5, "c0_watchlo,5" },
384 { 18, 6, "c0_watchlo,6" },
385 { 18, 7, "c0_watchlo,7" },
386 { 19, 1, "c0_watchhi,1" },
387 { 19, 2, "c0_watchhi,2" },
388 { 19, 3, "c0_watchhi,3" },
389 { 19, 4, "c0_watchhi,4" },
390 { 19, 5, "c0_watchhi,5" },
391 { 19, 6, "c0_watchhi,6" },
392 { 19, 7, "c0_watchhi,7" },
393 { 25, 1, "c0_perfcnt,1" },
394 { 25, 2, "c0_perfcnt,2" },
395 { 25, 3, "c0_perfcnt,3" },
396 { 25, 4, "c0_perfcnt,4" },
397 { 25, 5, "c0_perfcnt,5" },
398 { 25, 6, "c0_perfcnt,6" },
399 { 25, 7, "c0_perfcnt,7" },
400 { 27, 1, "c0_cacheerr,1" },
401 { 27, 2, "c0_cacheerr,2" },
402 { 27, 3, "c0_cacheerr,3" },
403 { 28, 1, "c0_datalo" },
404 { 29, 1, "c0_datahi" }
405};
406
47b0e7ad
NC
407static const char * const mips_hwr_names_numeric[32] =
408{
af7ee8bf
CD
409 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
410 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
411 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
412 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
413};
414
47b0e7ad
NC
415static const char * const mips_hwr_names_mips3264r2[32] =
416{
af7ee8bf
CD
417 "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
418 "$4", "$5", "$6", "$7",
419 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
420 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
421 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
422};
423
4edbb8e3
CF
424static const char * const msa_control_names[32] =
425{
426 "msa_ir", "msa_csr", "msa_access", "msa_save",
427 "msa_modify", "msa_request", "msa_map", "msa_unmap",
428 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
429 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
430 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
431};
432
47b0e7ad
NC
433struct mips_abi_choice
434{
435 const char * name;
640c0ccd
CD
436 const char * const *gpr_names;
437 const char * const *fpr_names;
438};
439
47b0e7ad
NC
440struct mips_abi_choice mips_abi_choices[] =
441{
640c0ccd
CD
442 { "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric },
443 { "32", mips_gpr_names_oldabi, mips_fpr_names_32 },
444 { "n32", mips_gpr_names_newabi, mips_fpr_names_n32 },
445 { "64", mips_gpr_names_newabi, mips_fpr_names_64 },
446};
447
47b0e7ad
NC
448struct mips_arch_choice
449{
640c0ccd
CD
450 const char *name;
451 int bfd_mach_valid;
452 unsigned long bfd_mach;
453 int processor;
454 int isa;
d301a56b 455 int ase;
640c0ccd 456 const char * const *cp0_names;
bbcc0807
CD
457 const struct mips_cp0sel_name *cp0sel_names;
458 unsigned int cp0sel_names_len;
dc76d757 459 const char * const *cp1_names;
af7ee8bf 460 const char * const *hwr_names;
640c0ccd
CD
461};
462
47b0e7ad
NC
463const struct mips_arch_choice mips_arch_choices[] =
464{
d301a56b 465 { "numeric", 0, 0, 0, 0, 0,
dc76d757
AB
466 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
467 mips_hwr_names_numeric },
bbcc0807 468
d301a56b 469 { "r3000", 1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1, 0,
dc76d757
AB
470 mips_cp0_names_r3000, NULL, 0, mips_cp1_names_numeric,
471 mips_hwr_names_numeric },
d301a56b 472 { "r3900", 1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1, 0,
dc76d757
AB
473 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
474 mips_hwr_names_numeric },
d301a56b 475 { "r4000", 1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3, 0,
dc76d757
AB
476 mips_cp0_names_r4000, NULL, 0, mips_cp1_names_numeric,
477 mips_hwr_names_numeric },
d301a56b 478 { "r4010", 1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2, 0,
dc76d757
AB
479 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
480 mips_hwr_names_numeric },
d301a56b 481 { "vr4100", 1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3, 0,
dc76d757
AB
482 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
483 mips_hwr_names_numeric },
d301a56b 484 { "vr4111", 1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3, 0,
dc76d757
AB
485 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
486 mips_hwr_names_numeric },
d301a56b 487 { "vr4120", 1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3, 0,
dc76d757
AB
488 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
489 mips_hwr_names_numeric },
d301a56b 490 { "r4300", 1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3, 0,
dc76d757
AB
491 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
492 mips_hwr_names_numeric },
d301a56b 493 { "r4400", 1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3, 0,
dc76d757
AB
494 mips_cp0_names_r4000, NULL, 0, mips_cp1_names_numeric,
495 mips_hwr_names_numeric },
d301a56b 496 { "r4600", 1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3, 0,
dc76d757
AB
497 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
498 mips_hwr_names_numeric },
d301a56b 499 { "r4650", 1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3, 0,
dc76d757
AB
500 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
501 mips_hwr_names_numeric },
d301a56b 502 { "r5000", 1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4, 0,
dc76d757
AB
503 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
504 mips_hwr_names_numeric },
d301a56b 505 { "vr5400", 1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4, 0,
dc76d757
AB
506 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
507 mips_hwr_names_numeric },
d301a56b 508 { "vr5500", 1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4, 0,
dc76d757
AB
509 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
510 mips_hwr_names_numeric },
d301a56b 511 { "r5900", 1, bfd_mach_mips5900, CPU_R5900, ISA_MIPS3, 0,
dc76d757
AB
512 mips_cp0_names_r5900, NULL, 0, mips_cp1_names_numeric,
513 mips_hwr_names_numeric },
d301a56b 514 { "r6000", 1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2, 0,
dc76d757
AB
515 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
516 mips_hwr_names_numeric },
d301a56b 517 { "rm7000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
dc76d757
AB
518 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
519 mips_hwr_names_numeric },
d301a56b 520 { "rm9000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
dc76d757
AB
521 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
522 mips_hwr_names_numeric },
d301a56b 523 { "r8000", 1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4, 0,
dc76d757
AB
524 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
525 mips_hwr_names_numeric },
d301a56b 526 { "r10000", 1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4, 0,
dc76d757
AB
527 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
528 mips_hwr_names_numeric },
d301a56b 529 { "r12000", 1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4, 0,
dc76d757
AB
530 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
531 mips_hwr_names_numeric },
d301a56b 532 { "r14000", 1, bfd_mach_mips14000, CPU_R14000, ISA_MIPS4, 0,
dc76d757
AB
533 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
534 mips_hwr_names_numeric },
d301a56b 535 { "r16000", 1, bfd_mach_mips16000, CPU_R16000, ISA_MIPS4, 0,
dc76d757
AB
536 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
537 mips_hwr_names_numeric },
d301a56b 538 { "mips5", 1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5, 0,
dc76d757
AB
539 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
540 mips_hwr_names_numeric },
bbcc0807 541
640c0ccd
CD
542 /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
543 Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
544 _MIPS32 Architecture For Programmers Volume I: Introduction to the
545 MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
546 page 1. */
547 { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32,
d301a56b 548 ISA_MIPS32, ASE_SMARTMIPS,
bbcc0807
CD
549 mips_cp0_names_mips3264,
550 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
dc76d757 551 mips_cp1_names_mips3264, mips_hwr_names_numeric },
bbcc0807 552
af7ee8bf 553 { "mips32r2", 1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
d301a56b 554 ISA_MIPS32R2,
7f3c4072 555 (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
4edbb8e3 556 | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA),
bbcc0807
CD
557 mips_cp0_names_mips3264r2,
558 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
dc76d757 559 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
bbcc0807 560
640c0ccd
CD
561 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
562 { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64,
d301a56b 563 ISA_MIPS64, ASE_MIPS3D | ASE_MDMX,
bbcc0807
CD
564 mips_cp0_names_mips3264,
565 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
dc76d757 566 mips_cp1_names_mips3264, mips_hwr_names_numeric },
bbcc0807 567
5f74bc13 568 { "mips64r2", 1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
d301a56b 569 ISA_MIPS64R2,
7f3c4072 570 (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
4edbb8e3 571 | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64),
5f74bc13
CD
572 mips_cp0_names_mips3264r2,
573 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
dc76d757 574 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
5f74bc13 575
640c0ccd 576 { "sb1", 1, bfd_mach_mips_sb1, CPU_SB1,
d301a56b 577 ISA_MIPS64 | INSN_SB1, ASE_MIPS3D,
bbcc0807
CD
578 mips_cp0_names_sb1,
579 mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
dc76d757 580 mips_cp1_names_mips3264, mips_hwr_names_numeric },
640c0ccd 581
350cc38d 582 { "loongson2e", 1, bfd_mach_mips_loongson_2e, CPU_LOONGSON_2E,
d301a56b 583 ISA_MIPS3 | INSN_LOONGSON_2E, 0, mips_cp0_names_numeric,
dc76d757 584 NULL, 0, mips_cp1_names_numeric, mips_hwr_names_numeric },
350cc38d
MS
585
586 { "loongson2f", 1, bfd_mach_mips_loongson_2f, CPU_LOONGSON_2F,
d301a56b 587 ISA_MIPS3 | INSN_LOONGSON_2F, 0, mips_cp0_names_numeric,
dc76d757 588 NULL, 0, mips_cp1_names_numeric, mips_hwr_names_numeric },
350cc38d 589
fd503541 590 { "loongson3a", 1, bfd_mach_mips_loongson_3a, CPU_LOONGSON_3A,
d301a56b 591 ISA_MIPS64 | INSN_LOONGSON_3A, 0, mips_cp0_names_numeric,
dc76d757 592 NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
fd503541 593
57b592a3 594 { "octeon", 1, bfd_mach_mips_octeon, CPU_OCTEON,
d301a56b 595 ISA_MIPS64R2 | INSN_OCTEON, 0, mips_cp0_names_numeric, NULL, 0,
dc76d757 596 mips_cp1_names_mips3264, mips_hwr_names_numeric },
57b592a3 597
dd6a37e7 598 { "octeon+", 1, bfd_mach_mips_octeonp, CPU_OCTEONP,
d301a56b 599 ISA_MIPS64R2 | INSN_OCTEONP, 0, mips_cp0_names_numeric,
dc76d757 600 NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
432233b3
AP
601
602 { "octeon2", 1, bfd_mach_mips_octeon2, CPU_OCTEON2,
d301a56b 603 ISA_MIPS64R2 | INSN_OCTEON2, 0, mips_cp0_names_numeric,
dc76d757 604 NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
dd6a37e7 605
52b6b6b9 606 { "xlr", 1, bfd_mach_mips_xlr, CPU_XLR,
d301a56b 607 ISA_MIPS64 | INSN_XLR, 0,
52b6b6b9
JM
608 mips_cp0_names_xlr,
609 mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
dc76d757 610 mips_cp1_names_mips3264, mips_hwr_names_numeric },
52b6b6b9 611
55a36193
MK
612 /* XLP is mostly like XLR, with the prominent exception it is being
613 MIPS64R2. */
614 { "xlp", 1, bfd_mach_mips_xlr, CPU_XLR,
d301a56b 615 ISA_MIPS64R2 | INSN_XLR, 0,
55a36193
MK
616 mips_cp0_names_xlr,
617 mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
dc76d757 618 mips_cp1_names_mips3264, mips_hwr_names_numeric },
55a36193 619
640c0ccd
CD
620 /* This entry, mips16, is here only for ISA/processor selection; do
621 not print its name. */
d301a56b 622 { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3, 0,
dc76d757
AB
623 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
624 mips_hwr_names_numeric },
640c0ccd
CD
625};
626
627/* ISA and processor type to disassemble for, and register names to use.
628 set_default_mips_dis_options and parse_mips_dis_options fill in these
629 values. */
630static int mips_processor;
631static int mips_isa;
d301a56b 632static int mips_ase;
df58fc94 633static int micromips_ase;
640c0ccd
CD
634static const char * const *mips_gpr_names;
635static const char * const *mips_fpr_names;
636static const char * const *mips_cp0_names;
bbcc0807
CD
637static const struct mips_cp0sel_name *mips_cp0sel_names;
638static int mips_cp0sel_names_len;
dc76d757 639static const char * const *mips_cp1_names;
af7ee8bf 640static const char * const *mips_hwr_names;
640c0ccd 641
986e18a5 642/* Other options */
47b0e7ad 643static int no_aliases; /* If set disassemble as most general inst. */
640c0ccd
CD
644\f
645static const struct mips_abi_choice *
47b0e7ad 646choose_abi_by_name (const char *name, unsigned int namelen)
640c0ccd
CD
647{
648 const struct mips_abi_choice *c;
649 unsigned int i;
650
651 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++)
47b0e7ad
NC
652 if (strncmp (mips_abi_choices[i].name, name, namelen) == 0
653 && strlen (mips_abi_choices[i].name) == namelen)
654 c = &mips_abi_choices[i];
655
640c0ccd
CD
656 return c;
657}
658
659static const struct mips_arch_choice *
47b0e7ad 660choose_arch_by_name (const char *name, unsigned int namelen)
640c0ccd
CD
661{
662 const struct mips_arch_choice *c = NULL;
663 unsigned int i;
664
665 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
47b0e7ad
NC
666 if (strncmp (mips_arch_choices[i].name, name, namelen) == 0
667 && strlen (mips_arch_choices[i].name) == namelen)
668 c = &mips_arch_choices[i];
669
640c0ccd
CD
670 return c;
671}
672
673static const struct mips_arch_choice *
47b0e7ad 674choose_arch_by_number (unsigned long mach)
640c0ccd
CD
675{
676 static unsigned long hint_bfd_mach;
677 static const struct mips_arch_choice *hint_arch_choice;
678 const struct mips_arch_choice *c;
679 unsigned int i;
680
681 /* We optimize this because even if the user specifies no
682 flags, this will be done for every instruction! */
683 if (hint_bfd_mach == mach
684 && hint_arch_choice != NULL
685 && hint_arch_choice->bfd_mach == hint_bfd_mach)
686 return hint_arch_choice;
687
688 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
689 {
690 if (mips_arch_choices[i].bfd_mach_valid
691 && mips_arch_choices[i].bfd_mach == mach)
692 {
693 c = &mips_arch_choices[i];
694 hint_bfd_mach = mach;
695 hint_arch_choice = c;
696 }
697 }
698 return c;
699}
700
47b0e7ad
NC
701/* Check if the object uses NewABI conventions. */
702
703static int
704is_newabi (Elf_Internal_Ehdr *header)
705{
706 /* There are no old-style ABIs which use 64-bit ELF. */
707 if (header->e_ident[EI_CLASS] == ELFCLASS64)
708 return 1;
709
710 /* If a 32-bit ELF file, n32 is a new-style ABI. */
711 if ((header->e_flags & EF_MIPS_ABI2) != 0)
712 return 1;
713
714 return 0;
715}
716
df58fc94
RS
717/* Check if the object has microMIPS ASE code. */
718
719static int
720is_micromips (Elf_Internal_Ehdr *header)
721{
722 if ((header->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0)
723 return 1;
724
725 return 0;
726}
727
47b0e7ad
NC
728static void
729set_default_mips_dis_options (struct disassemble_info *info)
640c0ccd
CD
730{
731 const struct mips_arch_choice *chosen_arch;
732
df58fc94
RS
733 /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
734 is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
735 CP0 register, and HWR names. */
640c0ccd 736 mips_isa = ISA_MIPS3;
df58fc94
RS
737 mips_processor = CPU_R3000;
738 micromips_ase = 0;
d301a56b 739 mips_ase = 0;
640c0ccd
CD
740 mips_gpr_names = mips_gpr_names_oldabi;
741 mips_fpr_names = mips_fpr_names_numeric;
742 mips_cp0_names = mips_cp0_names_numeric;
bbcc0807
CD
743 mips_cp0sel_names = NULL;
744 mips_cp0sel_names_len = 0;
dc76d757 745 mips_cp1_names = mips_cp1_names_numeric;
af7ee8bf 746 mips_hwr_names = mips_hwr_names_numeric;
986e18a5 747 no_aliases = 0;
640c0ccd 748
df58fc94 749 /* Update settings according to the ELF file header flags. */
fec06546 750 if (info->flavour == bfd_target_elf_flavour && info->section != NULL)
640c0ccd
CD
751 {
752 Elf_Internal_Ehdr *header;
753
fec06546 754 header = elf_elfheader (info->section->owner);
df58fc94 755 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
640c0ccd
CD
756 if (is_newabi (header))
757 mips_gpr_names = mips_gpr_names_newabi;
df58fc94
RS
758 /* If a microMIPS binary, then don't use MIPS16 bindings. */
759 micromips_ase = is_micromips (header);
640c0ccd
CD
760 }
761
762 /* Set ISA, architecture, and cp0 register names as best we can. */
763#if ! SYMTAB_AVAILABLE
764 /* This is running out on a target machine, not in a host tool.
765 FIXME: Where does mips_target_info come from? */
766 target_processor = mips_target_info.processor;
767 mips_isa = mips_target_info.isa;
d301a56b 768 mips_ase = mips_target_info.ase;
640c0ccd
CD
769#else
770 chosen_arch = choose_arch_by_number (info->mach);
771 if (chosen_arch != NULL)
772 {
773 mips_processor = chosen_arch->processor;
774 mips_isa = chosen_arch->isa;
d301a56b 775 mips_ase = chosen_arch->ase;
bbcc0807
CD
776 mips_cp0_names = chosen_arch->cp0_names;
777 mips_cp0sel_names = chosen_arch->cp0sel_names;
778 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
dc76d757 779 mips_cp1_names = chosen_arch->cp1_names;
bbcc0807 780 mips_hwr_names = chosen_arch->hwr_names;
640c0ccd
CD
781 }
782#endif
783}
784
47b0e7ad
NC
785static void
786parse_mips_dis_option (const char *option, unsigned int len)
640c0ccd
CD
787{
788 unsigned int i, optionlen, vallen;
789 const char *val;
790 const struct mips_abi_choice *chosen_abi;
791 const struct mips_arch_choice *chosen_arch;
792
986e18a5 793 /* Try to match options that are simple flags */
0112cd26 794 if (CONST_STRNEQ (option, "no-aliases"))
986e18a5
FF
795 {
796 no_aliases = 1;
797 return;
798 }
b015e599 799
4edbb8e3
CF
800 if (CONST_STRNEQ (option, "msa"))
801 {
802 mips_ase |= ASE_MSA;
803 if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R2)
804 mips_ase |= ASE_MSA64;
805 return;
806 }
807
b015e599
AP
808 if (CONST_STRNEQ (option, "virt"))
809 {
d301a56b 810 mips_ase |= ASE_VIRT;
b015e599 811 if (mips_isa & ISA_MIPS64R2)
d301a56b 812 mips_ase |= ASE_VIRT64;
b015e599
AP
813 return;
814 }
986e18a5 815
640c0ccd
CD
816 /* Look for the = that delimits the end of the option name. */
817 for (i = 0; i < len; i++)
47b0e7ad
NC
818 if (option[i] == '=')
819 break;
820
640c0ccd
CD
821 if (i == 0) /* Invalid option: no name before '='. */
822 return;
823 if (i == len) /* Invalid option: no '='. */
824 return;
825 if (i == (len - 1)) /* Invalid option: no value after '='. */
826 return;
827
828 optionlen = i;
829 val = option + (optionlen + 1);
830 vallen = len - (optionlen + 1);
831
47b0e7ad
NC
832 if (strncmp ("gpr-names", option, optionlen) == 0
833 && strlen ("gpr-names") == optionlen)
640c0ccd
CD
834 {
835 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 836 if (chosen_abi != NULL)
640c0ccd
CD
837 mips_gpr_names = chosen_abi->gpr_names;
838 return;
839 }
840
47b0e7ad
NC
841 if (strncmp ("fpr-names", option, optionlen) == 0
842 && strlen ("fpr-names") == optionlen)
640c0ccd
CD
843 {
844 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 845 if (chosen_abi != NULL)
640c0ccd
CD
846 mips_fpr_names = chosen_abi->fpr_names;
847 return;
848 }
849
47b0e7ad
NC
850 if (strncmp ("cp0-names", option, optionlen) == 0
851 && strlen ("cp0-names") == optionlen)
640c0ccd
CD
852 {
853 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807
CD
854 if (chosen_arch != NULL)
855 {
856 mips_cp0_names = chosen_arch->cp0_names;
857 mips_cp0sel_names = chosen_arch->cp0sel_names;
858 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
859 }
640c0ccd
CD
860 return;
861 }
862
dc76d757
AB
863 if (strncmp ("cp1-names", option, optionlen) == 0
864 && strlen ("cp1-names") == optionlen)
865 {
866 chosen_arch = choose_arch_by_name (val, vallen);
867 if (chosen_arch != NULL)
868 mips_cp1_names = chosen_arch->cp1_names;
869 return;
870 }
871
47b0e7ad
NC
872 if (strncmp ("hwr-names", option, optionlen) == 0
873 && strlen ("hwr-names") == optionlen)
af7ee8bf
CD
874 {
875 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807 876 if (chosen_arch != NULL)
af7ee8bf
CD
877 mips_hwr_names = chosen_arch->hwr_names;
878 return;
879 }
880
47b0e7ad
NC
881 if (strncmp ("reg-names", option, optionlen) == 0
882 && strlen ("reg-names") == optionlen)
640c0ccd
CD
883 {
884 /* We check both ABI and ARCH here unconditionally, so
885 that "numeric" will do the desirable thing: select
886 numeric register names for all registers. Other than
887 that, a given name probably won't match both. */
888 chosen_abi = choose_abi_by_name (val, vallen);
889 if (chosen_abi != NULL)
890 {
bbcc0807
CD
891 mips_gpr_names = chosen_abi->gpr_names;
892 mips_fpr_names = chosen_abi->fpr_names;
640c0ccd
CD
893 }
894 chosen_arch = choose_arch_by_name (val, vallen);
895 if (chosen_arch != NULL)
896 {
bbcc0807
CD
897 mips_cp0_names = chosen_arch->cp0_names;
898 mips_cp0sel_names = chosen_arch->cp0sel_names;
899 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
dc76d757 900 mips_cp1_names = chosen_arch->cp1_names;
bbcc0807 901 mips_hwr_names = chosen_arch->hwr_names;
640c0ccd
CD
902 }
903 return;
904 }
905
906 /* Invalid option. */
907}
908
47b0e7ad
NC
909static void
910parse_mips_dis_options (const char *options)
640c0ccd
CD
911{
912 const char *option_end;
913
914 if (options == NULL)
915 return;
916
917 while (*options != '\0')
918 {
919 /* Skip empty options. */
920 if (*options == ',')
921 {
922 options++;
923 continue;
924 }
925
926 /* We know that *options is neither NUL or a comma. */
927 option_end = options + 1;
928 while (*option_end != ',' && *option_end != '\0')
929 option_end++;
930
931 parse_mips_dis_option (options, option_end - options);
932
933 /* Go on to the next one. If option_end points to a comma, it
934 will be skipped above. */
935 options = option_end;
936 }
937}
938
bbcc0807 939static const struct mips_cp0sel_name *
47b0e7ad
NC
940lookup_mips_cp0sel_name (const struct mips_cp0sel_name *names,
941 unsigned int len,
942 unsigned int cp0reg,
943 unsigned int sel)
bbcc0807
CD
944{
945 unsigned int i;
946
947 for (i = 0; i < len; i++)
948 if (names[i].cp0reg == cp0reg && names[i].sel == sel)
949 return &names[i];
950 return NULL;
951}
ab902481
RS
952
953/* Print register REGNO, of type TYPE, for instruction OPCODE. */
aa5f19f2 954
794ac9d0 955static void
ab902481
RS
956print_reg (struct disassemble_info *info, const struct mips_opcode *opcode,
957 enum mips_reg_operand_type type, int regno)
252b5132 958{
ab902481
RS
959 switch (type)
960 {
961 case OP_REG_GP:
962 info->fprintf_func (info->stream, "%s", mips_gpr_names[regno]);
963 break;
440cc0bc 964
ab902481
RS
965 case OP_REG_FP:
966 info->fprintf_func (info->stream, "%s", mips_fpr_names[regno]);
967 break;
252b5132 968
ab902481
RS
969 case OP_REG_CCC:
970 if (opcode->pinfo & (FP_D | FP_S))
971 info->fprintf_func (info->stream, "$fcc%d", regno);
972 else
973 info->fprintf_func (info->stream, "$cc%d", regno);
974 break;
794ac9d0 975
ab902481
RS
976 case OP_REG_VEC:
977 if (opcode->membership & INSN_5400)
978 info->fprintf_func (info->stream, "$f%d", regno);
979 else
980 info->fprintf_func (info->stream, "$v%d", regno);
981 break;
794ac9d0 982
ab902481
RS
983 case OP_REG_ACC:
984 info->fprintf_func (info->stream, "$ac%d", regno);
985 break;
794ac9d0 986
ab902481
RS
987 case OP_REG_COPRO:
988 if (opcode->name[strlen (opcode->name) - 1] == '0')
989 info->fprintf_func (info->stream, "%s", mips_cp0_names[regno]);
dc76d757
AB
990 else if (opcode->name[strlen (opcode->name) - 1] == '1')
991 info->fprintf_func (info->stream, "%s", mips_cp1_names[regno]);
ab902481
RS
992 else
993 info->fprintf_func (info->stream, "$%d", regno);
994 break;
8b082fb1 995
ab902481
RS
996 case OP_REG_HW:
997 info->fprintf_func (info->stream, "%s", mips_hwr_names[regno]);
998 break;
14daeee3
RS
999
1000 case OP_REG_VF:
1001 info->fprintf_func (info->stream, "$vf%d", regno);
1002 break;
1003
1004 case OP_REG_VI:
1005 info->fprintf_func (info->stream, "$vi%d", regno);
1006 break;
1007
1008 case OP_REG_R5900_I:
1009 info->fprintf_func (info->stream, "$I");
1010 break;
1011
1012 case OP_REG_R5900_Q:
1013 info->fprintf_func (info->stream, "$Q");
1014 break;
1015
1016 case OP_REG_R5900_R:
1017 info->fprintf_func (info->stream, "$R");
1018 break;
1019
1020 case OP_REG_R5900_ACC:
1021 info->fprintf_func (info->stream, "$ACC");
1022 break;
4edbb8e3
CF
1023
1024 case OP_REG_MSA:
1025 info->fprintf_func (info->stream, "$w%d", regno);
1026 break;
1027
1028 case OP_REG_MSA_CTRL:
1029 info->fprintf_func (info->stream, "%s", msa_control_names[regno]);
1030 break;
1031
ab902481
RS
1032 }
1033}
1034\f
1035/* Used to track the state carried over from previous operands in
1036 an instruction. */
1037struct mips_print_arg_state {
1038 /* The value of the last OP_INT seen. We only use this for OP_MSB,
1039 where the value is known to be unsigned and small. */
1040 unsigned int last_int;
1041
1042 /* The type and number of the last OP_REG seen. We only use this for
1043 OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1044 enum mips_reg_operand_type last_reg_type;
1045 unsigned int last_regno;
1046};
fd25c5a9 1047
ab902481 1048/* Initialize STATE for the start of an instruction. */
fd25c5a9 1049
ab902481
RS
1050static inline void
1051init_print_arg_state (struct mips_print_arg_state *state)
1052{
1053 memset (state, 0, sizeof (*state));
1054}
fd25c5a9 1055
14daeee3
RS
1056/* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1057 whose value is given by UVAL. */
1058
1059static void
1060print_vu0_channel (struct disassemble_info *info,
1061 const struct mips_operand *operand, unsigned int uval)
1062{
1063 if (operand->size == 4)
1064 info->fprintf_func (info->stream, "%s%s%s%s",
1065 uval & 8 ? "x" : "",
1066 uval & 4 ? "y" : "",
1067 uval & 2 ? "z" : "",
1068 uval & 1 ? "w" : "");
1069 else if (operand->size == 2)
1070 info->fprintf_func (info->stream, "%c", "xyzw"[uval]);
1071 else
1072 abort ();
1073}
1074
ab902481
RS
1075/* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1076 UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1077 the base address for OP_PCREL operands. */
fd25c5a9 1078
ab902481
RS
1079static void
1080print_insn_arg (struct disassemble_info *info,
1081 struct mips_print_arg_state *state,
1082 const struct mips_opcode *opcode,
1083 const struct mips_operand *operand,
1084 bfd_vma base_pc,
1085 unsigned int uval)
1086{
1087 const fprintf_ftype infprintf = info->fprintf_func;
1088 void *is = info->stream;
fd25c5a9 1089
ab902481
RS
1090 switch (operand->type)
1091 {
1092 case OP_INT:
1093 {
1094 const struct mips_int_operand *int_op;
fd25c5a9 1095
ab902481
RS
1096 int_op = (const struct mips_int_operand *) operand;
1097 uval = mips_decode_int_operand (int_op, uval);
1098 state->last_int = uval;
1099 if (int_op->print_hex)
1100 infprintf (is, "0x%x", uval);
1101 else
1102 infprintf (is, "%d", uval);
1103 }
1104 break;
fd25c5a9 1105
ab902481
RS
1106 case OP_MAPPED_INT:
1107 {
1108 const struct mips_mapped_int_operand *mint_op;
fd25c5a9 1109
ab902481
RS
1110 mint_op = (const struct mips_mapped_int_operand *) operand;
1111 uval = mint_op->int_map[uval];
1112 state->last_int = uval;
1113 if (mint_op->print_hex)
1114 infprintf (is, "0x%x", uval);
1115 else
1116 infprintf (is, "%d", uval);
1117 }
1118 break;
fd25c5a9 1119
ab902481
RS
1120 case OP_MSB:
1121 {
1122 const struct mips_msb_operand *msb_op;
dec0624d 1123
ab902481
RS
1124 msb_op = (const struct mips_msb_operand *) operand;
1125 uval += msb_op->bias;
1126 if (msb_op->add_lsb)
1127 uval -= state->last_int;
1128 infprintf (is, "0x%x", uval);
1129 }
1130 break;
dec0624d 1131
ab902481 1132 case OP_REG:
0f35dbc4 1133 case OP_OPTIONAL_REG:
ab902481
RS
1134 {
1135 const struct mips_reg_operand *reg_op;
fd25c5a9 1136
ab902481 1137 reg_op = (const struct mips_reg_operand *) operand;
fc76e730 1138 uval = mips_decode_reg_operand (reg_op, uval);
ab902481 1139 print_reg (info, opcode, reg_op->reg_type, uval);
fd25c5a9 1140
ab902481
RS
1141 state->last_reg_type = reg_op->reg_type;
1142 state->last_regno = uval;
1143 }
1144 break;
61cc0267 1145
ab902481
RS
1146 case OP_REG_PAIR:
1147 {
1148 const struct mips_reg_pair_operand *pair_op;
1149
1150 pair_op = (const struct mips_reg_pair_operand *) operand;
1151 print_reg (info, opcode, pair_op->reg_type,
1152 pair_op->reg1_map[uval]);
1153 infprintf (is, ",");
1154 print_reg (info, opcode, pair_op->reg_type,
1155 pair_op->reg2_map[uval]);
1156 }
1157 break;
61cc0267 1158
ab902481
RS
1159 case OP_PCREL:
1160 {
1161 const struct mips_pcrel_operand *pcrel_op;
61cc0267 1162
ab902481
RS
1163 pcrel_op = (const struct mips_pcrel_operand *) operand;
1164 info->target = mips_decode_pcrel_operand (pcrel_op, base_pc, uval);
61cc0267 1165
ab902481
RS
1166 /* Preserve the ISA bit for the GDB disassembler,
1167 otherwise clear it. */
1168 if (info->flavour != bfd_target_unknown_flavour)
1169 info->target &= -2;
61cc0267 1170
ab902481
RS
1171 (*info->print_address_func) (info->target, info);
1172 }
1173 break;
794ac9d0 1174
ab902481
RS
1175 case OP_PERF_REG:
1176 infprintf (is, "%d", uval);
1177 break;
794ac9d0 1178
ab902481
RS
1179 case OP_ADDIUSP_INT:
1180 {
1181 int sval;
794ac9d0 1182
ab902481
RS
1183 sval = mips_signed_operand (operand, uval) * 4;
1184 if (sval >= -8 && sval < 8)
1185 sval ^= 0x400;
1186 infprintf (is, "%d", sval);
1187 break;
1188 }
794ac9d0 1189
ab902481
RS
1190 case OP_CLO_CLZ_DEST:
1191 {
1192 unsigned int reg1, reg2;
1193
1194 reg1 = uval & 31;
1195 reg2 = uval >> 5;
1196 /* If one is zero use the other. */
1197 if (reg1 == reg2 || reg2 == 0)
1198 infprintf (is, "%s", mips_gpr_names[reg1]);
1199 else if (reg1 == 0)
1200 infprintf (is, "%s", mips_gpr_names[reg2]);
1201 else
1202 /* Bogus, result depends on processor. */
1203 infprintf (is, "%s or %s", mips_gpr_names[reg1],
1204 mips_gpr_names[reg2]);
1205 }
1206 break;
794ac9d0 1207
ab902481
RS
1208 case OP_LWM_SWM_LIST:
1209 if (operand->size == 2)
1210 {
1211 if (uval == 0)
1212 infprintf (is, "%s,%s",
1213 mips_gpr_names[16],
1214 mips_gpr_names[31]);
1215 else
1216 infprintf (is, "%s-%s,%s",
1217 mips_gpr_names[16],
1218 mips_gpr_names[16 + uval],
1219 mips_gpr_names[31]);
1220 }
1221 else
1222 {
1223 int s_reg_encode;
794ac9d0 1224
ab902481
RS
1225 s_reg_encode = uval & 0xf;
1226 if (s_reg_encode != 0)
1227 {
1228 if (s_reg_encode == 1)
1229 infprintf (is, "%s", mips_gpr_names[16]);
1230 else if (s_reg_encode < 9)
1231 infprintf (is, "%s-%s",
1232 mips_gpr_names[16],
1233 mips_gpr_names[15 + s_reg_encode]);
1234 else if (s_reg_encode == 9)
1235 infprintf (is, "%s-%s,%s",
1236 mips_gpr_names[16],
1237 mips_gpr_names[23],
1238 mips_gpr_names[30]);
1239 else
1240 infprintf (is, "UNKNOWN");
1241 }
794ac9d0 1242
ab902481
RS
1243 if (uval & 0x10) /* For ra. */
1244 {
1245 if (s_reg_encode == 0)
1246 infprintf (is, "%s", mips_gpr_names[31]);
1247 else
1248 infprintf (is, ",%s", mips_gpr_names[31]);
1249 }
1250 }
1251 break;
794ac9d0 1252
c3c07478
RS
1253 case OP_ENTRY_EXIT_LIST:
1254 {
1255 const char *sep;
1256 unsigned int amask, smask;
1257
1258 sep = "";
1259 amask = (uval >> 3) & 7;
1260 if (amask > 0 && amask < 5)
1261 {
1262 infprintf (is, "%s", mips_gpr_names[4]);
1263 if (amask > 1)
1264 infprintf (is, "-%s", mips_gpr_names[amask + 3]);
1265 sep = ",";
1266 }
1267
1268 smask = (uval >> 1) & 3;
1269 if (smask == 3)
1270 {
1271 infprintf (is, "%s??", sep);
1272 sep = ",";
1273 }
1274 else if (smask > 0)
1275 {
1276 infprintf (is, "%s%s", sep, mips_gpr_names[16]);
1277 if (smask > 1)
1278 infprintf (is, "-%s", mips_gpr_names[smask + 15]);
1279 sep = ",";
1280 }
1281
1282 if (uval & 1)
1283 {
1284 infprintf (is, "%s%s", sep, mips_gpr_names[31]);
1285 sep = ",";
1286 }
1287
1288 if (amask == 5 || amask == 6)
1289 {
1290 infprintf (is, "%s%s", sep, mips_fpr_names[0]);
1291 if (amask == 6)
1292 infprintf (is, "-%s", mips_fpr_names[1]);
1293 }
1294 }
1295 break;
1296
1297 case OP_SAVE_RESTORE_LIST:
1298 /* Should be handled by the caller due to extend behavior. */
1299 abort ();
1300
ab902481
RS
1301 case OP_MDMX_IMM_REG:
1302 {
1303 unsigned int vsel;
794ac9d0 1304
ab902481
RS
1305 vsel = uval >> 5;
1306 uval &= 31;
1307 if ((vsel & 0x10) == 0)
794ac9d0 1308 {
ab902481
RS
1309 int fmt;
1310
1311 vsel &= 0x0f;
1312 for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
1313 if ((vsel & 1) == 0)
1314 break;
1315 print_reg (info, opcode, OP_REG_VEC, uval);
1316 infprintf (is, "[%d]", vsel >> 1);
794ac9d0 1317 }
ab902481
RS
1318 else if ((vsel & 0x08) == 0)
1319 print_reg (info, opcode, OP_REG_VEC, uval);
1320 else
1321 infprintf (is, "0x%x", uval);
1322 }
1323 break;
794ac9d0 1324
ab902481
RS
1325 case OP_REPEAT_PREV_REG:
1326 print_reg (info, opcode, state->last_reg_type, state->last_regno);
1327 break;
794ac9d0 1328
ab902481
RS
1329 case OP_REPEAT_DEST_REG:
1330 /* Should always match OP_REPEAT_PREV_REG first. */
1331 abort ();
794ac9d0 1332
ab902481
RS
1333 case OP_PC:
1334 infprintf (is, "$pc");
1335 break;
14daeee3
RS
1336
1337 case OP_VU0_SUFFIX:
1338 case OP_VU0_MATCH_SUFFIX:
1339 print_vu0_channel (info, operand, uval);
1340 break;
4edbb8e3
CF
1341
1342 case OP_IMM_INDEX:
1343 infprintf (is, "[%d]", uval);
1344 break;
1345
1346 case OP_REG_INDEX:
1347 infprintf (is, "[");
1348 print_reg (info, opcode, OP_REG_GP, uval);
1349 infprintf (is, "]");
1350 break;
ab902481
RS
1351 }
1352}
794ac9d0 1353
ab902481
RS
1354/* Print the arguments for INSN, which is described by OPCODE.
1355 Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
1356 as the base of OP_PCREL operands. */
af7ee8bf 1357
ab902481
RS
1358static void
1359print_insn_args (struct disassemble_info *info,
1360 const struct mips_opcode *opcode,
1361 const struct mips_operand *(*decode_operand) (const char *),
1362 unsigned int insn, bfd_vma base_pc)
1363{
1364 const fprintf_ftype infprintf = info->fprintf_func;
1365 void *is = info->stream;
1366 struct mips_print_arg_state state;
1367 const struct mips_operand *operand;
1368 const char *s;
794ac9d0 1369
ab902481
RS
1370 init_print_arg_state (&state);
1371 for (s = opcode->args; *s; ++s)
1372 {
1373 switch (*s)
1374 {
1375 case ',':
1376 case '(':
1377 case ')':
1378 infprintf (is, "%c", *s);
794ac9d0
CD
1379 break;
1380
14daeee3
RS
1381 case '#':
1382 ++s;
1383 infprintf (is, "%c%c", *s, *s);
1384 break;
1385
ab902481
RS
1386 default:
1387 operand = decode_operand (s);
1388 if (!operand)
fa7616a4 1389 {
ab902481
RS
1390 /* xgettext:c-format */
1391 infprintf (is,
1392 _("# internal error, undefined operand in `%s %s'"),
1393 opcode->name, opcode->args);
1394 return;
1395 }
1396 if (operand->type == OP_REG
1397 && s[1] == ','
1398 && s[2] == 'H'
1399 && opcode->name[strlen (opcode->name) - 1] == '0')
1400 {
1401 /* Coprocessor register 0 with sel field (MT ASE). */
1402 const struct mips_cp0sel_name *n;
1403 unsigned int reg, sel;
1404
1405 reg = mips_extract_operand (operand, insn);
1406 s += 2;
1407 operand = decode_operand (s);
1408 sel = mips_extract_operand (operand, insn);
1409
1410 /* CP0 register including 'sel' code for mftc0, to be
1411 printed textually if known. If not known, print both
1412 CP0 register name and sel numerically since CP0 register
1413 with sel 0 may have a name unrelated to register being
1414 printed. */
1415 n = lookup_mips_cp0sel_name (mips_cp0sel_names,
1416 mips_cp0sel_names_len,
1417 reg, sel);
1418 if (n != NULL)
1419 infprintf (is, "%s", n->name);
fa7616a4 1420 else
ab902481 1421 infprintf (is, "$%d,%d", reg, sel);
fa7616a4 1422 }
794ac9d0 1423 else
ab902481
RS
1424 print_insn_arg (info, &state, opcode, operand, base_pc,
1425 mips_extract_operand (operand, insn));
1426 if (*s == 'm' || *s == '+')
1427 ++s;
794ac9d0 1428 break;
af7ee8bf 1429 }
252b5132
RH
1430 }
1431}
1432\f
252b5132
RH
1433/* Print the mips instruction at address MEMADDR in debugged memory,
1434 on using INFO. Returns length of the instruction, in bytes, which is
aa5f19f2 1435 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
252b5132
RH
1436 this is little-endian code. */
1437
1438static int
47b0e7ad 1439print_insn_mips (bfd_vma memaddr,
fc8c4fd1 1440 int word,
47b0e7ad 1441 struct disassemble_info *info)
252b5132 1442{
ab902481
RS
1443#define GET_OP(insn, field) \
1444 (((insn) >> OP_SH_##field) & OP_MASK_##field)
fc8c4fd1
MR
1445 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
1446 const fprintf_ftype infprintf = info->fprintf_func;
47b0e7ad 1447 const struct mips_opcode *op;
b34976b6 1448 static bfd_boolean init = 0;
fc8c4fd1 1449 void *is = info->stream;
252b5132
RH
1450
1451 /* Build a hash table to shorten the search time. */
1452 if (! init)
1453 {
1454 unsigned int i;
1455
1456 for (i = 0; i <= OP_MASK_OP; i++)
1457 {
1458 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
1459 {
986e18a5 1460 if (op->pinfo == INSN_MACRO
9e836e3d 1461 || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
252b5132 1462 continue;
fc8c4fd1 1463 if (i == GET_OP (op->match, OP))
252b5132
RH
1464 {
1465 mips_hash[i] = op;
1466 break;
1467 }
1468 }
7f6621cd 1469 }
252b5132
RH
1470
1471 init = 1;
1472 }
1473
aa5f19f2 1474 info->bytes_per_chunk = INSNLEN;
252b5132 1475 info->display_endian = info->endian;
9bb28706
CD
1476 info->insn_info_valid = 1;
1477 info->branch_delay_insns = 0;
def7143b 1478 info->data_size = 0;
9bb28706
CD
1479 info->insn_type = dis_nonbranch;
1480 info->target = 0;
1481 info->target2 = 0;
252b5132 1482
fc8c4fd1 1483 op = mips_hash[GET_OP (word, OP)];
252b5132
RH
1484 if (op != NULL)
1485 {
1486 for (; op < &mips_opcodes[NUMOPCODES]; op++)
1487 {
986e18a5 1488 if (op->pinfo != INSN_MACRO
9e836e3d 1489 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
986e18a5 1490 && (word & op->mask) == op->match)
252b5132 1491 {
3396de36 1492 /* We always allow to disassemble the jalx instruction. */
d301a56b 1493 if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
3396de36 1494 && strcmp (op->name, "jalx"))
252b5132
RH
1495 continue;
1496
9bb28706
CD
1497 /* Figure out instruction type and branch delay information. */
1498 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
1499 {
fc76e730 1500 if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
9bb28706
CD
1501 info->insn_type = dis_jsr;
1502 else
1503 info->insn_type = dis_branch;
1504 info->branch_delay_insns = 1;
1505 }
1506 else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
1507 | INSN_COND_BRANCH_LIKELY)) != 0)
1508 {
c680e7f6 1509 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
9bb28706
CD
1510 info->insn_type = dis_condjsr;
1511 else
1512 info->insn_type = dis_condbranch;
1513 info->branch_delay_insns = 1;
1514 }
1515 else if ((op->pinfo & (INSN_STORE_MEMORY
67dc82bc 1516 | INSN_LOAD_MEMORY)) != 0)
9bb28706
CD
1517 info->insn_type = dis_dref;
1518
fc8c4fd1 1519 infprintf (is, "%s", op->name);
14daeee3
RS
1520 if (op->pinfo2 & INSN2_VU0_CHANNEL_SUFFIX)
1521 {
1522 unsigned int uval;
1523
1524 infprintf (is, ".");
1525 uval = mips_extract_operand (&mips_vu0_channel_mask, word);
1526 print_vu0_channel (info, &mips_vu0_channel_mask, uval);
1527 }
252b5132 1528
ab902481 1529 if (op->args[0])
252b5132 1530 {
fc8c4fd1 1531 infprintf (is, "\t");
ab902481
RS
1532 print_insn_args (info, op, decode_mips_operand, word,
1533 memaddr + 4);
252b5132
RH
1534 }
1535
aa5f19f2 1536 return INSNLEN;
252b5132
RH
1537 }
1538 }
1539 }
fc8c4fd1 1540#undef GET_OP
252b5132
RH
1541
1542 /* Handle undefined instructions. */
9bb28706 1543 info->insn_type = dis_noninsn;
fc8c4fd1 1544 infprintf (is, "0x%x", word);
aa5f19f2 1545 return INSNLEN;
252b5132 1546}
aa5f19f2 1547\f
252b5132
RH
1548/* Disassemble an operand for a mips16 instruction. */
1549
1550static void
c3c07478
RS
1551print_mips16_insn_arg (struct disassemble_info *info,
1552 struct mips_print_arg_state *state,
1553 const struct mips_opcode *opcode,
1554 char type, bfd_vma memaddr,
1555 unsigned insn, bfd_boolean use_extend,
1556 unsigned extend, bfd_boolean is_offset)
252b5132 1557{
fc8c4fd1
MR
1558 const fprintf_ftype infprintf = info->fprintf_func;
1559 void *is = info->stream;
c3c07478
RS
1560 const struct mips_operand *operand, *ext_operand;
1561 unsigned int uval;
1562 bfd_vma baseaddr;
1563
1564 if (!use_extend)
1565 extend = 0;
fc8c4fd1 1566
252b5132
RH
1567 switch (type)
1568 {
1569 case ',':
1570 case '(':
1571 case ')':
fc8c4fd1 1572 infprintf (is, "%c", type);
252b5132
RH
1573 break;
1574
c3c07478
RS
1575 default:
1576 operand = decode_mips16_operand (type, FALSE);
1577 if (!operand)
1578 {
1579 /* xgettext:c-format */
1580 infprintf (is, _("# internal error, undefined operand in `%s %s'"),
1581 opcode->name, opcode->args);
1582 return;
1583 }
252b5132 1584
c3c07478
RS
1585 if (operand->type == OP_SAVE_RESTORE_LIST)
1586 {
1587 /* Handle this case here because of the complex interation
1588 with the EXTEND opcode. */
1589 unsigned int amask, nargs, nstatics, nsreg, smask, frame_size, i, j;
1590 const char *sep;
252b5132 1591
c3c07478
RS
1592 amask = extend & 0xf;
1593 if (amask == MIPS16_ALL_ARGS)
1594 {
1595 nargs = 4;
1596 nstatics = 0;
1597 }
1598 else if (amask == MIPS16_ALL_STATICS)
1599 {
1600 nargs = 0;
1601 nstatics = 4;
1602 }
1603 else
1604 {
1605 nargs = amask >> 2;
1606 nstatics = amask & 3;
1607 }
252b5132 1608
c3c07478
RS
1609 sep = "";
1610 if (nargs > 0)
1611 {
1612 infprintf (is, "%s", mips_gpr_names[4]);
1613 if (nargs > 1)
1614 infprintf (is, "-%s", mips_gpr_names[4 + nargs - 1]);
1615 sep = ",";
1616 }
252b5132 1617
c3c07478
RS
1618 frame_size = ((extend & 0xf0) | (insn & 0x0f)) * 8;
1619 if (frame_size == 0 && !use_extend)
1620 frame_size = 128;
1621 infprintf (is, "%s%d", sep, frame_size);
1622
1623 if (insn & 0x40) /* $ra */
1624 infprintf (is, ",%s", mips_gpr_names[31]);
1625
1626 nsreg = (extend >> 8) & 0x7;
1627 smask = 0;
1628 if (insn & 0x20) /* $s0 */
1629 smask |= 1 << 0;
1630 if (insn & 0x10) /* $s1 */
1631 smask |= 1 << 1;
1632 if (nsreg > 0) /* $s2-$s8 */
1633 smask |= ((1 << nsreg) - 1) << 2;
1634
1635 for (i = 0; i < 9; i++)
1636 if (smask & (1 << i))
252b5132 1637 {
c3c07478
RS
1638 infprintf (is, ",%s", mips_gpr_names[i == 8 ? 30 : (16 + i)]);
1639 /* Skip over string of set bits. */
1640 for (j = i; smask & (2 << j); j++)
1641 continue;
1642 if (j > i)
1643 infprintf (is, "-%s", mips_gpr_names[j == 8 ? 30 : (16 + j)]);
1644 i = j + 1;
252b5132 1645 }
c3c07478
RS
1646 /* Statics $ax - $a3. */
1647 if (nstatics == 1)
1648 infprintf (is, ",%s", mips_gpr_names[7]);
1649 else if (nstatics > 0)
1650 infprintf (is, ",%s-%s",
1651 mips_gpr_names[7 - nstatics + 1],
1652 mips_gpr_names[7]);
1653 break;
1654 }
252b5132 1655
c3c07478
RS
1656 if (is_offset && operand->type == OP_INT)
1657 {
1658 const struct mips_int_operand *int_op;
252b5132 1659
c3c07478
RS
1660 int_op = (const struct mips_int_operand *) operand;
1661 info->insn_type = dis_dref;
1662 info->data_size = 1 << int_op->shift;
1663 }
252b5132 1664
c3c07478
RS
1665 if (operand->size == 26)
1666 /* In this case INSN is the first two bytes of the instruction
1667 and EXTEND is the second two bytes. */
1668 uval = ((insn & 0x1f) << 21) | ((insn & 0x3e0) << 11) | extend;
1669 else
1670 {
1671 /* Calculate the full field value. */
1672 uval = mips_extract_operand (operand, insn);
1673 if (use_extend)
1674 {
1675 ext_operand = decode_mips16_operand (type, TRUE);
1676 if (ext_operand != operand)
1677 {
1678 operand = ext_operand;
1679 if (operand->size == 16)
1680 uval |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1681 else if (operand->size == 15)
1682 uval |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1683 else
1684 uval = ((extend >> 6) & 0x1f) | (extend & 0x20);
1685 }
1686 }
1687 }
1688
1689 baseaddr = memaddr + 2;
1690 if (operand->type == OP_PCREL)
1691 {
1692 const struct mips_pcrel_operand *pcrel_op;
1693
1694 pcrel_op = (const struct mips_pcrel_operand *) operand;
1695 if (!pcrel_op->include_isa_bit && use_extend)
1696 baseaddr = memaddr - 2;
1697 else if (!pcrel_op->include_isa_bit)
1698 {
1699 bfd_byte buffer[2];
1700
1701 /* If this instruction is in the delay slot of a JR
1702 instruction, the base address is the address of the
1703 JR instruction. If it is in the delay slot of a JALR
1704 instruction, the base address is the address of the
1705 JALR instruction. This test is unreliable: we have
1706 no way of knowing whether the previous word is
1707 instruction or data. */
1708 if (info->read_memory_func (memaddr - 4, buffer, 2, info) == 0
1709 && (((info->endian == BFD_ENDIAN_BIG
1710 ? bfd_getb16 (buffer)
1711 : bfd_getl16 (buffer))
1712 & 0xf800) == 0x1800))
1713 baseaddr = memaddr - 4;
1714 else if (info->read_memory_func (memaddr - 2, buffer, 2,
1715 info) == 0
252b5132
RH
1716 && (((info->endian == BFD_ENDIAN_BIG
1717 ? bfd_getb16 (buffer)
1718 : bfd_getl16 (buffer))
1719 & 0xf81f) == 0xe800))
c3c07478
RS
1720 baseaddr = memaddr - 2;
1721 else
1722 baseaddr = memaddr;
1723 }
1724 }
0499d65b 1725
6d075bce 1726 print_insn_arg (info, state, opcode, operand, baseaddr + 1, uval);
0499d65b 1727 break;
252b5132
RH
1728 }
1729}
640c0ccd 1730
1bbce132
MR
1731
1732/* Check if the given address is the last word of a MIPS16 PLT entry.
1733 This word is data and depending on the value it may interfere with
1734 disassembly of further PLT entries. We make use of the fact PLT
1735 symbols are marked BSF_SYNTHETIC. */
1736static bfd_boolean
1737is_mips16_plt_tail (struct disassemble_info *info, bfd_vma addr)
1738{
1739 if (info->symbols
1740 && info->symbols[0]
1741 && (info->symbols[0]->flags & BSF_SYNTHETIC)
1742 && addr == bfd_asymbol_value (info->symbols[0]) + 12)
1743 return TRUE;
1744
1745 return FALSE;
1746}
1747
47b0e7ad
NC
1748/* Disassemble mips16 instructions. */
1749
1750static int
1751print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
1752{
fc8c4fd1 1753 const fprintf_ftype infprintf = info->fprintf_func;
47b0e7ad 1754 int status;
1bbce132 1755 bfd_byte buffer[4];
47b0e7ad
NC
1756 int length;
1757 int insn;
1758 bfd_boolean use_extend;
1759 int extend = 0;
1760 const struct mips_opcode *op, *opend;
c3c07478 1761 struct mips_print_arg_state state;
fc8c4fd1 1762 void *is = info->stream;
47b0e7ad
NC
1763
1764 info->bytes_per_chunk = 2;
1765 info->display_endian = info->endian;
1766 info->insn_info_valid = 1;
1767 info->branch_delay_insns = 0;
1768 info->data_size = 0;
47b0e7ad
NC
1769 info->target = 0;
1770 info->target2 = 0;
1771
c3c07478
RS
1772#define GET_OP(insn, field) \
1773 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
1bbce132
MR
1774 /* Decode PLT entry's GOT slot address word. */
1775 if (is_mips16_plt_tail (info, memaddr))
1776 {
1777 info->insn_type = dis_noninsn;
1778 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
1779 if (status == 0)
1780 {
1781 unsigned int gotslot;
1782
1783 if (info->endian == BFD_ENDIAN_BIG)
1784 gotslot = bfd_getb32 (buffer);
1785 else
1786 gotslot = bfd_getl32 (buffer);
1787 infprintf (is, ".word\t0x%x", gotslot);
1788
1789 return 4;
1790 }
1791 }
1792 else
1793 {
1794 info->insn_type = dis_nonbranch;
1795 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
1796 }
47b0e7ad
NC
1797 if (status != 0)
1798 {
1799 (*info->memory_error_func) (status, memaddr, info);
1800 return -1;
1801 }
1802
1803 length = 2;
1804
1805 if (info->endian == BFD_ENDIAN_BIG)
1806 insn = bfd_getb16 (buffer);
1807 else
1808 insn = bfd_getl16 (buffer);
1809
1810 /* Handle the extend opcode specially. */
1811 use_extend = FALSE;
1812 if ((insn & 0xf800) == 0xf000)
1813 {
1814 use_extend = TRUE;
1815 extend = insn & 0x7ff;
1816
1817 memaddr += 2;
1818
1819 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
1820 if (status != 0)
1821 {
fc8c4fd1 1822 infprintf (is, "extend 0x%x", (unsigned int) extend);
47b0e7ad
NC
1823 (*info->memory_error_func) (status, memaddr, info);
1824 return -1;
1825 }
1826
1827 if (info->endian == BFD_ENDIAN_BIG)
1828 insn = bfd_getb16 (buffer);
1829 else
1830 insn = bfd_getl16 (buffer);
1831
1832 /* Check for an extend opcode followed by an extend opcode. */
1833 if ((insn & 0xf800) == 0xf000)
1834 {
fc8c4fd1 1835 infprintf (is, "extend 0x%x", (unsigned int) extend);
47b0e7ad
NC
1836 info->insn_type = dis_noninsn;
1837 return length;
1838 }
1839
1840 length += 2;
1841 }
1842
1843 /* FIXME: Should probably use a hash table on the major opcode here. */
1844
1845 opend = mips16_opcodes + bfd_mips16_num_opcodes;
1846 for (op = mips16_opcodes; op < opend; op++)
1847 {
1848 if (op->pinfo != INSN_MACRO
1849 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
1850 && (insn & op->mask) == op->match)
1851 {
1852 const char *s;
1853
27c5c572 1854 if (op->args[0] == 'a' || op->args[0] == 'i')
47b0e7ad
NC
1855 {
1856 if (use_extend)
1857 {
fc8c4fd1 1858 infprintf (is, "extend 0x%x", (unsigned int) extend);
47b0e7ad
NC
1859 info->insn_type = dis_noninsn;
1860 return length - 2;
1861 }
1862
1863 use_extend = FALSE;
1864
1865 memaddr += 2;
1866
1867 status = (*info->read_memory_func) (memaddr, buffer, 2,
1868 info);
1869 if (status == 0)
1870 {
1871 use_extend = TRUE;
1872 if (info->endian == BFD_ENDIAN_BIG)
1873 extend = bfd_getb16 (buffer);
1874 else
1875 extend = bfd_getl16 (buffer);
1876 length += 2;
1877 }
1878 }
1879
fc8c4fd1 1880 infprintf (is, "%s", op->name);
47b0e7ad 1881 if (op->args[0] != '\0')
fc8c4fd1 1882 infprintf (is, "\t");
47b0e7ad 1883
c3c07478 1884 init_print_arg_state (&state);
47b0e7ad
NC
1885 for (s = op->args; *s != '\0'; s++)
1886 {
1887 if (*s == ','
1888 && s[1] == 'w'
fc8c4fd1 1889 && GET_OP (insn, RX) == GET_OP (insn, RY))
47b0e7ad
NC
1890 {
1891 /* Skip the register and the comma. */
1892 ++s;
1893 continue;
1894 }
1895 if (*s == ','
1896 && s[1] == 'v'
fc8c4fd1 1897 && GET_OP (insn, RZ) == GET_OP (insn, RX))
47b0e7ad
NC
1898 {
1899 /* Skip the register and the comma. */
1900 ++s;
1901 continue;
1902 }
c3c07478
RS
1903 print_mips16_insn_arg (info, &state, op, *s, memaddr, insn,
1904 use_extend, extend, s[1] == '(');
47b0e7ad
NC
1905 }
1906
9a2c7088 1907 /* Figure out branch instruction type and delay slot information. */
47b0e7ad 1908 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
9a2c7088 1909 info->branch_delay_insns = 1;
26545944
RS
1910 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0
1911 || (op->pinfo2 & INSN2_UNCOND_BRANCH) != 0)
47b0e7ad 1912 {
9a2c7088
MR
1913 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
1914 info->insn_type = dis_jsr;
1915 else
47b0e7ad
NC
1916 info->insn_type = dis_branch;
1917 }
26545944 1918 else if ((op->pinfo2 & INSN2_COND_BRANCH) != 0)
9a2c7088 1919 info->insn_type = dis_condbranch;
47b0e7ad
NC
1920
1921 return length;
1922 }
1923 }
fc8c4fd1 1924#undef GET_OP
47b0e7ad
NC
1925
1926 if (use_extend)
fc8c4fd1
MR
1927 infprintf (is, "0x%x", extend | 0xf000);
1928 infprintf (is, "0x%x", insn);
47b0e7ad
NC
1929 info->insn_type = dis_noninsn;
1930
1931 return length;
1932}
1933
df58fc94
RS
1934/* Disassemble microMIPS instructions. */
1935
1936static int
1937print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
1938{
0c7533d3 1939 const fprintf_ftype infprintf = info->fprintf_func;
df58fc94 1940 const struct mips_opcode *op, *opend;
df58fc94 1941 void *is = info->stream;
df58fc94 1942 bfd_byte buffer[2];
ab902481
RS
1943 unsigned int higher;
1944 unsigned int length;
df58fc94 1945 int status;
ab902481 1946 unsigned int insn;
df58fc94
RS
1947
1948 info->bytes_per_chunk = 2;
1949 info->display_endian = info->endian;
1950 info->insn_info_valid = 1;
1951 info->branch_delay_insns = 0;
1952 info->data_size = 0;
1953 info->insn_type = dis_nonbranch;
1954 info->target = 0;
1955 info->target2 = 0;
1956
1957 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
1958 if (status != 0)
1959 {
1960 (*info->memory_error_func) (status, memaddr, info);
1961 return -1;
1962 }
1963
1964 length = 2;
1965
1966 if (info->endian == BFD_ENDIAN_BIG)
1967 insn = bfd_getb16 (buffer);
1968 else
1969 insn = bfd_getl16 (buffer);
1970
1971 if ((insn & 0xfc00) == 0x7c00)
1972 {
1973 /* This is a 48-bit microMIPS instruction. */
1974 higher = insn;
1975
1976 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
1977 if (status != 0)
1978 {
0c7533d3 1979 infprintf (is, "micromips 0x%x", higher);
df58fc94
RS
1980 (*info->memory_error_func) (status, memaddr + 2, info);
1981 return -1;
1982 }
1983 if (info->endian == BFD_ENDIAN_BIG)
1984 insn = bfd_getb16 (buffer);
1985 else
1986 insn = bfd_getl16 (buffer);
1987 higher = (higher << 16) | insn;
1988
1989 status = (*info->read_memory_func) (memaddr + 4, buffer, 2, info);
1990 if (status != 0)
1991 {
0c7533d3 1992 infprintf (is, "micromips 0x%x", higher);
df58fc94
RS
1993 (*info->memory_error_func) (status, memaddr + 4, info);
1994 return -1;
1995 }
1996 if (info->endian == BFD_ENDIAN_BIG)
1997 insn = bfd_getb16 (buffer);
1998 else
1999 insn = bfd_getl16 (buffer);
0c7533d3 2000 infprintf (is, "0x%x%04x (48-bit insn)", higher, insn);
df58fc94
RS
2001
2002 info->insn_type = dis_noninsn;
2003 return 6;
2004 }
2005 else if ((insn & 0x1c00) == 0x0000 || (insn & 0x1000) == 0x1000)
2006 {
2007 /* This is a 32-bit microMIPS instruction. */
2008 higher = insn;
2009
2010 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2011 if (status != 0)
2012 {
0c7533d3 2013 infprintf (is, "micromips 0x%x", higher);
df58fc94
RS
2014 (*info->memory_error_func) (status, memaddr + 2, info);
2015 return -1;
2016 }
2017
2018 if (info->endian == BFD_ENDIAN_BIG)
2019 insn = bfd_getb16 (buffer);
2020 else
2021 insn = bfd_getl16 (buffer);
2022
2023 insn = insn | (higher << 16);
2024
2025 length += 2;
2026 }
2027
2028 /* FIXME: Should probably use a hash table on the major opcode here. */
2029
df58fc94
RS
2030 opend = micromips_opcodes + bfd_micromips_num_opcodes;
2031 for (op = micromips_opcodes; op < opend; op++)
2032 {
2033 if (op->pinfo != INSN_MACRO
2034 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
2035 && (insn & op->mask) == op->match
2036 && ((length == 2 && (op->mask & 0xffff0000) == 0)
2037 || (length == 4 && (op->mask & 0xffff0000) != 0)))
2038 {
0c7533d3 2039 infprintf (is, "%s", op->name);
df58fc94 2040
ab902481 2041 if (op->args[0])
df58fc94 2042 {
ab902481
RS
2043 infprintf (is, "\t");
2044 print_insn_args (info, op, decode_micromips_operand, insn,
2045 memaddr + length + 1);
df58fc94
RS
2046 }
2047
2048 /* Figure out instruction type and branch delay information. */
2049 if ((op->pinfo
2050 & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY)) != 0)
2051 info->branch_delay_insns = 1;
2052 if (((op->pinfo & INSN_UNCOND_BRANCH_DELAY)
2053 | (op->pinfo2 & INSN2_UNCOND_BRANCH)) != 0)
2054 {
fc76e730 2055 if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
df58fc94
RS
2056 info->insn_type = dis_jsr;
2057 else
2058 info->insn_type = dis_branch;
2059 }
2060 else if (((op->pinfo & INSN_COND_BRANCH_DELAY)
2061 | (op->pinfo2 & INSN2_COND_BRANCH)) != 0)
2062 {
2063 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2064 info->insn_type = dis_condjsr;
2065 else
2066 info->insn_type = dis_condbranch;
2067 }
2068 else if ((op->pinfo
67dc82bc 2069 & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY)) != 0)
df58fc94
RS
2070 info->insn_type = dis_dref;
2071
2072 return length;
2073 }
2074 }
df58fc94 2075
0c7533d3 2076 infprintf (is, "0x%x", insn);
df58fc94
RS
2077 info->insn_type = dis_noninsn;
2078
2079 return length;
2080}
2081
2082/* Return 1 if a symbol associated with the location being disassembled
2083 indicates a compressed (MIPS16 or microMIPS) mode. We iterate over
2084 all the symbols at the address being considered assuming if at least
2085 one of them indicates code compression, then such code has been
2086 genuinely produced here (other symbols could have been derived from
2087 function symbols defined elsewhere or could define data). Otherwise,
2088 return 0. */
2089
2090static bfd_boolean
2091is_compressed_mode_p (struct disassemble_info *info)
2092{
df58fc94 2093 int i;
1bbce132
MR
2094 int l;
2095
2096 for (i = info->symtab_pos, l = i + info->num_symbols; i < l; i++)
2097 if (((info->symtab[i])->flags & BSF_SYNTHETIC) != 0
2098 && ((!micromips_ase
2099 && ELF_ST_IS_MIPS16 ((*info->symbols)->udata.i))
2100 || (micromips_ase
2101 && ELF_ST_IS_MICROMIPS ((*info->symbols)->udata.i))))
2102 return 1;
2103 else if (bfd_asymbol_flavour (info->symtab[i]) == bfd_target_elf_flavour
2104 && info->symtab[i]->section == info->section)
2105 {
2106 elf_symbol_type *symbol = (elf_symbol_type *) info->symtab[i];
2107 if ((!micromips_ase
2108 && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
2109 || (micromips_ase
2110 && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
2111 return 1;
2112 }
df58fc94
RS
2113
2114 return 0;
2115}
2116
47b0e7ad
NC
2117/* In an environment where we do not know the symbol type of the
2118 instruction we are forced to assume that the low order bit of the
2119 instructions' address may mark it as a mips16 instruction. If we
2120 are single stepping, or the pc is within the disassembled function,
2121 this works. Otherwise, we need a clue. Sometimes. */
2122
2123static int
2124_print_insn_mips (bfd_vma memaddr,
2125 struct disassemble_info *info,
2126 enum bfd_endian endianness)
2127{
df58fc94 2128 int (*print_insn_compr) (bfd_vma, struct disassemble_info *);
47b0e7ad
NC
2129 bfd_byte buffer[INSNLEN];
2130 int status;
2131
2132 set_default_mips_dis_options (info);
2133 parse_mips_dis_options (info->disassembler_options);
2134
df58fc94
RS
2135 if (info->mach == bfd_mach_mips16)
2136 return print_insn_mips16 (memaddr, info);
2137 if (info->mach == bfd_mach_mips_micromips)
2138 return print_insn_micromips (memaddr, info);
2139
2140 print_insn_compr = !micromips_ase ? print_insn_mips16 : print_insn_micromips;
2141
47b0e7ad 2142#if 1
df58fc94 2143 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
47b0e7ad
NC
2144 /* Only a few tools will work this way. */
2145 if (memaddr & 0x01)
df58fc94 2146 return print_insn_compr (memaddr, info);
47b0e7ad
NC
2147#endif
2148
2149#if SYMTAB_AVAILABLE
df58fc94
RS
2150 if (is_compressed_mode_p (info))
2151 return print_insn_compr (memaddr, info);
47b0e7ad
NC
2152#endif
2153
2154 status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
2155 if (status == 0)
2156 {
fc8c4fd1 2157 int insn;
47b0e7ad
NC
2158
2159 if (endianness == BFD_ENDIAN_BIG)
fc8c4fd1 2160 insn = bfd_getb32 (buffer);
47b0e7ad 2161 else
fc8c4fd1 2162 insn = bfd_getl32 (buffer);
47b0e7ad
NC
2163
2164 return print_insn_mips (memaddr, insn, info);
2165 }
2166 else
2167 {
2168 (*info->memory_error_func) (status, memaddr, info);
2169 return -1;
2170 }
2171}
2172
2173int
2174print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info)
2175{
2176 return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
2177}
2178
2179int
2180print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info)
2181{
2182 return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
2183}
2184\f
640c0ccd 2185void
47b0e7ad 2186print_mips_disassembler_options (FILE *stream)
640c0ccd 2187{
4a9a3c54 2188 unsigned int i;
640c0ccd
CD
2189
2190 fprintf (stream, _("\n\
2191The following MIPS specific disassembler options are supported for use\n\
2192with the -M switch (multiple options should be separated by commas):\n"));
2193
4edbb8e3
CF
2194 fprintf (stream, _("\n\
2195 msa Recognize MSA instructions.\n"));
2196
b015e599
AP
2197 fprintf (stream, _("\n\
2198 virt Recognize the virtualization ASE instructions.\n"));
2199
640c0ccd
CD
2200 fprintf (stream, _("\n\
2201 gpr-names=ABI Print GPR names according to specified ABI.\n\
2202 Default: based on binary being disassembled.\n"));
2203
2204 fprintf (stream, _("\n\
2205 fpr-names=ABI Print FPR names according to specified ABI.\n\
2206 Default: numeric.\n"));
2207
2208 fprintf (stream, _("\n\
2209 cp0-names=ARCH Print CP0 register names according to\n\
2210 specified architecture.\n\
2211 Default: based on binary being disassembled.\n"));
2212
af7ee8bf
CD
2213 fprintf (stream, _("\n\
2214 hwr-names=ARCH Print HWR names according to specified \n\
2215 architecture.\n\
2216 Default: based on binary being disassembled.\n"));
2217
640c0ccd
CD
2218 fprintf (stream, _("\n\
2219 reg-names=ABI Print GPR and FPR names according to\n\
2220 specified ABI.\n"));
2221
2222 fprintf (stream, _("\n\
af7ee8bf 2223 reg-names=ARCH Print CP0 register and HWR names according to\n\
640c0ccd
CD
2224 specified architecture.\n"));
2225
2226 fprintf (stream, _("\n\
2227 For the options above, the following values are supported for \"ABI\":\n\
2228 "));
4a9a3c54 2229 for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
640c0ccd
CD
2230 fprintf (stream, " %s", mips_abi_choices[i].name);
2231 fprintf (stream, _("\n"));
2232
2233 fprintf (stream, _("\n\
2234 For the options above, The following values are supported for \"ARCH\":\n\
2235 "));
4a9a3c54 2236 for (i = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
640c0ccd
CD
2237 if (*mips_arch_choices[i].name != '\0')
2238 fprintf (stream, " %s", mips_arch_choices[i].name);
2239 fprintf (stream, _("\n"));
2240
2241 fprintf (stream, _("\n"));
2242}