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