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