cgen: split GUILE setting out
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
252b5132 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
250d07de 2 Copyright (C) 1989-2021 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 },
d301a56b 492 { "vr4100", 1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3, 0,
dd844468 493 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 494 mips_hwr_names_numeric },
d301a56b 495 { "vr4111", 1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3, 0,
dd844468 496 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 497 mips_hwr_names_numeric },
d301a56b 498 { "vr4120", 1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3, 0,
dd844468 499 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 500 mips_hwr_names_numeric },
d301a56b 501 { "r4300", 1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3, 0,
dd844468 502 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 503 mips_hwr_names_numeric },
d301a56b 504 { "r4400", 1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3, 0,
dd844468 505 mips_cp0_names_r4000, NULL, 0, mips_cp1_names_mips,
dc76d757 506 mips_hwr_names_numeric },
d301a56b 507 { "r4600", 1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3, 0,
dd844468 508 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 509 mips_hwr_names_numeric },
d301a56b 510 { "r4650", 1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3, 0,
dd844468 511 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 512 mips_hwr_names_numeric },
d301a56b 513 { "r5000", 1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4, 0,
dd844468 514 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 515 mips_hwr_names_numeric },
d301a56b 516 { "vr5400", 1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4, 0,
dd844468 517 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 518 mips_hwr_names_numeric },
d301a56b 519 { "vr5500", 1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4, 0,
dd844468 520 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 521 mips_hwr_names_numeric },
d301a56b 522 { "r5900", 1, bfd_mach_mips5900, CPU_R5900, ISA_MIPS3, 0,
dd844468 523 mips_cp0_names_r5900, NULL, 0, mips_cp1_names_mips,
dc76d757 524 mips_hwr_names_numeric },
d301a56b 525 { "r6000", 1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2, 0,
dd844468 526 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 527 mips_hwr_names_numeric },
d301a56b 528 { "rm7000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
dd844468 529 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 530 mips_hwr_names_numeric },
d301a56b 531 { "rm9000", 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 { "r8000", 1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4, 0,
dd844468 535 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 536 mips_hwr_names_numeric },
d301a56b 537 { "r10000", 1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4, 0,
dd844468 538 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 539 mips_hwr_names_numeric },
d301a56b 540 { "r12000", 1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4, 0,
dd844468 541 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 542 mips_hwr_names_numeric },
d301a56b 543 { "r14000", 1, bfd_mach_mips14000, CPU_R14000, ISA_MIPS4, 0,
dd844468 544 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 545 mips_hwr_names_numeric },
d301a56b 546 { "r16000", 1, bfd_mach_mips16000, CPU_R16000, ISA_MIPS4, 0,
dd844468 547 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 548 mips_hwr_names_numeric },
d301a56b 549 { "mips5", 1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5, 0,
dd844468 550 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
dc76d757 551 mips_hwr_names_numeric },
bbcc0807 552
640c0ccd
CD
553 /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
554 Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
555 _MIPS32 Architecture For Programmers Volume I: Introduction to the
556 MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
557 page 1. */
558 { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32,
d301a56b 559 ISA_MIPS32, ASE_SMARTMIPS,
bbcc0807
CD
560 mips_cp0_names_mips3264,
561 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
dc76d757 562 mips_cp1_names_mips3264, mips_hwr_names_numeric },
bbcc0807 563
af7ee8bf 564 { "mips32r2", 1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
d301a56b 565 ISA_MIPS32R2,
7f3c4072 566 (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
7d64c587 567 | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
bbcc0807
CD
568 mips_cp0_names_mips3264r2,
569 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
dc76d757 570 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
bbcc0807 571
ae52f483
AB
572 { "mips32r3", 1, bfd_mach_mipsisa32r3, CPU_MIPS32R3,
573 ISA_MIPS32R3,
574 (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
575 | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
576 mips_cp0_names_mips3264r2,
577 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
578 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
579
580 { "mips32r5", 1, bfd_mach_mipsisa32r5, CPU_MIPS32R5,
581 ISA_MIPS32R5,
582 (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
583 | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
584 mips_cp0_names_mips3264r2,
585 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
586 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
587
7361da2c
AB
588 { "mips32r6", 1, bfd_mach_mipsisa32r6, CPU_MIPS32R6,
589 ISA_MIPS32R6,
590 (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_XPA | ASE_MCU | ASE_MT | ASE_DSP
6f20c942 591 | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC | ASE_GINV),
7361da2c
AB
592 mips_cp0_names_mips3264r2,
593 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
594 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
595
640c0ccd
CD
596 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
597 { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64,
d301a56b 598 ISA_MIPS64, ASE_MIPS3D | ASE_MDMX,
bbcc0807
CD
599 mips_cp0_names_mips3264,
600 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
dc76d757 601 mips_cp1_names_mips3264, mips_hwr_names_numeric },
bbcc0807 602
5f74bc13 603 { "mips64r2", 1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
d301a56b 604 ISA_MIPS64R2,
7f3c4072 605 (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
7d64c587 606 | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
5f74bc13
CD
607 mips_cp0_names_mips3264r2,
608 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
dc76d757 609 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
5f74bc13 610
ae52f483
AB
611 { "mips64r3", 1, bfd_mach_mipsisa64r3, CPU_MIPS64R3,
612 ISA_MIPS64R3,
613 (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
614 | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
615 mips_cp0_names_mips3264r2,
616 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
617 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
618
619 { "mips64r5", 1, bfd_mach_mipsisa64r5, CPU_MIPS64R5,
620 ISA_MIPS64R5,
621 (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
622 | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
623 mips_cp0_names_mips3264r2,
624 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
625 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
626
7361da2c
AB
627 { "mips64r6", 1, bfd_mach_mipsisa64r6, CPU_MIPS64R6,
628 ISA_MIPS64R6,
629 (ASE_EVA | ASE_MSA | ASE_MSA64 | ASE_XPA | ASE_VIRT | ASE_VIRT64
730c3174 630 | ASE_MCU | ASE_MT | ASE_DSP | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC
6f20c942 631 | ASE_CRC64 | ASE_GINV),
7361da2c
AB
632 mips_cp0_names_mips3264r2,
633 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
634 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
635
38bf472a
MR
636 { "interaptiv-mr2", 1, bfd_mach_mips_interaptiv_mr2, CPU_INTERAPTIV_MR2,
637 ISA_MIPS32R3,
638 ASE_MT | ASE_EVA | ASE_DSP | ASE_DSPR2 | ASE_MIPS16E2 | ASE_MIPS16E2_MT,
639 mips_cp0_names_mips3264r2,
640 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
641 mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
642
640c0ccd 643 { "sb1", 1, bfd_mach_mips_sb1, CPU_SB1,
d301a56b 644 ISA_MIPS64 | INSN_SB1, ASE_MIPS3D,
bbcc0807
CD
645 mips_cp0_names_sb1,
646 mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
dc76d757 647 mips_cp1_names_mips3264, mips_hwr_names_numeric },
640c0ccd 648
350cc38d 649 { "loongson2e", 1, bfd_mach_mips_loongson_2e, CPU_LOONGSON_2E,
d301a56b 650 ISA_MIPS3 | INSN_LOONGSON_2E, 0, mips_cp0_names_numeric,
dd844468 651 NULL, 0, mips_cp1_names_mips, mips_hwr_names_numeric },
350cc38d
MS
652
653 { "loongson2f", 1, bfd_mach_mips_loongson_2f, CPU_LOONGSON_2F,
8095d2f7 654 ISA_MIPS3 | INSN_LOONGSON_2F, ASE_LOONGSON_MMI, mips_cp0_names_numeric,
dd844468 655 NULL, 0, mips_cp1_names_mips, mips_hwr_names_numeric },
350cc38d 656
ac8cb70f
CX
657 /* The loongson3a is an alias of gs464 for compatibility */
658 { "loongson3a", 1, bfd_mach_mips_gs464, CPU_GS464,
659 ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
660 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
661 mips_hwr_names_numeric },
662
57299f48 663 { "gs464", 1, bfd_mach_mips_gs464, CPU_GS464,
bdc6c06e 664 ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
716c08de
CX
665 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
666 mips_hwr_names_numeric },
fd503541 667
57299f48 668 { "gs464e", 1, bfd_mach_mips_gs464e, CPU_GS464E,
bd782c07
CX
669 ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
670 | ASE_LOONGSON_EXT2, mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
671 mips_hwr_names_numeric },
672
57299f48 673 { "gs264e", 1, bfd_mach_mips_gs464e, CPU_GS264E,
9108bc33
CX
674 ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
675 | ASE_LOONGSON_EXT2 | ASE_MSA | ASE_MSA64, mips_cp0_names_numeric, NULL,
676 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
677
57b592a3 678 { "octeon", 1, bfd_mach_mips_octeon, CPU_OCTEON,
d301a56b 679 ISA_MIPS64R2 | INSN_OCTEON, 0, mips_cp0_names_numeric, NULL, 0,
dc76d757 680 mips_cp1_names_mips3264, mips_hwr_names_numeric },
57b592a3 681
dd6a37e7 682 { "octeon+", 1, bfd_mach_mips_octeonp, CPU_OCTEONP,
d301a56b 683 ISA_MIPS64R2 | INSN_OCTEONP, 0, mips_cp0_names_numeric,
dc76d757 684 NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
432233b3
AP
685
686 { "octeon2", 1, bfd_mach_mips_octeon2, CPU_OCTEON2,
d301a56b 687 ISA_MIPS64R2 | INSN_OCTEON2, 0, mips_cp0_names_numeric,
dc76d757 688 NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
dd6a37e7 689
2c629856
N
690 { "octeon3", 1, bfd_mach_mips_octeon3, CPU_OCTEON3,
691 ISA_MIPS64R5 | INSN_OCTEON3, ASE_VIRT | ASE_VIRT64,
692 mips_cp0_names_numeric,
693 NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
694
52b6b6b9 695 { "xlr", 1, bfd_mach_mips_xlr, CPU_XLR,
d301a56b 696 ISA_MIPS64 | INSN_XLR, 0,
52b6b6b9
JM
697 mips_cp0_names_xlr,
698 mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
dc76d757 699 mips_cp1_names_mips3264, mips_hwr_names_numeric },
52b6b6b9 700
55a36193
MK
701 /* XLP is mostly like XLR, with the prominent exception it is being
702 MIPS64R2. */
703 { "xlp", 1, bfd_mach_mips_xlr, CPU_XLR,
d301a56b 704 ISA_MIPS64R2 | INSN_XLR, 0,
55a36193
MK
705 mips_cp0_names_xlr,
706 mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
dc76d757 707 mips_cp1_names_mips3264, mips_hwr_names_numeric },
55a36193 708
640c0ccd
CD
709 /* This entry, mips16, is here only for ISA/processor selection; do
710 not print its name. */
25499ac7
MR
711 { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS64,
712 ASE_MIPS16E2 | ASE_MIPS16E2_MT,
dc76d757
AB
713 mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
714 mips_hwr_names_numeric },
640c0ccd
CD
715};
716
717/* ISA and processor type to disassemble for, and register names to use.
718 set_default_mips_dis_options and parse_mips_dis_options fill in these
719 values. */
720static int mips_processor;
721static int mips_isa;
d301a56b 722static int mips_ase;
df58fc94 723static int micromips_ase;
640c0ccd
CD
724static const char * const *mips_gpr_names;
725static const char * const *mips_fpr_names;
726static const char * const *mips_cp0_names;
bbcc0807
CD
727static const struct mips_cp0sel_name *mips_cp0sel_names;
728static int mips_cp0sel_names_len;
dc76d757 729static const char * const *mips_cp1_names;
af7ee8bf 730static const char * const *mips_hwr_names;
640c0ccd 731
986e18a5 732/* Other options */
47b0e7ad 733static int no_aliases; /* If set disassemble as most general inst. */
640c0ccd
CD
734\f
735static const struct mips_abi_choice *
47b0e7ad 736choose_abi_by_name (const char *name, unsigned int namelen)
640c0ccd
CD
737{
738 const struct mips_abi_choice *c;
739 unsigned int i;
740
741 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++)
47b0e7ad
NC
742 if (strncmp (mips_abi_choices[i].name, name, namelen) == 0
743 && strlen (mips_abi_choices[i].name) == namelen)
744 c = &mips_abi_choices[i];
745
640c0ccd
CD
746 return c;
747}
748
749static const struct mips_arch_choice *
47b0e7ad 750choose_arch_by_name (const char *name, unsigned int namelen)
640c0ccd
CD
751{
752 const struct mips_arch_choice *c = NULL;
753 unsigned int i;
754
755 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
47b0e7ad
NC
756 if (strncmp (mips_arch_choices[i].name, name, namelen) == 0
757 && strlen (mips_arch_choices[i].name) == namelen)
758 c = &mips_arch_choices[i];
759
640c0ccd
CD
760 return c;
761}
762
763static const struct mips_arch_choice *
47b0e7ad 764choose_arch_by_number (unsigned long mach)
640c0ccd
CD
765{
766 static unsigned long hint_bfd_mach;
767 static const struct mips_arch_choice *hint_arch_choice;
768 const struct mips_arch_choice *c;
769 unsigned int i;
770
771 /* We optimize this because even if the user specifies no
772 flags, this will be done for every instruction! */
773 if (hint_bfd_mach == mach
774 && hint_arch_choice != NULL
775 && hint_arch_choice->bfd_mach == hint_bfd_mach)
776 return hint_arch_choice;
777
778 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
779 {
780 if (mips_arch_choices[i].bfd_mach_valid
781 && mips_arch_choices[i].bfd_mach == mach)
782 {
783 c = &mips_arch_choices[i];
784 hint_bfd_mach = mach;
785 hint_arch_choice = c;
786 }
787 }
788 return c;
789}
790
47b0e7ad
NC
791/* Check if the object uses NewABI conventions. */
792
793static int
794is_newabi (Elf_Internal_Ehdr *header)
795{
796 /* There are no old-style ABIs which use 64-bit ELF. */
797 if (header->e_ident[EI_CLASS] == ELFCLASS64)
798 return 1;
799
800 /* If a 32-bit ELF file, n32 is a new-style ABI. */
801 if ((header->e_flags & EF_MIPS_ABI2) != 0)
802 return 1;
803
804 return 0;
805}
806
df58fc94
RS
807/* Check if the object has microMIPS ASE code. */
808
809static int
810is_micromips (Elf_Internal_Ehdr *header)
811{
812 if ((header->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0)
813 return 1;
814
815 return 0;
816}
817
5e7fc731
MR
818/* Convert ASE flags from .MIPS.abiflags to internal values. */
819
820static unsigned long
821mips_convert_abiflags_ases (unsigned long afl_ases)
822{
823 unsigned long opcode_ases = 0;
824
825 if (afl_ases & AFL_ASE_DSP)
826 opcode_ases |= ASE_DSP;
827 if (afl_ases & AFL_ASE_DSPR2)
828 opcode_ases |= ASE_DSPR2;
829 if (afl_ases & AFL_ASE_EVA)
830 opcode_ases |= ASE_EVA;
831 if (afl_ases & AFL_ASE_MCU)
832 opcode_ases |= ASE_MCU;
833 if (afl_ases & AFL_ASE_MDMX)
834 opcode_ases |= ASE_MDMX;
835 if (afl_ases & AFL_ASE_MIPS3D)
836 opcode_ases |= ASE_MIPS3D;
837 if (afl_ases & AFL_ASE_MT)
838 opcode_ases |= ASE_MT;
839 if (afl_ases & AFL_ASE_SMARTMIPS)
840 opcode_ases |= ASE_SMARTMIPS;
841 if (afl_ases & AFL_ASE_VIRT)
842 opcode_ases |= ASE_VIRT;
843 if (afl_ases & AFL_ASE_MSA)
844 opcode_ases |= ASE_MSA;
845 if (afl_ases & AFL_ASE_XPA)
846 opcode_ases |= ASE_XPA;
847 if (afl_ases & AFL_ASE_DSPR3)
848 opcode_ases |= ASE_DSPR3;
25499ac7
MR
849 if (afl_ases & AFL_ASE_MIPS16E2)
850 opcode_ases |= ASE_MIPS16E2;
5e7fc731
MR
851 return opcode_ases;
852}
853
60804c53
MR
854/* Calculate combination ASE flags from regular ASE flags. */
855
856static unsigned long
41cee089 857mips_calculate_combination_ases (int opcode_isa, unsigned long opcode_ases)
60804c53
MR
858{
859 unsigned long combination_ases = 0;
860
9785fc2a
MR
861 if ((opcode_ases & (ASE_XPA | ASE_VIRT)) == (ASE_XPA | ASE_VIRT))
862 combination_ases |= ASE_XPA_VIRT;
60804c53
MR
863 if ((opcode_ases & (ASE_MIPS16E2 | ASE_MT)) == (ASE_MIPS16E2 | ASE_MT))
864 combination_ases |= ASE_MIPS16E2_MT;
41cee089
FS
865 if ((opcode_ases & ASE_EVA)
866 && ((opcode_isa & INSN_ISA_MASK) == ISA_MIPS64R6
867 || (opcode_isa & INSN_ISA_MASK) == ISA_MIPS32R6))
868 combination_ases |= ASE_EVA_R6;
60804c53
MR
869 return combination_ases;
870}
871
47b0e7ad
NC
872static void
873set_default_mips_dis_options (struct disassemble_info *info)
640c0ccd
CD
874{
875 const struct mips_arch_choice *chosen_arch;
876
df58fc94
RS
877 /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
878 is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
879 CP0 register, and HWR names. */
640c0ccd 880 mips_isa = ISA_MIPS3;
df58fc94
RS
881 mips_processor = CPU_R3000;
882 micromips_ase = 0;
d301a56b 883 mips_ase = 0;
640c0ccd
CD
884 mips_gpr_names = mips_gpr_names_oldabi;
885 mips_fpr_names = mips_fpr_names_numeric;
886 mips_cp0_names = mips_cp0_names_numeric;
bbcc0807
CD
887 mips_cp0sel_names = NULL;
888 mips_cp0sel_names_len = 0;
dc76d757 889 mips_cp1_names = mips_cp1_names_numeric;
af7ee8bf 890 mips_hwr_names = mips_hwr_names_numeric;
986e18a5 891 no_aliases = 0;
640c0ccd 892
640c0ccd
CD
893 /* Set ISA, architecture, and cp0 register names as best we can. */
894#if ! SYMTAB_AVAILABLE
895 /* This is running out on a target machine, not in a host tool.
896 FIXME: Where does mips_target_info come from? */
897 target_processor = mips_target_info.processor;
898 mips_isa = mips_target_info.isa;
d301a56b 899 mips_ase = mips_target_info.ase;
640c0ccd
CD
900#else
901 chosen_arch = choose_arch_by_number (info->mach);
902 if (chosen_arch != NULL)
903 {
904 mips_processor = chosen_arch->processor;
905 mips_isa = chosen_arch->isa;
d301a56b 906 mips_ase = chosen_arch->ase;
bbcc0807
CD
907 mips_cp0_names = chosen_arch->cp0_names;
908 mips_cp0sel_names = chosen_arch->cp0sel_names;
909 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
dc76d757 910 mips_cp1_names = chosen_arch->cp1_names;
bbcc0807 911 mips_hwr_names = chosen_arch->hwr_names;
640c0ccd 912 }
8184783a
MR
913
914 /* Update settings according to the ELF file header flags. */
915 if (info->flavour == bfd_target_elf_flavour && info->section != NULL)
916 {
5e7fc731
MR
917 struct bfd *abfd = info->section->owner;
918 Elf_Internal_Ehdr *header = elf_elfheader (abfd);
4df995c7
MR
919 Elf_Internal_ABIFlags_v0 *abiflags = NULL;
920
9e76c212
MR
921 /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
922 because we won't then have a MIPS/ELF BFD, however we need
923 to guard against a link error in a `--enable-targets=...'
924 configuration with a 32-bit host where the MIPS target is
925 a secondary, or with MIPS/ECOFF configurations. */
926#ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
4df995c7
MR
927 abiflags = bfd_mips_elf_get_abiflags (abfd);
928#endif
8184783a
MR
929 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
930 if (is_newabi (header))
931 mips_gpr_names = mips_gpr_names_newabi;
932 /* If a microMIPS binary, then don't use MIPS16 bindings. */
933 micromips_ase = is_micromips (header);
5e7fc731
MR
934 /* OR in any extra ASE flags set in ELF file structures. */
935 if (abiflags)
936 mips_ase |= mips_convert_abiflags_ases (abiflags->ases);
937 else if (header->e_flags & EF_MIPS_ARCH_ASE_MDMX)
938 mips_ase |= ASE_MDMX;
8184783a 939 }
91068ec6 940#endif
41cee089 941 mips_ase |= mips_calculate_combination_ases (mips_isa, mips_ase);
640c0ccd
CD
942}
943
9785fc2a
MR
944/* Parse an ASE disassembler option and set the corresponding global
945 ASE flag(s). Return TRUE if successful, FALSE otherwise. */
b015e599 946
78933a4a 947static bool
9785fc2a
MR
948parse_mips_ase_option (const char *option)
949{
08dedd66 950 if (startswith (option, "msa"))
4edbb8e3
CF
951 {
952 mips_ase |= ASE_MSA;
ae52f483
AB
953 if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R2
954 || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R3
7361da2c
AB
955 || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R5
956 || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6)
4edbb8e3 957 mips_ase |= ASE_MSA64;
78933a4a 958 return true;
4edbb8e3
CF
959 }
960
08dedd66 961 if (startswith (option, "virt"))
b015e599 962 {
d301a56b 963 mips_ase |= ASE_VIRT;
ae52f483
AB
964 if (mips_isa & ISA_MIPS64R2
965 || mips_isa & ISA_MIPS64R3
7361da2c
AB
966 || mips_isa & ISA_MIPS64R5
967 || mips_isa & ISA_MIPS64R6)
d301a56b 968 mips_ase |= ASE_VIRT64;
78933a4a 969 return true;
b015e599 970 }
7d64c587 971
08dedd66 972 if (startswith (option, "xpa"))
7d64c587
AB
973 {
974 mips_ase |= ASE_XPA;
78933a4a 975 return true;
9785fc2a
MR
976 }
977
08dedd66 978 if (startswith (option, "ginv"))
6f20c942
FS
979 {
980 mips_ase |= ASE_GINV;
78933a4a 981 return true;
6f20c942
FS
982 }
983
08dedd66 984 if (startswith (option, "loongson-mmi"))
8095d2f7
CX
985 {
986 mips_ase |= ASE_LOONGSON_MMI;
78933a4a 987 return true;
8095d2f7
CX
988 }
989
08dedd66 990 if (startswith (option, "loongson-cam"))
716c08de
CX
991 {
992 mips_ase |= ASE_LOONGSON_CAM;
78933a4a 993 return true;
716c08de 994 }
a693765e
CX
995
996 /* Put here for match ext2 frist */
08dedd66 997 if (startswith (option, "loongson-ext2"))
a693765e
CX
998 {
999 mips_ase |= ASE_LOONGSON_EXT2;
78933a4a 1000 return true;
a693765e 1001 }
716c08de 1002
08dedd66 1003 if (startswith (option, "loongson-ext"))
bdc6c06e
CX
1004 {
1005 mips_ase |= ASE_LOONGSON_EXT;
78933a4a 1006 return true;
bdc6c06e
CX
1007 }
1008
78933a4a 1009 return false;
9785fc2a
MR
1010}
1011
1012static void
1013parse_mips_dis_option (const char *option, unsigned int len)
1014{
1015 unsigned int i, optionlen, vallen;
1016 const char *val;
1017 const struct mips_abi_choice *chosen_abi;
1018 const struct mips_arch_choice *chosen_arch;
1019
1020 /* Try to match options that are simple flags */
08dedd66 1021 if (startswith (option, "no-aliases"))
9785fc2a
MR
1022 {
1023 no_aliases = 1;
7d64c587
AB
1024 return;
1025 }
43e65147 1026
9785fc2a
MR
1027 if (parse_mips_ase_option (option))
1028 {
41cee089 1029 mips_ase |= mips_calculate_combination_ases (mips_isa, mips_ase);
9785fc2a
MR
1030 return;
1031 }
43e65147 1032
640c0ccd
CD
1033 /* Look for the = that delimits the end of the option name. */
1034 for (i = 0; i < len; i++)
47b0e7ad
NC
1035 if (option[i] == '=')
1036 break;
1037
640c0ccd
CD
1038 if (i == 0) /* Invalid option: no name before '='. */
1039 return;
1040 if (i == len) /* Invalid option: no '='. */
1041 return;
1042 if (i == (len - 1)) /* Invalid option: no value after '='. */
1043 return;
1044
1045 optionlen = i;
1046 val = option + (optionlen + 1);
1047 vallen = len - (optionlen + 1);
1048
47b0e7ad
NC
1049 if (strncmp ("gpr-names", option, optionlen) == 0
1050 && strlen ("gpr-names") == optionlen)
640c0ccd
CD
1051 {
1052 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 1053 if (chosen_abi != NULL)
640c0ccd
CD
1054 mips_gpr_names = chosen_abi->gpr_names;
1055 return;
1056 }
1057
47b0e7ad
NC
1058 if (strncmp ("fpr-names", option, optionlen) == 0
1059 && strlen ("fpr-names") == optionlen)
640c0ccd
CD
1060 {
1061 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 1062 if (chosen_abi != NULL)
640c0ccd
CD
1063 mips_fpr_names = chosen_abi->fpr_names;
1064 return;
1065 }
1066
47b0e7ad
NC
1067 if (strncmp ("cp0-names", option, optionlen) == 0
1068 && strlen ("cp0-names") == optionlen)
640c0ccd
CD
1069 {
1070 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807
CD
1071 if (chosen_arch != NULL)
1072 {
1073 mips_cp0_names = chosen_arch->cp0_names;
1074 mips_cp0sel_names = chosen_arch->cp0sel_names;
1075 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
1076 }
640c0ccd
CD
1077 return;
1078 }
1079
dc76d757
AB
1080 if (strncmp ("cp1-names", option, optionlen) == 0
1081 && strlen ("cp1-names") == optionlen)
1082 {
1083 chosen_arch = choose_arch_by_name (val, vallen);
1084 if (chosen_arch != NULL)
1085 mips_cp1_names = chosen_arch->cp1_names;
1086 return;
1087 }
1088
47b0e7ad
NC
1089 if (strncmp ("hwr-names", option, optionlen) == 0
1090 && strlen ("hwr-names") == optionlen)
af7ee8bf
CD
1091 {
1092 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807 1093 if (chosen_arch != NULL)
af7ee8bf
CD
1094 mips_hwr_names = chosen_arch->hwr_names;
1095 return;
1096 }
1097
47b0e7ad
NC
1098 if (strncmp ("reg-names", option, optionlen) == 0
1099 && strlen ("reg-names") == optionlen)
640c0ccd
CD
1100 {
1101 /* We check both ABI and ARCH here unconditionally, so
1102 that "numeric" will do the desirable thing: select
1103 numeric register names for all registers. Other than
1104 that, a given name probably won't match both. */
1105 chosen_abi = choose_abi_by_name (val, vallen);
1106 if (chosen_abi != NULL)
1107 {
bbcc0807
CD
1108 mips_gpr_names = chosen_abi->gpr_names;
1109 mips_fpr_names = chosen_abi->fpr_names;
640c0ccd
CD
1110 }
1111 chosen_arch = choose_arch_by_name (val, vallen);
1112 if (chosen_arch != NULL)
1113 {
bbcc0807
CD
1114 mips_cp0_names = chosen_arch->cp0_names;
1115 mips_cp0sel_names = chosen_arch->cp0sel_names;
1116 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
dc76d757 1117 mips_cp1_names = chosen_arch->cp1_names;
bbcc0807 1118 mips_hwr_names = chosen_arch->hwr_names;
640c0ccd
CD
1119 }
1120 return;
1121 }
1122
1123 /* Invalid option. */
1124}
1125
47b0e7ad
NC
1126static void
1127parse_mips_dis_options (const char *options)
640c0ccd
CD
1128{
1129 const char *option_end;
1130
1131 if (options == NULL)
1132 return;
1133
1134 while (*options != '\0')
1135 {
1136 /* Skip empty options. */
1137 if (*options == ',')
1138 {
1139 options++;
1140 continue;
1141 }
1142
1143 /* We know that *options is neither NUL or a comma. */
1144 option_end = options + 1;
1145 while (*option_end != ',' && *option_end != '\0')
1146 option_end++;
1147
1148 parse_mips_dis_option (options, option_end - options);
1149
1150 /* Go on to the next one. If option_end points to a comma, it
1151 will be skipped above. */
1152 options = option_end;
1153 }
1154}
1155
bbcc0807 1156static const struct mips_cp0sel_name *
47b0e7ad
NC
1157lookup_mips_cp0sel_name (const struct mips_cp0sel_name *names,
1158 unsigned int len,
1159 unsigned int cp0reg,
1160 unsigned int sel)
bbcc0807
CD
1161{
1162 unsigned int i;
1163
1164 for (i = 0; i < len; i++)
1165 if (names[i].cp0reg == cp0reg && names[i].sel == sel)
1166 return &names[i];
1167 return NULL;
1168}
ab902481
RS
1169
1170/* Print register REGNO, of type TYPE, for instruction OPCODE. */
aa5f19f2 1171
794ac9d0 1172static void
ab902481
RS
1173print_reg (struct disassemble_info *info, const struct mips_opcode *opcode,
1174 enum mips_reg_operand_type type, int regno)
252b5132 1175{
ab902481
RS
1176 switch (type)
1177 {
1178 case OP_REG_GP:
1179 info->fprintf_func (info->stream, "%s", mips_gpr_names[regno]);
1180 break;
440cc0bc 1181
ab902481
RS
1182 case OP_REG_FP:
1183 info->fprintf_func (info->stream, "%s", mips_fpr_names[regno]);
1184 break;
252b5132 1185
ab902481
RS
1186 case OP_REG_CCC:
1187 if (opcode->pinfo & (FP_D | FP_S))
1188 info->fprintf_func (info->stream, "$fcc%d", regno);
1189 else
1190 info->fprintf_func (info->stream, "$cc%d", regno);
1191 break;
794ac9d0 1192
ab902481
RS
1193 case OP_REG_VEC:
1194 if (opcode->membership & INSN_5400)
1195 info->fprintf_func (info->stream, "$f%d", regno);
1196 else
1197 info->fprintf_func (info->stream, "$v%d", regno);
1198 break;
794ac9d0 1199
ab902481
RS
1200 case OP_REG_ACC:
1201 info->fprintf_func (info->stream, "$ac%d", regno);
1202 break;
794ac9d0 1203
ab902481
RS
1204 case OP_REG_COPRO:
1205 if (opcode->name[strlen (opcode->name) - 1] == '0')
1206 info->fprintf_func (info->stream, "%s", mips_cp0_names[regno]);
9204ccd4
MR
1207 else
1208 info->fprintf_func (info->stream, "$%d", regno);
1209 break;
1210
1211 case OP_REG_CONTROL:
1212 if (opcode->name[strlen (opcode->name) - 1] == '1')
dc76d757 1213 info->fprintf_func (info->stream, "%s", mips_cp1_names[regno]);
ab902481
RS
1214 else
1215 info->fprintf_func (info->stream, "$%d", regno);
1216 break;
8b082fb1 1217
ab902481
RS
1218 case OP_REG_HW:
1219 info->fprintf_func (info->stream, "%s", mips_hwr_names[regno]);
1220 break;
14daeee3
RS
1221
1222 case OP_REG_VF:
1223 info->fprintf_func (info->stream, "$vf%d", regno);
1224 break;
1225
1226 case OP_REG_VI:
1227 info->fprintf_func (info->stream, "$vi%d", regno);
1228 break;
1229
1230 case OP_REG_R5900_I:
1231 info->fprintf_func (info->stream, "$I");
1232 break;
1233
1234 case OP_REG_R5900_Q:
1235 info->fprintf_func (info->stream, "$Q");
1236 break;
1237
1238 case OP_REG_R5900_R:
1239 info->fprintf_func (info->stream, "$R");
1240 break;
1241
1242 case OP_REG_R5900_ACC:
1243 info->fprintf_func (info->stream, "$ACC");
1244 break;
4edbb8e3
CF
1245
1246 case OP_REG_MSA:
1247 info->fprintf_func (info->stream, "$w%d", regno);
1248 break;
1249
1250 case OP_REG_MSA_CTRL:
1251 info->fprintf_func (info->stream, "%s", msa_control_names[regno]);
1252 break;
1253
ab902481
RS
1254 }
1255}
1256\f
1257/* Used to track the state carried over from previous operands in
1258 an instruction. */
1259struct mips_print_arg_state {
1260 /* The value of the last OP_INT seen. We only use this for OP_MSB,
1261 where the value is known to be unsigned and small. */
1262 unsigned int last_int;
1263
1264 /* The type and number of the last OP_REG seen. We only use this for
1265 OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1266 enum mips_reg_operand_type last_reg_type;
1267 unsigned int last_regno;
7361da2c
AB
1268 unsigned int dest_regno;
1269 unsigned int seen_dest;
ab902481 1270};
fd25c5a9 1271
ab902481 1272/* Initialize STATE for the start of an instruction. */
fd25c5a9 1273
ab902481
RS
1274static inline void
1275init_print_arg_state (struct mips_print_arg_state *state)
1276{
1277 memset (state, 0, sizeof (*state));
1278}
fd25c5a9 1279
14daeee3
RS
1280/* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1281 whose value is given by UVAL. */
1282
1283static void
1284print_vu0_channel (struct disassemble_info *info,
1285 const struct mips_operand *operand, unsigned int uval)
1286{
1287 if (operand->size == 4)
1288 info->fprintf_func (info->stream, "%s%s%s%s",
1289 uval & 8 ? "x" : "",
1290 uval & 4 ? "y" : "",
1291 uval & 2 ? "z" : "",
1292 uval & 1 ? "w" : "");
1293 else if (operand->size == 2)
1294 info->fprintf_func (info->stream, "%c", "xyzw"[uval]);
1295 else
1296 abort ();
1297}
1298
7361da2c
AB
1299/* Record information about a register operand. */
1300
1301static void
1302mips_seen_register (struct mips_print_arg_state *state,
1303 unsigned int regno,
1304 enum mips_reg_operand_type reg_type)
1305{
1306 state->last_reg_type = reg_type;
1307 state->last_regno = regno;
1308
1309 if (!state->seen_dest)
1310 {
1311 state->seen_dest = 1;
1312 state->dest_regno = regno;
1313 }
1314}
1315
38bf472a
MR
1316/* Print SAVE/RESTORE instruction operands according to the argument
1317 register mask AMASK, the number of static registers saved NSREG,
1318 the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1319 and the frame size FRAME_SIZE. */
1320
1321static void
1322mips_print_save_restore (struct disassemble_info *info, unsigned int amask,
1323 unsigned int nsreg, unsigned int ra,
1324 unsigned int s0, unsigned int s1,
1325 unsigned int frame_size)
1326{
1327 const fprintf_ftype infprintf = info->fprintf_func;
1328 unsigned int nargs, nstatics, smask, i, j;
1329 void *is = info->stream;
1330 const char *sep;
1331
1332 if (amask == MIPS_SVRS_ALL_ARGS)
1333 {
1334 nargs = 4;
1335 nstatics = 0;
1336 }
1337 else if (amask == MIPS_SVRS_ALL_STATICS)
1338 {
1339 nargs = 0;
1340 nstatics = 4;
1341 }
1342 else
1343 {
1344 nargs = amask >> 2;
1345 nstatics = amask & 3;
1346 }
1347
1348 sep = "";
1349 if (nargs > 0)
1350 {
1351 infprintf (is, "%s", mips_gpr_names[4]);
1352 if (nargs > 1)
1353 infprintf (is, "-%s", mips_gpr_names[4 + nargs - 1]);
1354 sep = ",";
1355 }
1356
1357 infprintf (is, "%s%d", sep, frame_size);
1358
1359 if (ra) /* $ra */
1360 infprintf (is, ",%s", mips_gpr_names[31]);
1361
1362 smask = 0;
1363 if (s0) /* $s0 */
1364 smask |= 1 << 0;
1365 if (s1) /* $s1 */
1366 smask |= 1 << 1;
1367 if (nsreg > 0) /* $s2-$s8 */
1368 smask |= ((1 << nsreg) - 1) << 2;
1369
1370 for (i = 0; i < 9; i++)
1371 if (smask & (1 << i))
1372 {
1373 infprintf (is, ",%s", mips_gpr_names[i == 8 ? 30 : (16 + i)]);
1374 /* Skip over string of set bits. */
1375 for (j = i; smask & (2 << j); j++)
1376 continue;
1377 if (j > i)
1378 infprintf (is, "-%s", mips_gpr_names[j == 8 ? 30 : (16 + j)]);
1379 i = j + 1;
1380 }
1381 /* Statics $ax - $a3. */
1382 if (nstatics == 1)
1383 infprintf (is, ",%s", mips_gpr_names[7]);
1384 else if (nstatics > 0)
1385 infprintf (is, ",%s-%s",
1386 mips_gpr_names[7 - nstatics + 1],
1387 mips_gpr_names[7]);
1388}
1389
1390
ab902481
RS
1391/* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1392 UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1393 the base address for OP_PCREL operands. */
fd25c5a9 1394
ab902481
RS
1395static void
1396print_insn_arg (struct disassemble_info *info,
1397 struct mips_print_arg_state *state,
1398 const struct mips_opcode *opcode,
1399 const struct mips_operand *operand,
1400 bfd_vma base_pc,
1401 unsigned int uval)
1402{
1403 const fprintf_ftype infprintf = info->fprintf_func;
1404 void *is = info->stream;
fd25c5a9 1405
ab902481
RS
1406 switch (operand->type)
1407 {
1408 case OP_INT:
1409 {
1410 const struct mips_int_operand *int_op;
fd25c5a9 1411
ab902481
RS
1412 int_op = (const struct mips_int_operand *) operand;
1413 uval = mips_decode_int_operand (int_op, uval);
1414 state->last_int = uval;
1415 if (int_op->print_hex)
1416 infprintf (is, "0x%x", uval);
1417 else
1418 infprintf (is, "%d", uval);
1419 }
1420 break;
fd25c5a9 1421
ab902481
RS
1422 case OP_MAPPED_INT:
1423 {
1424 const struct mips_mapped_int_operand *mint_op;
fd25c5a9 1425
ab902481
RS
1426 mint_op = (const struct mips_mapped_int_operand *) operand;
1427 uval = mint_op->int_map[uval];
1428 state->last_int = uval;
1429 if (mint_op->print_hex)
1430 infprintf (is, "0x%x", uval);
1431 else
1432 infprintf (is, "%d", uval);
1433 }
1434 break;
fd25c5a9 1435
ab902481
RS
1436 case OP_MSB:
1437 {
1438 const struct mips_msb_operand *msb_op;
dec0624d 1439
ab902481
RS
1440 msb_op = (const struct mips_msb_operand *) operand;
1441 uval += msb_op->bias;
1442 if (msb_op->add_lsb)
1443 uval -= state->last_int;
1444 infprintf (is, "0x%x", uval);
1445 }
1446 break;
dec0624d 1447
ab902481 1448 case OP_REG:
0f35dbc4 1449 case OP_OPTIONAL_REG:
ab902481
RS
1450 {
1451 const struct mips_reg_operand *reg_op;
fd25c5a9 1452
ab902481 1453 reg_op = (const struct mips_reg_operand *) operand;
fc76e730 1454 uval = mips_decode_reg_operand (reg_op, uval);
ab902481 1455 print_reg (info, opcode, reg_op->reg_type, uval);
fd25c5a9 1456
7361da2c 1457 mips_seen_register (state, uval, reg_op->reg_type);
ab902481
RS
1458 }
1459 break;
61cc0267 1460
ab902481
RS
1461 case OP_REG_PAIR:
1462 {
1463 const struct mips_reg_pair_operand *pair_op;
1464
1465 pair_op = (const struct mips_reg_pair_operand *) operand;
1466 print_reg (info, opcode, pair_op->reg_type,
1467 pair_op->reg1_map[uval]);
1468 infprintf (is, ",");
1469 print_reg (info, opcode, pair_op->reg_type,
1470 pair_op->reg2_map[uval]);
1471 }
1472 break;
61cc0267 1473
ab902481
RS
1474 case OP_PCREL:
1475 {
1476 const struct mips_pcrel_operand *pcrel_op;
61cc0267 1477
ab902481
RS
1478 pcrel_op = (const struct mips_pcrel_operand *) operand;
1479 info->target = mips_decode_pcrel_operand (pcrel_op, base_pc, uval);
61cc0267 1480
a4ddc54e
MR
1481 /* For jumps and branches clear the ISA bit except for
1482 the GDB disassembler. */
1483 if (pcrel_op->include_isa_bit
1484 && info->flavour != bfd_target_unknown_flavour)
ab902481 1485 info->target &= -2;
61cc0267 1486
ab902481
RS
1487 (*info->print_address_func) (info->target, info);
1488 }
1489 break;
794ac9d0 1490
ab902481
RS
1491 case OP_PERF_REG:
1492 infprintf (is, "%d", uval);
1493 break;
794ac9d0 1494
ab902481
RS
1495 case OP_ADDIUSP_INT:
1496 {
1497 int sval;
794ac9d0 1498
ab902481
RS
1499 sval = mips_signed_operand (operand, uval) * 4;
1500 if (sval >= -8 && sval < 8)
1501 sval ^= 0x400;
1502 infprintf (is, "%d", sval);
1503 break;
1504 }
794ac9d0 1505
ab902481
RS
1506 case OP_CLO_CLZ_DEST:
1507 {
1508 unsigned int reg1, reg2;
1509
1510 reg1 = uval & 31;
1511 reg2 = uval >> 5;
1512 /* If one is zero use the other. */
1513 if (reg1 == reg2 || reg2 == 0)
1514 infprintf (is, "%s", mips_gpr_names[reg1]);
1515 else if (reg1 == 0)
1516 infprintf (is, "%s", mips_gpr_names[reg2]);
1517 else
1518 /* Bogus, result depends on processor. */
1519 infprintf (is, "%s or %s", mips_gpr_names[reg1],
1520 mips_gpr_names[reg2]);
1521 }
1522 break;
794ac9d0 1523
7361da2c
AB
1524 case OP_SAME_RS_RT:
1525 case OP_CHECK_PREV:
1526 case OP_NON_ZERO_REG:
1527 {
1528 print_reg (info, opcode, OP_REG_GP, uval & 31);
1529 mips_seen_register (state, uval, OP_REG_GP);
1530 }
1531 break;
1532
ab902481
RS
1533 case OP_LWM_SWM_LIST:
1534 if (operand->size == 2)
1535 {
1536 if (uval == 0)
1537 infprintf (is, "%s,%s",
1538 mips_gpr_names[16],
1539 mips_gpr_names[31]);
1540 else
1541 infprintf (is, "%s-%s,%s",
1542 mips_gpr_names[16],
1543 mips_gpr_names[16 + uval],
1544 mips_gpr_names[31]);
1545 }
1546 else
1547 {
1548 int s_reg_encode;
794ac9d0 1549
ab902481
RS
1550 s_reg_encode = uval & 0xf;
1551 if (s_reg_encode != 0)
1552 {
1553 if (s_reg_encode == 1)
1554 infprintf (is, "%s", mips_gpr_names[16]);
1555 else if (s_reg_encode < 9)
1556 infprintf (is, "%s-%s",
1557 mips_gpr_names[16],
1558 mips_gpr_names[15 + s_reg_encode]);
1559 else if (s_reg_encode == 9)
1560 infprintf (is, "%s-%s,%s",
1561 mips_gpr_names[16],
1562 mips_gpr_names[23],
1563 mips_gpr_names[30]);
1564 else
1565 infprintf (is, "UNKNOWN");
1566 }
794ac9d0 1567
ab902481
RS
1568 if (uval & 0x10) /* For ra. */
1569 {
1570 if (s_reg_encode == 0)
1571 infprintf (is, "%s", mips_gpr_names[31]);
1572 else
1573 infprintf (is, ",%s", mips_gpr_names[31]);
1574 }
1575 }
1576 break;
794ac9d0 1577
c3c07478
RS
1578 case OP_ENTRY_EXIT_LIST:
1579 {
1580 const char *sep;
1581 unsigned int amask, smask;
1582
1583 sep = "";
1584 amask = (uval >> 3) & 7;
1585 if (amask > 0 && amask < 5)
1586 {
1587 infprintf (is, "%s", mips_gpr_names[4]);
1588 if (amask > 1)
1589 infprintf (is, "-%s", mips_gpr_names[amask + 3]);
1590 sep = ",";
1591 }
1592
1593 smask = (uval >> 1) & 3;
1594 if (smask == 3)
1595 {
1596 infprintf (is, "%s??", sep);
1597 sep = ",";
1598 }
1599 else if (smask > 0)
1600 {
1601 infprintf (is, "%s%s", sep, mips_gpr_names[16]);
1602 if (smask > 1)
1603 infprintf (is, "-%s", mips_gpr_names[smask + 15]);
1604 sep = ",";
1605 }
1606
1607 if (uval & 1)
1608 {
1609 infprintf (is, "%s%s", sep, mips_gpr_names[31]);
1610 sep = ",";
1611 }
1612
1613 if (amask == 5 || amask == 6)
1614 {
1615 infprintf (is, "%s%s", sep, mips_fpr_names[0]);
1616 if (amask == 6)
1617 infprintf (is, "-%s", mips_fpr_names[1]);
1618 }
1619 }
1620 break;
1621
1622 case OP_SAVE_RESTORE_LIST:
38bf472a 1623 /* Should be handled by the caller due to complex behavior. */
c3c07478
RS
1624 abort ();
1625
ab902481
RS
1626 case OP_MDMX_IMM_REG:
1627 {
1628 unsigned int vsel;
794ac9d0 1629
ab902481
RS
1630 vsel = uval >> 5;
1631 uval &= 31;
1632 if ((vsel & 0x10) == 0)
794ac9d0 1633 {
ab902481
RS
1634 int fmt;
1635
1636 vsel &= 0x0f;
1637 for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
1638 if ((vsel & 1) == 0)
1639 break;
1640 print_reg (info, opcode, OP_REG_VEC, uval);
1641 infprintf (is, "[%d]", vsel >> 1);
794ac9d0 1642 }
ab902481
RS
1643 else if ((vsel & 0x08) == 0)
1644 print_reg (info, opcode, OP_REG_VEC, uval);
1645 else
1646 infprintf (is, "0x%x", uval);
1647 }
1648 break;
794ac9d0 1649
ab902481
RS
1650 case OP_REPEAT_PREV_REG:
1651 print_reg (info, opcode, state->last_reg_type, state->last_regno);
1652 break;
794ac9d0 1653
ab902481 1654 case OP_REPEAT_DEST_REG:
7361da2c
AB
1655 print_reg (info, opcode, state->last_reg_type, state->dest_regno);
1656 break;
794ac9d0 1657
ab902481
RS
1658 case OP_PC:
1659 infprintf (is, "$pc");
1660 break;
14daeee3 1661
25499ac7
MR
1662 case OP_REG28:
1663 print_reg (info, opcode, OP_REG_GP, 28);
1664 break;
1665
14daeee3
RS
1666 case OP_VU0_SUFFIX:
1667 case OP_VU0_MATCH_SUFFIX:
1668 print_vu0_channel (info, operand, uval);
1669 break;
4edbb8e3
CF
1670
1671 case OP_IMM_INDEX:
1672 infprintf (is, "[%d]", uval);
1673 break;
1674
1675 case OP_REG_INDEX:
1676 infprintf (is, "[");
1677 print_reg (info, opcode, OP_REG_GP, uval);
1678 infprintf (is, "]");
1679 break;
ab902481
RS
1680 }
1681}
794ac9d0 1682
7361da2c
AB
1683/* Validate the arguments for INSN, which is described by OPCODE.
1684 Use DECODE_OPERAND to get the encoding of each operand. */
1685
78933a4a 1686static bool
7361da2c
AB
1687validate_insn_args (const struct mips_opcode *opcode,
1688 const struct mips_operand *(*decode_operand) (const char *),
1689 unsigned int insn)
1690{
1691 struct mips_print_arg_state state;
1692 const struct mips_operand *operand;
1693 const char *s;
1694 unsigned int uval;
1695
1696 init_print_arg_state (&state);
1697 for (s = opcode->args; *s; ++s)
1698 {
1699 switch (*s)
1700 {
1701 case ',':
1702 case '(':
1703 case ')':
1704 break;
1705
1706 case '#':
1707 ++s;
1708 break;
1709
1710 default:
1711 operand = decode_operand (s);
1712
1713 if (operand)
1714 {
1715 uval = mips_extract_operand (operand, insn);
1716 switch (operand->type)
1717 {
1718 case OP_REG:
1719 case OP_OPTIONAL_REG:
1720 {
1721 const struct mips_reg_operand *reg_op;
1722
1723 reg_op = (const struct mips_reg_operand *) operand;
1724 uval = mips_decode_reg_operand (reg_op, uval);
1725 mips_seen_register (&state, uval, reg_op->reg_type);
1726 }
1727 break;
1728
1729 case OP_SAME_RS_RT:
1730 {
1731 unsigned int reg1, reg2;
1732
1733 reg1 = uval & 31;
1734 reg2 = uval >> 5;
1735
1736 if (reg1 != reg2 || reg1 == 0)
78933a4a 1737 return false;
7361da2c
AB
1738 }
1739 break;
1740
1741 case OP_CHECK_PREV:
1742 {
1743 const struct mips_check_prev_operand *prev_op;
1744
1745 prev_op = (const struct mips_check_prev_operand *) operand;
1746
1747 if (!prev_op->zero_ok && uval == 0)
78933a4a 1748 return false;
7361da2c
AB
1749
1750 if (((prev_op->less_than_ok && uval < state.last_regno)
1751 || (prev_op->greater_than_ok && uval > state.last_regno)
1752 || (prev_op->equal_ok && uval == state.last_regno)))
1753 break;
1754
78933a4a 1755 return false;
7361da2c
AB
1756 }
1757
1758 case OP_NON_ZERO_REG:
1759 {
1760 if (uval == 0)
78933a4a 1761 return false;
7361da2c
AB
1762 }
1763 break;
1764
1765 case OP_INT:
1766 case OP_MAPPED_INT:
1767 case OP_MSB:
1768 case OP_REG_PAIR:
1769 case OP_PCREL:
1770 case OP_PERF_REG:
1771 case OP_ADDIUSP_INT:
1772 case OP_CLO_CLZ_DEST:
1773 case OP_LWM_SWM_LIST:
1774 case OP_ENTRY_EXIT_LIST:
1775 case OP_MDMX_IMM_REG:
1776 case OP_REPEAT_PREV_REG:
1777 case OP_REPEAT_DEST_REG:
1778 case OP_PC:
25499ac7 1779 case OP_REG28:
7361da2c
AB
1780 case OP_VU0_SUFFIX:
1781 case OP_VU0_MATCH_SUFFIX:
1782 case OP_IMM_INDEX:
1783 case OP_REG_INDEX:
7361da2c 1784 case OP_SAVE_RESTORE_LIST:
38bf472a 1785 break;
7361da2c
AB
1786 }
1787 }
1788 if (*s == 'm' || *s == '+' || *s == '-')
1789 ++s;
1790 }
1791 }
78933a4a 1792 return true;
7361da2c
AB
1793}
1794
ab902481
RS
1795/* Print the arguments for INSN, which is described by OPCODE.
1796 Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
7361da2c
AB
1797 as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1798 operand is for a branch or jump. */
af7ee8bf 1799
ab902481
RS
1800static void
1801print_insn_args (struct disassemble_info *info,
1802 const struct mips_opcode *opcode,
1803 const struct mips_operand *(*decode_operand) (const char *),
7361da2c 1804 unsigned int insn, bfd_vma insn_pc, unsigned int length)
ab902481
RS
1805{
1806 const fprintf_ftype infprintf = info->fprintf_func;
1807 void *is = info->stream;
1808 struct mips_print_arg_state state;
1809 const struct mips_operand *operand;
1810 const char *s;
794ac9d0 1811
ab902481
RS
1812 init_print_arg_state (&state);
1813 for (s = opcode->args; *s; ++s)
1814 {
1815 switch (*s)
1816 {
1817 case ',':
1818 case '(':
1819 case ')':
1820 infprintf (is, "%c", *s);
794ac9d0
CD
1821 break;
1822
14daeee3
RS
1823 case '#':
1824 ++s;
1825 infprintf (is, "%c%c", *s, *s);
1826 break;
1827
ab902481
RS
1828 default:
1829 operand = decode_operand (s);
1830 if (!operand)
fa7616a4 1831 {
ab902481
RS
1832 /* xgettext:c-format */
1833 infprintf (is,
1834 _("# internal error, undefined operand in `%s %s'"),
1835 opcode->name, opcode->args);
1836 return;
1837 }
38bf472a
MR
1838
1839 if (operand->type == OP_SAVE_RESTORE_LIST)
1840 {
1841 /* Handle this case here because of the complex behavior. */
1842 unsigned int amask = (insn >> 15) & 0xf;
1843 unsigned int nsreg = (insn >> 23) & 0x7;
1844 unsigned int ra = insn & 0x1000; /* $ra */
1845 unsigned int s0 = insn & 0x800; /* $s0 */
1846 unsigned int s1 = insn & 0x400; /* $s1 */
1847 unsigned int frame_size = (((insn >> 15) & 0xf0)
1848 | ((insn >> 6) & 0x0f)) * 8;
1849 mips_print_save_restore (info, amask, nsreg, ra, s0, s1,
1850 frame_size);
1851 }
1852 else if (operand->type == OP_REG
1853 && s[1] == ','
1854 && s[2] == 'H'
1855 && opcode->name[strlen (opcode->name) - 1] == '0')
ab902481 1856 {
fdfb4752 1857 /* Coprocessor register 0 with sel field. */
ab902481
RS
1858 const struct mips_cp0sel_name *n;
1859 unsigned int reg, sel;
1860
1861 reg = mips_extract_operand (operand, insn);
1862 s += 2;
1863 operand = decode_operand (s);
1864 sel = mips_extract_operand (operand, insn);
1865
1866 /* CP0 register including 'sel' code for mftc0, to be
1867 printed textually if known. If not known, print both
1868 CP0 register name and sel numerically since CP0 register
1869 with sel 0 may have a name unrelated to register being
1870 printed. */
1871 n = lookup_mips_cp0sel_name (mips_cp0sel_names,
1872 mips_cp0sel_names_len,
1873 reg, sel);
1874 if (n != NULL)
1875 infprintf (is, "%s", n->name);
fa7616a4 1876 else
ab902481 1877 infprintf (is, "$%d,%d", reg, sel);
fa7616a4 1878 }
794ac9d0 1879 else
7361da2c
AB
1880 {
1881 bfd_vma base_pc = insn_pc;
1882
1883 /* Adjust the PC relative base so that branch/jump insns use
1884 the following PC as the base but genuinely PC relative
1885 operands use the current PC. */
1886 if (operand->type == OP_PCREL)
1887 {
1888 const struct mips_pcrel_operand *pcrel_op;
1889
1890 pcrel_op = (const struct mips_pcrel_operand *) operand;
1891 /* The include_isa_bit flag is sufficient to distinguish
1892 branch/jump from other PC relative operands. */
1893 if (pcrel_op->include_isa_bit)
1894 base_pc += length;
1895 }
1896
1897 print_insn_arg (info, &state, opcode, operand, base_pc,
1898 mips_extract_operand (operand, insn));
1899 }
1900 if (*s == 'm' || *s == '+' || *s == '-')
ab902481 1901 ++s;
794ac9d0 1902 break;
af7ee8bf 1903 }
252b5132
RH
1904 }
1905}
1906\f
252b5132
RH
1907/* Print the mips instruction at address MEMADDR in debugged memory,
1908 on using INFO. Returns length of the instruction, in bytes, which is
aa5f19f2 1909 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
252b5132
RH
1910 this is little-endian code. */
1911
1912static int
47b0e7ad 1913print_insn_mips (bfd_vma memaddr,
fc8c4fd1 1914 int word,
47b0e7ad 1915 struct disassemble_info *info)
252b5132 1916{
ab902481
RS
1917#define GET_OP(insn, field) \
1918 (((insn) >> OP_SH_##field) & OP_MASK_##field)
fc8c4fd1
MR
1919 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
1920 const fprintf_ftype infprintf = info->fprintf_func;
47b0e7ad 1921 const struct mips_opcode *op;
78933a4a 1922 static bool init = 0;
fc8c4fd1 1923 void *is = info->stream;
252b5132
RH
1924
1925 /* Build a hash table to shorten the search time. */
1926 if (! init)
1927 {
1928 unsigned int i;
1929
1930 for (i = 0; i <= OP_MASK_OP; i++)
1931 {
1932 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
1933 {
986e18a5 1934 if (op->pinfo == INSN_MACRO
9e836e3d 1935 || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
252b5132 1936 continue;
fc8c4fd1 1937 if (i == GET_OP (op->match, OP))
252b5132
RH
1938 {
1939 mips_hash[i] = op;
1940 break;
1941 }
1942 }
7f6621cd 1943 }
252b5132
RH
1944
1945 init = 1;
1946 }
1947
aa5f19f2 1948 info->bytes_per_chunk = INSNLEN;
252b5132 1949 info->display_endian = info->endian;
9bb28706
CD
1950 info->insn_info_valid = 1;
1951 info->branch_delay_insns = 0;
def7143b 1952 info->data_size = 0;
9bb28706
CD
1953 info->insn_type = dis_nonbranch;
1954 info->target = 0;
1955 info->target2 = 0;
252b5132 1956
fc8c4fd1 1957 op = mips_hash[GET_OP (word, OP)];
252b5132
RH
1958 if (op != NULL)
1959 {
1960 for (; op < &mips_opcodes[NUMOPCODES]; op++)
1961 {
43e65147 1962 if (op->pinfo != INSN_MACRO
9e836e3d 1963 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
986e18a5 1964 && (word & op->mask) == op->match)
252b5132 1965 {
7361da2c 1966 /* We always disassemble the jalx instruction, except for MIPS r6. */
d301a56b 1967 if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
7361da2c
AB
1968 && (strcmp (op->name, "jalx")
1969 || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6
1970 || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6))
252b5132
RH
1971 continue;
1972
9bb28706
CD
1973 /* Figure out instruction type and branch delay information. */
1974 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
1975 {
fc76e730 1976 if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
9bb28706
CD
1977 info->insn_type = dis_jsr;
1978 else
1979 info->insn_type = dis_branch;
1980 info->branch_delay_insns = 1;
1981 }
1982 else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
1983 | INSN_COND_BRANCH_LIKELY)) != 0)
1984 {
c680e7f6 1985 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
9bb28706
CD
1986 info->insn_type = dis_condjsr;
1987 else
1988 info->insn_type = dis_condbranch;
1989 info->branch_delay_insns = 1;
1990 }
1991 else if ((op->pinfo & (INSN_STORE_MEMORY
67dc82bc 1992 | INSN_LOAD_MEMORY)) != 0)
9bb28706
CD
1993 info->insn_type = dis_dref;
1994
7361da2c
AB
1995 if (!validate_insn_args (op, decode_mips_operand, word))
1996 continue;
1997
fc8c4fd1 1998 infprintf (is, "%s", op->name);
14daeee3
RS
1999 if (op->pinfo2 & INSN2_VU0_CHANNEL_SUFFIX)
2000 {
2001 unsigned int uval;
2002
2003 infprintf (is, ".");
2004 uval = mips_extract_operand (&mips_vu0_channel_mask, word);
2005 print_vu0_channel (info, &mips_vu0_channel_mask, uval);
2006 }
252b5132 2007
ab902481 2008 if (op->args[0])
252b5132 2009 {
fc8c4fd1 2010 infprintf (is, "\t");
ab902481 2011 print_insn_args (info, op, decode_mips_operand, word,
7361da2c 2012 memaddr, 4);
252b5132
RH
2013 }
2014
aa5f19f2 2015 return INSNLEN;
252b5132
RH
2016 }
2017 }
2018 }
fc8c4fd1 2019#undef GET_OP
252b5132
RH
2020
2021 /* Handle undefined instructions. */
9bb28706 2022 info->insn_type = dis_noninsn;
fc8c4fd1 2023 infprintf (is, "0x%x", word);
aa5f19f2 2024 return INSNLEN;
252b5132 2025}
aa5f19f2 2026\f
252b5132
RH
2027/* Disassemble an operand for a mips16 instruction. */
2028
2029static void
c3c07478
RS
2030print_mips16_insn_arg (struct disassemble_info *info,
2031 struct mips_print_arg_state *state,
2032 const struct mips_opcode *opcode,
2033 char type, bfd_vma memaddr,
78933a4a
AM
2034 unsigned insn, bool use_extend,
2035 unsigned extend, bool is_offset)
252b5132 2036{
fc8c4fd1
MR
2037 const fprintf_ftype infprintf = info->fprintf_func;
2038 void *is = info->stream;
c3c07478 2039 const struct mips_operand *operand, *ext_operand;
bdd15286 2040 unsigned short ext_size;
c3c07478
RS
2041 unsigned int uval;
2042 bfd_vma baseaddr;
2043
2044 if (!use_extend)
2045 extend = 0;
fc8c4fd1 2046
252b5132
RH
2047 switch (type)
2048 {
2049 case ',':
2050 case '(':
2051 case ')':
fc8c4fd1 2052 infprintf (is, "%c", type);
252b5132
RH
2053 break;
2054
c3c07478 2055 default:
78933a4a 2056 operand = decode_mips16_operand (type, false);
c3c07478
RS
2057 if (!operand)
2058 {
2059 /* xgettext:c-format */
2060 infprintf (is, _("# internal error, undefined operand in `%s %s'"),
2061 opcode->name, opcode->args);
2062 return;
2063 }
252b5132 2064
c3c07478
RS
2065 if (operand->type == OP_SAVE_RESTORE_LIST)
2066 {
5f5c6e03 2067 /* Handle this case here because of the complex interaction
c3c07478 2068 with the EXTEND opcode. */
38bf472a
MR
2069 unsigned int amask = extend & 0xf;
2070 unsigned int nsreg = (extend >> 8) & 0x7;
2071 unsigned int ra = insn & 0x40; /* $ra */
2072 unsigned int s0 = insn & 0x20; /* $s0 */
2073 unsigned int s1 = insn & 0x10; /* $s1 */
2074 unsigned int frame_size = ((extend & 0xf0) | (insn & 0x0f)) * 8;
c3c07478
RS
2075 if (frame_size == 0 && !use_extend)
2076 frame_size = 128;
38bf472a 2077 mips_print_save_restore (info, amask, nsreg, ra, s0, s1, frame_size);
c3c07478
RS
2078 break;
2079 }
252b5132 2080
c3c07478
RS
2081 if (is_offset && operand->type == OP_INT)
2082 {
2083 const struct mips_int_operand *int_op;
252b5132 2084
c3c07478
RS
2085 int_op = (const struct mips_int_operand *) operand;
2086 info->insn_type = dis_dref;
2087 info->data_size = 1 << int_op->shift;
2088 }
252b5132 2089
bdd15286
MR
2090 ext_size = 0;
2091 if (use_extend)
c3c07478 2092 {
78933a4a 2093 ext_operand = decode_mips16_operand (type, true);
25499ac7
MR
2094 if (ext_operand != operand
2095 || (operand->type == OP_INT && operand->lsb == 0
2096 && mips_opcode_32bit_p (opcode)))
c3c07478 2097 {
bdd15286
MR
2098 ext_size = ext_operand->size;
2099 operand = ext_operand;
c3c07478
RS
2100 }
2101 }
bdd15286
MR
2102 if (operand->size == 26)
2103 uval = ((extend & 0x1f) << 21) | ((extend & 0x3e0) << 11) | insn;
25499ac7 2104 else if (ext_size == 16 || ext_size == 9)
bdd15286
MR
2105 uval = ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
2106 else if (ext_size == 15)
2107 uval = ((extend & 0xf) << 11) | (extend & 0x7f0) | (insn & 0xf);
2108 else if (ext_size == 6)
2109 uval = ((extend >> 6) & 0x1f) | (extend & 0x20);
2110 else
2111 uval = mips_extract_operand (operand, (extend << 16) | insn);
25499ac7
MR
2112 if (ext_size == 9)
2113 uval &= (1U << ext_size) - 1;
c3c07478
RS
2114
2115 baseaddr = memaddr + 2;
2116 if (operand->type == OP_PCREL)
2117 {
2118 const struct mips_pcrel_operand *pcrel_op;
2119
2120 pcrel_op = (const struct mips_pcrel_operand *) operand;
2121 if (!pcrel_op->include_isa_bit && use_extend)
2122 baseaddr = memaddr - 2;
2123 else if (!pcrel_op->include_isa_bit)
39f66f3a
MR
2124 {
2125 bfd_byte buffer[2];
2126
2127 /* If this instruction is in the delay slot of a JAL/JALX
2128 instruction, the base address is the address of the
2129 JAL/JALX instruction. If it is in the delay slot of
2130 a JR/JALR instruction, the base address is the address
2131 of the JR/JALR instruction. This test is unreliable:
2132 we have no way of knowing whether the previous word is
2133 instruction or data. */
2134 if (info->read_memory_func (memaddr - 4, buffer, 2, info) == 0
2135 && (((info->endian == BFD_ENDIAN_BIG
2136 ? bfd_getb16 (buffer)
2137 : bfd_getl16 (buffer))
2138 & 0xf800) == 0x1800))
2139 baseaddr = memaddr - 4;
2140 else if (info->read_memory_func (memaddr - 2, buffer, 2,
2141 info) == 0
2142 && (((info->endian == BFD_ENDIAN_BIG
2143 ? bfd_getb16 (buffer)
2144 : bfd_getl16 (buffer))
2145 & 0xf89f) == 0xe800)
2146 && (((info->endian == BFD_ENDIAN_BIG
2147 ? bfd_getb16 (buffer)
2148 : bfd_getl16 (buffer))
2149 & 0x0060) != 0x0060))
2150 baseaddr = memaddr - 2;
2151 else
2152 baseaddr = memaddr;
2153 }
c3c07478 2154 }
0499d65b 2155
6d075bce 2156 print_insn_arg (info, state, opcode, operand, baseaddr + 1, uval);
0499d65b 2157 break;
252b5132
RH
2158 }
2159}
640c0ccd 2160
1bbce132
MR
2161
2162/* Check if the given address is the last word of a MIPS16 PLT entry.
2163 This word is data and depending on the value it may interfere with
2164 disassembly of further PLT entries. We make use of the fact PLT
2165 symbols are marked BSF_SYNTHETIC. */
78933a4a 2166static bool
1bbce132
MR
2167is_mips16_plt_tail (struct disassemble_info *info, bfd_vma addr)
2168{
2169 if (info->symbols
2170 && info->symbols[0]
2171 && (info->symbols[0]->flags & BSF_SYNTHETIC)
2172 && addr == bfd_asymbol_value (info->symbols[0]) + 12)
78933a4a 2173 return true;
1bbce132 2174
78933a4a 2175 return false;
1bbce132
MR
2176}
2177
7fd53920
MR
2178/* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2179
2180enum match_kind
2181{
2182 MATCH_NONE,
2183 MATCH_FULL,
2184 MATCH_SHORT
2185};
2186
47b0e7ad
NC
2187/* Disassemble mips16 instructions. */
2188
2189static int
2190print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
2191{
fc8c4fd1 2192 const fprintf_ftype infprintf = info->fprintf_func;
47b0e7ad 2193 int status;
1bbce132 2194 bfd_byte buffer[4];
47b0e7ad 2195 const struct mips_opcode *op, *opend;
c3c07478 2196 struct mips_print_arg_state state;
fc8c4fd1 2197 void *is = info->stream;
78933a4a
AM
2198 bool have_second;
2199 bool extend_only;
7fd53920
MR
2200 unsigned int second;
2201 unsigned int first;
2202 unsigned int full;
47b0e7ad
NC
2203
2204 info->bytes_per_chunk = 2;
2205 info->display_endian = info->endian;
2206 info->insn_info_valid = 1;
2207 info->branch_delay_insns = 0;
2208 info->data_size = 0;
47b0e7ad
NC
2209 info->target = 0;
2210 info->target2 = 0;
2211
c3c07478
RS
2212#define GET_OP(insn, field) \
2213 (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
1bbce132
MR
2214 /* Decode PLT entry's GOT slot address word. */
2215 if (is_mips16_plt_tail (info, memaddr))
2216 {
2217 info->insn_type = dis_noninsn;
2218 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
2219 if (status == 0)
2220 {
2221 unsigned int gotslot;
2222
2223 if (info->endian == BFD_ENDIAN_BIG)
2224 gotslot = bfd_getb32 (buffer);
2225 else
2226 gotslot = bfd_getl32 (buffer);
2227 infprintf (is, ".word\t0x%x", gotslot);
2228
2229 return 4;
2230 }
2231 }
2232 else
2233 {
2234 info->insn_type = dis_nonbranch;
2235 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2236 }
47b0e7ad
NC
2237 if (status != 0)
2238 {
2239 (*info->memory_error_func) (status, memaddr, info);
2240 return -1;
2241 }
2242
78933a4a 2243 extend_only = false;
25499ac7 2244
47b0e7ad 2245 if (info->endian == BFD_ENDIAN_BIG)
7fd53920 2246 first = bfd_getb16 (buffer);
47b0e7ad 2247 else
7fd53920 2248 first = bfd_getl16 (buffer);
47b0e7ad 2249
7fd53920
MR
2250 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2251 if (status == 0)
47b0e7ad 2252 {
78933a4a 2253 have_second = true;
47b0e7ad 2254 if (info->endian == BFD_ENDIAN_BIG)
7fd53920 2255 second = bfd_getb16 (buffer);
47b0e7ad 2256 else
7fd53920
MR
2257 second = bfd_getl16 (buffer);
2258 full = (first << 16) | second;
2259 }
2260 else
2261 {
78933a4a 2262 have_second = false;
7fd53920
MR
2263 second = 0;
2264 full = first;
47b0e7ad
NC
2265 }
2266
2267 /* FIXME: Should probably use a hash table on the major opcode here. */
2268
2269 opend = mips16_opcodes + bfd_mips16_num_opcodes;
2270 for (op = mips16_opcodes; op < opend; op++)
2271 {
7fd53920 2272 enum match_kind match;
47b0e7ad 2273
11dd08e9
MR
2274 if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor))
2275 continue;
2276
7fd53920
MR
2277 if (op->pinfo == INSN_MACRO
2278 || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
2279 match = MATCH_NONE;
2280 else if (mips_opcode_32bit_p (op))
2281 {
2282 if (have_second
2283 && (full & op->mask) == op->match)
2284 match = MATCH_FULL;
2285 else
2286 match = MATCH_NONE;
2287 }
2288 else if ((first & op->mask) == op->match)
2289 {
2290 match = MATCH_SHORT;
2291 second = 0;
2292 full = first;
2293 }
2294 else if ((first & 0xf800) == 0xf000
2295 && have_second
25499ac7 2296 && !extend_only
7fd53920 2297 && (second & op->mask) == op->match)
25499ac7
MR
2298 {
2299 if (op->pinfo2 & INSN2_SHORT_ONLY)
2300 {
2301 match = MATCH_NONE;
78933a4a 2302 extend_only = true;
25499ac7
MR
2303 }
2304 else
2305 match = MATCH_FULL;
2306 }
7fd53920
MR
2307 else
2308 match = MATCH_NONE;
47b0e7ad 2309
7fd53920
MR
2310 if (match != MATCH_NONE)
2311 {
2312 const char *s;
47b0e7ad 2313
fc8c4fd1 2314 infprintf (is, "%s", op->name);
47b0e7ad 2315 if (op->args[0] != '\0')
fc8c4fd1 2316 infprintf (is, "\t");
47b0e7ad 2317
c3c07478 2318 init_print_arg_state (&state);
47b0e7ad
NC
2319 for (s = op->args; *s != '\0'; s++)
2320 {
2321 if (*s == ','
2322 && s[1] == 'w'
7fd53920 2323 && GET_OP (full, RX) == GET_OP (full, RY))
47b0e7ad
NC
2324 {
2325 /* Skip the register and the comma. */
2326 ++s;
2327 continue;
2328 }
2329 if (*s == ','
2330 && s[1] == 'v'
7fd53920 2331 && GET_OP (full, RZ) == GET_OP (full, RX))
47b0e7ad
NC
2332 {
2333 /* Skip the register and the comma. */
2334 ++s;
2335 continue;
2336 }
25499ac7
MR
2337 if (s[0] == 'N'
2338 && s[1] == ','
2339 && s[2] == 'O'
2340 && op->name[strlen (op->name) - 1] == '0')
7fd53920 2341 {
25499ac7
MR
2342 /* Coprocessor register 0 with sel field. */
2343 const struct mips_cp0sel_name *n;
2344 const struct mips_operand *operand;
2345 unsigned int reg, sel;
2346
78933a4a 2347 operand = decode_mips16_operand (*s, true);
25499ac7
MR
2348 reg = mips_extract_operand (operand, (first << 16) | second);
2349 s += 2;
78933a4a 2350 operand = decode_mips16_operand (*s, true);
25499ac7
MR
2351 sel = mips_extract_operand (operand, (first << 16) | second);
2352
2353 /* CP0 register including 'sel' code for mftc0, to be
2354 printed textually if known. If not known, print both
2355 CP0 register name and sel numerically since CP0 register
2356 with sel 0 may have a name unrelated to register being
2357 printed. */
2358 n = lookup_mips_cp0sel_name (mips_cp0sel_names,
2359 mips_cp0sel_names_len,
2360 reg, sel);
2361 if (n != NULL)
2362 infprintf (is, "%s", n->name);
2363 else
2364 infprintf (is, "$%d,%d", reg, sel);
7fd53920 2365 }
25499ac7
MR
2366 else
2367 switch (match)
2368 {
2369 case MATCH_FULL:
2370 print_mips16_insn_arg (info, &state, op, *s, memaddr + 2,
78933a4a 2371 second, true, first, s[1] == '(');
25499ac7
MR
2372 break;
2373 case MATCH_SHORT:
2374 print_mips16_insn_arg (info, &state, op, *s, memaddr,
78933a4a 2375 first, false, 0, s[1] == '(');
25499ac7
MR
2376 break;
2377 case MATCH_NONE: /* Stop the compiler complaining. */
2378 break;
2379 }
47b0e7ad
NC
2380 }
2381
9a2c7088 2382 /* Figure out branch instruction type and delay slot information. */
47b0e7ad 2383 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
9a2c7088 2384 info->branch_delay_insns = 1;
26545944
RS
2385 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0
2386 || (op->pinfo2 & INSN2_UNCOND_BRANCH) != 0)
47b0e7ad 2387 {
9a2c7088
MR
2388 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2389 info->insn_type = dis_jsr;
2390 else
47b0e7ad
NC
2391 info->insn_type = dis_branch;
2392 }
26545944 2393 else if ((op->pinfo2 & INSN2_COND_BRANCH) != 0)
9a2c7088 2394 info->insn_type = dis_condbranch;
47b0e7ad 2395
7fd53920 2396 return match == MATCH_FULL ? 4 : 2;
47b0e7ad
NC
2397 }
2398 }
fc8c4fd1 2399#undef GET_OP
47b0e7ad 2400
7fd53920 2401 infprintf (is, "0x%x", first);
47b0e7ad
NC
2402 info->insn_type = dis_noninsn;
2403
7fd53920 2404 return 2;
47b0e7ad
NC
2405}
2406
df58fc94
RS
2407/* Disassemble microMIPS instructions. */
2408
2409static int
2410print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
2411{
0c7533d3 2412 const fprintf_ftype infprintf = info->fprintf_func;
df58fc94 2413 const struct mips_opcode *op, *opend;
df58fc94 2414 void *is = info->stream;
df58fc94 2415 bfd_byte buffer[2];
ab902481
RS
2416 unsigned int higher;
2417 unsigned int length;
df58fc94 2418 int status;
ab902481 2419 unsigned int insn;
df58fc94
RS
2420
2421 info->bytes_per_chunk = 2;
2422 info->display_endian = info->endian;
2423 info->insn_info_valid = 1;
2424 info->branch_delay_insns = 0;
2425 info->data_size = 0;
2426 info->insn_type = dis_nonbranch;
2427 info->target = 0;
2428 info->target2 = 0;
2429
2430 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2431 if (status != 0)
2432 {
2433 (*info->memory_error_func) (status, memaddr, info);
2434 return -1;
2435 }
2436
2437 length = 2;
2438
2439 if (info->endian == BFD_ENDIAN_BIG)
2440 insn = bfd_getb16 (buffer);
2441 else
2442 insn = bfd_getl16 (buffer);
2443
100b4f2e 2444 if ((insn & 0x1c00) == 0x0000 || (insn & 0x1000) == 0x1000)
df58fc94
RS
2445 {
2446 /* This is a 32-bit microMIPS instruction. */
2447 higher = insn;
2448
2449 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2450 if (status != 0)
2451 {
0c7533d3 2452 infprintf (is, "micromips 0x%x", higher);
df58fc94
RS
2453 (*info->memory_error_func) (status, memaddr + 2, info);
2454 return -1;
2455 }
2456
2457 if (info->endian == BFD_ENDIAN_BIG)
2458 insn = bfd_getb16 (buffer);
2459 else
2460 insn = bfd_getl16 (buffer);
2461
2462 insn = insn | (higher << 16);
2463
2464 length += 2;
2465 }
2466
2467 /* FIXME: Should probably use a hash table on the major opcode here. */
2468
df58fc94
RS
2469 opend = micromips_opcodes + bfd_micromips_num_opcodes;
2470 for (op = micromips_opcodes; op < opend; op++)
2471 {
2472 if (op->pinfo != INSN_MACRO
2473 && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
2474 && (insn & op->mask) == op->match
2475 && ((length == 2 && (op->mask & 0xffff0000) == 0)
2476 || (length == 4 && (op->mask & 0xffff0000) != 0)))
2477 {
7361da2c
AB
2478 if (!validate_insn_args (op, decode_micromips_operand, insn))
2479 continue;
2480
0c7533d3 2481 infprintf (is, "%s", op->name);
df58fc94 2482
ab902481 2483 if (op->args[0])
df58fc94 2484 {
ab902481
RS
2485 infprintf (is, "\t");
2486 print_insn_args (info, op, decode_micromips_operand, insn,
7361da2c 2487 memaddr + 1, length);
df58fc94
RS
2488 }
2489
2490 /* Figure out instruction type and branch delay information. */
2491 if ((op->pinfo
2492 & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY)) != 0)
2493 info->branch_delay_insns = 1;
2494 if (((op->pinfo & INSN_UNCOND_BRANCH_DELAY)
2495 | (op->pinfo2 & INSN2_UNCOND_BRANCH)) != 0)
2496 {
fc76e730 2497 if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
df58fc94
RS
2498 info->insn_type = dis_jsr;
2499 else
2500 info->insn_type = dis_branch;
2501 }
2502 else if (((op->pinfo & INSN_COND_BRANCH_DELAY)
2503 | (op->pinfo2 & INSN2_COND_BRANCH)) != 0)
2504 {
2505 if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2506 info->insn_type = dis_condjsr;
2507 else
2508 info->insn_type = dis_condbranch;
2509 }
2510 else if ((op->pinfo
67dc82bc 2511 & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY)) != 0)
df58fc94
RS
2512 info->insn_type = dis_dref;
2513
2514 return length;
2515 }
2516 }
df58fc94 2517
0c7533d3 2518 infprintf (is, "0x%x", insn);
df58fc94
RS
2519 info->insn_type = dis_noninsn;
2520
2521 return length;
2522}
2523
2524/* Return 1 if a symbol associated with the location being disassembled
1401d2fe
MR
2525 indicates a compressed mode, either MIPS16 or microMIPS, according to
2526 MICROMIPS_P. We iterate over all the symbols at the address being
2527 considered assuming if at least one of them indicates code compression,
2528 then such code has been genuinely produced here (other symbols could
2529 have been derived from function symbols defined elsewhere or could
2530 define data). Otherwise, return 0. */
df58fc94 2531
78933a4a
AM
2532static bool
2533is_compressed_mode_p (struct disassemble_info *info, bool micromips_p)
df58fc94 2534{
df58fc94 2535 int i;
1bbce132
MR
2536 int l;
2537
2538 for (i = info->symtab_pos, l = i + info->num_symbols; i < l; i++)
2539 if (((info->symtab[i])->flags & BSF_SYNTHETIC) != 0
1401d2fe 2540 && ((!micromips_p
1bbce132 2541 && ELF_ST_IS_MIPS16 ((*info->symbols)->udata.i))
1401d2fe 2542 || (micromips_p
1bbce132
MR
2543 && ELF_ST_IS_MICROMIPS ((*info->symbols)->udata.i))))
2544 return 1;
2545 else if (bfd_asymbol_flavour (info->symtab[i]) == bfd_target_elf_flavour
2546 && info->symtab[i]->section == info->section)
2547 {
2548 elf_symbol_type *symbol = (elf_symbol_type *) info->symtab[i];
1401d2fe 2549 if ((!micromips_p
1bbce132 2550 && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
1401d2fe 2551 || (micromips_p
1bbce132
MR
2552 && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
2553 return 1;
2554 }
df58fc94
RS
2555
2556 return 0;
2557}
2558
47b0e7ad
NC
2559/* In an environment where we do not know the symbol type of the
2560 instruction we are forced to assume that the low order bit of the
2561 instructions' address may mark it as a mips16 instruction. If we
2562 are single stepping, or the pc is within the disassembled function,
2563 this works. Otherwise, we need a clue. Sometimes. */
2564
2565static int
2566_print_insn_mips (bfd_vma memaddr,
2567 struct disassemble_info *info,
2568 enum bfd_endian endianness)
2569{
2570 bfd_byte buffer[INSNLEN];
2571 int status;
2572
2573 set_default_mips_dis_options (info);
2574 parse_mips_dis_options (info->disassembler_options);
2575
df58fc94
RS
2576 if (info->mach == bfd_mach_mips16)
2577 return print_insn_mips16 (memaddr, info);
2578 if (info->mach == bfd_mach_mips_micromips)
2579 return print_insn_micromips (memaddr, info);
2580
47b0e7ad 2581#if 1
df58fc94 2582 /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
47b0e7ad
NC
2583 /* Only a few tools will work this way. */
2584 if (memaddr & 0x01)
1401d2fe
MR
2585 {
2586 if (micromips_ase)
2587 return print_insn_micromips (memaddr, info);
2588 else
2589 return print_insn_mips16 (memaddr, info);
2590 }
47b0e7ad
NC
2591#endif
2592
2593#if SYMTAB_AVAILABLE
78933a4a 2594 if (is_compressed_mode_p (info, true))
1401d2fe 2595 return print_insn_micromips (memaddr, info);
78933a4a 2596 if (is_compressed_mode_p (info, false))
1401d2fe 2597 return print_insn_mips16 (memaddr, info);
47b0e7ad
NC
2598#endif
2599
2600 status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
2601 if (status == 0)
2602 {
fc8c4fd1 2603 int insn;
47b0e7ad
NC
2604
2605 if (endianness == BFD_ENDIAN_BIG)
fc8c4fd1 2606 insn = bfd_getb32 (buffer);
47b0e7ad 2607 else
fc8c4fd1 2608 insn = bfd_getl32 (buffer);
47b0e7ad
NC
2609
2610 return print_insn_mips (memaddr, insn, info);
2611 }
2612 else
2613 {
2614 (*info->memory_error_func) (status, memaddr, info);
2615 return -1;
2616 }
2617}
2618
2619int
2620print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info)
2621{
2622 return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
2623}
2624
2625int
2626print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info)
2627{
2628 return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
2629}
2630\f
471b9d15
MR
2631/* Indices into option argument vector for options accepting an argument.
2632 Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2633typedef enum
640c0ccd 2634{
471b9d15
MR
2635 MIPS_OPTION_ARG_NONE = -1,
2636 MIPS_OPTION_ARG_ABI,
2637 MIPS_OPTION_ARG_ARCH,
2638 MIPS_OPTION_ARG_SIZE
2639} mips_option_arg_t;
2640
2641/* Valid MIPS disassembler options. */
2642static struct
2643{
2644 const char *name;
2645 const char *description;
2646 mips_option_arg_t arg;
2647} mips_options[] =
2648{
2649 { "no-aliases", N_("Use canonical instruction forms.\n"),
2650 MIPS_OPTION_ARG_NONE },
2651 { "msa", N_("Recognize MSA instructions.\n"),
2652 MIPS_OPTION_ARG_NONE },
2653 { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2654 MIPS_OPTION_ARG_NONE },
2655 { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2656 instructions.\n"),
2657 MIPS_OPTION_ARG_NONE },
2658 { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2659 "instructions.\n"),
2660 MIPS_OPTION_ARG_NONE },
8095d2f7
CX
2661 { "loongson-mmi",
2662 N_("Recognize the Loongson MultiMedia extensions "
2663 "Instructions (MMI) ASE instructions.\n"),
2664 MIPS_OPTION_ARG_NONE },
716c08de
CX
2665 { "loongson-cam",
2666 N_("Recognize the Loongson Content Address Memory (CAM) "
2667 " instructions.\n"),
2668 MIPS_OPTION_ARG_NONE },
bdc6c06e
CX
2669 { "loongson-ext",
2670 N_("Recognize the Loongson EXTensions (EXT) "
2671 " instructions.\n"),
2672 MIPS_OPTION_ARG_NONE },
a693765e
CX
2673 { "loongson-ext2",
2674 N_("Recognize the Loongson EXTensions R2 (EXT2) "
2675 " instructions.\n"),
2676 MIPS_OPTION_ARG_NONE },
471b9d15
MR
2677 { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2678 Default: based on binary being disassembled.\n"),
2679 MIPS_OPTION_ARG_ABI },
2680 { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2681 Default: numeric.\n"),
2682 MIPS_OPTION_ARG_ABI },
2683 { "cp0-names=", N_("Print CP0 register names according to specified "
2684 "architecture.\n\
2685 Default: based on binary being disassembled.\n"),
2686 MIPS_OPTION_ARG_ARCH },
2687 { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2688 Default: based on binary being disassembled.\n"),
2689 MIPS_OPTION_ARG_ARCH },
2690 { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2691 MIPS_OPTION_ARG_ABI },
2692 { "reg-names=", N_("Print CP0 register and HWR names according to "
2693 "specified\n\
2694 architecture."),
2695 MIPS_OPTION_ARG_ARCH }
2696};
0348fd79 2697
471b9d15
MR
2698/* Build the structure representing valid MIPS disassembler options.
2699 This is done dynamically for maintenance ease purpose; a static
2700 initializer would be unreadable. */
4edbb8e3 2701
471b9d15
MR
2702const disasm_options_and_args_t *
2703disassembler_options_mips (void)
2704{
2705 static disasm_options_and_args_t *opts_and_args;
b015e599 2706
471b9d15
MR
2707 if (opts_and_args == NULL)
2708 {
2709 size_t num_options = ARRAY_SIZE (mips_options);
2710 size_t num_args = MIPS_OPTION_ARG_SIZE;
2711 disasm_option_arg_t *args;
2712 disasm_options_t *opts;
2713 size_t i;
2714 size_t j;
2715
2716 args = XNEWVEC (disasm_option_arg_t, num_args + 1);
2717
2718 args[MIPS_OPTION_ARG_ABI].name = "ABI";
2719 args[MIPS_OPTION_ARG_ABI].values
2720 = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices) + 1);
2721 for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
2722 args[MIPS_OPTION_ARG_ABI].values[i] = mips_abi_choices[i].name;
2723 /* The array we return must be NULL terminated. */
2724 args[MIPS_OPTION_ARG_ABI].values[i] = NULL;
2725
2726 args[MIPS_OPTION_ARG_ARCH].name = "ARCH";
2727 args[MIPS_OPTION_ARG_ARCH].values
2728 = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices) + 1);
2729 for (i = 0, j = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
2730 if (*mips_arch_choices[i].name != '\0')
2731 args[MIPS_OPTION_ARG_ARCH].values[j++] = mips_arch_choices[i].name;
2732 /* The array we return must be NULL terminated. */
2733 args[MIPS_OPTION_ARG_ARCH].values[j] = NULL;
2734
2735 /* The array we return must be NULL terminated. */
2736 args[MIPS_OPTION_ARG_SIZE].name = NULL;
2737 args[MIPS_OPTION_ARG_SIZE].values = NULL;
2738
2739 opts_and_args = XNEW (disasm_options_and_args_t);
2740 opts_and_args->args = args;
2741
2742 opts = &opts_and_args->options;
2743 opts->name = XNEWVEC (const char *, num_options + 1);
2744 opts->description = XNEWVEC (const char *, num_options + 1);
2745 opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1);
2746 for (i = 0; i < num_options; i++)
2747 {
2748 opts->name[i] = mips_options[i].name;
2749 opts->description[i] = _(mips_options[i].description);
2750 if (mips_options[i].arg != MIPS_OPTION_ARG_NONE)
2751 opts->arg[i] = &args[mips_options[i].arg];
2752 else
2753 opts->arg[i] = NULL;
2754 }
2755 /* The array we return must be NULL terminated. */
2756 opts->name[i] = NULL;
2757 opts->description[i] = NULL;
2758 opts->arg[i] = NULL;
2759 }
7d64c587 2760
471b9d15
MR
2761 return opts_and_args;
2762}
6f20c942 2763
471b9d15
MR
2764void
2765print_mips_disassembler_options (FILE *stream)
2766{
2767 const disasm_options_and_args_t *opts_and_args;
2768 const disasm_option_arg_t *args;
2769 const disasm_options_t *opts;
2770 size_t max_len = 0;
2771 size_t i;
2772 size_t j;
640c0ccd 2773
471b9d15
MR
2774 opts_and_args = disassembler_options_mips ();
2775 opts = &opts_and_args->options;
2776 args = opts_and_args->args;
640c0ccd
CD
2777
2778 fprintf (stream, _("\n\
471b9d15
MR
2779The following MIPS specific disassembler options are supported for use\n\
2780with the -M switch (multiple options should be separated by commas):\n\n"));
640c0ccd 2781
471b9d15
MR
2782 /* Compute the length of the longest option name. */
2783 for (i = 0; opts->name[i] != NULL; i++)
2784 {
2785 size_t len = strlen (opts->name[i]);
af7ee8bf 2786
471b9d15
MR
2787 if (opts->arg[i] != NULL)
2788 len += strlen (opts->arg[i]->name);
2789 if (max_len < len)
2790 max_len = len;
2791 }
640c0ccd 2792
471b9d15
MR
2793 for (i = 0, max_len++; opts->name[i] != NULL; i++)
2794 {
2795 fprintf (stream, " %s", opts->name[i]);
2796 if (opts->arg[i] != NULL)
2797 fprintf (stream, "%s", opts->arg[i]->name);
2798 if (opts->description[i] != NULL)
2799 {
2800 size_t len = strlen (opts->name[i]);
640c0ccd 2801
471b9d15
MR
2802 if (opts->arg[i] != NULL)
2803 len += strlen (opts->arg[i]->name);
2804 fprintf (stream,
2805 "%*c %s", (int) (max_len - len), ' ', opts->description[i]);
2806 }
2807 fprintf (stream, _("\n"));
2808 }
640c0ccd 2809
471b9d15
MR
2810 for (i = 0; args[i].name != NULL; i++)
2811 {
2812 fprintf (stream, _("\n\
2813 For the options above, the following values are supported for \"%s\":\n "),
2814 args[i].name);
2815 for (j = 0; args[i].values[j] != NULL; j++)
2816 fprintf (stream, " %s", args[i].values[j]);
2817 fprintf (stream, _("\n"));
2818 }
640c0ccd
CD
2819
2820 fprintf (stream, _("\n"));
2821}
This page took 1.201113 seconds and 4 git commands to generate.