]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/mips-dis.c
2003-01-02 H.J. Lu <hjl@gnu.org>
[thirdparty/binutils-gdb.git] / opcodes / mips-dis.c
CommitLineData
252b5132 1/* Print mips instructions for GDB, the GNU debugger, or for objdump.
060d22b0 2 Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
82f6ea4a 3 2000, 2001, 2002
73da6b6b 4 Free Software Foundation, Inc.
252b5132
RH
5 Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
6
7This file is part of GDB, GAS, and the GNU binutils.
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22
252b5132
RH
23#include "sysdep.h"
24#include "dis-asm.h"
640c0ccd 25#include "libiberty.h"
252b5132
RH
26#include "opcode/mips.h"
27#include "opintl.h"
28
29/* FIXME: These are needed to figure out if the code is mips16 or
30 not. The low bit of the address is often a good indicator. No
31 symbol table is available when this code runs out in an embedded
7f6621cd 32 system as when it is used for disassembler support in a monitor. */
252b5132
RH
33
34#if !defined(EMBEDDED_ENV)
35#define SYMTAB_AVAILABLE 1
36#include "elf-bfd.h"
37#include "elf/mips.h"
38#endif
39
aa5f19f2
NC
40/* Mips instructions are at maximum this many bytes long. */
41#define INSNLEN 4
42
640c0ccd
CD
43static void set_default_mips_dis_options
44 PARAMS ((struct disassemble_info *));
45static void parse_mips_dis_option
46 PARAMS ((const char *, unsigned int));
47static void parse_mips_dis_options
48 PARAMS ((const char *));
aa5f19f2
NC
49static int _print_insn_mips
50 PARAMS ((bfd_vma, struct disassemble_info *, enum bfd_endian));
51static int print_insn_mips
52 PARAMS ((bfd_vma, unsigned long int, struct disassemble_info *));
af7ee8bf 53static int print_insn_arg
aa5f19f2
NC
54 PARAMS ((const char *, unsigned long, bfd_vma, struct disassemble_info *));
55static int print_insn_mips16
56 PARAMS ((bfd_vma, struct disassemble_info *));
7fa108a4
AJ
57static int is_newabi
58 PARAMS ((Elf_Internal_Ehdr *));
252b5132 59static void print_mips16_insn_arg
b34976b6 60 PARAMS ((int, const struct mips_opcode *, int, bfd_boolean, int, bfd_vma,
252b5132 61 struct disassemble_info *));
252b5132 62\f
aa5f19f2 63/* FIXME: These should be shared with gdb somehow. */
252b5132 64
bbcc0807
CD
65struct mips_cp0sel_name {
66 unsigned int cp0reg;
67 unsigned int sel;
68 const char * const name;
69};
70
252b5132 71/* The mips16 register names. */
7f6621cd 72static const char * const mips16_reg_names[] = {
252b5132
RH
73 "s0", "s1", "v0", "v1", "a0", "a1", "a2", "a3"
74};
fb48caed 75
640c0ccd
CD
76static const char * const mips_gpr_names_numeric[32] = {
77 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
78 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
79 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
80 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
aa5f19f2
NC
81};
82
640c0ccd
CD
83static const char * const mips_gpr_names_oldabi[32] = {
84 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
85 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
86 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
87 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
aa5f19f2
NC
88};
89
640c0ccd
CD
90static const char * const mips_gpr_names_newabi[32] = {
91 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
92 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
93 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
94 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
95};
96
97static const char * const mips_fpr_names_numeric[32] = {
98 "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
99 "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
100 "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
101 "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
102};
103
104static const char * const mips_fpr_names_32[32] = {
105 "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
106 "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
107 "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f",
108 "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f"
109};
110
111static const char * const mips_fpr_names_n32[32] = {
112 "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3",
113 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
114 "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9",
115 "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13"
116};
117
118static const char * const mips_fpr_names_64[32] = {
119 "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
120 "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
121 "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
122 "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
123};
124
125static const char * const mips_cp0_names_numeric[32] = {
126 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
127 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
128 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
129 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
130};
131
132static const char * const mips_cp0_names_mips3264[32] = {
133 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
134 "c0_context", "c0_pagemask", "c0_wired", "$7",
135 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
136 "c0_status", "c0_cause", "c0_epc", "c0_prid",
137 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
138 "c0_xcontext", "$21", "$22", "c0_debug",
139 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
140 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
141};
142
bbcc0807
CD
143static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] = {
144 { 16, 1, "c0_config1" },
145 { 16, 2, "c0_config2" },
146 { 16, 3, "c0_config3" },
147 { 18, 1, "c0_watchlo,1" },
148 { 18, 2, "c0_watchlo,2" },
149 { 18, 3, "c0_watchlo,3" },
150 { 18, 4, "c0_watchlo,4" },
151 { 18, 5, "c0_watchlo,5" },
152 { 18, 6, "c0_watchlo,6" },
153 { 18, 7, "c0_watchlo,7" },
154 { 19, 1, "c0_watchhi,1" },
155 { 19, 2, "c0_watchhi,2" },
156 { 19, 3, "c0_watchhi,3" },
157 { 19, 4, "c0_watchhi,4" },
158 { 19, 5, "c0_watchhi,5" },
159 { 19, 6, "c0_watchhi,6" },
160 { 19, 7, "c0_watchhi,7" },
161 { 25, 1, "c0_perfcnt,1" },
162 { 25, 2, "c0_perfcnt,2" },
163 { 25, 3, "c0_perfcnt,3" },
164 { 25, 4, "c0_perfcnt,4" },
165 { 25, 5, "c0_perfcnt,5" },
166 { 25, 6, "c0_perfcnt,6" },
167 { 25, 7, "c0_perfcnt,7" },
168 { 27, 1, "c0_cacheerr,1" },
169 { 27, 2, "c0_cacheerr,2" },
170 { 27, 3, "c0_cacheerr,3" },
171 { 28, 1, "c0_datalo" },
172 { 29, 1, "c0_datahi" }
173};
174
af7ee8bf
CD
175static const char * const mips_cp0_names_mips3264r2[32] = {
176 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
177 "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
178 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
179 "c0_status", "c0_cause", "c0_epc", "c0_prid",
180 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
181 "c0_xcontext", "$21", "$22", "c0_debug",
182 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
183 "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
184};
185
bbcc0807
CD
186static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] = {
187 { 4, 1, "c0_contextconfig" },
188 { 5, 1, "c0_pagegrain" },
189 { 12, 1, "c0_intctl" },
190 { 12, 2, "c0_srsctl" },
191 { 12, 3, "c0_srsmap" },
192 { 15, 1, "c0_ebase" },
193 { 16, 1, "c0_config1" },
194 { 16, 2, "c0_config2" },
195 { 16, 3, "c0_config3" },
196 { 18, 1, "c0_watchlo,1" },
197 { 18, 2, "c0_watchlo,2" },
198 { 18, 3, "c0_watchlo,3" },
199 { 18, 4, "c0_watchlo,4" },
200 { 18, 5, "c0_watchlo,5" },
201 { 18, 6, "c0_watchlo,6" },
202 { 18, 7, "c0_watchlo,7" },
203 { 19, 1, "c0_watchhi,1" },
204 { 19, 2, "c0_watchhi,2" },
205 { 19, 3, "c0_watchhi,3" },
206 { 19, 4, "c0_watchhi,4" },
207 { 19, 5, "c0_watchhi,5" },
208 { 19, 6, "c0_watchhi,6" },
209 { 19, 7, "c0_watchhi,7" },
210 { 23, 1, "c0_tracecontrol" },
211 { 23, 2, "c0_tracecontrol2" },
212 { 23, 3, "c0_usertracedata" },
213 { 23, 4, "c0_tracebpc" },
214 { 25, 1, "c0_perfcnt,1" },
215 { 25, 2, "c0_perfcnt,2" },
216 { 25, 3, "c0_perfcnt,3" },
217 { 25, 4, "c0_perfcnt,4" },
218 { 25, 5, "c0_perfcnt,5" },
219 { 25, 6, "c0_perfcnt,6" },
220 { 25, 7, "c0_perfcnt,7" },
221 { 27, 1, "c0_cacheerr,1" },
222 { 27, 2, "c0_cacheerr,2" },
223 { 27, 3, "c0_cacheerr,3" },
224 { 28, 1, "c0_datalo" },
225 { 28, 2, "c0_taglo1" },
226 { 28, 3, "c0_datalo1" },
227 { 28, 4, "c0_taglo2" },
228 { 28, 5, "c0_datalo2" },
229 { 28, 6, "c0_taglo3" },
230 { 28, 7, "c0_datalo3" },
231 { 29, 1, "c0_datahi" },
232 { 29, 2, "c0_taghi1" },
233 { 29, 3, "c0_datahi1" },
234 { 29, 4, "c0_taghi2" },
235 { 29, 5, "c0_datahi2" },
236 { 29, 6, "c0_taghi3" },
237 { 29, 7, "c0_datahi3" },
238};
239
640c0ccd
CD
240/* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
241static const char * const mips_cp0_names_sb1[32] = {
242 "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
243 "c0_context", "c0_pagemask", "c0_wired", "$7",
244 "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
245 "c0_status", "c0_cause", "c0_epc", "c0_prid",
246 "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
247 "c0_xcontext", "$21", "$22", "c0_debug",
248 "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
249 "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
250};
251
bbcc0807
CD
252static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] = {
253 { 16, 1, "c0_config1" },
254 { 18, 1, "c0_watchlo,1" },
255 { 19, 1, "c0_watchhi,1" },
256 { 22, 0, "c0_perftrace" },
257 { 23, 3, "c0_edebug" },
258 { 25, 1, "c0_perfcnt,1" },
259 { 25, 2, "c0_perfcnt,2" },
260 { 25, 3, "c0_perfcnt,3" },
261 { 25, 4, "c0_perfcnt,4" },
262 { 25, 5, "c0_perfcnt,5" },
263 { 25, 6, "c0_perfcnt,6" },
264 { 25, 7, "c0_perfcnt,7" },
265 { 26, 1, "c0_buserr_pa" },
266 { 27, 1, "c0_cacheerr_d" },
267 { 27, 3, "c0_cacheerr_d_pa" },
268 { 28, 1, "c0_datalo_i" },
269 { 28, 2, "c0_taglo_d" },
270 { 28, 3, "c0_datalo_d" },
271 { 29, 1, "c0_datahi_i" },
272 { 29, 2, "c0_taghi_d" },
273 { 29, 3, "c0_datahi_d" },
274};
275
af7ee8bf
CD
276static const char * const mips_hwr_names_numeric[32] = {
277 "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
278 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
279 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
280 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
281};
282
283static const char * const mips_hwr_names_mips3264r2[32] = {
284 "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
285 "$4", "$5", "$6", "$7",
286 "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
287 "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
288 "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
289};
290
640c0ccd
CD
291struct mips_abi_choice {
292 const char *name;
293 const char * const *gpr_names;
294 const char * const *fpr_names;
295};
296
297struct mips_abi_choice mips_abi_choices[] = {
298 { "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric },
299 { "32", mips_gpr_names_oldabi, mips_fpr_names_32 },
300 { "n32", mips_gpr_names_newabi, mips_fpr_names_n32 },
301 { "64", mips_gpr_names_newabi, mips_fpr_names_64 },
302};
303
304struct mips_arch_choice {
305 const char *name;
306 int bfd_mach_valid;
307 unsigned long bfd_mach;
308 int processor;
309 int isa;
310 const char * const *cp0_names;
bbcc0807
CD
311 const struct mips_cp0sel_name *cp0sel_names;
312 unsigned int cp0sel_names_len;
af7ee8bf 313 const char * const *hwr_names;
640c0ccd
CD
314};
315
bbcc0807 316const struct mips_arch_choice mips_arch_choices[] = {
640c0ccd 317 { "numeric", 0, 0, 0, 0,
bbcc0807
CD
318 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
319
640c0ccd 320 { "r3000", 1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1,
bbcc0807 321 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 322 { "r3900", 1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1,
bbcc0807 323 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 324 { "r4000", 1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3,
bbcc0807 325 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 326 { "r4010", 1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2,
bbcc0807 327 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 328 { "vr4100", 1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3,
bbcc0807 329 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 330 { "vr4111", 1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3,
bbcc0807 331 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 332 { "vr4120", 1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3,
bbcc0807 333 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 334 { "r4300", 1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3,
bbcc0807 335 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 336 { "r4400", 1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3,
bbcc0807 337 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 338 { "r4600", 1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3,
bbcc0807 339 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 340 { "r4650", 1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3,
bbcc0807 341 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 342 { "r5000", 1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4,
bbcc0807 343 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 344 { "vr5400", 1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4,
bbcc0807 345 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 346 { "vr5500", 1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4,
bbcc0807 347 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 348 { "r6000", 1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2,
bbcc0807 349 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 350 { "r8000", 1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4,
bbcc0807 351 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 352 { "r10000", 1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4,
bbcc0807 353 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 354 { "r12000", 1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4,
bbcc0807 355 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 356 { "mips5", 1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5,
bbcc0807
CD
357 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
358
640c0ccd
CD
359 /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
360 Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
361 _MIPS32 Architecture For Programmers Volume I: Introduction to the
362 MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
363 page 1. */
364 { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32,
365 ISA_MIPS32 | INSN_MIPS16,
bbcc0807
CD
366 mips_cp0_names_mips3264,
367 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
368 mips_hwr_names_numeric },
369
af7ee8bf
CD
370 { "mips32r2", 1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
371 ISA_MIPS32R2 | INSN_MIPS16,
bbcc0807
CD
372 mips_cp0_names_mips3264r2,
373 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
374 mips_hwr_names_mips3264r2 },
375
640c0ccd
CD
376 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
377 { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64,
378 ISA_MIPS64 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX,
bbcc0807
CD
379 mips_cp0_names_mips3264,
380 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
381 mips_hwr_names_numeric },
382
640c0ccd
CD
383 { "sb1", 1, bfd_mach_mips_sb1, CPU_SB1,
384 ISA_MIPS64 | INSN_MIPS3D | INSN_SB1,
bbcc0807
CD
385 mips_cp0_names_sb1,
386 mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
387 mips_hwr_names_numeric },
640c0ccd
CD
388
389 /* This entry, mips16, is here only for ISA/processor selection; do
390 not print its name. */
391 { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3 | INSN_MIPS16,
bbcc0807 392 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd
CD
393};
394
395/* ISA and processor type to disassemble for, and register names to use.
396 set_default_mips_dis_options and parse_mips_dis_options fill in these
397 values. */
398static int mips_processor;
399static int mips_isa;
400static const char * const *mips_gpr_names;
401static const char * const *mips_fpr_names;
402static const char * const *mips_cp0_names;
bbcc0807
CD
403static const struct mips_cp0sel_name *mips_cp0sel_names;
404static int mips_cp0sel_names_len;
af7ee8bf 405static const char * const *mips_hwr_names;
640c0ccd
CD
406
407static const struct mips_abi_choice *choose_abi_by_name
408 PARAMS ((const char *, unsigned int));
409static const struct mips_arch_choice *choose_arch_by_name
410 PARAMS ((const char *, unsigned int));
411static const struct mips_arch_choice *choose_arch_by_number
412 PARAMS ((unsigned long));
bbcc0807
CD
413static const struct mips_cp0sel_name *lookup_mips_cp0sel_name
414 PARAMS ((const struct mips_cp0sel_name *, unsigned int, unsigned int,
415 unsigned int));
640c0ccd
CD
416\f
417static const struct mips_abi_choice *
418choose_abi_by_name (name, namelen)
419 const char *name;
420 unsigned int namelen;
421{
422 const struct mips_abi_choice *c;
423 unsigned int i;
424
425 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++)
426 {
427 if (strncmp (mips_abi_choices[i].name, name, namelen) == 0
428 && strlen (mips_abi_choices[i].name) == namelen)
429 c = &mips_abi_choices[i];
430 }
431 return c;
432}
433
434static const struct mips_arch_choice *
435choose_arch_by_name (name, namelen)
436 const char *name;
437 unsigned int namelen;
438{
439 const struct mips_arch_choice *c = NULL;
440 unsigned int i;
441
442 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
443 {
444 if (strncmp (mips_arch_choices[i].name, name, namelen) == 0
445 && strlen (mips_arch_choices[i].name) == namelen)
446 c = &mips_arch_choices[i];
447 }
448 return c;
449}
450
451static const struct mips_arch_choice *
452choose_arch_by_number (mach)
453 unsigned long mach;
454{
455 static unsigned long hint_bfd_mach;
456 static const struct mips_arch_choice *hint_arch_choice;
457 const struct mips_arch_choice *c;
458 unsigned int i;
459
460 /* We optimize this because even if the user specifies no
461 flags, this will be done for every instruction! */
462 if (hint_bfd_mach == mach
463 && hint_arch_choice != NULL
464 && hint_arch_choice->bfd_mach == hint_bfd_mach)
465 return hint_arch_choice;
466
467 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
468 {
469 if (mips_arch_choices[i].bfd_mach_valid
470 && mips_arch_choices[i].bfd_mach == mach)
471 {
472 c = &mips_arch_choices[i];
473 hint_bfd_mach = mach;
474 hint_arch_choice = c;
475 }
476 }
477 return c;
478}
479
480void
481set_default_mips_dis_options (info)
482 struct disassemble_info *info;
483{
484 const struct mips_arch_choice *chosen_arch;
485
486 /* Defaults: mipsIII/r3000 (?!), (o)32-style ("oldabi") GPR names,
af7ee8bf 487 and numeric FPR, CP0 register, and HWR names. */
640c0ccd
CD
488 mips_isa = ISA_MIPS3;
489 mips_processor = CPU_R3000;
490 mips_gpr_names = mips_gpr_names_oldabi;
491 mips_fpr_names = mips_fpr_names_numeric;
492 mips_cp0_names = mips_cp0_names_numeric;
bbcc0807
CD
493 mips_cp0sel_names = NULL;
494 mips_cp0sel_names_len = 0;
af7ee8bf 495 mips_hwr_names = mips_hwr_names_numeric;
640c0ccd
CD
496
497 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
498 if (info->flavour == bfd_target_elf_flavour && info->symbols != NULL)
499 {
500 Elf_Internal_Ehdr *header;
501
502 header = elf_elfheader (bfd_asymbol_bfd (*(info->symbols)));
503 if (is_newabi (header))
504 mips_gpr_names = mips_gpr_names_newabi;
505 }
506
507 /* Set ISA, architecture, and cp0 register names as best we can. */
508#if ! SYMTAB_AVAILABLE
509 /* This is running out on a target machine, not in a host tool.
510 FIXME: Where does mips_target_info come from? */
511 target_processor = mips_target_info.processor;
512 mips_isa = mips_target_info.isa;
513#else
514 chosen_arch = choose_arch_by_number (info->mach);
515 if (chosen_arch != NULL)
516 {
517 mips_processor = chosen_arch->processor;
518 mips_isa = chosen_arch->isa;
bbcc0807
CD
519 mips_cp0_names = chosen_arch->cp0_names;
520 mips_cp0sel_names = chosen_arch->cp0sel_names;
521 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
522 mips_hwr_names = chosen_arch->hwr_names;
640c0ccd
CD
523 }
524#endif
525}
526
527void
528parse_mips_dis_option (option, len)
529 const char *option;
530 unsigned int len;
531{
532 unsigned int i, optionlen, vallen;
533 const char *val;
534 const struct mips_abi_choice *chosen_abi;
535 const struct mips_arch_choice *chosen_arch;
536
537 /* Look for the = that delimits the end of the option name. */
538 for (i = 0; i < len; i++)
539 {
540 if (option[i] == '=')
541 break;
542 }
543 if (i == 0) /* Invalid option: no name before '='. */
544 return;
545 if (i == len) /* Invalid option: no '='. */
546 return;
547 if (i == (len - 1)) /* Invalid option: no value after '='. */
548 return;
549
550 optionlen = i;
551 val = option + (optionlen + 1);
552 vallen = len - (optionlen + 1);
553
554 if (strncmp("gpr-names", option, optionlen) == 0
555 && strlen("gpr-names") == optionlen)
556 {
557 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 558 if (chosen_abi != NULL)
640c0ccd
CD
559 mips_gpr_names = chosen_abi->gpr_names;
560 return;
561 }
562
563 if (strncmp("fpr-names", option, optionlen) == 0
564 && strlen("fpr-names") == optionlen)
565 {
566 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 567 if (chosen_abi != NULL)
640c0ccd
CD
568 mips_fpr_names = chosen_abi->fpr_names;
569 return;
570 }
571
572 if (strncmp("cp0-names", option, optionlen) == 0
573 && strlen("cp0-names") == optionlen)
574 {
575 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807
CD
576 if (chosen_arch != NULL)
577 {
578 mips_cp0_names = chosen_arch->cp0_names;
579 mips_cp0sel_names = chosen_arch->cp0sel_names;
580 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
581 }
640c0ccd
CD
582 return;
583 }
584
af7ee8bf
CD
585 if (strncmp("hwr-names", option, optionlen) == 0
586 && strlen("hwr-names") == optionlen)
587 {
588 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807 589 if (chosen_arch != NULL)
af7ee8bf
CD
590 mips_hwr_names = chosen_arch->hwr_names;
591 return;
592 }
593
640c0ccd
CD
594 if (strncmp("reg-names", option, optionlen) == 0
595 && strlen("reg-names") == optionlen)
596 {
597 /* We check both ABI and ARCH here unconditionally, so
598 that "numeric" will do the desirable thing: select
599 numeric register names for all registers. Other than
600 that, a given name probably won't match both. */
601 chosen_abi = choose_abi_by_name (val, vallen);
602 if (chosen_abi != NULL)
603 {
bbcc0807
CD
604 mips_gpr_names = chosen_abi->gpr_names;
605 mips_fpr_names = chosen_abi->fpr_names;
640c0ccd
CD
606 }
607 chosen_arch = choose_arch_by_name (val, vallen);
608 if (chosen_arch != NULL)
609 {
bbcc0807
CD
610 mips_cp0_names = chosen_arch->cp0_names;
611 mips_cp0sel_names = chosen_arch->cp0sel_names;
612 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
613 mips_hwr_names = chosen_arch->hwr_names;
640c0ccd
CD
614 }
615 return;
616 }
617
618 /* Invalid option. */
619}
620
621void
622parse_mips_dis_options (options)
623 const char *options;
624{
625 const char *option_end;
626
627 if (options == NULL)
628 return;
629
630 while (*options != '\0')
631 {
632 /* Skip empty options. */
633 if (*options == ',')
634 {
635 options++;
636 continue;
637 }
638
639 /* We know that *options is neither NUL or a comma. */
640 option_end = options + 1;
641 while (*option_end != ',' && *option_end != '\0')
642 option_end++;
643
644 parse_mips_dis_option (options, option_end - options);
645
646 /* Go on to the next one. If option_end points to a comma, it
647 will be skipped above. */
648 options = option_end;
649 }
650}
651
bbcc0807
CD
652static const struct mips_cp0sel_name *
653lookup_mips_cp0sel_name(names, len, cp0reg, sel)
654 const struct mips_cp0sel_name *names;
655 unsigned int len, cp0reg, sel;
656{
657 unsigned int i;
658
659 for (i = 0; i < len; i++)
660 if (names[i].cp0reg == cp0reg && names[i].sel == sel)
661 return &names[i];
662 return NULL;
663}
252b5132 664\f
7f6621cd 665/* Print insn arguments for 32/64-bit code. */
aa5f19f2 666
af7ee8bf 667static int
252b5132
RH
668print_insn_arg (d, l, pc, info)
669 const char *d;
670 register unsigned long int l;
671 bfd_vma pc;
672 struct disassemble_info *info;
673{
af7ee8bf 674 int op, delta, consumed;
252b5132 675
af7ee8bf 676 consumed = 1;
252b5132
RH
677 switch (*d)
678 {
679 case ',':
680 case '(':
681 case ')':
9752cf1b
RS
682 case '[':
683 case ']':
252b5132
RH
684 (*info->fprintf_func) (info->stream, "%c", *d);
685 break;
686
af7ee8bf
CD
687 case '+':
688 /* Extension character; switch for second char. */
689 d++;
690 consumed++;
691 switch (*d)
692 {
693 case 'A':
694 (*info->fprintf_func) (info->stream, "0x%x",
695 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
696 break;
697
698 case 'B':
699 (*info->fprintf_func) (info->stream, "0x%x",
700 (((l >> OP_SH_INSMSB) & OP_MASK_INSMSB)
701 - ((l >> OP_SH_SHAMT) & OP_MASK_SHAMT)
702 + 1));
703 break;
704
705 case 'C':
706 (*info->fprintf_func) (info->stream, "0x%x",
707 (((l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD)
708 + 1));
709 break;
710
bbcc0807
CD
711 case 'D':
712 {
713 const struct mips_cp0sel_name *n;
714 unsigned int cp0reg, sel;
715
716 cp0reg = (l >> OP_SH_RD) & OP_MASK_RD;
717 sel = (l >> OP_SH_SEL) & OP_MASK_SEL;
718
719 /* CP0 register including 'sel' code for mtcN (et al.), to be
720 printed textually if known. If not known, print both
721 CP0 register name and sel numerically since CP0 register
722 with sel 0 may have a name unrelated to register being
723 printed. */
724 n = lookup_mips_cp0sel_name(mips_cp0sel_names,
725 mips_cp0sel_names_len, cp0reg, sel);
726 if (n != NULL)
727 (*info->fprintf_func) (info->stream, "%s", n->name);
728 else
729 (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel);
730 break;
731 }
732
af7ee8bf
CD
733 default:
734 /* xgettext:c-format */
735 (*info->fprintf_func) (info->stream,
736 _("# internal error, undefined extension sequence (+%c)"),
737 *d);
738 /* Do not eat the trailing newline. */
739 if (*d == '\0')
740 consumed--;
741 break;
742 }
743 break;
744
252b5132
RH
745 case 's':
746 case 'b':
747 case 'r':
748 case 'v':
aa5f19f2 749 (*info->fprintf_func) (info->stream, "%s",
640c0ccd 750 mips_gpr_names[(l >> OP_SH_RS) & OP_MASK_RS]);
252b5132
RH
751 break;
752
753 case 't':
754 case 'w':
aa5f19f2 755 (*info->fprintf_func) (info->stream, "%s",
640c0ccd 756 mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
252b5132
RH
757 break;
758
759 case 'i':
760 case 'u':
761 (*info->fprintf_func) (info->stream, "0x%x",
7f6621cd 762 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
252b5132
RH
763 break;
764
7f6621cd 765 case 'j': /* Same as i, but sign-extended. */
252b5132
RH
766 case 'o':
767 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
768 if (delta & 0x8000)
769 delta |= ~0xffff;
770 (*info->fprintf_func) (info->stream, "%d",
771 delta);
772 break;
773
774 case 'h':
775 (*info->fprintf_func) (info->stream, "0x%x",
776 (unsigned int) ((l >> OP_SH_PREFX)
777 & OP_MASK_PREFX));
778 break;
779
780 case 'k':
781 (*info->fprintf_func) (info->stream, "0x%x",
782 (unsigned int) ((l >> OP_SH_CACHE)
783 & OP_MASK_CACHE));
784 break;
785
786 case 'a':
9bb28706
CD
787 info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
788 | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2));
789 (*info->print_address_func) (info->target, info);
252b5132
RH
790 break;
791
792 case 'p':
7f6621cd 793 /* Sign extend the displacement. */
252b5132
RH
794 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
795 if (delta & 0x8000)
796 delta |= ~0xffff;
9bb28706
CD
797 info->target = (delta << 2) + pc + INSNLEN;
798 (*info->print_address_func) (info->target, info);
252b5132
RH
799 break;
800
801 case 'd':
aa5f19f2 802 (*info->fprintf_func) (info->stream, "%s",
640c0ccd 803 mips_gpr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
252b5132
RH
804 break;
805
4372b673
NC
806 case 'U':
807 {
7f6621cd
KH
808 /* First check for both rd and rt being equal. */
809 unsigned int reg = (l >> OP_SH_RD) & OP_MASK_RD;
810 if (reg == ((l >> OP_SH_RT) & OP_MASK_RT))
811 (*info->fprintf_func) (info->stream, "%s",
640c0ccd 812 mips_gpr_names[reg]);
7f6621cd
KH
813 else
814 {
815 /* If one is zero use the other. */
816 if (reg == 0)
817 (*info->fprintf_func) (info->stream, "%s",
640c0ccd 818 mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
7f6621cd
KH
819 else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0)
820 (*info->fprintf_func) (info->stream, "%s",
640c0ccd 821 mips_gpr_names[reg]);
7f6621cd
KH
822 else /* Bogus, result depends on processor. */
823 (*info->fprintf_func) (info->stream, "%s or %s",
640c0ccd
CD
824 mips_gpr_names[reg],
825 mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
7f6621cd 826 }
4372b673
NC
827 }
828 break;
829
252b5132 830 case 'z':
640c0ccd 831 (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]);
252b5132
RH
832 break;
833
834 case '<':
835 (*info->fprintf_func) (info->stream, "0x%x",
836 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
837 break;
838
839 case 'c':
840 (*info->fprintf_func) (info->stream, "0x%x",
841 (l >> OP_SH_CODE) & OP_MASK_CODE);
842 break;
843
252b5132
RH
844 case 'q':
845 (*info->fprintf_func) (info->stream, "0x%x",
846 (l >> OP_SH_CODE2) & OP_MASK_CODE2);
847 break;
848
849 case 'C':
850 (*info->fprintf_func) (info->stream, "0x%x",
851 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
852 break;
853
854 case 'B':
855 (*info->fprintf_func) (info->stream, "0x%x",
4372b673
NC
856 (l >> OP_SH_CODE20) & OP_MASK_CODE20);
857 break;
858
859 case 'J':
860 (*info->fprintf_func) (info->stream, "0x%x",
861 (l >> OP_SH_CODE19) & OP_MASK_CODE19);
252b5132
RH
862 break;
863
864 case 'S':
865 case 'V':
640c0ccd
CD
866 (*info->fprintf_func) (info->stream, "%s",
867 mips_fpr_names[(l >> OP_SH_FS) & OP_MASK_FS]);
252b5132
RH
868 break;
869
252b5132
RH
870 case 'T':
871 case 'W':
640c0ccd
CD
872 (*info->fprintf_func) (info->stream, "%s",
873 mips_fpr_names[(l >> OP_SH_FT) & OP_MASK_FT]);
252b5132
RH
874 break;
875
876 case 'D':
640c0ccd
CD
877 (*info->fprintf_func) (info->stream, "%s",
878 mips_fpr_names[(l >> OP_SH_FD) & OP_MASK_FD]);
252b5132
RH
879 break;
880
881 case 'R':
640c0ccd
CD
882 (*info->fprintf_func) (info->stream, "%s",
883 mips_fpr_names[(l >> OP_SH_FR) & OP_MASK_FR]);
252b5132
RH
884 break;
885
886 case 'E':
640c0ccd
CD
887 /* Coprocessor register for lwcN instructions, et al.
888
889 Note that there is no load/store cp0 instructions, and
890 that FPU (cp1) instructions disassemble this field using
891 'T' format. Therefore, until we gain understanding of
892 cp2 register names,
893 we can simply print the register numbers. */
21d34b1c
TS
894 (*info->fprintf_func) (info->stream, "$%d",
895 (l >> OP_SH_RT) & OP_MASK_RT);
252b5132
RH
896 break;
897
898 case 'G':
640c0ccd
CD
899 /* Coprocessor register for mtcN instructions, et al.
900 Note that FPU (cp1) instructions disassemble this field using
901 'S' format. Therefore, we only need to worry about cp0, cp2,
902 and cp3. */
903 op = (l >> OP_SH_OP) & OP_MASK_OP;
904 if (op == OP_OP_COP0)
905 (*info->fprintf_func) (info->stream, "%s",
906 mips_cp0_names[(l >> OP_SH_RD) & OP_MASK_RD]);
907 else
908 (*info->fprintf_func) (info->stream, "$%d",
909 (l >> OP_SH_RD) & OP_MASK_RD);
252b5132
RH
910 break;
911
af7ee8bf
CD
912 case 'K':
913 (*info->fprintf_func) (info->stream, "%s",
914 mips_hwr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
915 break;
916
252b5132
RH
917 case 'N':
918 (*info->fprintf_func) (info->stream, "$fcc%d",
919 (l >> OP_SH_BCC) & OP_MASK_BCC);
920 break;
921
922 case 'M':
923 (*info->fprintf_func) (info->stream, "$fcc%d",
924 (l >> OP_SH_CCC) & OP_MASK_CCC);
925 break;
926
927 case 'P':
928 (*info->fprintf_func) (info->stream, "%d",
929 (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
930 break;
931
9752cf1b
RS
932 case 'e':
933 (*info->fprintf_func) (info->stream, "%d",
934 (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE);
935 break;
936
937 case '%':
938 (*info->fprintf_func) (info->stream, "%d",
939 (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN);
940 break;
941
156c2f8b 942 case 'H':
e93d7199 943 (*info->fprintf_func) (info->stream, "%d",
156c2f8b
NC
944 (l >> OP_SH_SEL) & OP_MASK_SEL);
945 break;
252b5132 946
deec1734
CD
947 case 'O':
948 (*info->fprintf_func) (info->stream, "%d",
949 (l >> OP_SH_ALN) & OP_MASK_ALN);
950 break;
951
952 case 'Q':
953 {
954 unsigned int vsel = (l >> OP_SH_VSEL) & OP_MASK_VSEL;
955 if ((vsel & 0x10) == 0)
956 {
957 int fmt;
958 vsel &= 0x0f;
959 for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
960 if ((vsel & 1) == 0)
961 break;
962 (*info->fprintf_func) (info->stream, "$v%d[%d]",
b34976b6 963 (l >> OP_SH_FT) & OP_MASK_FT,
deec1734
CD
964 vsel >> 1);
965 }
966 else if ((vsel & 0x08) == 0)
967 {
968 (*info->fprintf_func) (info->stream, "$v%d",
969 (l >> OP_SH_FT) & OP_MASK_FT);
970 }
971 else
972 {
973 (*info->fprintf_func) (info->stream, "0x%x",
974 (l >> OP_SH_FT) & OP_MASK_FT);
975 }
976 }
977 break;
978
979 case 'X':
980 (*info->fprintf_func) (info->stream, "$v%d",
981 (l >> OP_SH_FD) & OP_MASK_FD);
982 break;
983
984 case 'Y':
985 (*info->fprintf_func) (info->stream, "$v%d",
986 (l >> OP_SH_FS) & OP_MASK_FS);
987 break;
988
989 case 'Z':
990 (*info->fprintf_func) (info->stream, "$v%d",
991 (l >> OP_SH_FT) & OP_MASK_FT);
992 break;
993
252b5132
RH
994 default:
995 /* xgettext:c-format */
996 (*info->fprintf_func) (info->stream,
997 _("# internal error, undefined modifier(%c)"),
998 *d);
999 break;
1000 }
af7ee8bf
CD
1001
1002 return consumed;
252b5132
RH
1003}
1004\f
21d34b1c 1005/* Check if the object uses NewABI conventions. */
aa5f19f2
NC
1006
1007static int
7f6621cd 1008is_newabi (header)
21d34b1c 1009 Elf_Internal_Ehdr *header;
aa5f19f2 1010{
4c563ebf
CD
1011 /* There are no old-style ABIs which use 64-bit ELF. */
1012 if (header->e_ident[EI_CLASS] == ELFCLASS64)
1013 return 1;
1014
563773fe
TS
1015 /* If a 32-bit ELF file, n32 is a new-style ABI. */
1016 if ((header->e_flags & EF_MIPS_ABI2) != 0)
21d34b1c 1017 return 1;
252b5132 1018
21d34b1c 1019 return 0;
aa5f19f2
NC
1020}
1021\f
252b5132
RH
1022/* Print the mips instruction at address MEMADDR in debugged memory,
1023 on using INFO. Returns length of the instruction, in bytes, which is
aa5f19f2 1024 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
252b5132
RH
1025 this is little-endian code. */
1026
1027static int
aa5f19f2 1028print_insn_mips (memaddr, word, info)
252b5132
RH
1029 bfd_vma memaddr;
1030 unsigned long int word;
1031 struct disassemble_info *info;
1032{
1033 register const struct mips_opcode *op;
b34976b6 1034 static bfd_boolean init = 0;
252b5132
RH
1035 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
1036
1037 /* Build a hash table to shorten the search time. */
1038 if (! init)
1039 {
1040 unsigned int i;
1041
1042 for (i = 0; i <= OP_MASK_OP; i++)
1043 {
1044 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
1045 {
1046 if (op->pinfo == INSN_MACRO)
1047 continue;
1048 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
1049 {
1050 mips_hash[i] = op;
1051 break;
1052 }
1053 }
7f6621cd 1054 }
252b5132
RH
1055
1056 init = 1;
1057 }
1058
aa5f19f2 1059 info->bytes_per_chunk = INSNLEN;
252b5132 1060 info->display_endian = info->endian;
9bb28706
CD
1061 info->insn_info_valid = 1;
1062 info->branch_delay_insns = 0;
def7143b 1063 info->data_size = 0;
9bb28706
CD
1064 info->insn_type = dis_nonbranch;
1065 info->target = 0;
1066 info->target2 = 0;
252b5132
RH
1067
1068 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
1069 if (op != NULL)
1070 {
1071 for (; op < &mips_opcodes[NUMOPCODES]; op++)
1072 {
1073 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
1074 {
1075 register const char *d;
2bd7f1f3 1076
3396de36 1077 /* We always allow to disassemble the jalx instruction. */
640c0ccd 1078 if (! OPCODE_IS_MEMBER (op, mips_isa, mips_processor)
3396de36 1079 && strcmp (op->name, "jalx"))
252b5132
RH
1080 continue;
1081
9bb28706
CD
1082 /* Figure out instruction type and branch delay information. */
1083 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
1084 {
1085 if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
1086 info->insn_type = dis_jsr;
1087 else
1088 info->insn_type = dis_branch;
1089 info->branch_delay_insns = 1;
1090 }
1091 else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
1092 | INSN_COND_BRANCH_LIKELY)) != 0)
1093 {
1094 if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
1095 info->insn_type = dis_condjsr;
1096 else
1097 info->insn_type = dis_condbranch;
1098 info->branch_delay_insns = 1;
1099 }
1100 else if ((op->pinfo & (INSN_STORE_MEMORY
1101 | INSN_LOAD_MEMORY_DELAY)) != 0)
1102 info->insn_type = dis_dref;
1103
252b5132
RH
1104 (*info->fprintf_func) (info->stream, "%s", op->name);
1105
1106 d = op->args;
1107 if (d != NULL && *d != '\0')
1108 {
af7ee8bf
CD
1109 int consumed;
1110
7f6621cd 1111 (*info->fprintf_func) (info->stream, "\t");
af7ee8bf
CD
1112 while (*d != '\0')
1113 {
1114 /* print_insn_arg will not eat the trailing NUL
1115 of (erroneous) multi-character strings. */
1116 consumed = print_insn_arg (d, word, memaddr, info);
1117 d += consumed;
1118 }
252b5132
RH
1119 }
1120
aa5f19f2 1121 return INSNLEN;
252b5132
RH
1122 }
1123 }
1124 }
1125
1126 /* Handle undefined instructions. */
9bb28706 1127 info->insn_type = dis_noninsn;
252b5132 1128 (*info->fprintf_func) (info->stream, "0x%x", word);
aa5f19f2 1129 return INSNLEN;
252b5132 1130}
aa5f19f2 1131\f
252b5132
RH
1132/* In an environment where we do not know the symbol type of the
1133 instruction we are forced to assume that the low order bit of the
1134 instructions' address may mark it as a mips16 instruction. If we
1135 are single stepping, or the pc is within the disassembled function,
1136 this works. Otherwise, we need a clue. Sometimes. */
1137
aa5f19f2
NC
1138static int
1139_print_insn_mips (memaddr, info, endianness)
252b5132
RH
1140 bfd_vma memaddr;
1141 struct disassemble_info *info;
aa5f19f2 1142 enum bfd_endian endianness;
252b5132 1143{
aa5f19f2 1144 bfd_byte buffer[INSNLEN];
252b5132
RH
1145 int status;
1146
640c0ccd
CD
1147 set_default_mips_dis_options (info);
1148 parse_mips_dis_options (info->disassembler_options);
1149
252b5132
RH
1150#if 1
1151 /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */
1152 /* Only a few tools will work this way. */
1153 if (memaddr & 0x01)
1154 return print_insn_mips16 (memaddr, info);
e93d7199 1155#endif
252b5132
RH
1156
1157#if SYMTAB_AVAILABLE
53f32ea5 1158 if (info->mach == bfd_mach_mips16
252b5132
RH
1159 || (info->flavour == bfd_target_elf_flavour
1160 && info->symbols != NULL
1161 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
1162 == STO_MIPS16)))
1163 return print_insn_mips16 (memaddr, info);
e93d7199 1164#endif
252b5132 1165
aa5f19f2 1166 status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
252b5132 1167 if (status == 0)
aa5f19f2
NC
1168 {
1169 unsigned long insn;
1170
1171 if (endianness == BFD_ENDIAN_BIG)
7f6621cd 1172 insn = (unsigned long) bfd_getb32 (buffer);
aa5f19f2
NC
1173 else
1174 insn = (unsigned long) bfd_getl32 (buffer);
1175
1176 return print_insn_mips (memaddr, insn, info);
1177 }
252b5132
RH
1178 else
1179 {
1180 (*info->memory_error_func) (status, memaddr, info);
1181 return -1;
1182 }
1183}
1184
1185int
aa5f19f2 1186print_insn_big_mips (memaddr, info)
252b5132
RH
1187 bfd_vma memaddr;
1188 struct disassemble_info *info;
1189{
aa5f19f2
NC
1190 return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
1191}
252b5132 1192
aa5f19f2
NC
1193int
1194print_insn_little_mips (memaddr, info)
1195 bfd_vma memaddr;
1196 struct disassemble_info *info;
1197{
1198 return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
252b5132
RH
1199}
1200\f
1201/* Disassemble mips16 instructions. */
1202
1203static int
1204print_insn_mips16 (memaddr, info)
1205 bfd_vma memaddr;
1206 struct disassemble_info *info;
1207{
1208 int status;
1209 bfd_byte buffer[2];
1210 int length;
1211 int insn;
b34976b6 1212 bfd_boolean use_extend;
252b5132
RH
1213 int extend = 0;
1214 const struct mips_opcode *op, *opend;
1215
1216 info->bytes_per_chunk = 2;
1217 info->display_endian = info->endian;
252b5132
RH
1218 info->insn_info_valid = 1;
1219 info->branch_delay_insns = 0;
1220 info->data_size = 0;
1221 info->insn_type = dis_nonbranch;
1222 info->target = 0;
1223 info->target2 = 0;
1224
1225 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
1226 if (status != 0)
1227 {
1228 (*info->memory_error_func) (status, memaddr, info);
1229 return -1;
1230 }
1231
1232 length = 2;
1233
1234 if (info->endian == BFD_ENDIAN_BIG)
1235 insn = bfd_getb16 (buffer);
1236 else
1237 insn = bfd_getl16 (buffer);
1238
1239 /* Handle the extend opcode specially. */
b34976b6 1240 use_extend = FALSE;
252b5132
RH
1241 if ((insn & 0xf800) == 0xf000)
1242 {
b34976b6 1243 use_extend = TRUE;
252b5132
RH
1244 extend = insn & 0x7ff;
1245
1246 memaddr += 2;
1247
1248 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
1249 if (status != 0)
1250 {
1251 (*info->fprintf_func) (info->stream, "extend 0x%x",
1252 (unsigned int) extend);
1253 (*info->memory_error_func) (status, memaddr, info);
1254 return -1;
1255 }
1256
1257 if (info->endian == BFD_ENDIAN_BIG)
1258 insn = bfd_getb16 (buffer);
1259 else
1260 insn = bfd_getl16 (buffer);
1261
1262 /* Check for an extend opcode followed by an extend opcode. */
1263 if ((insn & 0xf800) == 0xf000)
1264 {
1265 (*info->fprintf_func) (info->stream, "extend 0x%x",
1266 (unsigned int) extend);
1267 info->insn_type = dis_noninsn;
1268 return length;
1269 }
1270
1271 length += 2;
1272 }
1273
1274 /* FIXME: Should probably use a hash table on the major opcode here. */
1275
1276 opend = mips16_opcodes + bfd_mips16_num_opcodes;
1277 for (op = mips16_opcodes; op < opend; op++)
1278 {
1279 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
1280 {
1281 const char *s;
1282
1283 if (strchr (op->args, 'a') != NULL)
1284 {
1285 if (use_extend)
1286 {
1287 (*info->fprintf_func) (info->stream, "extend 0x%x",
1288 (unsigned int) extend);
1289 info->insn_type = dis_noninsn;
1290 return length - 2;
1291 }
1292
b34976b6 1293 use_extend = FALSE;
252b5132
RH
1294
1295 memaddr += 2;
1296
1297 status = (*info->read_memory_func) (memaddr, buffer, 2,
1298 info);
1299 if (status == 0)
1300 {
b34976b6 1301 use_extend = TRUE;
252b5132
RH
1302 if (info->endian == BFD_ENDIAN_BIG)
1303 extend = bfd_getb16 (buffer);
1304 else
1305 extend = bfd_getl16 (buffer);
1306 length += 2;
1307 }
1308 }
1309
1310 (*info->fprintf_func) (info->stream, "%s", op->name);
1311 if (op->args[0] != '\0')
1312 (*info->fprintf_func) (info->stream, "\t");
1313
1314 for (s = op->args; *s != '\0'; s++)
1315 {
1316 if (*s == ','
1317 && s[1] == 'w'
1318 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
1319 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
1320 {
1321 /* Skip the register and the comma. */
1322 ++s;
1323 continue;
1324 }
1325 if (*s == ','
1326 && s[1] == 'v'
1327 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
1328 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
1329 {
1330 /* Skip the register and the comma. */
1331 ++s;
1332 continue;
1333 }
1334 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
1335 info);
1336 }
1337
1338 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
1339 {
1340 info->branch_delay_insns = 1;
1341 if (info->insn_type != dis_jsr)
1342 info->insn_type = dis_branch;
1343 }
1344
1345 return length;
1346 }
1347 }
1348
1349 if (use_extend)
1350 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
1351 (*info->fprintf_func) (info->stream, "0x%x", insn);
1352 info->insn_type = dis_noninsn;
1353
1354 return length;
1355}
1356
1357/* Disassemble an operand for a mips16 instruction. */
1358
1359static void
1360print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
aa5f19f2 1361 char type;
252b5132
RH
1362 const struct mips_opcode *op;
1363 int l;
b34976b6 1364 bfd_boolean use_extend;
252b5132
RH
1365 int extend;
1366 bfd_vma memaddr;
1367 struct disassemble_info *info;
1368{
1369 switch (type)
1370 {
1371 case ',':
1372 case '(':
1373 case ')':
1374 (*info->fprintf_func) (info->stream, "%c", type);
1375 break;
1376
1377 case 'y':
1378 case 'w':
aa5f19f2 1379 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
1380 mips16_reg_names[((l >> MIPS16OP_SH_RY)
1381 & MIPS16OP_MASK_RY)]);
1382 break;
1383
1384 case 'x':
1385 case 'v':
aa5f19f2 1386 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
1387 mips16_reg_names[((l >> MIPS16OP_SH_RX)
1388 & MIPS16OP_MASK_RX)]);
1389 break;
1390
1391 case 'z':
aa5f19f2 1392 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
1393 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
1394 & MIPS16OP_MASK_RZ)]);
1395 break;
1396
1397 case 'Z':
aa5f19f2 1398 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
1399 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
1400 & MIPS16OP_MASK_MOVE32Z)]);
1401 break;
1402
1403 case '0':
640c0ccd 1404 (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]);
252b5132
RH
1405 break;
1406
1407 case 'S':
640c0ccd 1408 (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[29]);
252b5132
RH
1409 break;
1410
1411 case 'P':
1412 (*info->fprintf_func) (info->stream, "$pc");
1413 break;
1414
1415 case 'R':
640c0ccd 1416 (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[31]);
252b5132
RH
1417 break;
1418
1419 case 'X':
aa5f19f2 1420 (*info->fprintf_func) (info->stream, "%s",
640c0ccd
CD
1421 mips_gpr_names[((l >> MIPS16OP_SH_REGR32)
1422 & MIPS16OP_MASK_REGR32)]);
252b5132
RH
1423 break;
1424
1425 case 'Y':
aa5f19f2 1426 (*info->fprintf_func) (info->stream, "%s",
640c0ccd 1427 mips_gpr_names[MIPS16OP_EXTRACT_REG32R (l)]);
252b5132
RH
1428 break;
1429
1430 case '<':
1431 case '>':
1432 case '[':
1433 case ']':
1434 case '4':
1435 case '5':
1436 case 'H':
1437 case 'W':
1438 case 'D':
1439 case 'j':
1440 case '6':
1441 case '8':
1442 case 'V':
1443 case 'C':
1444 case 'U':
1445 case 'k':
1446 case 'K':
1447 case 'p':
1448 case 'q':
1449 case 'A':
1450 case 'B':
1451 case 'E':
1452 {
1453 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
1454
1455 shift = 0;
1456 signedp = 0;
1457 extbits = 16;
1458 pcrel = 0;
1459 extu = 0;
1460 branch = 0;
1461 switch (type)
1462 {
1463 case '<':
1464 nbits = 3;
1465 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
1466 extbits = 5;
1467 extu = 1;
1468 break;
1469 case '>':
1470 nbits = 3;
1471 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
1472 extbits = 5;
1473 extu = 1;
1474 break;
1475 case '[':
1476 nbits = 3;
1477 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
1478 extbits = 6;
1479 extu = 1;
1480 break;
1481 case ']':
1482 nbits = 3;
1483 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
1484 extbits = 6;
1485 extu = 1;
1486 break;
1487 case '4':
1488 nbits = 4;
1489 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
1490 signedp = 1;
1491 extbits = 15;
1492 break;
1493 case '5':
1494 nbits = 5;
1495 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1496 info->insn_type = dis_dref;
1497 info->data_size = 1;
1498 break;
1499 case 'H':
1500 nbits = 5;
1501 shift = 1;
1502 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1503 info->insn_type = dis_dref;
1504 info->data_size = 2;
1505 break;
1506 case 'W':
1507 nbits = 5;
1508 shift = 2;
1509 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1510 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
1511 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
1512 {
1513 info->insn_type = dis_dref;
1514 info->data_size = 4;
1515 }
1516 break;
1517 case 'D':
1518 nbits = 5;
1519 shift = 3;
1520 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1521 info->insn_type = dis_dref;
1522 info->data_size = 8;
1523 break;
1524 case 'j':
1525 nbits = 5;
1526 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1527 signedp = 1;
1528 break;
1529 case '6':
1530 nbits = 6;
1531 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1532 break;
1533 case '8':
1534 nbits = 8;
1535 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1536 break;
1537 case 'V':
1538 nbits = 8;
1539 shift = 2;
1540 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1541 /* FIXME: This might be lw, or it might be addiu to $sp or
1542 $pc. We assume it's load. */
1543 info->insn_type = dis_dref;
1544 info->data_size = 4;
1545 break;
1546 case 'C':
1547 nbits = 8;
1548 shift = 3;
1549 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1550 info->insn_type = dis_dref;
1551 info->data_size = 8;
1552 break;
1553 case 'U':
1554 nbits = 8;
1555 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1556 extu = 1;
1557 break;
1558 case 'k':
1559 nbits = 8;
1560 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1561 signedp = 1;
1562 break;
1563 case 'K':
1564 nbits = 8;
1565 shift = 3;
1566 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1567 signedp = 1;
1568 break;
1569 case 'p':
1570 nbits = 8;
1571 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1572 signedp = 1;
1573 pcrel = 1;
1574 branch = 1;
1575 info->insn_type = dis_condbranch;
1576 break;
1577 case 'q':
1578 nbits = 11;
1579 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
1580 signedp = 1;
1581 pcrel = 1;
1582 branch = 1;
1583 info->insn_type = dis_branch;
1584 break;
1585 case 'A':
1586 nbits = 8;
1587 shift = 2;
1588 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1589 pcrel = 1;
1590 /* FIXME: This can be lw or la. We assume it is lw. */
1591 info->insn_type = dis_dref;
1592 info->data_size = 4;
1593 break;
1594 case 'B':
1595 nbits = 5;
1596 shift = 3;
1597 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1598 pcrel = 1;
1599 info->insn_type = dis_dref;
1600 info->data_size = 8;
1601 break;
1602 case 'E':
1603 nbits = 5;
1604 shift = 2;
1605 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1606 pcrel = 1;
1607 break;
1608 default:
1609 abort ();
1610 }
1611
1612 if (! use_extend)
1613 {
1614 if (signedp && immed >= (1 << (nbits - 1)))
1615 immed -= 1 << nbits;
1616 immed <<= shift;
1617 if ((type == '<' || type == '>' || type == '[' || type == ']')
1618 && immed == 0)
1619 immed = 8;
1620 }
1621 else
1622 {
1623 if (extbits == 16)
1624 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1625 else if (extbits == 15)
1626 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1627 else
1628 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1629 immed &= (1 << extbits) - 1;
1630 if (! extu && immed >= (1 << (extbits - 1)))
1631 immed -= 1 << extbits;
1632 }
1633
1634 if (! pcrel)
1635 (*info->fprintf_func) (info->stream, "%d", immed);
1636 else
1637 {
1638 bfd_vma baseaddr;
252b5132
RH
1639
1640 if (branch)
1641 {
1642 immed *= 2;
1643 baseaddr = memaddr + 2;
1644 }
1645 else if (use_extend)
1646 baseaddr = memaddr - 2;
1647 else
1648 {
1649 int status;
1650 bfd_byte buffer[2];
1651
1652 baseaddr = memaddr;
1653
1654 /* If this instruction is in the delay slot of a jr
1655 instruction, the base address is the address of the
1656 jr instruction. If it is in the delay slot of jalr
1657 instruction, the base address is the address of the
1658 jalr instruction. This test is unreliable: we have
1659 no way of knowing whether the previous word is
1660 instruction or data. */
1661 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
1662 info);
1663 if (status == 0
1664 && (((info->endian == BFD_ENDIAN_BIG
1665 ? bfd_getb16 (buffer)
1666 : bfd_getl16 (buffer))
1667 & 0xf800) == 0x1800))
1668 baseaddr = memaddr - 4;
1669 else
1670 {
1671 status = (*info->read_memory_func) (memaddr - 2, buffer,
1672 2, info);
1673 if (status == 0
1674 && (((info->endian == BFD_ENDIAN_BIG
1675 ? bfd_getb16 (buffer)
1676 : bfd_getl16 (buffer))
1677 & 0xf81f) == 0xe800))
1678 baseaddr = memaddr - 2;
1679 }
1680 }
9bb28706
CD
1681 info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
1682 (*info->print_address_func) (info->target, info);
252b5132
RH
1683 }
1684 }
1685 break;
1686
1687 case 'a':
1688 if (! use_extend)
1689 extend = 0;
1690 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
9bb28706
CD
1691 info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
1692 (*info->print_address_func) (info->target, info);
252b5132 1693 info->insn_type = dis_jsr;
252b5132
RH
1694 info->branch_delay_insns = 1;
1695 break;
1696
1697 case 'l':
1698 case 'L':
1699 {
1700 int need_comma, amask, smask;
1701
1702 need_comma = 0;
1703
1704 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1705
1706 amask = (l >> 3) & 7;
1707
1708 if (amask > 0 && amask < 5)
1709 {
640c0ccd 1710 (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]);
252b5132 1711 if (amask > 1)
aa5f19f2 1712 (*info->fprintf_func) (info->stream, "-%s",
640c0ccd 1713 mips_gpr_names[amask + 3]);
252b5132
RH
1714 need_comma = 1;
1715 }
1716
1717 smask = (l >> 1) & 3;
1718 if (smask == 3)
1719 {
1720 (*info->fprintf_func) (info->stream, "%s??",
1721 need_comma ? "," : "");
1722 need_comma = 1;
1723 }
1724 else if (smask > 0)
1725 {
aa5f19f2 1726 (*info->fprintf_func) (info->stream, "%s%s",
252b5132 1727 need_comma ? "," : "",
640c0ccd 1728 mips_gpr_names[16]);
252b5132 1729 if (smask > 1)
aa5f19f2 1730 (*info->fprintf_func) (info->stream, "-%s",
640c0ccd 1731 mips_gpr_names[smask + 15]);
252b5132
RH
1732 need_comma = 1;
1733 }
1734
1735 if (l & 1)
1736 {
aa5f19f2 1737 (*info->fprintf_func) (info->stream, "%s%s",
252b5132 1738 need_comma ? "," : "",
640c0ccd 1739 mips_gpr_names[31]);
252b5132
RH
1740 need_comma = 1;
1741 }
1742
1743 if (amask == 5 || amask == 6)
1744 {
1745 (*info->fprintf_func) (info->stream, "%s$f0",
1746 need_comma ? "," : "");
1747 if (amask == 6)
1748 (*info->fprintf_func) (info->stream, "-$f1");
1749 }
1750 }
1751 break;
1752
1753 default:
aa5f19f2
NC
1754 /* xgettext:c-format */
1755 (*info->fprintf_func)
1756 (info->stream,
1757 _("# internal disassembler error, unrecognised modifier (%c)"),
1758 type);
252b5132
RH
1759 abort ();
1760 }
1761}
640c0ccd
CD
1762
1763void
1764print_mips_disassembler_options (stream)
1765 FILE *stream;
1766{
1767 int i;
1768
1769 fprintf (stream, _("\n\
1770The following MIPS specific disassembler options are supported for use\n\
1771with the -M switch (multiple options should be separated by commas):\n"));
1772
1773 fprintf (stream, _("\n\
1774 gpr-names=ABI Print GPR names according to specified ABI.\n\
1775 Default: based on binary being disassembled.\n"));
1776
1777 fprintf (stream, _("\n\
1778 fpr-names=ABI Print FPR names according to specified ABI.\n\
1779 Default: numeric.\n"));
1780
1781 fprintf (stream, _("\n\
1782 cp0-names=ARCH Print CP0 register names according to\n\
1783 specified architecture.\n\
1784 Default: based on binary being disassembled.\n"));
1785
af7ee8bf
CD
1786 fprintf (stream, _("\n\
1787 hwr-names=ARCH Print HWR names according to specified \n\
1788 architecture.\n\
1789 Default: based on binary being disassembled.\n"));
1790
640c0ccd
CD
1791 fprintf (stream, _("\n\
1792 reg-names=ABI Print GPR and FPR names according to\n\
1793 specified ABI.\n"));
1794
1795 fprintf (stream, _("\n\
af7ee8bf 1796 reg-names=ARCH Print CP0 register and HWR names according to\n\
640c0ccd
CD
1797 specified architecture.\n"));
1798
1799 fprintf (stream, _("\n\
1800 For the options above, the following values are supported for \"ABI\":\n\
1801 "));
1802 for (i = 0; mips_abi_choices[i].name != NULL; i++)
1803 fprintf (stream, " %s", mips_abi_choices[i].name);
1804 fprintf (stream, _("\n"));
1805
1806 fprintf (stream, _("\n\
1807 For the options above, The following values are supported for \"ARCH\":\n\
1808 "));
1809 for (i = 0; mips_arch_choices[i].name != NULL; i++)
1810 if (*mips_arch_choices[i].name != '\0')
1811 fprintf (stream, " %s", mips_arch_choices[i].name);
1812 fprintf (stream, _("\n"));
1813
1814 fprintf (stream, _("\n"));
1815}