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