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