]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/mips-dis.c
aarch64: Add some DT_RELR ld tests
[thirdparty/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
252b5132 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
fd67aa11 2 Copyright (C) 1989-2024 Free Software Foundation, Inc.
252b5132
RH
3 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
4
9b201bb5 5 This file is part of the GNU opcodes library.
252b5132 6
9b201bb5 7 This library is free software; you can redistribute it and/or modify
47b0e7ad 8 it under the terms of the GNU General Public License as published by
9b201bb5
NC
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
252b5132 11
9b201bb5
NC
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
252b5132 16
47b0e7ad
NC
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
252b5132 21
252b5132 22#include "sysdep.h"
6394c606 23#include "disassemble.h"
640c0ccd 24#include "libiberty.h"
252b5132
RH
25#include "opcode/mips.h"
26#include "opintl.h"
7beeaeb8
AM
27#include "elf-bfd.h"
28#include "elf/mips.h"
29#include "elfxx-mips.h"
252b5132
RH
30
31/* FIXME: These are needed to figure out if the code is mips16 or
32 not. The low bit of the address is often a good indicator. No
33 symbol table is available when this code runs out in an embedded
7f6621cd 34 system as when it is used for disassembler support in a monitor. */
252b5132
RH
35
36#if !defined(EMBEDDED_ENV)
37#define SYMTAB_AVAILABLE 1
252b5132
RH
38#endif
39
aa5f19f2
NC
40/* Mips instructions are at maximum this many bytes long. */
41#define INSNLEN 4
42
252b5132 43\f
aa5f19f2 44/* FIXME: These should be shared with gdb somehow. */
252b5132 45
47b0e7ad
NC
46struct mips_cp0sel_name
47{
48 unsigned int cp0reg;
49 unsigned int sel;
50 const char * const name;
bbcc0807
CD
51};
52
47b0e7ad
NC
53static const char * const mips_gpr_names_numeric[32] =
54{
640c0ccd
CD
55 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
56 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
57 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
58 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
aa5f19f2
NC
59};
60
47b0e7ad
NC
61static const char * const mips_gpr_names_oldabi[32] =
62{
640c0ccd
CD
63 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
64 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
65 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
66 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
aa5f19f2
NC
67};
68
47b0e7ad
NC
69static const char * const mips_gpr_names_newabi[32] =
70{
640c0ccd 71 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
0b14f26e 72 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
640c0ccd
CD
73 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
74 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
75};
76
47b0e7ad
NC
77static const char * const mips_fpr_names_numeric[32] =
78{
640c0ccd
CD
79 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
80 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
81 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
82 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
83};
84
47b0e7ad
NC
85static const char * const mips_fpr_names_32[32] =
86{
640c0ccd
CD
87 "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
88 "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
89 "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f",
90 "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f"
91};
92
47b0e7ad
NC
93static const char * const mips_fpr_names_n32[32] =
94{
640c0ccd
CD
95 "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3",
96 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
97 "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9",
98 "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13"
99};
100
47b0e7ad
NC
101static const char * const mips_fpr_names_64[32] =
102{
640c0ccd
CD
103 "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
104 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
105 "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
106 "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
107};
108
47b0e7ad
NC
109static const char * const mips_cp0_names_numeric[32] =
110{
640c0ccd
CD
111 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
112 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
113 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
114 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
115};
116
dc76d757
AB
117static const char * const mips_cp1_names_numeric[32] =
118{
119 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
120 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
121 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
122 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
123};
124
a3fb396f
MR
125static const char * const mips_cp0_names_r3900[32] =
126{
127 "$0", "$1", "$2", "c0_config",
128 "$4", "$5", "$6", "c0_cache",
129 "c0_badvaddr", "$9", "$10", "$11",
130 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
131 "c0_debug", "c0_depc", "$18", "$19",
132 "$20", "$21", "$22", "$23",
133 "$24", "$25", "$26", "$27",
134 "$28", "$29", "$30", "$31",
135};
136
f409fd1e
MR
137static const char * const mips_cp0_names_r3000[32] =
138{
139 "c0_index", "c0_random", "c0_entrylo", "$3",
140 "c0_context", "$5", "$6", "$7",
141 "c0_badvaddr", "$9", "c0_entryhi", "$11",
142 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
143 "$16", "$17", "$18", "$19",
144 "$20", "$21", "$22", "$23",
145 "$24", "$25", "$26", "$27",
146 "$28", "$29", "$30", "$31",
147};
148
149static const char * const mips_cp0_names_r4000[32] =
150{
151 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
152 "c0_context", "c0_pagemask", "c0_wired", "$7",
153 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
154 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
155 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
156 "c0_xcontext", "$21", "$22", "$23",
157 "$24", "$25", "c0_ecc", "c0_cacheerr",
158 "c0_taglo", "c0_taghi", "c0_errorepc", "$31",
159};
160
e407c74b
NC
161static const char * const mips_cp0_names_r5900[32] =
162{
163 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
164 "c0_context", "c0_pagemask", "c0_wired", "$7",
165 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
166 "c0_sr", "c0_cause", "c0_epc", "c0_prid",
167 "c0_config", "$17", "$18", "$19",
168 "$20", "$21", "$22", "c0_badpaddr",
169 "c0_depc", "c0_perfcnt", "$26", "$27",
170 "c0_taglo", "c0_taghi", "c0_errorepc", "$31"
171};
172
47b0e7ad
NC
173static const char * const mips_cp0_names_mips3264[32] =
174{
640c0ccd
CD
175 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
176 "c0_context", "c0_pagemask", "c0_wired", "$7",
177 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
178 "c0_status", "c0_cause", "c0_epc", "c0_prid",
179 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
180 "c0_xcontext", "$21", "$22", "c0_debug",
181 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
182 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
183};
184
dd844468
MR
185static const char * const mips_cp1_names_mips[32] =
186{
187 "c1_fir", "$1", "$2", "$3",
188 "$4", "$5", "$6", "$7",
189 "$8", "$9", "$10", "$11",
190 "$12", "$13", "$14", "$15",
191 "$16", "$17", "$18", "$19",
192 "$20", "$21", "$22", "$23",
193 "$24", "$25", "$26", "$27",
194 "$28", "$29", "$30", "c1_fcsr"
195};
196
dc76d757
AB
197static const char * const mips_cp1_names_mips3264[32] =
198{
199 "c1_fir", "c1_ufr", "$2", "$3",
200 "c1_unfr", "$5", "$6", "$7",
201 "$8", "$9", "$10", "$11",
202 "$12", "$13", "$14", "$15",
203 "$16", "$17", "$18", "$19",
204 "$20", "$21", "$22", "$23",
205 "$24", "c1_fccr", "c1_fexr", "$27",
206 "c1_fenr", "$29", "$30", "c1_fcsr"
207};
208
47b0e7ad
NC
209static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] =
210{
bbcc0807
CD
211 { 16, 1, "c0_config1" },
212 { 16, 2, "c0_config2" },
213 { 16, 3, "c0_config3" },
214 { 18, 1, "c0_watchlo,1" },
215 { 18, 2, "c0_watchlo,2" },
216 { 18, 3, "c0_watchlo,3" },
217 { 18, 4, "c0_watchlo,4" },
218 { 18, 5, "c0_watchlo,5" },
219 { 18, 6, "c0_watchlo,6" },
220 { 18, 7, "c0_watchlo,7" },
221 { 19, 1, "c0_watchhi,1" },
222 { 19, 2, "c0_watchhi,2" },
223 { 19, 3, "c0_watchhi,3" },
224 { 19, 4, "c0_watchhi,4" },
225 { 19, 5, "c0_watchhi,5" },
226 { 19, 6, "c0_watchhi,6" },
227 { 19, 7, "c0_watchhi,7" },
228 { 25, 1, "c0_perfcnt,1" },
229 { 25, 2, "c0_perfcnt,2" },
230 { 25, 3, "c0_perfcnt,3" },
231 { 25, 4, "c0_perfcnt,4" },
232 { 25, 5, "c0_perfcnt,5" },
233 { 25, 6, "c0_perfcnt,6" },
234 { 25, 7, "c0_perfcnt,7" },
235 { 27, 1, "c0_cacheerr,1" },
236 { 27, 2, "c0_cacheerr,2" },
237 { 27, 3, "c0_cacheerr,3" },
238 { 28, 1, "c0_datalo" },
239 { 29, 1, "c0_datahi" }
240};
241
47b0e7ad
NC
242static const char * const mips_cp0_names_mips3264r2[32] =
243{
af7ee8bf
CD
244 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
245 "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
246 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
247 "c0_status", "c0_cause", "c0_epc", "c0_prid",
248 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
249 "c0_xcontext", "$21", "$22", "c0_debug",
250 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
251 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
252};
253
47b0e7ad
NC
254static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] =
255{
bbcc0807 256 { 4, 1, "c0_contextconfig" },
59c455b3
TS
257 { 0, 1, "c0_mvpcontrol" },
258 { 0, 2, "c0_mvpconf0" },
259 { 0, 3, "c0_mvpconf1" },
260 { 1, 1, "c0_vpecontrol" },
261 { 1, 2, "c0_vpeconf0" },
262 { 1, 3, "c0_vpeconf1" },
263 { 1, 4, "c0_yqmask" },
264 { 1, 5, "c0_vpeschedule" },
265 { 1, 6, "c0_vpeschefback" },
266 { 2, 1, "c0_tcstatus" },
267 { 2, 2, "c0_tcbind" },
268 { 2, 3, "c0_tcrestart" },
269 { 2, 4, "c0_tchalt" },
270 { 2, 5, "c0_tccontext" },
271 { 2, 6, "c0_tcschedule" },
272 { 2, 7, "c0_tcschefback" },
bbcc0807 273 { 5, 1, "c0_pagegrain" },
59c455b3
TS
274 { 6, 1, "c0_srsconf0" },
275 { 6, 2, "c0_srsconf1" },
276 { 6, 3, "c0_srsconf2" },
277 { 6, 4, "c0_srsconf3" },
278 { 6, 5, "c0_srsconf4" },
bbcc0807
CD
279 { 12, 1, "c0_intctl" },
280 { 12, 2, "c0_srsctl" },
281 { 12, 3, "c0_srsmap" },
282 { 15, 1, "c0_ebase" },
283 { 16, 1, "c0_config1" },
284 { 16, 2, "c0_config2" },
285 { 16, 3, "c0_config3" },
286 { 18, 1, "c0_watchlo,1" },
287 { 18, 2, "c0_watchlo,2" },
288 { 18, 3, "c0_watchlo,3" },
289 { 18, 4, "c0_watchlo,4" },
290 { 18, 5, "c0_watchlo,5" },
291 { 18, 6, "c0_watchlo,6" },
292 { 18, 7, "c0_watchlo,7" },
293 { 19, 1, "c0_watchhi,1" },
294 { 19, 2, "c0_watchhi,2" },
295 { 19, 3, "c0_watchhi,3" },
296 { 19, 4, "c0_watchhi,4" },
297 { 19, 5, "c0_watchhi,5" },
298 { 19, 6, "c0_watchhi,6" },
299 { 19, 7, "c0_watchhi,7" },
300 { 23, 1, "c0_tracecontrol" },
301 { 23, 2, "c0_tracecontrol2" },
302 { 23, 3, "c0_usertracedata" },
303 { 23, 4, "c0_tracebpc" },
304 { 25, 1, "c0_perfcnt,1" },
305 { 25, 2, "c0_perfcnt,2" },
306 { 25, 3, "c0_perfcnt,3" },
307 { 25, 4, "c0_perfcnt,4" },
308 { 25, 5, "c0_perfcnt,5" },
309 { 25, 6, "c0_perfcnt,6" },
310 { 25, 7, "c0_perfcnt,7" },
311 { 27, 1, "c0_cacheerr,1" },
312 { 27, 2, "c0_cacheerr,2" },
313 { 27, 3, "c0_cacheerr,3" },
314 { 28, 1, "c0_datalo" },
315 { 28, 2, "c0_taglo1" },
316 { 28, 3, "c0_datalo1" },
317 { 28, 4, "c0_taglo2" },
318 { 28, 5, "c0_datalo2" },
319 { 28, 6, "c0_taglo3" },
320 { 28, 7, "c0_datalo3" },
321 { 29, 1, "c0_datahi" },
322 { 29, 2, "c0_taghi1" },
323 { 29, 3, "c0_datahi1" },
324 { 29, 4, "c0_taghi2" },
325 { 29, 5, "c0_datahi2" },
326 { 29, 6, "c0_taghi3" },
327 { 29, 7, "c0_datahi3" },
328};
329
640c0ccd 330/* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
47b0e7ad
NC
331static const char * const mips_cp0_names_sb1[32] =
332{
640c0ccd
CD
333 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
334 "c0_context", "c0_pagemask", "c0_wired", "$7",
335 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
336 "c0_status", "c0_cause", "c0_epc", "c0_prid",
337 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
338 "c0_xcontext", "$21", "$22", "c0_debug",
339 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
340 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
341};
342
47b0e7ad
NC
343static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] =
344{
bbcc0807
CD
345 { 16, 1, "c0_config1" },
346 { 18, 1, "c0_watchlo,1" },
347 { 19, 1, "c0_watchhi,1" },
348 { 22, 0, "c0_perftrace" },
349 { 23, 3, "c0_edebug" },
350 { 25, 1, "c0_perfcnt,1" },
351 { 25, 2, "c0_perfcnt,2" },
352 { 25, 3, "c0_perfcnt,3" },
353 { 25, 4, "c0_perfcnt,4" },
354 { 25, 5, "c0_perfcnt,5" },
355 { 25, 6, "c0_perfcnt,6" },
356 { 25, 7, "c0_perfcnt,7" },
357 { 26, 1, "c0_buserr_pa" },
358 { 27, 1, "c0_cacheerr_d" },
359 { 27, 3, "c0_cacheerr_d_pa" },
360 { 28, 1, "c0_datalo_i" },
361 { 28, 2, "c0_taglo_d" },
362 { 28, 3, "c0_datalo_d" },
363 { 29, 1, "c0_datahi_i" },
364 { 29, 2, "c0_taghi_d" },
365 { 29, 3, "c0_datahi_d" },
366};
367
52b6b6b9
JM
368/* Xlr cop0 register names. */
369static const char * const mips_cp0_names_xlr[32] = {
370 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
371 "c0_context", "c0_pagemask", "c0_wired", "$7",
372 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
373 "c0_status", "c0_cause", "c0_epc", "c0_prid",
374 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
375 "c0_xcontext", "$21", "$22", "c0_debug",
376 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
377 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
378};
379
380/* XLR's CP0 Select Registers. */
381
382static const struct mips_cp0sel_name mips_cp0sel_names_xlr[] = {
383 { 9, 6, "c0_extintreq" },
384 { 9, 7, "c0_extintmask" },
385 { 15, 1, "c0_ebase" },
386 { 16, 1, "c0_config1" },
387 { 16, 2, "c0_config2" },
388 { 16, 3, "c0_config3" },
389 { 16, 7, "c0_procid2" },
390 { 18, 1, "c0_watchlo,1" },
391 { 18, 2, "c0_watchlo,2" },
392 { 18, 3, "c0_watchlo,3" },
393 { 18, 4, "c0_watchlo,4" },
394 { 18, 5, "c0_watchlo,5" },
395 { 18, 6, "c0_watchlo,6" },
396 { 18, 7, "c0_watchlo,7" },
397 { 19, 1, "c0_watchhi,1" },
398 { 19, 2, "c0_watchhi,2" },
399 { 19, 3, "c0_watchhi,3" },
400 { 19, 4, "c0_watchhi,4" },
401 { 19, 5, "c0_watchhi,5" },
402 { 19, 6, "c0_watchhi,6" },
403 { 19, 7, "c0_watchhi,7" },
404 { 25, 1, "c0_perfcnt,1" },
405 { 25, 2, "c0_perfcnt,2" },
406 { 25, 3, "c0_perfcnt,3" },
407 { 25, 4, "c0_perfcnt,4" },
408 { 25, 5, "c0_perfcnt,5" },
409 { 25, 6, "c0_perfcnt,6" },
410 { 25, 7, "c0_perfcnt,7" },
411 { 27, 1, "c0_cacheerr,1" },
412 { 27, 2, "c0_cacheerr,2" },
413 { 27, 3, "c0_cacheerr,3" },
414 { 28, 1, "c0_datalo" },
415 { 29, 1, "c0_datahi" }
416};
417
47b0e7ad
NC
418static const char * const mips_hwr_names_numeric[32] =
419{
af7ee8bf
CD
420 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
421 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
422 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
423 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
424};
425
47b0e7ad
NC
426static const char * const mips_hwr_names_mips3264r2[32] =
427{
af7ee8bf
CD
428 "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
429 "$4", "$5", "$6", "$7",
430 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
431 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
432 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
433};
434
4edbb8e3
CF
435static const char * const msa_control_names[32] =
436{
437 "msa_ir", "msa_csr", "msa_access", "msa_save",
438 "msa_modify", "msa_request", "msa_map", "msa_unmap",
439 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
440 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
441 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
442};
443
47b0e7ad
NC
444struct mips_abi_choice
445{
446 const char * name;
640c0ccd
CD
447 const char * const *gpr_names;
448 const char * const *fpr_names;
449};
450
47b0e7ad
NC
451struct mips_abi_choice mips_abi_choices[] =
452{
640c0ccd
CD
453 { "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric },
454 { "32", mips_gpr_names_oldabi, mips_fpr_names_32 },
455 { "n32", mips_gpr_names_newabi, mips_fpr_names_n32 },
456 { "64", mips_gpr_names_newabi, mips_fpr_names_64 },
457};
458
47b0e7ad
NC
459struct mips_arch_choice
460{
640c0ccd
CD
461 const char *name;
462 int bfd_mach_valid;
463 unsigned long bfd_mach;
464 int processor;
465 int isa;
d301a56b 466 int ase;
640c0ccd 467 const char * const *cp0_names;
bbcc0807
CD
468 const struct mips_cp0sel_name *cp0sel_names;
469 unsigned int cp0sel_names_len;
dc76d757 470 const char * const *cp1_names;
af7ee8bf 471 const char * const *hwr_names;
640c0ccd
CD
472};
473
47b0e7ad
NC
474const struct mips_arch_choice mips_arch_choices[] =
475{
d301a56b 476 { "numeric", 0, 0, 0, 0, 0,
dc76d757
AB
477 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
478 mips_hwr_names_numeric },
bbcc0807 479
d301a56b 480 { "r3000", 1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1, 0,
dd844468 481 mips_cp0_names_r3000, NULL, 0, mips_cp1_names_mips,
dc76d757 482 mips_hwr_names_numeric },
d301a56b 483 { "r3900", 1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1, 0,
a3fb396f 484 mips_cp0_names_r3900, NULL, 0, mips_cp1_names_numeric,
dc76d757 485 mips_hwr_names_numeric },
d301a56b 486 { "r4000", 1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3, 0,
dd844468 487 mips_cp0_names_r4000, NULL, 0, mips_cp1_names_mips,
dc76d757 488 mips_hwr_names_numeric },
d301a56b 489 { "r4010", 1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2, 0,
dd844468 490 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 491 mips_hwr_names_numeric },
df18f71b
DGF
492 { "allegrex", 1, bfd_mach_mips_allegrex, CPU_ALLEGREX, ISA_MIPS2, 0,
493 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
494 mips_hwr_names_numeric },
d301a56b 495 { "vr4100", 1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3, 0,
dd844468 496 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 497 mips_hwr_names_numeric },
d301a56b 498 { "vr4111", 1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3, 0,
dd844468 499 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 500 mips_hwr_names_numeric },
d301a56b 501 { "vr4120", 1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3, 0,
dd844468 502 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 503 mips_hwr_names_numeric },
d301a56b 504 { "r4300", 1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3, 0,
dd844468 505 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 506 mips_hwr_names_numeric },
d301a56b 507 { "r4400", 1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3, 0,
dd844468 508 mips_cp0_names_r4000, NULL, 0, mips_cp1_names_mips,
dc76d757 509 mips_hwr_names_numeric },
d301a56b 510 { "r4600", 1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3, 0,
dd844468 511 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 512 mips_hwr_names_numeric },
d301a56b 513 { "r4650", 1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3, 0,
dd844468 514 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 515 mips_hwr_names_numeric },
d301a56b 516 { "r5000", 1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4, 0,
dd844468 517 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 518 mips_hwr_names_numeric },
d301a56b 519 { "vr5400", 1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4, 0,
dd844468 520 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 521 mips_hwr_names_numeric },
d301a56b 522 { "vr5500", 1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4, 0,
dd844468 523 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 524 mips_hwr_names_numeric },
d301a56b 525 { "r5900", 1, bfd_mach_mips5900, CPU_R5900, ISA_MIPS3, 0,
dd844468 526 mips_cp0_names_r5900, NULL, 0, mips_cp1_names_mips,
dc76d757 527 mips_hwr_names_numeric },
d301a56b 528 { "r6000", 1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2, 0,
dd844468 529 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 530 mips_hwr_names_numeric },
d301a56b 531 { "rm7000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
dd844468 532 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 533 mips_hwr_names_numeric },
d301a56b 534 { "rm9000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
dd844468 535 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 536 mips_hwr_names_numeric },
d301a56b 537 { "r8000", 1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4, 0,
dd844468 538 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 539 mips_hwr_names_numeric },
d301a56b 540 { "r10000", 1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4, 0,
dd844468 541 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 542 mips_hwr_names_numeric },
d301a56b 543 { "r12000", 1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4, 0,
dd844468 544 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 545 mips_hwr_names_numeric },
d301a56b 546 { "r14000", 1, bfd_mach_mips14000, CPU_R14000, ISA_MIPS4, 0,
dd844468 547 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 548 mips_hwr_names_numeric },
d301a56b 549 { "r16000", 1, bfd_mach_mips16000, CPU_R16000, ISA_MIPS4, 0,
dd844468 550 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 551 mips_hwr_names_numeric },
d301a56b 552 { "mips5", 1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5, 0,
dd844468 553 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 554 mips_hwr_names_numeric },
bbcc0807 555
640c0ccd
CD
556 /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
557 Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
558 _MIPS32 Architecture For Programmers Volume I: Introduction to the
559 MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
560 page 1. */
561 { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32,
d301a56b 562 ISA_MIPS32, ASE_SMARTMIPS,
bbcc0807
CD
563 mips_cp0_names_mips3264,
564 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
dc76d757 565 mips_cp1_names_mips3264, mips_hwr_names_numeric },
bbcc0807 566
af7ee8bf 567 { "mips32r2", 1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
d301a56b 568 ISA_MIPS32R2,
7f3c4072 569 (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
7d64c587 570 | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
bbcc0807
CD
571 mips_cp0_names_mips3264r2,
572 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
dc76d757 573 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
bbcc0807 574
ae52f483
AB
575 { "mips32r3", 1, bfd_mach_mipsisa32r3, CPU_MIPS32R3,
576 ISA_MIPS32R3,
577 (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
578 | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
579 mips_cp0_names_mips3264r2,
580 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
581 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
582
583 { "mips32r5", 1, bfd_mach_mipsisa32r5, CPU_MIPS32R5,
584 ISA_MIPS32R5,
585 (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
586 | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
587 mips_cp0_names_mips3264r2,
588 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
589 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
590
7361da2c
AB
591 { "mips32r6", 1, bfd_mach_mipsisa32r6, CPU_MIPS32R6,
592 ISA_MIPS32R6,
593 (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_XPA | ASE_MCU | ASE_MT | ASE_DSP
6f20c942 594 | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC | ASE_GINV),
7361da2c
AB
595 mips_cp0_names_mips3264r2,
596 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
597 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
598
640c0ccd
CD
599 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
600 { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64,
d301a56b 601 ISA_MIPS64, ASE_MIPS3D | ASE_MDMX,
bbcc0807
CD
602 mips_cp0_names_mips3264,
603 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
dc76d757 604 mips_cp1_names_mips3264, mips_hwr_names_numeric },
bbcc0807 605
5f74bc13 606 { "mips64r2", 1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
d301a56b 607 ISA_MIPS64R2,
7f3c4072 608 (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
7d64c587 609 | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
5f74bc13
CD
610 mips_cp0_names_mips3264r2,
611 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
dc76d757 612 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
5f74bc13 613
ae52f483
AB
614 { "mips64r3", 1, bfd_mach_mipsisa64r3, CPU_MIPS64R3,
615 ISA_MIPS64R3,
616 (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
617 | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
618 mips_cp0_names_mips3264r2,
619 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
620 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
621
622 { "mips64r5", 1, bfd_mach_mipsisa64r5, CPU_MIPS64R5,
623 ISA_MIPS64R5,
624 (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
625 | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
626 mips_cp0_names_mips3264r2,
627 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
628 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
629
7361da2c
AB
630 { "mips64r6", 1, bfd_mach_mipsisa64r6, CPU_MIPS64R6,
631 ISA_MIPS64R6,
632 (ASE_EVA | ASE_MSA | ASE_MSA64 | ASE_XPA | ASE_VIRT | ASE_VIRT64
730c3174 633 | ASE_MCU | ASE_MT | ASE_DSP | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC
6f20c942 634 | ASE_CRC64 | ASE_GINV),
7361da2c
AB
635 mips_cp0_names_mips3264r2,
636 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
637 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
638
38bf472a
MR
639 { "interaptiv-mr2", 1, bfd_mach_mips_interaptiv_mr2, CPU_INTERAPTIV_MR2,
640 ISA_MIPS32R3,
641 ASE_MT | ASE_EVA | ASE_DSP | ASE_DSPR2 | ASE_MIPS16E2 | ASE_MIPS16E2_MT,
642 mips_cp0_names_mips3264r2,
643 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
644 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
645
640c0ccd 646 { "sb1", 1, bfd_mach_mips_sb1, CPU_SB1,
d301a56b 647 ISA_MIPS64 | INSN_SB1, ASE_MIPS3D,
bbcc0807
CD
648 mips_cp0_names_sb1,
649 mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
dc76d757 650 mips_cp1_names_mips3264, mips_hwr_names_numeric },
640c0ccd 651
350cc38d 652 { "loongson2e", 1, bfd_mach_mips_loongson_2e, CPU_LOONGSON_2E,
d301a56b 653 ISA_MIPS3 | INSN_LOONGSON_2E, 0, mips_cp0_names_numeric,
dd844468 654 NULL, 0, mips_cp1_names_mips, mips_hwr_names_numeric },
350cc38d
MS
655
656 { "loongson2f", 1, bfd_mach_mips_loongson_2f, CPU_LOONGSON_2F,
8095d2f7 657 ISA_MIPS3 | INSN_LOONGSON_2F, ASE_LOONGSON_MMI, mips_cp0_names_numeric,
dd844468 658 NULL, 0, mips_cp1_names_mips, mips_hwr_names_numeric },
350cc38d 659
ac8cb70f
CX
660 /* The loongson3a is an alias of gs464 for compatibility */
661 { "loongson3a", 1, bfd_mach_mips_gs464, CPU_GS464,
662 ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
663 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
664 mips_hwr_names_numeric },
665
57299f48 666 { "gs464", 1, bfd_mach_mips_gs464, CPU_GS464,
bdc6c06e 667 ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
716c08de
CX
668 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
669 mips_hwr_names_numeric },
fd503541 670
57299f48 671 { "gs464e", 1, bfd_mach_mips_gs464e, CPU_GS464E,
bd782c07
CX
672 ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
673 | ASE_LOONGSON_EXT2, mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
674 mips_hwr_names_numeric },
675
8d56b9fc 676 { "gs264e", 1, bfd_mach_mips_gs264e, CPU_GS264E,
9108bc33
CX
677 ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
678 | ASE_LOONGSON_EXT2 | ASE_MSA | ASE_MSA64, mips_cp0_names_numeric, NULL,
679 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
680
57b592a3 681 { "octeon", 1, bfd_mach_mips_octeon, CPU_OCTEON,
d301a56b 682 ISA_MIPS64R2 | INSN_OCTEON, 0, mips_cp0_names_numeric, NULL, 0,
dc76d757 683 mips_cp1_names_mips3264, mips_hwr_names_numeric },
57b592a3 684
dd6a37e7 685 { "octeon+", 1, bfd_mach_mips_octeonp, CPU_OCTEONP,
d301a56b 686 ISA_MIPS64R2 | INSN_OCTEONP, 0, mips_cp0_names_numeric,
dc76d757 687 NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
432233b3
AP
688
689 { "octeon2", 1, bfd_mach_mips_octeon2, CPU_OCTEON2,
d301a56b 690 ISA_MIPS64R2 | INSN_OCTEON2, 0, mips_cp0_names_numeric,
dc76d757 691 NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
dd6a37e7 692
2c629856
N
693 { "octeon3", 1, bfd_mach_mips_octeon3, CPU_OCTEON3,
694 ISA_MIPS64R5 | INSN_OCTEON3, ASE_VIRT | ASE_VIRT64,
695 mips_cp0_names_numeric,
696 NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
697
52b6b6b9 698 { "xlr", 1, bfd_mach_mips_xlr, CPU_XLR,
d301a56b 699 ISA_MIPS64 | INSN_XLR, 0,
52b6b6b9
JM
700 mips_cp0_names_xlr,
701 mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
dc76d757 702 mips_cp1_names_mips3264, mips_hwr_names_numeric },
52b6b6b9 703
55a36193
MK
704 /* XLP is mostly like XLR, with the prominent exception it is being
705 MIPS64R2. */
706 { "xlp", 1, bfd_mach_mips_xlr, CPU_XLR,
d301a56b 707 ISA_MIPS64R2 | INSN_XLR, 0,
55a36193
MK
708 mips_cp0_names_xlr,
709 mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
dc76d757 710 mips_cp1_names_mips3264, mips_hwr_names_numeric },
55a36193 711
640c0ccd
CD
712 /* This entry, mips16, is here only for ISA/processor selection; do
713 not print its name. */
25499ac7
MR
714 { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS64,
715 ASE_MIPS16E2 | ASE_MIPS16E2_MT,
dc76d757
AB
716 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
717 mips_hwr_names_numeric },
640c0ccd
CD
718};
719
720/* ISA and processor type to disassemble for, and register names to use.
721 set_default_mips_dis_options and parse_mips_dis_options fill in these
722 values. */
723static int mips_processor;
724static int mips_isa;
d301a56b 725static int mips_ase;
df58fc94 726static int micromips_ase;
640c0ccd
CD
727static const char * const *mips_gpr_names;
728static const char * const *mips_fpr_names;
729static const char * const *mips_cp0_names;
bbcc0807
CD
730static const struct mips_cp0sel_name *mips_cp0sel_names;
731static int mips_cp0sel_names_len;
dc76d757 732static const char * const *mips_cp1_names;
af7ee8bf 733static const char * const *mips_hwr_names;
640c0ccd 734
986e18a5 735/* Other options */
47b0e7ad 736static int no_aliases; /* If set disassemble as most general inst. */
640c0ccd
CD
737\f
738static const struct mips_abi_choice *
47b0e7ad 739choose_abi_by_name (const char *name, unsigned int namelen)
640c0ccd
CD
740{
741 const struct mips_abi_choice *c;
742 unsigned int i;
743
744 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++)
47b0e7ad
NC
745 if (strncmp (mips_abi_choices[i].name, name, namelen) == 0
746 && strlen (mips_abi_choices[i].name) == namelen)
747 c = &mips_abi_choices[i];
748
640c0ccd
CD
749 return c;
750}
751
752static const struct mips_arch_choice *
47b0e7ad 753choose_arch_by_name (const char *name, unsigned int namelen)
640c0ccd
CD
754{
755 const struct mips_arch_choice *c = NULL;
756 unsigned int i;
757
758 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
47b0e7ad
NC
759 if (strncmp (mips_arch_choices[i].name, name, namelen) == 0
760 && strlen (mips_arch_choices[i].name) == namelen)
761 c = &mips_arch_choices[i];
762
640c0ccd
CD
763 return c;
764}
765
766static const struct mips_arch_choice *
47b0e7ad 767choose_arch_by_number (unsigned long mach)
640c0ccd
CD
768{
769 static unsigned long hint_bfd_mach;
770 static const struct mips_arch_choice *hint_arch_choice;
771 const struct mips_arch_choice *c;
772 unsigned int i;
773
774 /* We optimize this because even if the user specifies no
775 flags, this will be done for every instruction! */
776 if (hint_bfd_mach == mach
777 && hint_arch_choice != NULL
778 && hint_arch_choice->bfd_mach == hint_bfd_mach)
779 return hint_arch_choice;
780
781 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
782 {
783 if (mips_arch_choices[i].bfd_mach_valid
784 && mips_arch_choices[i].bfd_mach == mach)
785 {
786 c = &mips_arch_choices[i];
787 hint_bfd_mach = mach;
788 hint_arch_choice = c;
789 }
790 }
791 return c;
792}
793
47b0e7ad
NC
794/* Check if the object uses NewABI conventions. */
795
796static int
797is_newabi (Elf_Internal_Ehdr *header)
798{
799 /* There are no old-style ABIs which use 64-bit ELF. */
800 if (header->e_ident[EI_CLASS] == ELFCLASS64)
801 return 1;
802
803 /* If a 32-bit ELF file, n32 is a new-style ABI. */
804 if ((header->e_flags & EF_MIPS_ABI2) != 0)
805 return 1;
806
807 return 0;
808}
809
df58fc94
RS
810/* Check if the object has microMIPS ASE code. */
811
812static int
813is_micromips (Elf_Internal_Ehdr *header)
814{
815 if ((header->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0)
816 return 1;
817
818 return 0;
819}
820
5e7fc731
MR
821/* Convert ASE flags from .MIPS.abiflags to internal values. */
822
823static unsigned long
824mips_convert_abiflags_ases (unsigned long afl_ases)
825{
826 unsigned long opcode_ases = 0;
827
828 if (afl_ases & AFL_ASE_DSP)
829 opcode_ases |= ASE_DSP;
830 if (afl_ases & AFL_ASE_DSPR2)
831 opcode_ases |= ASE_DSPR2;
832 if (afl_ases & AFL_ASE_EVA)
833 opcode_ases |= ASE_EVA;
834 if (afl_ases & AFL_ASE_MCU)
835 opcode_ases |= ASE_MCU;
836 if (afl_ases & AFL_ASE_MDMX)
837 opcode_ases |= ASE_MDMX;
838 if (afl_ases & AFL_ASE_MIPS3D)
839 opcode_ases |= ASE_MIPS3D;
840 if (afl_ases & AFL_ASE_MT)
841 opcode_ases |= ASE_MT;
842 if (afl_ases & AFL_ASE_SMARTMIPS)
843 opcode_ases |= ASE_SMARTMIPS;
844 if (afl_ases & AFL_ASE_VIRT)
845 opcode_ases |= ASE_VIRT;
846 if (afl_ases & AFL_ASE_MSA)
847 opcode_ases |= ASE_MSA;
848 if (afl_ases & AFL_ASE_XPA)
849 opcode_ases |= ASE_XPA;
850 if (afl_ases & AFL_ASE_DSPR3)
851 opcode_ases |= ASE_DSPR3;
25499ac7
MR
852 if (afl_ases & AFL_ASE_MIPS16E2)
853 opcode_ases |= ASE_MIPS16E2;
5e7fc731
MR
854 return opcode_ases;
855}
856
60804c53
MR
857/* Calculate combination ASE flags from regular ASE flags. */
858
859static unsigned long
41cee089 860mips_calculate_combination_ases (int opcode_isa, unsigned long opcode_ases)
60804c53
MR
861{
862 unsigned long combination_ases = 0;
863
9785fc2a
MR
864 if ((opcode_ases & (ASE_XPA | ASE_VIRT)) == (ASE_XPA | ASE_VIRT))
865 combination_ases |= ASE_XPA_VIRT;
60804c53
MR
866 if ((opcode_ases & (ASE_MIPS16E2 | ASE_MT)) == (ASE_MIPS16E2 | ASE_MT))
867 combination_ases |= ASE_MIPS16E2_MT;
41cee089
FS
868 if ((opcode_ases & ASE_EVA)
869 && ((opcode_isa & INSN_ISA_MASK) == ISA_MIPS64R6
870 || (opcode_isa & INSN_ISA_MASK) == ISA_MIPS32R6))
871 combination_ases |= ASE_EVA_R6;
60804c53
MR
872 return combination_ases;
873}
874
47b0e7ad
NC
875static void
876set_default_mips_dis_options (struct disassemble_info *info)
640c0ccd
CD
877{
878 const struct mips_arch_choice *chosen_arch;
879
df58fc94
RS
880 /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
881 is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
882 CP0 register, and HWR names. */
640c0ccd 883 mips_isa = ISA_MIPS3;
df58fc94
RS
884 mips_processor = CPU_R3000;
885 micromips_ase = 0;
d301a56b 886 mips_ase = 0;
640c0ccd
CD
887 mips_gpr_names = mips_gpr_names_oldabi;
888 mips_fpr_names = mips_fpr_names_numeric;
889 mips_cp0_names = mips_cp0_names_numeric;
bbcc0807
CD
890 mips_cp0sel_names = NULL;
891 mips_cp0sel_names_len = 0;
dc76d757 892 mips_cp1_names = mips_cp1_names_numeric;
af7ee8bf 893 mips_hwr_names = mips_hwr_names_numeric;
986e18a5 894 no_aliases = 0;
640c0ccd 895
640c0ccd
CD
896 /* Set ISA, architecture, and cp0 register names as best we can. */
897#if ! SYMTAB_AVAILABLE
898 /* This is running out on a target machine, not in a host tool.
899 FIXME: Where does mips_target_info come from? */
900 target_processor = mips_target_info.processor;
901 mips_isa = mips_target_info.isa;
d301a56b 902 mips_ase = mips_target_info.ase;
640c0ccd
CD
903#else
904 chosen_arch = choose_arch_by_number (info->mach);
905 if (chosen_arch != NULL)
906 {
907 mips_processor = chosen_arch->processor;
908 mips_isa = chosen_arch->isa;
d301a56b 909 mips_ase = chosen_arch->ase;
bbcc0807
CD
910 mips_cp0_names = chosen_arch->cp0_names;
911 mips_cp0sel_names = chosen_arch->cp0sel_names;
912 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
dc76d757 913 mips_cp1_names = chosen_arch->cp1_names;
bbcc0807 914 mips_hwr_names = chosen_arch->hwr_names;
640c0ccd 915 }
8184783a
MR
916
917 /* Update settings according to the ELF file header flags. */
918 if (info->flavour == bfd_target_elf_flavour && info->section != NULL)
919 {
5e7fc731
MR
920 struct bfd *abfd = info->section->owner;
921 Elf_Internal_Ehdr *header = elf_elfheader (abfd);
4df995c7
MR
922 Elf_Internal_ABIFlags_v0 *abiflags = NULL;
923
9e76c212
MR
924 /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
925 because we won't then have a MIPS/ELF BFD, however we need
926 to guard against a link error in a `--enable-targets=...'
927 configuration with a 32-bit host where the MIPS target is
928 a secondary, or with MIPS/ECOFF configurations. */
929#ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
4df995c7
MR
930 abiflags = bfd_mips_elf_get_abiflags (abfd);
931#endif
8184783a
MR
932 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
933 if (is_newabi (header))
934 mips_gpr_names = mips_gpr_names_newabi;
935 /* If a microMIPS binary, then don't use MIPS16 bindings. */
936 micromips_ase = is_micromips (header);
5e7fc731
MR
937 /* OR in any extra ASE flags set in ELF file structures. */
938 if (abiflags)
939 mips_ase |= mips_convert_abiflags_ases (abiflags->ases);
940 else if (header->e_flags & EF_MIPS_ARCH_ASE_MDMX)
941 mips_ase |= ASE_MDMX;
8184783a 942 }
91068ec6 943#endif
41cee089 944 mips_ase |= mips_calculate_combination_ases (mips_isa, mips_ase);
640c0ccd
CD
945}
946
9785fc2a
MR
947/* Parse an ASE disassembler option and set the corresponding global
948 ASE flag(s). Return TRUE if successful, FALSE otherwise. */
b015e599 949
78933a4a 950static bool
9785fc2a
MR
951parse_mips_ase_option (const char *option)
952{
08dedd66 953 if (startswith (option, "msa"))
4edbb8e3
CF
954 {
955 mips_ase |= ASE_MSA;
ae52f483
AB
956 if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R2
957 || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R3
7361da2c
AB
958 || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R5
959 || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6)
4edbb8e3 960 mips_ase |= ASE_MSA64;
78933a4a 961 return true;
4edbb8e3
CF
962 }
963
08dedd66 964 if (startswith (option, "virt"))
b015e599 965 {
d301a56b 966 mips_ase |= ASE_VIRT;
ae52f483
AB
967 if (mips_isa & ISA_MIPS64R2
968 || mips_isa & ISA_MIPS64R3
7361da2c
AB
969 || mips_isa & ISA_MIPS64R5
970 || mips_isa & ISA_MIPS64R6)
d301a56b 971 mips_ase |= ASE_VIRT64;
78933a4a 972 return true;
b015e599 973 }
7d64c587 974
08dedd66 975 if (startswith (option, "xpa"))
7d64c587
AB
976 {
977 mips_ase |= ASE_XPA;
78933a4a 978 return true;
9785fc2a
MR
979 }
980
08dedd66 981 if (startswith (option, "ginv"))
6f20c942
FS
982 {
983 mips_ase |= ASE_GINV;
78933a4a 984 return true;
6f20c942
FS
985 }
986
08dedd66 987 if (startswith (option, "loongson-mmi"))
8095d2f7
CX
988 {
989 mips_ase |= ASE_LOONGSON_MMI;
78933a4a 990 return true;
8095d2f7
CX
991 }
992
08dedd66 993 if (startswith (option, "loongson-cam"))
716c08de
CX
994 {
995 mips_ase |= ASE_LOONGSON_CAM;
78933a4a 996 return true;
716c08de 997 }
a693765e
CX
998
999 /* Put here for match ext2 frist */
08dedd66 1000 if (startswith (option, "loongson-ext2"))
a693765e
CX
1001 {
1002 mips_ase |= ASE_LOONGSON_EXT2;
78933a4a 1003 return true;
a693765e 1004 }
716c08de 1005
08dedd66 1006 if (startswith (option, "loongson-ext"))
bdc6c06e
CX
1007 {
1008 mips_ase |= ASE_LOONGSON_EXT;
78933a4a 1009 return true;
bdc6c06e
CX
1010 }
1011
78933a4a 1012 return false;
9785fc2a
MR
1013}
1014
1015static void
1016parse_mips_dis_option (const char *option, unsigned int len)
1017{
1018 unsigned int i, optionlen, vallen;
1019 const char *val;
1020 const struct mips_abi_choice *chosen_abi;
1021 const struct mips_arch_choice *chosen_arch;
1022
1023 /* Try to match options that are simple flags */
08dedd66 1024 if (startswith (option, "no-aliases"))
9785fc2a
MR
1025 {
1026 no_aliases = 1;
7d64c587
AB
1027 return;
1028 }
43e65147 1029
9785fc2a
MR
1030 if (parse_mips_ase_option (option))
1031 {
41cee089 1032 mips_ase |= mips_calculate_combination_ases (mips_isa, mips_ase);
9785fc2a
MR
1033 return;
1034 }
43e65147 1035
640c0ccd
CD
1036 /* Look for the = that delimits the end of the option name. */
1037 for (i = 0; i < len; i++)
47b0e7ad
NC
1038 if (option[i] == '=')
1039 break;
1040
640c0ccd
CD
1041 if (i == 0) /* Invalid option: no name before '='. */
1042 return;
1043 if (i == len) /* Invalid option: no '='. */
1044 return;
1045 if (i == (len - 1)) /* Invalid option: no value after '='. */
1046 return;
1047
1048 optionlen = i;
1049 val = option + (optionlen + 1);
1050 vallen = len - (optionlen + 1);
1051
47b0e7ad
NC
1052 if (strncmp ("gpr-names", option, optionlen) == 0
1053 && strlen ("gpr-names") == optionlen)
640c0ccd
CD
1054 {
1055 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 1056 if (chosen_abi != NULL)
640c0ccd
CD
1057 mips_gpr_names = chosen_abi->gpr_names;
1058 return;
1059 }
1060
47b0e7ad
NC
1061 if (strncmp ("fpr-names", option, optionlen) == 0
1062 && strlen ("fpr-names") == optionlen)
640c0ccd
CD
1063 {
1064 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 1065 if (chosen_abi != NULL)
640c0ccd
CD
1066 mips_fpr_names = chosen_abi->fpr_names;
1067 return;
1068 }
1069
47b0e7ad
NC
1070 if (strncmp ("cp0-names", option, optionlen) == 0
1071 && strlen ("cp0-names") == optionlen)
640c0ccd
CD
1072 {
1073 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807
CD
1074 if (chosen_arch != NULL)
1075 {
1076 mips_cp0_names = chosen_arch->cp0_names;
1077 mips_cp0sel_names = chosen_arch->cp0sel_names;
1078 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
1079 }
640c0ccd
CD
1080 return;
1081 }
1082
dc76d757
AB
1083 if (strncmp ("cp1-names", option, optionlen) == 0
1084 && strlen ("cp1-names") == optionlen)
1085 {
1086 chosen_arch = choose_arch_by_name (val, vallen);
1087 if (chosen_arch != NULL)
1088 mips_cp1_names = chosen_arch->cp1_names;
1089 return;
1090 }
1091
47b0e7ad
NC
1092 if (strncmp ("hwr-names", option, optionlen) == 0
1093 && strlen ("hwr-names") == optionlen)
af7ee8bf
CD
1094 {
1095 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807 1096 if (chosen_arch != NULL)
af7ee8bf
CD
1097 mips_hwr_names = chosen_arch->hwr_names;
1098 return;
1099 }
1100
47b0e7ad
NC
1101 if (strncmp ("reg-names", option, optionlen) == 0
1102 && strlen ("reg-names") == optionlen)
640c0ccd
CD
1103 {
1104 /* We check both ABI and ARCH here unconditionally, so
1105 that "numeric" will do the desirable thing: select
1106 numeric register names for all registers. Other than
1107 that, a given name probably won't match both. */
1108 chosen_abi = choose_abi_by_name (val, vallen);
1109 if (chosen_abi != NULL)
1110 {
bbcc0807
CD
1111 mips_gpr_names = chosen_abi->gpr_names;
1112 mips_fpr_names = chosen_abi->fpr_names;
640c0ccd
CD
1113 }
1114 chosen_arch = choose_arch_by_name (val, vallen);
1115 if (chosen_arch != NULL)
1116 {
bbcc0807
CD
1117 mips_cp0_names = chosen_arch->cp0_names;
1118 mips_cp0sel_names = chosen_arch->cp0sel_names;
1119 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
dc76d757 1120 mips_cp1_names = chosen_arch->cp1_names;
bbcc0807 1121 mips_hwr_names = chosen_arch->hwr_names;
640c0ccd
CD
1122 }
1123 return;
1124 }
1125
1126 /* Invalid option. */
1127}
1128
47b0e7ad
NC
1129static void
1130parse_mips_dis_options (const char *options)
640c0ccd
CD
1131{
1132 const char *option_end;
1133
1134 if (options == NULL)
1135 return;
1136
1137 while (*options != '\0')
1138 {
1139 /* Skip empty options. */
1140 if (*options == ',')
1141 {
1142 options++;
1143 continue;
1144 }
1145
1146 /* We know that *options is neither NUL or a comma. */
1147 option_end = options + 1;
1148 while (*option_end != ',' && *option_end != '\0')
1149 option_end++;
1150
1151 parse_mips_dis_option (options, option_end - options);
1152
1153 /* Go on to the next one. If option_end points to a comma, it
1154 will be skipped above. */
1155 options = option_end;
1156 }
1157}
1158
bbcc0807 1159static const struct mips_cp0sel_name *
47b0e7ad
NC
1160lookup_mips_cp0sel_name (const struct mips_cp0sel_name *names,
1161 unsigned int len,
1162 unsigned int cp0reg,
1163 unsigned int sel)
bbcc0807
CD
1164{
1165 unsigned int i;
1166
1167 for (i = 0; i < len; i++)
1168 if (names[i].cp0reg == cp0reg && names[i].sel == sel)
1169 return &names[i];
1170 return NULL;
1171}
ab902481
RS
1172
1173/* Print register REGNO, of type TYPE, for instruction OPCODE. */
aa5f19f2 1174
794ac9d0 1175static void
ab902481
RS
1176print_reg (struct disassemble_info *info, const struct mips_opcode *opcode,
1177 enum mips_reg_operand_type type, int regno)
252b5132 1178{
ecfbeec8
AB
1179 const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1180
ab902481
RS
1181 switch (type)
1182 {
1183 case OP_REG_GP:
ecfbeec8
AB
1184 infprintf (info->stream, dis_style_register, "%s",
1185 mips_gpr_names[regno]);
ab902481 1186 break;
440cc0bc 1187
ab902481 1188 case OP_REG_FP:
ecfbeec8
AB
1189 infprintf (info->stream, dis_style_register, "%s",
1190 mips_fpr_names[regno]);
ab902481 1191 break;
252b5132 1192
ab902481
RS
1193 case OP_REG_CCC:
1194 if (opcode->pinfo & (FP_D | FP_S))
ecfbeec8 1195 infprintf (info->stream, dis_style_register, "$fcc%d", regno);
ab902481 1196 else
ecfbeec8 1197 infprintf (info->stream, dis_style_register, "$cc%d", regno);
ab902481 1198 break;
794ac9d0 1199
ab902481
RS
1200 case OP_REG_VEC:
1201 if (opcode->membership & INSN_5400)
ecfbeec8 1202 infprintf (info->stream, dis_style_register, "$f%d", regno);
ab902481 1203 else
ecfbeec8 1204 infprintf (info->stream, dis_style_register, "$v%d", regno);
ab902481 1205 break;
794ac9d0 1206
ab902481 1207 case OP_REG_ACC:
ecfbeec8 1208 infprintf (info->stream, dis_style_register, "$ac%d", regno);
ab902481 1209 break;
794ac9d0 1210
ab902481
RS
1211 case OP_REG_COPRO:
1212 if (opcode->name[strlen (opcode->name) - 1] == '0')
ecfbeec8 1213 infprintf (info->stream, dis_style_register, "%s", mips_cp0_names[regno]);
9204ccd4 1214 else
ecfbeec8 1215 infprintf (info->stream, dis_style_register, "$%d", regno);
9204ccd4
MR
1216 break;
1217
1218 case OP_REG_CONTROL:
1219 if (opcode->name[strlen (opcode->name) - 1] == '1')
ecfbeec8 1220 infprintf (info->stream, dis_style_register, "%s", mips_cp1_names[regno]);
ab902481 1221 else
ecfbeec8 1222 infprintf (info->stream, dis_style_register, "$%d", regno);
ab902481 1223 break;
8b082fb1 1224
ab902481 1225 case OP_REG_HW:
ecfbeec8 1226 infprintf (info->stream, dis_style_register, "%s", mips_hwr_names[regno]);
ab902481 1227 break;
14daeee3
RS
1228
1229 case OP_REG_VF:
ecfbeec8 1230 infprintf (info->stream, dis_style_register, "$vf%d", regno);
14daeee3
RS
1231 break;
1232
1233 case OP_REG_VI:
ecfbeec8 1234 infprintf (info->stream, dis_style_register, "$vi%d", regno);
14daeee3
RS
1235 break;
1236
1237 case OP_REG_R5900_I:
ecfbeec8 1238 infprintf (info->stream, dis_style_register, "$I");
14daeee3
RS
1239 break;
1240
1241 case OP_REG_R5900_Q:
ecfbeec8 1242 infprintf (info->stream, dis_style_register, "$Q");
14daeee3
RS
1243 break;
1244
1245 case OP_REG_R5900_R:
ecfbeec8 1246 infprintf (info->stream, dis_style_register, "$R");
14daeee3
RS
1247 break;
1248
1249 case OP_REG_R5900_ACC:
ecfbeec8 1250 infprintf (info->stream, dis_style_register, "$ACC");
14daeee3 1251 break;
4edbb8e3
CF
1252
1253 case OP_REG_MSA:
ecfbeec8 1254 infprintf (info->stream, dis_style_register, "$w%d", regno);
4edbb8e3
CF
1255 break;
1256
1257 case OP_REG_MSA_CTRL:
ecfbeec8
AB
1258 infprintf (info->stream, dis_style_register, "%s",
1259 msa_control_names[regno]);
4edbb8e3
CF
1260 break;
1261
ab902481
RS
1262 }
1263}
1264\f
1265/* Used to track the state carried over from previous operands in
1266 an instruction. */
1267struct mips_print_arg_state {
1268 /* The value of the last OP_INT seen. We only use this for OP_MSB,
1269 where the value is known to be unsigned and small. */
1270 unsigned int last_int;
1271
1272 /* The type and number of the last OP_REG seen. We only use this for
1273 OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1274 enum mips_reg_operand_type last_reg_type;
1275 unsigned int last_regno;
7361da2c
AB
1276 unsigned int dest_regno;
1277 unsigned int seen_dest;
ab902481 1278};
fd25c5a9 1279
ab902481 1280/* Initialize STATE for the start of an instruction. */
fd25c5a9 1281
ab902481
RS
1282static inline void
1283init_print_arg_state (struct mips_print_arg_state *state)
1284{
1285 memset (state, 0, sizeof (*state));
1286}
fd25c5a9 1287
14daeee3
RS
1288/* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1289 whose value is given by UVAL. */
1290
1291static void
1292print_vu0_channel (struct disassemble_info *info,
ecfbeec8
AB
1293 const struct mips_operand *operand, unsigned int uval,
1294 enum disassembler_style style)
14daeee3 1295{
ecfbeec8
AB
1296 const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1297
14daeee3 1298 if (operand->size == 4)
ecfbeec8 1299 infprintf (info->stream, style, "%s%s%s%s",
14daeee3
RS
1300 uval & 8 ? "x" : "",
1301 uval & 4 ? "y" : "",
1302 uval & 2 ? "z" : "",
1303 uval & 1 ? "w" : "");
1304 else if (operand->size == 2)
ecfbeec8 1305 infprintf (info->stream, style, "%c", "xyzw"[uval]);
14daeee3
RS
1306 else
1307 abort ();
1308}
1309
7361da2c
AB
1310/* Record information about a register operand. */
1311
1312static void
1313mips_seen_register (struct mips_print_arg_state *state,
1314 unsigned int regno,
1315 enum mips_reg_operand_type reg_type)
1316{
1317 state->last_reg_type = reg_type;
1318 state->last_regno = regno;
1319
1320 if (!state->seen_dest)
1321 {
1322 state->seen_dest = 1;
1323 state->dest_regno = regno;
1324 }
1325}
1326
38bf472a
MR
1327/* Print SAVE/RESTORE instruction operands according to the argument
1328 register mask AMASK, the number of static registers saved NSREG,
1329 the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1330 and the frame size FRAME_SIZE. */
1331
1332static void
1333mips_print_save_restore (struct disassemble_info *info, unsigned int amask,
1334 unsigned int nsreg, unsigned int ra,
1335 unsigned int s0, unsigned int s1,
1336 unsigned int frame_size)
1337{
ecfbeec8 1338 const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
38bf472a
MR
1339 unsigned int nargs, nstatics, smask, i, j;
1340 void *is = info->stream;
1341 const char *sep;
1342
1343 if (amask == MIPS_SVRS_ALL_ARGS)
1344 {
1345 nargs = 4;
1346 nstatics = 0;
1347 }
1348 else if (amask == MIPS_SVRS_ALL_STATICS)
1349 {
1350 nargs = 0;
1351 nstatics = 4;
1352 }
1353 else
1354 {
1355 nargs = amask >> 2;
1356 nstatics = amask & 3;
1357 }
1358
1359 sep = "";
1360 if (nargs > 0)
1361 {
ecfbeec8 1362 infprintf (is, dis_style_register, "%s", mips_gpr_names[4]);
38bf472a 1363 if (nargs > 1)
ecfbeec8 1364 infprintf (is, dis_style_register, "-%s", mips_gpr_names[4 + nargs - 1]);
38bf472a
MR
1365 sep = ",";
1366 }
1367
ecfbeec8
AB
1368 infprintf (is, dis_style_text, "%s", sep);
1369 infprintf (is, dis_style_immediate, "%d", frame_size);
38bf472a
MR
1370
1371 if (ra) /* $ra */
ecfbeec8
AB
1372 {
1373 infprintf (is, dis_style_text, ",");
1374 infprintf (is, dis_style_register, "%s", mips_gpr_names[31]);
1375 }
38bf472a
MR
1376
1377 smask = 0;
1378 if (s0) /* $s0 */
1379 smask |= 1 << 0;
1380 if (s1) /* $s1 */
1381 smask |= 1 << 1;
1382 if (nsreg > 0) /* $s2-$s8 */
1383 smask |= ((1 << nsreg) - 1) << 2;
1384
1385 for (i = 0; i < 9; i++)
1386 if (smask & (1 << i))
1387 {
ecfbeec8
AB
1388 infprintf (is, dis_style_text, ",");
1389 infprintf (is, dis_style_register, "%s",
1390 mips_gpr_names[i == 8 ? 30 : (16 + i)]);
38bf472a
MR
1391 /* Skip over string of set bits. */
1392 for (j = i; smask & (2 << j); j++)
1393 continue;
1394 if (j > i)
ecfbeec8
AB
1395 {
1396 infprintf (is, dis_style_text, "-");
1397 infprintf (is, dis_style_register, "%s",
1398 mips_gpr_names[j == 8 ? 30 : (16 + j)]);
1399 }
38bf472a
MR
1400 i = j + 1;
1401 }
1402 /* Statics $ax - $a3. */
1403 if (nstatics == 1)
ecfbeec8
AB
1404 {
1405 infprintf (is, dis_style_text, ",");
1406 infprintf (is, dis_style_register, "%s", mips_gpr_names[7]);
1407 }
38bf472a 1408 else if (nstatics > 0)
ecfbeec8
AB
1409 {
1410 infprintf (is, dis_style_text, ",");
1411 infprintf (is, dis_style_register, "%s",
1412 mips_gpr_names[7 - nstatics + 1]);
1413 infprintf (is, dis_style_text, "-");
1414 infprintf (is, dis_style_register, "%s", mips_gpr_names[7]);
1415 }
38bf472a
MR
1416}
1417
1418
ab902481
RS
1419/* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1420 UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1421 the base address for OP_PCREL operands. */
fd25c5a9 1422
ab902481
RS
1423static void
1424print_insn_arg (struct disassemble_info *info,
1425 struct mips_print_arg_state *state,
1426 const struct mips_opcode *opcode,
1427 const struct mips_operand *operand,
1428 bfd_vma base_pc,
1429 unsigned int uval)
1430{
ecfbeec8 1431 const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
ab902481 1432 void *is = info->stream;
fd25c5a9 1433
ab902481
RS
1434 switch (operand->type)
1435 {
1436 case OP_INT:
1437 {
1438 const struct mips_int_operand *int_op;
fd25c5a9 1439
ab902481
RS
1440 int_op = (const struct mips_int_operand *) operand;
1441 uval = mips_decode_int_operand (int_op, uval);
1442 state->last_int = uval;
1443 if (int_op->print_hex)
ecfbeec8 1444 infprintf (is, dis_style_immediate, "0x%x", uval);
ab902481 1445 else
ecfbeec8 1446 infprintf (is, dis_style_immediate, "%d", uval);
ab902481
RS
1447 }
1448 break;
fd25c5a9 1449
ab902481
RS
1450 case OP_MAPPED_INT:
1451 {
1452 const struct mips_mapped_int_operand *mint_op;
fd25c5a9 1453
ab902481
RS
1454 mint_op = (const struct mips_mapped_int_operand *) operand;
1455 uval = mint_op->int_map[uval];
1456 state->last_int = uval;
1457 if (mint_op->print_hex)
ecfbeec8 1458 infprintf (is, dis_style_immediate, "0x%x", uval);
ab902481 1459 else
ecfbeec8 1460 infprintf (is, dis_style_immediate, "%d", uval);
ab902481
RS
1461 }
1462 break;
fd25c5a9 1463
ab902481
RS
1464 case OP_MSB:
1465 {
1466 const struct mips_msb_operand *msb_op;
dec0624d 1467
ab902481
RS
1468 msb_op = (const struct mips_msb_operand *) operand;
1469 uval += msb_op->bias;
1470 if (msb_op->add_lsb)
1471 uval -= state->last_int;
ecfbeec8 1472 infprintf (is, dis_style_immediate, "0x%x", uval);
ab902481
RS
1473 }
1474 break;
dec0624d 1475
ab902481 1476 case OP_REG:
0f35dbc4 1477 case OP_OPTIONAL_REG:
ab902481
RS
1478 {
1479 const struct mips_reg_operand *reg_op;
fd25c5a9 1480
ab902481 1481 reg_op = (const struct mips_reg_operand *) operand;
fc76e730 1482 uval = mips_decode_reg_operand (reg_op, uval);
ab902481 1483 print_reg (info, opcode, reg_op->reg_type, uval);
fd25c5a9 1484
7361da2c 1485 mips_seen_register (state, uval, reg_op->reg_type);
ab902481
RS
1486 }
1487 break;
61cc0267 1488
ab902481
RS
1489 case OP_REG_PAIR:
1490 {
1491 const struct mips_reg_pair_operand *pair_op;
1492
1493 pair_op = (const struct mips_reg_pair_operand *) operand;
1494 print_reg (info, opcode, pair_op->reg_type,
1495 pair_op->reg1_map[uval]);
ecfbeec8 1496 infprintf (is, dis_style_text, ",");
ab902481
RS
1497 print_reg (info, opcode, pair_op->reg_type,
1498 pair_op->reg2_map[uval]);
1499 }
1500 break;
61cc0267 1501
ab902481
RS
1502 case OP_PCREL:
1503 {
1504 const struct mips_pcrel_operand *pcrel_op;
61cc0267 1505
ab902481
RS
1506 pcrel_op = (const struct mips_pcrel_operand *) operand;
1507 info->target = mips_decode_pcrel_operand (pcrel_op, base_pc, uval);
61cc0267 1508
a4ddc54e
MR
1509 /* For jumps and branches clear the ISA bit except for
1510 the GDB disassembler. */
1511 if (pcrel_op->include_isa_bit
1512 && info->flavour != bfd_target_unknown_flavour)
ab902481 1513 info->target &= -2;
61cc0267 1514
ab902481
RS
1515 (*info->print_address_func) (info->target, info);
1516 }
1517 break;
794ac9d0 1518
ab902481 1519 case OP_PERF_REG:
ecfbeec8 1520 infprintf (is, dis_style_register, "%d", uval);
ab902481 1521 break;
794ac9d0 1522
ab902481
RS
1523 case OP_ADDIUSP_INT:
1524 {
1525 int sval;
794ac9d0 1526
ab902481
RS
1527 sval = mips_signed_operand (operand, uval) * 4;
1528 if (sval >= -8 && sval < 8)
1529 sval ^= 0x400;
ecfbeec8 1530 infprintf (is, dis_style_immediate, "%d", sval);
ab902481
RS
1531 break;
1532 }
794ac9d0 1533
ab902481
RS
1534 case OP_CLO_CLZ_DEST:
1535 {
1536 unsigned int reg1, reg2;
1537
1538 reg1 = uval & 31;
1539 reg2 = uval >> 5;
1540 /* If one is zero use the other. */
1541 if (reg1 == reg2 || reg2 == 0)
ecfbeec8 1542 infprintf (is, dis_style_register, "%s", mips_gpr_names[reg1]);
ab902481 1543 else if (reg1 == 0)
ecfbeec8 1544 infprintf (is, dis_style_register, "%s", mips_gpr_names[reg2]);
ab902481 1545 else
ecfbeec8
AB
1546 {
1547 /* Bogus, result depends on processor. */
1548 infprintf (is, dis_style_register, "%s", mips_gpr_names[reg1]);
1549 infprintf (is, dis_style_text, " or ");
1550 infprintf (is, dis_style_register, "%s", mips_gpr_names[reg2]);
1551 }
ab902481
RS
1552 }
1553 break;
794ac9d0 1554
7361da2c
AB
1555 case OP_SAME_RS_RT:
1556 case OP_CHECK_PREV:
1557 case OP_NON_ZERO_REG:
1558 {
1559 print_reg (info, opcode, OP_REG_GP, uval & 31);
1560 mips_seen_register (state, uval, OP_REG_GP);
1561 }
1562 break;
1563
ab902481
RS
1564 case OP_LWM_SWM_LIST:
1565 if (operand->size == 2)
1566 {
1567 if (uval == 0)
ecfbeec8
AB
1568 {
1569 infprintf (is, dis_style_register, "%s",
1570 mips_gpr_names[16]);
1571 infprintf (is, dis_style_text, ",");
1572 infprintf (is, dis_style_register, "%s",
1573 mips_gpr_names[31]);
1574 }
ab902481 1575 else
ecfbeec8
AB
1576 {
1577 infprintf (is, dis_style_register, "%s",
1578 mips_gpr_names[16]);
1579 infprintf (is, dis_style_text, "-");
1580 infprintf (is, dis_style_register, "%s",
1581 mips_gpr_names[16 + uval]);
1582 infprintf (is, dis_style_text, ",");
1583 infprintf (is, dis_style_register, "%s",
1584 mips_gpr_names[31]);
1585 }
ab902481
RS
1586 }
1587 else
1588 {
1589 int s_reg_encode;
794ac9d0 1590
ab902481
RS
1591 s_reg_encode = uval & 0xf;
1592 if (s_reg_encode != 0)
1593 {
1594 if (s_reg_encode == 1)
ecfbeec8 1595 infprintf (is, dis_style_register, "%s", mips_gpr_names[16]);
ab902481 1596 else if (s_reg_encode < 9)
ecfbeec8
AB
1597 {
1598 infprintf (is, dis_style_register, "%s",
1599 mips_gpr_names[16]);
1600 infprintf (is, dis_style_text, "-");
1601 infprintf (is, dis_style_register, "%s",
1602 mips_gpr_names[15 + s_reg_encode]);
1603 }
ab902481 1604 else if (s_reg_encode == 9)
ecfbeec8
AB
1605 {
1606 infprintf (is, dis_style_register, "%s",
1607 mips_gpr_names[16]);
1608 infprintf (is, dis_style_text, "-");
1609 infprintf (is, dis_style_register, "%s",
1610 mips_gpr_names[23]);
1611 infprintf (is, dis_style_text, ",");
1612 infprintf (is, dis_style_register, "%s",
1613 mips_gpr_names[30]);
1614 }
ab902481 1615 else
ecfbeec8 1616 infprintf (is, dis_style_text, "UNKNOWN");
ab902481 1617 }
794ac9d0 1618
ab902481
RS
1619 if (uval & 0x10) /* For ra. */
1620 {
1621 if (s_reg_encode == 0)
ecfbeec8 1622 infprintf (is, dis_style_register, "%s", mips_gpr_names[31]);
ab902481 1623 else
ecfbeec8
AB
1624 {
1625 infprintf (is, dis_style_text, ",");
1626 infprintf (is, dis_style_register, "%s",
1627 mips_gpr_names[31]);
1628 }
ab902481
RS
1629 }
1630 }
1631 break;
794ac9d0 1632
c3c07478
RS
1633 case OP_ENTRY_EXIT_LIST:
1634 {
1635 const char *sep;
1636 unsigned int amask, smask;
1637
1638 sep = "";
1639 amask = (uval >> 3) & 7;
1640 if (amask > 0 && amask < 5)
1641 {
ecfbeec8 1642 infprintf (is, dis_style_register, "%s", mips_gpr_names[4]);
c3c07478 1643 if (amask > 1)
ecfbeec8
AB
1644 {
1645 infprintf (is, dis_style_text, "-");
1646 infprintf (is, dis_style_register, "%s",
1647 mips_gpr_names[amask + 3]);
1648 }
c3c07478
RS
1649 sep = ",";
1650 }
1651
1652 smask = (uval >> 1) & 3;
1653 if (smask == 3)
1654 {
ecfbeec8 1655 infprintf (is, dis_style_text, "%s??", sep);
c3c07478
RS
1656 sep = ",";
1657 }
1658 else if (smask > 0)
1659 {
ecfbeec8
AB
1660 infprintf (is, dis_style_text, "%s", sep);
1661 infprintf (is, dis_style_register, "%s", mips_gpr_names[16]);
c3c07478 1662 if (smask > 1)
ecfbeec8
AB
1663 {
1664 infprintf (is, dis_style_text, "-");
1665 infprintf (is, dis_style_register, "%s",
1666 mips_gpr_names[smask + 15]);
1667 }
c3c07478
RS
1668 sep = ",";
1669 }
1670
1671 if (uval & 1)
1672 {
ecfbeec8
AB
1673 infprintf (is, dis_style_text, "%s", sep);
1674 infprintf (is, dis_style_register, "%s", mips_gpr_names[31]);
c3c07478
RS
1675 sep = ",";
1676 }
1677
1678 if (amask == 5 || amask == 6)
1679 {
ecfbeec8
AB
1680 infprintf (is, dis_style_text, "%s", sep);
1681 infprintf (is, dis_style_register, "%s", mips_fpr_names[0]);
c3c07478 1682 if (amask == 6)
ecfbeec8
AB
1683 {
1684 infprintf (is, dis_style_text, "-");
1685 infprintf (is, dis_style_register, "%s", mips_fpr_names[1]);
1686 }
c3c07478
RS
1687 }
1688 }
1689 break;
1690
1691 case OP_SAVE_RESTORE_LIST:
38bf472a 1692 /* Should be handled by the caller due to complex behavior. */
c3c07478
RS
1693 abort ();
1694
ab902481
RS
1695 case OP_MDMX_IMM_REG:
1696 {
1697 unsigned int vsel;
794ac9d0 1698
ab902481
RS
1699 vsel = uval >> 5;
1700 uval &= 31;
1701 if ((vsel & 0x10) == 0)
794ac9d0 1702 {
ab902481
RS
1703 int fmt;
1704
1705 vsel &= 0x0f;
1706 for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
1707 if ((vsel & 1) == 0)
1708 break;
1709 print_reg (info, opcode, OP_REG_VEC, uval);
ecfbeec8
AB
1710 infprintf (is, dis_style_text, "[");
1711 infprintf (is, dis_style_immediate, "%d", vsel >> 1);
1712 infprintf (is, dis_style_text, "]");
794ac9d0 1713 }
ab902481
RS
1714 else if ((vsel & 0x08) == 0)
1715 print_reg (info, opcode, OP_REG_VEC, uval);
1716 else
ecfbeec8 1717 infprintf (is, dis_style_immediate, "0x%x", uval);
ab902481
RS
1718 }
1719 break;
794ac9d0 1720
ab902481
RS
1721 case OP_REPEAT_PREV_REG:
1722 print_reg (info, opcode, state->last_reg_type, state->last_regno);
1723 break;
794ac9d0 1724
ab902481 1725 case OP_REPEAT_DEST_REG:
7361da2c
AB
1726 print_reg (info, opcode, state->last_reg_type, state->dest_regno);
1727 break;
794ac9d0 1728
ab902481 1729 case OP_PC:
ecfbeec8 1730 infprintf (is, dis_style_register, "$pc");
ab902481 1731 break;
14daeee3 1732
25499ac7
MR
1733 case OP_REG28:
1734 print_reg (info, opcode, OP_REG_GP, 28);
1735 break;
1736
14daeee3
RS
1737 case OP_VU0_SUFFIX:
1738 case OP_VU0_MATCH_SUFFIX:
ecfbeec8 1739 print_vu0_channel (info, operand, uval, dis_style_register);
14daeee3 1740 break;
4edbb8e3
CF
1741
1742 case OP_IMM_INDEX:
ecfbeec8
AB
1743 infprintf (is, dis_style_text, "[");
1744 infprintf (is, dis_style_immediate, "%d", uval);
1745 infprintf (is, dis_style_text, "]");
4edbb8e3
CF
1746 break;
1747
1748 case OP_REG_INDEX:
ecfbeec8 1749 infprintf (is, dis_style_text, "[");
4edbb8e3 1750 print_reg (info, opcode, OP_REG_GP, uval);
ecfbeec8 1751 infprintf (is, dis_style_text, "]");
4edbb8e3 1752 break;
ab902481
RS
1753 }
1754}
794ac9d0 1755
7361da2c
AB
1756/* Validate the arguments for INSN, which is described by OPCODE.
1757 Use DECODE_OPERAND to get the encoding of each operand. */
1758
78933a4a 1759static bool
7361da2c
AB
1760validate_insn_args (const struct mips_opcode *opcode,
1761 const struct mips_operand *(*decode_operand) (const char *),
1762 unsigned int insn)
1763{
1764 struct mips_print_arg_state state;
1765 const struct mips_operand *operand;
1766 const char *s;
1767 unsigned int uval;
1768
1769 init_print_arg_state (&state);
1770 for (s = opcode->args; *s; ++s)
1771 {
1772 switch (*s)
1773 {
1774 case ',':
1775 case '(':
1776 case ')':
1777 break;
1778
1779 case '#':
1780 ++s;
1781 break;
1782
1783 default:
1784 operand = decode_operand (s);
1785
1786 if (operand)
1787 {
1788 uval = mips_extract_operand (operand, insn);
1789 switch (operand->type)
1790 {
1791 case OP_REG:
1792 case OP_OPTIONAL_REG:
1793 {
1794 const struct mips_reg_operand *reg_op;
1795
1796 reg_op = (const struct mips_reg_operand *) operand;
1797 uval = mips_decode_reg_operand (reg_op, uval);
1798 mips_seen_register (&state, uval, reg_op->reg_type);
1799 }
1800 break;
1801
1802 case OP_SAME_RS_RT:
1803 {
1804 unsigned int reg1, reg2;
1805
1806 reg1 = uval & 31;
1807 reg2 = uval >> 5;
1808
1809 if (reg1 != reg2 || reg1 == 0)
78933a4a 1810 return false;
7361da2c
AB
1811 }
1812 break;
1813
1814 case OP_CHECK_PREV:
1815 {
1816 const struct mips_check_prev_operand *prev_op;
1817
1818 prev_op = (const struct mips_check_prev_operand *) operand;
1819
1820 if (!prev_op->zero_ok && uval == 0)
78933a4a 1821 return false;
7361da2c
AB
1822
1823 if (((prev_op->less_than_ok && uval < state.last_regno)
1824 || (prev_op->greater_than_ok && uval > state.last_regno)
1825 || (prev_op->equal_ok && uval == state.last_regno)))
1826 break;
1827
78933a4a 1828 return false;
7361da2c
AB
1829 }
1830
1831 case OP_NON_ZERO_REG:
1832 {
1833 if (uval == 0)
78933a4a 1834 return false;
7361da2c
AB
1835 }
1836 break;
1837
1838 case OP_INT:
1839 case OP_MAPPED_INT:
1840 case OP_MSB:
1841 case OP_REG_PAIR:
1842 case OP_PCREL:
1843 case OP_PERF_REG:
1844 case OP_ADDIUSP_INT:
1845 case OP_CLO_CLZ_DEST:
1846 case OP_LWM_SWM_LIST:
1847 case OP_ENTRY_EXIT_LIST:
1848 case OP_MDMX_IMM_REG:
1849 case OP_REPEAT_PREV_REG:
1850 case OP_REPEAT_DEST_REG:
1851 case OP_PC:
25499ac7 1852 case OP_REG28:
7361da2c
AB
1853 case OP_VU0_SUFFIX:
1854 case OP_VU0_MATCH_SUFFIX:
1855 case OP_IMM_INDEX:
1856 case OP_REG_INDEX:
7361da2c 1857 case OP_SAVE_RESTORE_LIST:
38bf472a 1858 break;
7361da2c
AB
1859 }
1860 }
1861 if (*s == 'm' || *s == '+' || *s == '-')
1862 ++s;
1863 }
1864 }
78933a4a 1865 return true;
7361da2c
AB
1866}
1867
ab902481
RS
1868/* Print the arguments for INSN, which is described by OPCODE.
1869 Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
7361da2c
AB
1870 as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1871 operand is for a branch or jump. */
af7ee8bf 1872
ab902481
RS
1873static void
1874print_insn_args (struct disassemble_info *info,
1875 const struct mips_opcode *opcode,
1876 const struct mips_operand *(*decode_operand) (const char *),
7361da2c 1877 unsigned int insn, bfd_vma insn_pc, unsigned int length)
ab902481 1878{
ecfbeec8 1879 const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
ab902481
RS
1880 void *is = info->stream;
1881 struct mips_print_arg_state state;
1882 const struct mips_operand *operand;
1883 const char *s;
794ac9d0 1884
ab902481
RS
1885 init_print_arg_state (&state);
1886 for (s = opcode->args; *s; ++s)
1887 {
1888 switch (*s)
1889 {
1890 case ',':
1891 case '(':
1892 case ')':
ecfbeec8 1893 infprintf (is, dis_style_text, "%c", *s);
794ac9d0
CD
1894 break;
1895
14daeee3
RS
1896 case '#':
1897 ++s;
ecfbeec8 1898 infprintf (is, dis_style_text, "%c%c", *s, *s);
14daeee3
RS
1899 break;
1900
ab902481
RS
1901 default:
1902 operand = decode_operand (s);
1903 if (!operand)
fa7616a4 1904 {
ab902481 1905 /* xgettext:c-format */
ecfbeec8 1906 infprintf (is, dis_style_text,
ab902481
RS
1907 _("# internal error, undefined operand in `%s %s'"),
1908 opcode->name, opcode->args);
1909 return;
1910 }
38bf472a
MR
1911
1912 if (operand->type == OP_SAVE_RESTORE_LIST)
1913 {
1914 /* Handle this case here because of the complex behavior. */
1915 unsigned int amask = (insn >> 15) & 0xf;
1916 unsigned int nsreg = (insn >> 23) & 0x7;
1917 unsigned int ra = insn & 0x1000; /* $ra */
1918 unsigned int s0 = insn & 0x800; /* $s0 */
1919 unsigned int s1 = insn & 0x400; /* $s1 */
1920 unsigned int frame_size = (((insn >> 15) & 0xf0)
1921 | ((insn >> 6) & 0x0f)) * 8;
1922 mips_print_save_restore (info, amask, nsreg, ra, s0, s1,
1923 frame_size);
1924 }
1925 else if (operand->type == OP_REG
1926 && s[1] == ','
0c5c669c 1927 && s[2] == 'H'
38bf472a 1928 && opcode->name[strlen (opcode->name) - 1] == '0')
ab902481 1929 {
fdfb4752 1930 /* Coprocessor register 0 with sel field. */
ab902481
RS
1931 const struct mips_cp0sel_name *n;
1932 unsigned int reg, sel;
1933
1934 reg = mips_extract_operand (operand, insn);
1935 s += 2;
1936 operand = decode_operand (s);
1937 sel = mips_extract_operand (operand, insn);
1938
1939 /* CP0 register including 'sel' code for mftc0, to be
1940 printed textually if known. If not known, print both
1941 CP0 register name and sel numerically since CP0 register
1942 with sel 0 may have a name unrelated to register being
1943 printed. */
1944 n = lookup_mips_cp0sel_name (mips_cp0sel_names,
1945 mips_cp0sel_names_len,
1946 reg, sel);
1947 if (n != NULL)
ecfbeec8 1948 infprintf (is, dis_style_register, "%s", n->name);
fa7616a4 1949 else
ecfbeec8
AB
1950 {
1951 infprintf (is, dis_style_register, "$%d", reg);
1952 infprintf (is, dis_style_text, ",");
1953 infprintf (is, dis_style_immediate, "%d", sel);
1954 }
fa7616a4 1955 }
794ac9d0 1956 else
7361da2c
AB
1957 {
1958 bfd_vma base_pc = insn_pc;
1959
1960 /* Adjust the PC relative base so that branch/jump insns use
1961 the following PC as the base but genuinely PC relative
1962 operands use the current PC. */
1963 if (operand->type == OP_PCREL)
1964 {
1965 const struct mips_pcrel_operand *pcrel_op;
1966
1967 pcrel_op = (const struct mips_pcrel_operand *) operand;
1968 /* The include_isa_bit flag is sufficient to distinguish
1969 branch/jump from other PC relative operands. */
1970 if (pcrel_op->include_isa_bit)
1971 base_pc += length;
1972 }
1973
1974 print_insn_arg (info, &state, opcode, operand, base_pc,
1975 mips_extract_operand (operand, insn));
1976 }
1977 if (*s == 'm' || *s == '+' || *s == '-')
ab902481 1978 ++s;
794ac9d0 1979 break;
af7ee8bf 1980 }
252b5132
RH
1981 }
1982}
1983\f
252b5132
RH
1984/* Print the mips instruction at address MEMADDR in debugged memory,
1985 on using INFO. Returns length of the instruction, in bytes, which is
aa5f19f2 1986 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
252b5132
RH
1987 this is little-endian code. */
1988
1989static int
47b0e7ad 1990print_insn_mips (bfd_vma memaddr,
fc8c4fd1 1991 int word,
47b0e7ad 1992 struct disassemble_info *info)
252b5132 1993{
ab902481
RS
1994#define GET_OP(insn, field) \
1995 (((insn) >> OP_SH_##field) & OP_MASK_##field)
fc8c4fd1 1996 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
ecfbeec8 1997 const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
47b0e7ad 1998 const struct mips_opcode *op;
78933a4a 1999 static bool init = 0;
fc8c4fd1 2000 void *is = info->stream;
252b5132
RH
2001
2002 /* Build a hash table to shorten the search time. */
2003 if (! init)
2004 {
2005 unsigned int i;
2006
2007 for (i = 0; i <= OP_MASK_OP; i++)
2008 {
2009 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
2010 {
986e18a5 2011 if (op->pinfo == INSN_MACRO
9e836e3d 2012 || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
252b5132 2013 continue;
fc8c4fd1 2014 if (i == GET_OP (op->match, OP))
252b5132
RH
2015 {
2016 mips_hash[i] = op;
2017 break;
2018 }
2019 }
7f6621cd 2020 }
252b5132
RH
2021
2022 init = 1;
2023 }
2024
aa5f19f2 2025 info->bytes_per_chunk = INSNLEN;
252b5132 2026 info->display_endian = info->endian;
9bb28706
CD
2027 info->insn_info_valid = 1;
2028 info->branch_delay_insns = 0;
def7143b 2029 info->data_size = 0;
9bb28706
CD
2030 info->insn_type = dis_nonbranch;
2031 info->target = 0;
2032 info->target2 = 0;
252b5132 2033
fc8c4fd1 2034 op = mips_hash[GET_OP (word, OP)];
252b5132
RH
2035 if (op != NULL)
2036 {
2037 for (; op < &mips_opcodes[NUMOPCODES]; op++)
2038 {
43e65147 2039 if (op->pinfo != INSN_MACRO
9e836e3d 2040 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
986e18a5 2041 && (word & op->mask) == op->match)
252b5132 2042 {
7361da2c 2043 /* We always disassemble the jalx instruction, except for MIPS r6. */
d301a56b 2044 if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
7361da2c
AB
2045 && (strcmp (op->name, "jalx")
2046 || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6
2047 || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6))
252b5132
RH
2048 continue;
2049
9bb28706
CD
2050 /* Figure out instruction type and branch delay information. */
2051 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
2052 {
fc76e730 2053 if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
9bb28706
CD
2054 info->insn_type = dis_jsr;
2055 else
2056 info->insn_type = dis_branch;
2057 info->branch_delay_insns = 1;
2058 }
2059 else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
2060 | INSN_COND_BRANCH_LIKELY)) != 0)
2061 {
c680e7f6 2062 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
9bb28706
CD
2063 info->insn_type = dis_condjsr;
2064 else
2065 info->insn_type = dis_condbranch;
2066 info->branch_delay_insns = 1;
2067 }
2068 else if ((op->pinfo & (INSN_STORE_MEMORY
67dc82bc 2069 | INSN_LOAD_MEMORY)) != 0)
9bb28706
CD
2070 info->insn_type = dis_dref;
2071
7361da2c
AB
2072 if (!validate_insn_args (op, decode_mips_operand, word))
2073 continue;
2074
ecfbeec8 2075 infprintf (is, dis_style_mnemonic, "%s", op->name);
14daeee3
RS
2076 if (op->pinfo2 & INSN2_VU0_CHANNEL_SUFFIX)
2077 {
2078 unsigned int uval;
2079
ecfbeec8 2080 infprintf (is, dis_style_mnemonic, ".");
14daeee3 2081 uval = mips_extract_operand (&mips_vu0_channel_mask, word);
ecfbeec8
AB
2082 print_vu0_channel (info, &mips_vu0_channel_mask, uval,
2083 dis_style_mnemonic);
14daeee3 2084 }
252b5132 2085
ab902481 2086 if (op->args[0])
252b5132 2087 {
ecfbeec8 2088 infprintf (is, dis_style_text, "\t");
ab902481 2089 print_insn_args (info, op, decode_mips_operand, word,
7361da2c 2090 memaddr, 4);
252b5132
RH
2091 }
2092
aa5f19f2 2093 return INSNLEN;
252b5132
RH
2094 }
2095 }
2096 }
fc8c4fd1 2097#undef GET_OP
252b5132
RH
2098
2099 /* Handle undefined instructions. */
9bb28706 2100 info->insn_type = dis_noninsn;
ecfbeec8
AB
2101 infprintf (is, dis_style_assembler_directive, ".word");
2102 infprintf (is, dis_style_text, "\t");
2103 infprintf (is, dis_style_immediate, "0x%x", word);
aa5f19f2 2104 return INSNLEN;
252b5132 2105}
aa5f19f2 2106\f
252b5132
RH
2107/* Disassemble an operand for a mips16 instruction. */
2108
2109static void
c3c07478
RS
2110print_mips16_insn_arg (struct disassemble_info *info,
2111 struct mips_print_arg_state *state,
2112 const struct mips_opcode *opcode,
2113 char type, bfd_vma memaddr,
78933a4a
AM
2114 unsigned insn, bool use_extend,
2115 unsigned extend, bool is_offset)
252b5132 2116{
ecfbeec8 2117 const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
fc8c4fd1 2118 void *is = info->stream;
c3c07478 2119 const struct mips_operand *operand, *ext_operand;
bdd15286 2120 unsigned short ext_size;
c3c07478
RS
2121 unsigned int uval;
2122 bfd_vma baseaddr;
2123
2124 if (!use_extend)
2125 extend = 0;
fc8c4fd1 2126
252b5132
RH
2127 switch (type)
2128 {
2129 case ',':
2130 case '(':
2131 case ')':
ecfbeec8 2132 infprintf (is, dis_style_text, "%c", type);
252b5132
RH
2133 break;
2134
c3c07478 2135 default:
78933a4a 2136 operand = decode_mips16_operand (type, false);
c3c07478
RS
2137 if (!operand)
2138 {
2139 /* xgettext:c-format */
ecfbeec8 2140 infprintf (is, dis_style_text, _("# internal error, undefined operand in `%s %s'"),
c3c07478
RS
2141 opcode->name, opcode->args);
2142 return;
2143 }
252b5132 2144
c3c07478
RS
2145 if (operand->type == OP_SAVE_RESTORE_LIST)
2146 {
5f5c6e03 2147 /* Handle this case here because of the complex interaction
c3c07478 2148 with the EXTEND opcode. */
38bf472a
MR
2149 unsigned int amask = extend & 0xf;
2150 unsigned int nsreg = (extend >> 8) & 0x7;
2151 unsigned int ra = insn & 0x40; /* $ra */
2152 unsigned int s0 = insn & 0x20; /* $s0 */
2153 unsigned int s1 = insn & 0x10; /* $s1 */
2154 unsigned int frame_size = ((extend & 0xf0) | (insn & 0x0f)) * 8;
c3c07478
RS
2155 if (frame_size == 0 && !use_extend)
2156 frame_size = 128;
38bf472a 2157 mips_print_save_restore (info, amask, nsreg, ra, s0, s1, frame_size);
c3c07478
RS
2158 break;
2159 }
252b5132 2160
c3c07478
RS
2161 if (is_offset && operand->type == OP_INT)
2162 {
2163 const struct mips_int_operand *int_op;
252b5132 2164
c3c07478
RS
2165 int_op = (const struct mips_int_operand *) operand;
2166 info->insn_type = dis_dref;
2167 info->data_size = 1 << int_op->shift;
2168 }
252b5132 2169
bdd15286
MR
2170 ext_size = 0;
2171 if (use_extend)
c3c07478 2172 {
78933a4a 2173 ext_operand = decode_mips16_operand (type, true);
25499ac7
MR
2174 if (ext_operand != operand
2175 || (operand->type == OP_INT && operand->lsb == 0
2176 && mips_opcode_32bit_p (opcode)))
c3c07478 2177 {
bdd15286
MR
2178 ext_size = ext_operand->size;
2179 operand = ext_operand;
c3c07478
RS
2180 }
2181 }
bdd15286
MR
2182 if (operand->size == 26)
2183 uval = ((extend & 0x1f) << 21) | ((extend & 0x3e0) << 11) | insn;
25499ac7 2184 else if (ext_size == 16 || ext_size == 9)
bdd15286
MR
2185 uval = ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
2186 else if (ext_size == 15)
2187 uval = ((extend & 0xf) << 11) | (extend & 0x7f0) | (insn & 0xf);
2188 else if (ext_size == 6)
2189 uval = ((extend >> 6) & 0x1f) | (extend & 0x20);
2190 else
2191 uval = mips_extract_operand (operand, (extend << 16) | insn);
25499ac7
MR
2192 if (ext_size == 9)
2193 uval &= (1U << ext_size) - 1;
c3c07478
RS
2194
2195 baseaddr = memaddr + 2;
2196 if (operand->type == OP_PCREL)
2197 {
2198 const struct mips_pcrel_operand *pcrel_op;
2199
2200 pcrel_op = (const struct mips_pcrel_operand *) operand;
2201 if (!pcrel_op->include_isa_bit && use_extend)
2202 baseaddr = memaddr - 2;
2203 else if (!pcrel_op->include_isa_bit)
39f66f3a
MR
2204 {
2205 bfd_byte buffer[2];
2206
2207 /* If this instruction is in the delay slot of a JAL/JALX
2208 instruction, the base address is the address of the
2209 JAL/JALX instruction. If it is in the delay slot of
2210 a JR/JALR instruction, the base address is the address
2211 of the JR/JALR instruction. This test is unreliable:
2212 we have no way of knowing whether the previous word is
2213 instruction or data. */
2214 if (info->read_memory_func (memaddr - 4, buffer, 2, info) == 0
2215 && (((info->endian == BFD_ENDIAN_BIG
2216 ? bfd_getb16 (buffer)
2217 : bfd_getl16 (buffer))
2218 & 0xf800) == 0x1800))
2219 baseaddr = memaddr - 4;
2220 else if (info->read_memory_func (memaddr - 2, buffer, 2,
2221 info) == 0
2222 && (((info->endian == BFD_ENDIAN_BIG
2223 ? bfd_getb16 (buffer)
2224 : bfd_getl16 (buffer))
2225 & 0xf89f) == 0xe800)
2226 && (((info->endian == BFD_ENDIAN_BIG
2227 ? bfd_getb16 (buffer)
2228 : bfd_getl16 (buffer))
2229 & 0x0060) != 0x0060))
2230 baseaddr = memaddr - 2;
2231 else
2232 baseaddr = memaddr;
2233 }
c3c07478 2234 }
0499d65b 2235
6d075bce 2236 print_insn_arg (info, state, opcode, operand, baseaddr + 1, uval);
0499d65b 2237 break;
252b5132
RH
2238 }
2239}
640c0ccd 2240
1bbce132
MR
2241
2242/* Check if the given address is the last word of a MIPS16 PLT entry.
2243 This word is data and depending on the value it may interfere with
2244 disassembly of further PLT entries. We make use of the fact PLT
2245 symbols are marked BSF_SYNTHETIC. */
78933a4a 2246static bool
1bbce132
MR
2247is_mips16_plt_tail (struct disassemble_info *info, bfd_vma addr)
2248{
2249 if (info->symbols
2250 && info->symbols[0]
2251 && (info->symbols[0]->flags & BSF_SYNTHETIC)
2252 && addr == bfd_asymbol_value (info->symbols[0]) + 12)
78933a4a 2253 return true;
1bbce132 2254
78933a4a 2255 return false;
1bbce132
MR
2256}
2257
7fd53920
MR
2258/* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2259
2260enum match_kind
2261{
2262 MATCH_NONE,
2263 MATCH_FULL,
2264 MATCH_SHORT
2265};
2266
47b0e7ad
NC
2267/* Disassemble mips16 instructions. */
2268
2269static int
2270print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
2271{
ecfbeec8 2272 const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
47b0e7ad 2273 int status;
1bbce132 2274 bfd_byte buffer[4];
47b0e7ad 2275 const struct mips_opcode *op, *opend;
c3c07478 2276 struct mips_print_arg_state state;
fc8c4fd1 2277 void *is = info->stream;
78933a4a
AM
2278 bool have_second;
2279 bool extend_only;
7fd53920
MR
2280 unsigned int second;
2281 unsigned int first;
2282 unsigned int full;
47b0e7ad
NC
2283
2284 info->bytes_per_chunk = 2;
2285 info->display_endian = info->endian;
2286 info->insn_info_valid = 1;
2287 info->branch_delay_insns = 0;
2288 info->data_size = 0;
47b0e7ad
NC
2289 info->target = 0;
2290 info->target2 = 0;
2291
c3c07478
RS
2292#define GET_OP(insn, field) \
2293 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
1bbce132
MR
2294 /* Decode PLT entry's GOT slot address word. */
2295 if (is_mips16_plt_tail (info, memaddr))
2296 {
2297 info->insn_type = dis_noninsn;
2298 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
2299 if (status == 0)
2300 {
2301 unsigned int gotslot;
2302
2303 if (info->endian == BFD_ENDIAN_BIG)
2304 gotslot = bfd_getb32 (buffer);
2305 else
2306 gotslot = bfd_getl32 (buffer);
ecfbeec8
AB
2307 infprintf (is, dis_style_assembler_directive, ".word");
2308 infprintf (is, dis_style_text, "\t");
2309 infprintf (is, dis_style_immediate, "0x%x", gotslot);
1bbce132
MR
2310
2311 return 4;
2312 }
2313 }
2314 else
2315 {
2316 info->insn_type = dis_nonbranch;
2317 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2318 }
47b0e7ad
NC
2319 if (status != 0)
2320 {
2321 (*info->memory_error_func) (status, memaddr, info);
2322 return -1;
2323 }
2324
78933a4a 2325 extend_only = false;
25499ac7 2326
47b0e7ad 2327 if (info->endian == BFD_ENDIAN_BIG)
7fd53920 2328 first = bfd_getb16 (buffer);
47b0e7ad 2329 else
7fd53920 2330 first = bfd_getl16 (buffer);
47b0e7ad 2331
7fd53920
MR
2332 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2333 if (status == 0)
47b0e7ad 2334 {
78933a4a 2335 have_second = true;
47b0e7ad 2336 if (info->endian == BFD_ENDIAN_BIG)
7fd53920 2337 second = bfd_getb16 (buffer);
47b0e7ad 2338 else
7fd53920
MR
2339 second = bfd_getl16 (buffer);
2340 full = (first << 16) | second;
2341 }
2342 else
2343 {
78933a4a 2344 have_second = false;
7fd53920
MR
2345 second = 0;
2346 full = first;
47b0e7ad
NC
2347 }
2348
2349 /* FIXME: Should probably use a hash table on the major opcode here. */
2350
2351 opend = mips16_opcodes + bfd_mips16_num_opcodes;
2352 for (op = mips16_opcodes; op < opend; op++)
2353 {
7fd53920 2354 enum match_kind match;
47b0e7ad 2355
11dd08e9
MR
2356 if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor))
2357 continue;
2358
7fd53920
MR
2359 if (op->pinfo == INSN_MACRO
2360 || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
2361 match = MATCH_NONE;
2362 else if (mips_opcode_32bit_p (op))
2363 {
2364 if (have_second
2365 && (full & op->mask) == op->match)
2366 match = MATCH_FULL;
2367 else
2368 match = MATCH_NONE;
2369 }
2370 else if ((first & op->mask) == op->match)
2371 {
2372 match = MATCH_SHORT;
2373 second = 0;
2374 full = first;
2375 }
2376 else if ((first & 0xf800) == 0xf000
2377 && have_second
25499ac7 2378 && !extend_only
7fd53920 2379 && (second & op->mask) == op->match)
25499ac7
MR
2380 {
2381 if (op->pinfo2 & INSN2_SHORT_ONLY)
2382 {
2383 match = MATCH_NONE;
78933a4a 2384 extend_only = true;
25499ac7
MR
2385 }
2386 else
2387 match = MATCH_FULL;
2388 }
7fd53920
MR
2389 else
2390 match = MATCH_NONE;
47b0e7ad 2391
7fd53920
MR
2392 if (match != MATCH_NONE)
2393 {
2394 const char *s;
47b0e7ad 2395
ecfbeec8 2396 infprintf (is, dis_style_mnemonic, "%s", op->name);
47b0e7ad 2397 if (op->args[0] != '\0')
ecfbeec8 2398 infprintf (is, dis_style_text, "\t");
47b0e7ad 2399
c3c07478 2400 init_print_arg_state (&state);
47b0e7ad
NC
2401 for (s = op->args; *s != '\0'; s++)
2402 {
2403 if (*s == ','
2404 && s[1] == 'w'
7fd53920 2405 && GET_OP (full, RX) == GET_OP (full, RY))
47b0e7ad
NC
2406 {
2407 /* Skip the register and the comma. */
2408 ++s;
2409 continue;
2410 }
2411 if (*s == ','
2412 && s[1] == 'v'
7fd53920 2413 && GET_OP (full, RZ) == GET_OP (full, RX))
47b0e7ad
NC
2414 {
2415 /* Skip the register and the comma. */
2416 ++s;
2417 continue;
2418 }
25499ac7
MR
2419 if (s[0] == 'N'
2420 && s[1] == ','
2421 && s[2] == 'O'
2422 && op->name[strlen (op->name) - 1] == '0')
7fd53920 2423 {
25499ac7
MR
2424 /* Coprocessor register 0 with sel field. */
2425 const struct mips_cp0sel_name *n;
2426 const struct mips_operand *operand;
2427 unsigned int reg, sel;
2428
78933a4a 2429 operand = decode_mips16_operand (*s, true);
25499ac7
MR
2430 reg = mips_extract_operand (operand, (first << 16) | second);
2431 s += 2;
78933a4a 2432 operand = decode_mips16_operand (*s, true);
25499ac7
MR
2433 sel = mips_extract_operand (operand, (first << 16) | second);
2434
2435 /* CP0 register including 'sel' code for mftc0, to be
2436 printed textually if known. If not known, print both
2437 CP0 register name and sel numerically since CP0 register
2438 with sel 0 may have a name unrelated to register being
2439 printed. */
2440 n = lookup_mips_cp0sel_name (mips_cp0sel_names,
2441 mips_cp0sel_names_len,
2442 reg, sel);
2443 if (n != NULL)
ecfbeec8 2444 infprintf (is, dis_style_register, "%s", n->name);
25499ac7 2445 else
ecfbeec8
AB
2446 {
2447 infprintf (is, dis_style_register, "$%d", reg);
2448 infprintf (is, dis_style_text, ",");
2449 infprintf (is, dis_style_immediate, "%d", sel);
2450 }
7fd53920 2451 }
25499ac7
MR
2452 else
2453 switch (match)
2454 {
2455 case MATCH_FULL:
2456 print_mips16_insn_arg (info, &state, op, *s, memaddr + 2,
78933a4a 2457 second, true, first, s[1] == '(');
25499ac7
MR
2458 break;
2459 case MATCH_SHORT:
2460 print_mips16_insn_arg (info, &state, op, *s, memaddr,
78933a4a 2461 first, false, 0, s[1] == '(');
25499ac7
MR
2462 break;
2463 case MATCH_NONE: /* Stop the compiler complaining. */
2464 break;
2465 }
47b0e7ad
NC
2466 }
2467
9a2c7088 2468 /* Figure out branch instruction type and delay slot information. */
47b0e7ad 2469 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
9a2c7088 2470 info->branch_delay_insns = 1;
26545944
RS
2471 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0
2472 || (op->pinfo2 & INSN2_UNCOND_BRANCH) != 0)
47b0e7ad 2473 {
9a2c7088
MR
2474 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2475 info->insn_type = dis_jsr;
2476 else
47b0e7ad
NC
2477 info->insn_type = dis_branch;
2478 }
26545944 2479 else if ((op->pinfo2 & INSN2_COND_BRANCH) != 0)
9a2c7088 2480 info->insn_type = dis_condbranch;
47b0e7ad 2481
7fd53920 2482 return match == MATCH_FULL ? 4 : 2;
47b0e7ad
NC
2483 }
2484 }
fc8c4fd1 2485#undef GET_OP
47b0e7ad 2486
ecfbeec8
AB
2487 infprintf (is, dis_style_assembler_directive, ".short");
2488 infprintf (is, dis_style_text, "\t");
2489 infprintf (is, dis_style_immediate, "0x%x", first);
47b0e7ad
NC
2490 info->insn_type = dis_noninsn;
2491
7fd53920 2492 return 2;
47b0e7ad
NC
2493}
2494
df58fc94
RS
2495/* Disassemble microMIPS instructions. */
2496
2497static int
2498print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
2499{
ecfbeec8 2500 const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
df58fc94 2501 const struct mips_opcode *op, *opend;
df58fc94 2502 void *is = info->stream;
df58fc94 2503 bfd_byte buffer[2];
ab902481
RS
2504 unsigned int higher;
2505 unsigned int length;
df58fc94 2506 int status;
ab902481 2507 unsigned int insn;
df58fc94
RS
2508
2509 info->bytes_per_chunk = 2;
2510 info->display_endian = info->endian;
2511 info->insn_info_valid = 1;
2512 info->branch_delay_insns = 0;
2513 info->data_size = 0;
2514 info->insn_type = dis_nonbranch;
2515 info->target = 0;
2516 info->target2 = 0;
2517
2518 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2519 if (status != 0)
2520 {
2521 (*info->memory_error_func) (status, memaddr, info);
2522 return -1;
2523 }
2524
2525 length = 2;
2526
2527 if (info->endian == BFD_ENDIAN_BIG)
2528 insn = bfd_getb16 (buffer);
2529 else
2530 insn = bfd_getl16 (buffer);
2531
100b4f2e 2532 if ((insn & 0x1c00) == 0x0000 || (insn & 0x1000) == 0x1000)
df58fc94
RS
2533 {
2534 /* This is a 32-bit microMIPS instruction. */
2535 higher = insn;
2536
2537 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2538 if (status != 0)
2539 {
ecfbeec8 2540 infprintf (is, dis_style_text, "micromips 0x%x", higher);
df58fc94
RS
2541 (*info->memory_error_func) (status, memaddr + 2, info);
2542 return -1;
2543 }
2544
2545 if (info->endian == BFD_ENDIAN_BIG)
2546 insn = bfd_getb16 (buffer);
2547 else
2548 insn = bfd_getl16 (buffer);
2549
2550 insn = insn | (higher << 16);
2551
2552 length += 2;
2553 }
2554
2555 /* FIXME: Should probably use a hash table on the major opcode here. */
2556
df58fc94
RS
2557 opend = micromips_opcodes + bfd_micromips_num_opcodes;
2558 for (op = micromips_opcodes; op < opend; op++)
2559 {
2560 if (op->pinfo != INSN_MACRO
2561 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
2562 && (insn & op->mask) == op->match
2563 && ((length == 2 && (op->mask & 0xffff0000) == 0)
2564 || (length == 4 && (op->mask & 0xffff0000) != 0)))
2565 {
7361da2c
AB
2566 if (!validate_insn_args (op, decode_micromips_operand, insn))
2567 continue;
2568
ecfbeec8 2569 infprintf (is, dis_style_mnemonic, "%s", op->name);
df58fc94 2570
ab902481 2571 if (op->args[0])
df58fc94 2572 {
ecfbeec8 2573 infprintf (is, dis_style_text, "\t");
ab902481 2574 print_insn_args (info, op, decode_micromips_operand, insn,
7361da2c 2575 memaddr + 1, length);
df58fc94
RS
2576 }
2577
2578 /* Figure out instruction type and branch delay information. */
2579 if ((op->pinfo
2580 & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY)) != 0)
2581 info->branch_delay_insns = 1;
2582 if (((op->pinfo & INSN_UNCOND_BRANCH_DELAY)
2583 | (op->pinfo2 & INSN2_UNCOND_BRANCH)) != 0)
2584 {
fc76e730 2585 if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
df58fc94
RS
2586 info->insn_type = dis_jsr;
2587 else
2588 info->insn_type = dis_branch;
2589 }
2590 else if (((op->pinfo & INSN_COND_BRANCH_DELAY)
2591 | (op->pinfo2 & INSN2_COND_BRANCH)) != 0)
2592 {
2593 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2594 info->insn_type = dis_condjsr;
2595 else
2596 info->insn_type = dis_condbranch;
2597 }
2598 else if ((op->pinfo
67dc82bc 2599 & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY)) != 0)
df58fc94
RS
2600 info->insn_type = dis_dref;
2601
2602 return length;
2603 }
2604 }
df58fc94 2605
77be7257 2606 infprintf (is, dis_style_assembler_directive, ".short");
ecfbeec8 2607 infprintf (is, dis_style_text, "\t");
77be7257
AB
2608 if (length != 2)
2609 {
2610 infprintf (is, dis_style_immediate, "0x%x", (insn >> 16) & 0xffff);
2611 infprintf (is, dis_style_text, ", ");
2612 }
2613 infprintf (is, dis_style_immediate, "0x%x", (insn & 0xffff));
2614
df58fc94
RS
2615 info->insn_type = dis_noninsn;
2616
2617 return length;
2618}
2619
2620/* Return 1 if a symbol associated with the location being disassembled
1401d2fe
MR
2621 indicates a compressed mode, either MIPS16 or microMIPS, according to
2622 MICROMIPS_P. We iterate over all the symbols at the address being
2623 considered assuming if at least one of them indicates code compression,
2624 then such code has been genuinely produced here (other symbols could
2625 have been derived from function symbols defined elsewhere or could
2626 define data). Otherwise, return 0. */
df58fc94 2627
78933a4a
AM
2628static bool
2629is_compressed_mode_p (struct disassemble_info *info, bool micromips_p)
df58fc94 2630{
df58fc94 2631 int i;
1bbce132
MR
2632 int l;
2633
2634 for (i = info->symtab_pos, l = i + info->num_symbols; i < l; i++)
2635 if (((info->symtab[i])->flags & BSF_SYNTHETIC) != 0
1401d2fe 2636 && ((!micromips_p
1bbce132 2637 && ELF_ST_IS_MIPS16 ((*info->symbols)->udata.i))
1401d2fe 2638 || (micromips_p
1bbce132
MR
2639 && ELF_ST_IS_MICROMIPS ((*info->symbols)->udata.i))))
2640 return 1;
2641 else if (bfd_asymbol_flavour (info->symtab[i]) == bfd_target_elf_flavour
2642 && info->symtab[i]->section == info->section)
2643 {
2644 elf_symbol_type *symbol = (elf_symbol_type *) info->symtab[i];
1401d2fe 2645 if ((!micromips_p
1bbce132 2646 && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
1401d2fe 2647 || (micromips_p
1bbce132
MR
2648 && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
2649 return 1;
2650 }
df58fc94
RS
2651
2652 return 0;
2653}
2654
47b0e7ad
NC
2655/* In an environment where we do not know the symbol type of the
2656 instruction we are forced to assume that the low order bit of the
2657 instructions' address may mark it as a mips16 instruction. If we
2658 are single stepping, or the pc is within the disassembled function,
2659 this works. Otherwise, we need a clue. Sometimes. */
2660
2661static int
2662_print_insn_mips (bfd_vma memaddr,
2663 struct disassemble_info *info,
2664 enum bfd_endian endianness)
2665{
2666 bfd_byte buffer[INSNLEN];
2667 int status;
2668
2669 set_default_mips_dis_options (info);
2670 parse_mips_dis_options (info->disassembler_options);
2671
df58fc94
RS
2672 if (info->mach == bfd_mach_mips16)
2673 return print_insn_mips16 (memaddr, info);
2674 if (info->mach == bfd_mach_mips_micromips)
2675 return print_insn_micromips (memaddr, info);
2676
47b0e7ad 2677#if 1
df58fc94 2678 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
47b0e7ad
NC
2679 /* Only a few tools will work this way. */
2680 if (memaddr & 0x01)
1401d2fe
MR
2681 {
2682 if (micromips_ase)
2683 return print_insn_micromips (memaddr, info);
2684 else
2685 return print_insn_mips16 (memaddr, info);
2686 }
47b0e7ad
NC
2687#endif
2688
2689#if SYMTAB_AVAILABLE
78933a4a 2690 if (is_compressed_mode_p (info, true))
1401d2fe 2691 return print_insn_micromips (memaddr, info);
78933a4a 2692 if (is_compressed_mode_p (info, false))
1401d2fe 2693 return print_insn_mips16 (memaddr, info);
47b0e7ad
NC
2694#endif
2695
2696 status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
2697 if (status == 0)
2698 {
fc8c4fd1 2699 int insn;
47b0e7ad
NC
2700
2701 if (endianness == BFD_ENDIAN_BIG)
fc8c4fd1 2702 insn = bfd_getb32 (buffer);
47b0e7ad 2703 else
fc8c4fd1 2704 insn = bfd_getl32 (buffer);
47b0e7ad
NC
2705
2706 return print_insn_mips (memaddr, insn, info);
2707 }
2708 else
2709 {
2710 (*info->memory_error_func) (status, memaddr, info);
2711 return -1;
2712 }
2713}
2714
2715int
2716print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info)
2717{
2718 return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
2719}
2720
2721int
2722print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info)
2723{
2724 return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
2725}
2726\f
471b9d15
MR
2727/* Indices into option argument vector for options accepting an argument.
2728 Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2729typedef enum
640c0ccd 2730{
471b9d15
MR
2731 MIPS_OPTION_ARG_NONE = -1,
2732 MIPS_OPTION_ARG_ABI,
2733 MIPS_OPTION_ARG_ARCH,
2734 MIPS_OPTION_ARG_SIZE
2735} mips_option_arg_t;
2736
2737/* Valid MIPS disassembler options. */
2738static struct
2739{
2740 const char *name;
2741 const char *description;
2742 mips_option_arg_t arg;
2743} mips_options[] =
2744{
2745 { "no-aliases", N_("Use canonical instruction forms.\n"),
2746 MIPS_OPTION_ARG_NONE },
2747 { "msa", N_("Recognize MSA instructions.\n"),
2748 MIPS_OPTION_ARG_NONE },
2749 { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2750 MIPS_OPTION_ARG_NONE },
2751 { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2752 instructions.\n"),
2753 MIPS_OPTION_ARG_NONE },
2754 { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2755 "instructions.\n"),
2756 MIPS_OPTION_ARG_NONE },
8095d2f7
CX
2757 { "loongson-mmi",
2758 N_("Recognize the Loongson MultiMedia extensions "
2759 "Instructions (MMI) ASE instructions.\n"),
2760 MIPS_OPTION_ARG_NONE },
716c08de
CX
2761 { "loongson-cam",
2762 N_("Recognize the Loongson Content Address Memory (CAM) "
2763 " instructions.\n"),
2764 MIPS_OPTION_ARG_NONE },
bdc6c06e
CX
2765 { "loongson-ext",
2766 N_("Recognize the Loongson EXTensions (EXT) "
2767 " instructions.\n"),
2768 MIPS_OPTION_ARG_NONE },
a693765e
CX
2769 { "loongson-ext2",
2770 N_("Recognize the Loongson EXTensions R2 (EXT2) "
2771 " instructions.\n"),
2772 MIPS_OPTION_ARG_NONE },
471b9d15
MR
2773 { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2774 Default: based on binary being disassembled.\n"),
2775 MIPS_OPTION_ARG_ABI },
2776 { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2777 Default: numeric.\n"),
2778 MIPS_OPTION_ARG_ABI },
2779 { "cp0-names=", N_("Print CP0 register names according to specified "
2780 "architecture.\n\
2781 Default: based on binary being disassembled.\n"),
2782 MIPS_OPTION_ARG_ARCH },
2783 { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2784 Default: based on binary being disassembled.\n"),
2785 MIPS_OPTION_ARG_ARCH },
2786 { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2787 MIPS_OPTION_ARG_ABI },
2788 { "reg-names=", N_("Print CP0 register and HWR names according to "
2789 "specified\n\
2790 architecture."),
2791 MIPS_OPTION_ARG_ARCH }
2792};
0348fd79 2793
471b9d15
MR
2794/* Build the structure representing valid MIPS disassembler options.
2795 This is done dynamically for maintenance ease purpose; a static
2796 initializer would be unreadable. */
4edbb8e3 2797
471b9d15
MR
2798const disasm_options_and_args_t *
2799disassembler_options_mips (void)
2800{
2801 static disasm_options_and_args_t *opts_and_args;
b015e599 2802
471b9d15
MR
2803 if (opts_and_args == NULL)
2804 {
2805 size_t num_options = ARRAY_SIZE (mips_options);
2806 size_t num_args = MIPS_OPTION_ARG_SIZE;
2807 disasm_option_arg_t *args;
2808 disasm_options_t *opts;
2809 size_t i;
2810 size_t j;
2811
2812 args = XNEWVEC (disasm_option_arg_t, num_args + 1);
2813
2814 args[MIPS_OPTION_ARG_ABI].name = "ABI";
2815 args[MIPS_OPTION_ARG_ABI].values
2816 = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices) + 1);
2817 for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
2818 args[MIPS_OPTION_ARG_ABI].values[i] = mips_abi_choices[i].name;
2819 /* The array we return must be NULL terminated. */
2820 args[MIPS_OPTION_ARG_ABI].values[i] = NULL;
2821
2822 args[MIPS_OPTION_ARG_ARCH].name = "ARCH";
2823 args[MIPS_OPTION_ARG_ARCH].values
2824 = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices) + 1);
2825 for (i = 0, j = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
2826 if (*mips_arch_choices[i].name != '\0')
2827 args[MIPS_OPTION_ARG_ARCH].values[j++] = mips_arch_choices[i].name;
2828 /* The array we return must be NULL terminated. */
2829 args[MIPS_OPTION_ARG_ARCH].values[j] = NULL;
2830
2831 /* The array we return must be NULL terminated. */
2832 args[MIPS_OPTION_ARG_SIZE].name = NULL;
2833 args[MIPS_OPTION_ARG_SIZE].values = NULL;
2834
2835 opts_and_args = XNEW (disasm_options_and_args_t);
2836 opts_and_args->args = args;
2837
2838 opts = &opts_and_args->options;
2839 opts->name = XNEWVEC (const char *, num_options + 1);
2840 opts->description = XNEWVEC (const char *, num_options + 1);
2841 opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1);
2842 for (i = 0; i < num_options; i++)
2843 {
2844 opts->name[i] = mips_options[i].name;
2845 opts->description[i] = _(mips_options[i].description);
2846 if (mips_options[i].arg != MIPS_OPTION_ARG_NONE)
2847 opts->arg[i] = &args[mips_options[i].arg];
2848 else
2849 opts->arg[i] = NULL;
2850 }
2851 /* The array we return must be NULL terminated. */
2852 opts->name[i] = NULL;
2853 opts->description[i] = NULL;
2854 opts->arg[i] = NULL;
2855 }
7d64c587 2856
471b9d15
MR
2857 return opts_and_args;
2858}
6f20c942 2859
471b9d15
MR
2860void
2861print_mips_disassembler_options (FILE *stream)
2862{
2863 const disasm_options_and_args_t *opts_and_args;
2864 const disasm_option_arg_t *args;
2865 const disasm_options_t *opts;
2866 size_t max_len = 0;
2867 size_t i;
2868 size_t j;
640c0ccd 2869
471b9d15
MR
2870 opts_and_args = disassembler_options_mips ();
2871 opts = &opts_and_args->options;
2872 args = opts_and_args->args;
640c0ccd
CD
2873
2874 fprintf (stream, _("\n\
471b9d15
MR
2875The following MIPS specific disassembler options are supported for use\n\
2876with the -M switch (multiple options should be separated by commas):\n\n"));
640c0ccd 2877
471b9d15
MR
2878 /* Compute the length of the longest option name. */
2879 for (i = 0; opts->name[i] != NULL; i++)
2880 {
2881 size_t len = strlen (opts->name[i]);
af7ee8bf 2882
471b9d15
MR
2883 if (opts->arg[i] != NULL)
2884 len += strlen (opts->arg[i]->name);
2885 if (max_len < len)
2886 max_len = len;
2887 }
640c0ccd 2888
471b9d15
MR
2889 for (i = 0, max_len++; opts->name[i] != NULL; i++)
2890 {
2891 fprintf (stream, " %s", opts->name[i]);
2892 if (opts->arg[i] != NULL)
2893 fprintf (stream, "%s", opts->arg[i]->name);
2894 if (opts->description[i] != NULL)
2895 {
2896 size_t len = strlen (opts->name[i]);
640c0ccd 2897
471b9d15
MR
2898 if (opts->arg[i] != NULL)
2899 len += strlen (opts->arg[i]->name);
2900 fprintf (stream,
2901 "%*c %s", (int) (max_len - len), ' ', opts->description[i]);
2902 }
2903 fprintf (stream, _("\n"));
2904 }
640c0ccd 2905
471b9d15
MR
2906 for (i = 0; args[i].name != NULL; i++)
2907 {
9869e2e5
TO
2908 if (args[i].values == NULL)
2909 continue;
471b9d15
MR
2910 fprintf (stream, _("\n\
2911 For the options above, the following values are supported for \"%s\":\n "),
2912 args[i].name);
2913 for (j = 0; args[i].values[j] != NULL; j++)
2914 fprintf (stream, " %s", args[i].values[j]);
2915 fprintf (stream, _("\n"));
2916 }
640c0ccd
CD
2917
2918 fprintf (stream, _("\n"));
2919}