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