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