2005-01-19 Fred Fish <fnf@specifixinc.com>
[deliverable/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,
794ac9d0 3 2000, 2001, 2002, 2003
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 *));
794ac9d0 53static void print_insn_args
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",
0b14f26e 92 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
640c0ccd
CD
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 },
5a7ea749
RS
350 { "rm7000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4,
351 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
352 { "rm9000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4,
353 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 354 { "r8000", 1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4,
bbcc0807 355 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 356 { "r10000", 1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4,
bbcc0807 357 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 358 { "r12000", 1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4,
bbcc0807 359 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd 360 { "mips5", 1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5,
bbcc0807
CD
361 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
362
640c0ccd
CD
363 /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
364 Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
365 _MIPS32 Architecture For Programmers Volume I: Introduction to the
366 MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
367 page 1. */
368 { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32,
369 ISA_MIPS32 | INSN_MIPS16,
bbcc0807
CD
370 mips_cp0_names_mips3264,
371 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
372 mips_hwr_names_numeric },
373
af7ee8bf
CD
374 { "mips32r2", 1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
375 ISA_MIPS32R2 | INSN_MIPS16,
bbcc0807
CD
376 mips_cp0_names_mips3264r2,
377 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
378 mips_hwr_names_mips3264r2 },
379
640c0ccd
CD
380 /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
381 { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64,
382 ISA_MIPS64 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX,
bbcc0807
CD
383 mips_cp0_names_mips3264,
384 mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
385 mips_hwr_names_numeric },
386
5f74bc13
CD
387 { "mips64r2", 1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
388 ISA_MIPS64R2 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX,
389 mips_cp0_names_mips3264r2,
390 mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
391 mips_hwr_names_mips3264r2 },
392
640c0ccd
CD
393 { "sb1", 1, bfd_mach_mips_sb1, CPU_SB1,
394 ISA_MIPS64 | INSN_MIPS3D | INSN_SB1,
bbcc0807
CD
395 mips_cp0_names_sb1,
396 mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
397 mips_hwr_names_numeric },
640c0ccd
CD
398
399 /* This entry, mips16, is here only for ISA/processor selection; do
400 not print its name. */
401 { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3 | INSN_MIPS16,
bbcc0807 402 mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
640c0ccd
CD
403};
404
405/* ISA and processor type to disassemble for, and register names to use.
406 set_default_mips_dis_options and parse_mips_dis_options fill in these
407 values. */
408static int mips_processor;
409static int mips_isa;
410static const char * const *mips_gpr_names;
411static const char * const *mips_fpr_names;
412static const char * const *mips_cp0_names;
bbcc0807
CD
413static const struct mips_cp0sel_name *mips_cp0sel_names;
414static int mips_cp0sel_names_len;
af7ee8bf 415static const char * const *mips_hwr_names;
640c0ccd
CD
416
417static const struct mips_abi_choice *choose_abi_by_name
418 PARAMS ((const char *, unsigned int));
419static const struct mips_arch_choice *choose_arch_by_name
420 PARAMS ((const char *, unsigned int));
421static const struct mips_arch_choice *choose_arch_by_number
422 PARAMS ((unsigned long));
bbcc0807
CD
423static const struct mips_cp0sel_name *lookup_mips_cp0sel_name
424 PARAMS ((const struct mips_cp0sel_name *, unsigned int, unsigned int,
425 unsigned int));
640c0ccd
CD
426\f
427static const struct mips_abi_choice *
428choose_abi_by_name (name, namelen)
429 const char *name;
430 unsigned int namelen;
431{
432 const struct mips_abi_choice *c;
433 unsigned int i;
434
435 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++)
436 {
437 if (strncmp (mips_abi_choices[i].name, name, namelen) == 0
438 && strlen (mips_abi_choices[i].name) == namelen)
439 c = &mips_abi_choices[i];
440 }
441 return c;
442}
443
444static const struct mips_arch_choice *
445choose_arch_by_name (name, namelen)
446 const char *name;
447 unsigned int namelen;
448{
449 const struct mips_arch_choice *c = NULL;
450 unsigned int i;
451
452 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
453 {
454 if (strncmp (mips_arch_choices[i].name, name, namelen) == 0
455 && strlen (mips_arch_choices[i].name) == namelen)
456 c = &mips_arch_choices[i];
457 }
458 return c;
459}
460
461static const struct mips_arch_choice *
462choose_arch_by_number (mach)
463 unsigned long mach;
464{
465 static unsigned long hint_bfd_mach;
466 static const struct mips_arch_choice *hint_arch_choice;
467 const struct mips_arch_choice *c;
468 unsigned int i;
469
470 /* We optimize this because even if the user specifies no
471 flags, this will be done for every instruction! */
472 if (hint_bfd_mach == mach
473 && hint_arch_choice != NULL
474 && hint_arch_choice->bfd_mach == hint_bfd_mach)
475 return hint_arch_choice;
476
477 for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
478 {
479 if (mips_arch_choices[i].bfd_mach_valid
480 && mips_arch_choices[i].bfd_mach == mach)
481 {
482 c = &mips_arch_choices[i];
483 hint_bfd_mach = mach;
484 hint_arch_choice = c;
485 }
486 }
487 return c;
488}
489
490void
491set_default_mips_dis_options (info)
492 struct disassemble_info *info;
493{
494 const struct mips_arch_choice *chosen_arch;
495
496 /* Defaults: mipsIII/r3000 (?!), (o)32-style ("oldabi") GPR names,
af7ee8bf 497 and numeric FPR, CP0 register, and HWR names. */
640c0ccd
CD
498 mips_isa = ISA_MIPS3;
499 mips_processor = CPU_R3000;
500 mips_gpr_names = mips_gpr_names_oldabi;
501 mips_fpr_names = mips_fpr_names_numeric;
502 mips_cp0_names = mips_cp0_names_numeric;
bbcc0807
CD
503 mips_cp0sel_names = NULL;
504 mips_cp0sel_names_len = 0;
af7ee8bf 505 mips_hwr_names = mips_hwr_names_numeric;
640c0ccd
CD
506
507 /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
fec06546 508 if (info->flavour == bfd_target_elf_flavour && info->section != NULL)
640c0ccd
CD
509 {
510 Elf_Internal_Ehdr *header;
511
fec06546 512 header = elf_elfheader (info->section->owner);
640c0ccd
CD
513 if (is_newabi (header))
514 mips_gpr_names = mips_gpr_names_newabi;
515 }
516
517 /* Set ISA, architecture, and cp0 register names as best we can. */
518#if ! SYMTAB_AVAILABLE
519 /* This is running out on a target machine, not in a host tool.
520 FIXME: Where does mips_target_info come from? */
521 target_processor = mips_target_info.processor;
522 mips_isa = mips_target_info.isa;
523#else
524 chosen_arch = choose_arch_by_number (info->mach);
525 if (chosen_arch != NULL)
526 {
527 mips_processor = chosen_arch->processor;
528 mips_isa = chosen_arch->isa;
bbcc0807
CD
529 mips_cp0_names = chosen_arch->cp0_names;
530 mips_cp0sel_names = chosen_arch->cp0sel_names;
531 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
532 mips_hwr_names = chosen_arch->hwr_names;
640c0ccd
CD
533 }
534#endif
535}
536
537void
538parse_mips_dis_option (option, len)
539 const char *option;
540 unsigned int len;
541{
542 unsigned int i, optionlen, vallen;
543 const char *val;
544 const struct mips_abi_choice *chosen_abi;
545 const struct mips_arch_choice *chosen_arch;
546
547 /* Look for the = that delimits the end of the option name. */
548 for (i = 0; i < len; i++)
549 {
550 if (option[i] == '=')
551 break;
552 }
553 if (i == 0) /* Invalid option: no name before '='. */
554 return;
555 if (i == len) /* Invalid option: no '='. */
556 return;
557 if (i == (len - 1)) /* Invalid option: no value after '='. */
558 return;
559
560 optionlen = i;
561 val = option + (optionlen + 1);
562 vallen = len - (optionlen + 1);
563
564 if (strncmp("gpr-names", option, optionlen) == 0
565 && strlen("gpr-names") == optionlen)
566 {
567 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 568 if (chosen_abi != NULL)
640c0ccd
CD
569 mips_gpr_names = chosen_abi->gpr_names;
570 return;
571 }
572
573 if (strncmp("fpr-names", option, optionlen) == 0
574 && strlen("fpr-names") == optionlen)
575 {
576 chosen_abi = choose_abi_by_name (val, vallen);
bbcc0807 577 if (chosen_abi != NULL)
640c0ccd
CD
578 mips_fpr_names = chosen_abi->fpr_names;
579 return;
580 }
581
582 if (strncmp("cp0-names", option, optionlen) == 0
583 && strlen("cp0-names") == optionlen)
584 {
585 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807
CD
586 if (chosen_arch != NULL)
587 {
588 mips_cp0_names = chosen_arch->cp0_names;
589 mips_cp0sel_names = chosen_arch->cp0sel_names;
590 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
591 }
640c0ccd
CD
592 return;
593 }
594
af7ee8bf
CD
595 if (strncmp("hwr-names", option, optionlen) == 0
596 && strlen("hwr-names") == optionlen)
597 {
598 chosen_arch = choose_arch_by_name (val, vallen);
bbcc0807 599 if (chosen_arch != NULL)
af7ee8bf
CD
600 mips_hwr_names = chosen_arch->hwr_names;
601 return;
602 }
603
640c0ccd
CD
604 if (strncmp("reg-names", option, optionlen) == 0
605 && strlen("reg-names") == optionlen)
606 {
607 /* We check both ABI and ARCH here unconditionally, so
608 that "numeric" will do the desirable thing: select
609 numeric register names for all registers. Other than
610 that, a given name probably won't match both. */
611 chosen_abi = choose_abi_by_name (val, vallen);
612 if (chosen_abi != NULL)
613 {
bbcc0807
CD
614 mips_gpr_names = chosen_abi->gpr_names;
615 mips_fpr_names = chosen_abi->fpr_names;
640c0ccd
CD
616 }
617 chosen_arch = choose_arch_by_name (val, vallen);
618 if (chosen_arch != NULL)
619 {
bbcc0807
CD
620 mips_cp0_names = chosen_arch->cp0_names;
621 mips_cp0sel_names = chosen_arch->cp0sel_names;
622 mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
623 mips_hwr_names = chosen_arch->hwr_names;
640c0ccd
CD
624 }
625 return;
626 }
627
628 /* Invalid option. */
629}
630
631void
632parse_mips_dis_options (options)
633 const char *options;
634{
635 const char *option_end;
636
637 if (options == NULL)
638 return;
639
640 while (*options != '\0')
641 {
642 /* Skip empty options. */
643 if (*options == ',')
644 {
645 options++;
646 continue;
647 }
648
649 /* We know that *options is neither NUL or a comma. */
650 option_end = options + 1;
651 while (*option_end != ',' && *option_end != '\0')
652 option_end++;
653
654 parse_mips_dis_option (options, option_end - options);
655
656 /* Go on to the next one. If option_end points to a comma, it
657 will be skipped above. */
658 options = option_end;
659 }
660}
661
bbcc0807
CD
662static const struct mips_cp0sel_name *
663lookup_mips_cp0sel_name(names, len, cp0reg, sel)
664 const struct mips_cp0sel_name *names;
665 unsigned int len, cp0reg, sel;
666{
667 unsigned int i;
668
669 for (i = 0; i < len; i++)
670 if (names[i].cp0reg == cp0reg && names[i].sel == sel)
671 return &names[i];
672 return NULL;
673}
252b5132 674\f
7f6621cd 675/* Print insn arguments for 32/64-bit code. */
aa5f19f2 676
794ac9d0
CD
677static void
678print_insn_args (d, l, pc, info)
252b5132
RH
679 const char *d;
680 register unsigned long int l;
681 bfd_vma pc;
682 struct disassemble_info *info;
683{
794ac9d0 684 int op, delta;
440cc0bc
CD
685 unsigned int lsb, msb, msbd;
686
687 lsb = 0;
252b5132 688
794ac9d0 689 for (; *d != '\0'; d++)
252b5132 690 {
af7ee8bf
CD
691 switch (*d)
692 {
794ac9d0
CD
693 case ',':
694 case '(':
695 case ')':
696 case '[':
697 case ']':
698 (*info->fprintf_func) (info->stream, "%c", *d);
699 break;
700
701 case '+':
702 /* Extension character; switch for second char. */
703 d++;
704 switch (*d)
705 {
706 case '\0':
707 /* xgettext:c-format */
708 (*info->fprintf_func) (info->stream,
709 _("# internal error, incomplete extension sequence (+)"));
710 return;
711
712 case 'A':
440cc0bc
CD
713 lsb = (l >> OP_SH_SHAMT) & OP_MASK_SHAMT;
714 (*info->fprintf_func) (info->stream, "0x%x", lsb);
794ac9d0
CD
715 break;
716
717 case 'B':
440cc0bc
CD
718 msb = (l >> OP_SH_INSMSB) & OP_MASK_INSMSB;
719 (*info->fprintf_func) (info->stream, "0x%x", msb - lsb + 1);
794ac9d0
CD
720 break;
721
722 case 'C':
5f74bc13 723 case 'H':
440cc0bc
CD
724 msbd = (l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD;
725 (*info->fprintf_func) (info->stream, "0x%x", msbd + 1);
794ac9d0
CD
726 break;
727
728 case 'D':
729 {
730 const struct mips_cp0sel_name *n;
731 unsigned int cp0reg, sel;
732
733 cp0reg = (l >> OP_SH_RD) & OP_MASK_RD;
734 sel = (l >> OP_SH_SEL) & OP_MASK_SEL;
735
736 /* CP0 register including 'sel' code for mtcN (et al.), to be
737 printed textually if known. If not known, print both
738 CP0 register name and sel numerically since CP0 register
739 with sel 0 may have a name unrelated to register being
740 printed. */
741 n = lookup_mips_cp0sel_name(mips_cp0sel_names,
742 mips_cp0sel_names_len, cp0reg, sel);
743 if (n != NULL)
744 (*info->fprintf_func) (info->stream, "%s", n->name);
745 else
746 (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel);
747 break;
748 }
749
5f74bc13
CD
750 case 'E':
751 lsb = ((l >> OP_SH_SHAMT) & OP_MASK_SHAMT) + 32;
752 (*info->fprintf_func) (info->stream, "0x%x", lsb);
753 break;
754
755 case 'F':
756 msb = ((l >> OP_SH_INSMSB) & OP_MASK_INSMSB) + 32;
757 (*info->fprintf_func) (info->stream, "0x%x", msb - lsb + 1);
758 break;
759
760 case 'G':
761 msbd = ((l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD) + 32;
762 (*info->fprintf_func) (info->stream, "0x%x", msbd + 1);
763 break;
764
794ac9d0
CD
765 default:
766 /* xgettext:c-format */
767 (*info->fprintf_func) (info->stream,
768 _("# internal error, undefined extension sequence (+%c)"),
769 *d);
770 return;
771 }
772 break;
773
774 case 's':
775 case 'b':
776 case 'r':
777 case 'v':
778 (*info->fprintf_func) (info->stream, "%s",
779 mips_gpr_names[(l >> OP_SH_RS) & OP_MASK_RS]);
780 break;
781
782 case 't':
783 case 'w':
784 (*info->fprintf_func) (info->stream, "%s",
785 mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
786 break;
787
788 case 'i':
789 case 'u':
790 (*info->fprintf_func) (info->stream, "0x%x",
791 (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
792 break;
793
794 case 'j': /* Same as i, but sign-extended. */
795 case 'o':
796 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
797 if (delta & 0x8000)
798 delta |= ~0xffff;
799 (*info->fprintf_func) (info->stream, "%d",
800 delta);
801 break;
802
803 case 'h':
804 (*info->fprintf_func) (info->stream, "0x%x",
805 (unsigned int) ((l >> OP_SH_PREFX)
806 & OP_MASK_PREFX));
807 break;
808
809 case 'k':
810 (*info->fprintf_func) (info->stream, "0x%x",
811 (unsigned int) ((l >> OP_SH_CACHE)
812 & OP_MASK_CACHE));
813 break;
814
815 case 'a':
816 info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
817 | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2));
818 (*info->print_address_func) (info->target, info);
819 break;
820
821 case 'p':
822 /* Sign extend the displacement. */
823 delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
824 if (delta & 0x8000)
825 delta |= ~0xffff;
826 info->target = (delta << 2) + pc + INSNLEN;
827 (*info->print_address_func) (info->target, info);
828 break;
829
830 case 'd':
831 (*info->fprintf_func) (info->stream, "%s",
832 mips_gpr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
833 break;
834
835 case 'U':
836 {
837 /* First check for both rd and rt being equal. */
838 unsigned int reg = (l >> OP_SH_RD) & OP_MASK_RD;
839 if (reg == ((l >> OP_SH_RT) & OP_MASK_RT))
840 (*info->fprintf_func) (info->stream, "%s",
841 mips_gpr_names[reg]);
842 else
843 {
844 /* If one is zero use the other. */
845 if (reg == 0)
846 (*info->fprintf_func) (info->stream, "%s",
847 mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
848 else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0)
849 (*info->fprintf_func) (info->stream, "%s",
850 mips_gpr_names[reg]);
851 else /* Bogus, result depends on processor. */
852 (*info->fprintf_func) (info->stream, "%s or %s",
853 mips_gpr_names[reg],
854 mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
855 }
856 }
857 break;
858
859 case 'z':
860 (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]);
861 break;
862
863 case '<':
af7ee8bf
CD
864 (*info->fprintf_func) (info->stream, "0x%x",
865 (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
866 break;
794ac9d0
CD
867
868 case 'c':
af7ee8bf 869 (*info->fprintf_func) (info->stream, "0x%x",
794ac9d0
CD
870 (l >> OP_SH_CODE) & OP_MASK_CODE);
871 break;
872
873 case 'q':
874 (*info->fprintf_func) (info->stream, "0x%x",
875 (l >> OP_SH_CODE2) & OP_MASK_CODE2);
af7ee8bf
CD
876 break;
877
878 case 'C':
879 (*info->fprintf_func) (info->stream, "0x%x",
794ac9d0
CD
880 (l >> OP_SH_COPZ) & OP_MASK_COPZ);
881 break;
882
883 case 'B':
884 (*info->fprintf_func) (info->stream, "0x%x",
885 (l >> OP_SH_CODE20) & OP_MASK_CODE20);
886 break;
887
888 case 'J':
889 (*info->fprintf_func) (info->stream, "0x%x",
890 (l >> OP_SH_CODE19) & OP_MASK_CODE19);
891 break;
892
893 case 'S':
894 case 'V':
895 (*info->fprintf_func) (info->stream, "%s",
896 mips_fpr_names[(l >> OP_SH_FS) & OP_MASK_FS]);
897 break;
898
899 case 'T':
900 case 'W':
901 (*info->fprintf_func) (info->stream, "%s",
902 mips_fpr_names[(l >> OP_SH_FT) & OP_MASK_FT]);
af7ee8bf
CD
903 break;
904
bbcc0807 905 case 'D':
794ac9d0
CD
906 (*info->fprintf_func) (info->stream, "%s",
907 mips_fpr_names[(l >> OP_SH_FD) & OP_MASK_FD]);
908 break;
909
910 case 'R':
911 (*info->fprintf_func) (info->stream, "%s",
912 mips_fpr_names[(l >> OP_SH_FR) & OP_MASK_FR]);
913 break;
914
915 case 'E':
916 /* Coprocessor register for lwcN instructions, et al.
917
918 Note that there is no load/store cp0 instructions, and
919 that FPU (cp1) instructions disassemble this field using
920 'T' format. Therefore, until we gain understanding of
921 cp2 register names, we can simply print the register
922 numbers. */
923 (*info->fprintf_func) (info->stream, "$%d",
924 (l >> OP_SH_RT) & OP_MASK_RT);
925 break;
926
927 case 'G':
928 /* Coprocessor register for mtcN instructions, et al. Note
929 that FPU (cp1) instructions disassemble this field using
930 'S' format. Therefore, we only need to worry about cp0,
931 cp2, and cp3. */
932 op = (l >> OP_SH_OP) & OP_MASK_OP;
933 if (op == OP_OP_COP0)
934 (*info->fprintf_func) (info->stream, "%s",
935 mips_cp0_names[(l >> OP_SH_RD) & OP_MASK_RD]);
936 else
937 (*info->fprintf_func) (info->stream, "$%d",
938 (l >> OP_SH_RD) & OP_MASK_RD);
939 break;
940
941 case 'K':
942 (*info->fprintf_func) (info->stream, "%s",
943 mips_hwr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
944 break;
945
946 case 'N':
947 (*info->fprintf_func) (info->stream, "$fcc%d",
948 (l >> OP_SH_BCC) & OP_MASK_BCC);
949 break;
950
951 case 'M':
952 (*info->fprintf_func) (info->stream, "$fcc%d",
953 (l >> OP_SH_CCC) & OP_MASK_CCC);
954 break;
955
956 case 'P':
957 (*info->fprintf_func) (info->stream, "%d",
958 (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
959 break;
960
961 case 'e':
962 (*info->fprintf_func) (info->stream, "%d",
963 (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE);
964 break;
965
966 case '%':
967 (*info->fprintf_func) (info->stream, "%d",
968 (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN);
969 break;
970
971 case 'H':
972 (*info->fprintf_func) (info->stream, "%d",
973 (l >> OP_SH_SEL) & OP_MASK_SEL);
974 break;
975
976 case 'O':
977 (*info->fprintf_func) (info->stream, "%d",
978 (l >> OP_SH_ALN) & OP_MASK_ALN);
979 break;
980
981 case 'Q':
bbcc0807 982 {
794ac9d0
CD
983 unsigned int vsel = (l >> OP_SH_VSEL) & OP_MASK_VSEL;
984 if ((vsel & 0x10) == 0)
985 {
986 int fmt;
987 vsel &= 0x0f;
988 for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
989 if ((vsel & 1) == 0)
990 break;
991 (*info->fprintf_func) (info->stream, "$v%d[%d]",
992 (l >> OP_SH_FT) & OP_MASK_FT,
993 vsel >> 1);
994 }
995 else if ((vsel & 0x08) == 0)
996 {
997 (*info->fprintf_func) (info->stream, "$v%d",
998 (l >> OP_SH_FT) & OP_MASK_FT);
999 }
bbcc0807 1000 else
794ac9d0
CD
1001 {
1002 (*info->fprintf_func) (info->stream, "0x%x",
1003 (l >> OP_SH_FT) & OP_MASK_FT);
1004 }
bbcc0807 1005 }
794ac9d0
CD
1006 break;
1007
1008 case 'X':
1009 (*info->fprintf_func) (info->stream, "$v%d",
1010 (l >> OP_SH_FD) & OP_MASK_FD);
1011 break;
1012
1013 case 'Y':
1014 (*info->fprintf_func) (info->stream, "$v%d",
1015 (l >> OP_SH_FS) & OP_MASK_FS);
1016 break;
1017
1018 case 'Z':
1019 (*info->fprintf_func) (info->stream, "$v%d",
1020 (l >> OP_SH_FT) & OP_MASK_FT);
1021 break;
bbcc0807 1022
af7ee8bf
CD
1023 default:
1024 /* xgettext:c-format */
1025 (*info->fprintf_func) (info->stream,
794ac9d0 1026 _("# internal error, undefined modifier(%c)"),
af7ee8bf 1027 *d);
794ac9d0 1028 return;
af7ee8bf 1029 }
252b5132
RH
1030 }
1031}
1032\f
21d34b1c 1033/* Check if the object uses NewABI conventions. */
aa5f19f2
NC
1034
1035static int
7f6621cd 1036is_newabi (header)
21d34b1c 1037 Elf_Internal_Ehdr *header;
aa5f19f2 1038{
4c563ebf
CD
1039 /* There are no old-style ABIs which use 64-bit ELF. */
1040 if (header->e_ident[EI_CLASS] == ELFCLASS64)
1041 return 1;
1042
563773fe
TS
1043 /* If a 32-bit ELF file, n32 is a new-style ABI. */
1044 if ((header->e_flags & EF_MIPS_ABI2) != 0)
21d34b1c 1045 return 1;
252b5132 1046
21d34b1c 1047 return 0;
aa5f19f2
NC
1048}
1049\f
252b5132
RH
1050/* Print the mips instruction at address MEMADDR in debugged memory,
1051 on using INFO. Returns length of the instruction, in bytes, which is
aa5f19f2 1052 always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
252b5132
RH
1053 this is little-endian code. */
1054
1055static int
aa5f19f2 1056print_insn_mips (memaddr, word, info)
252b5132
RH
1057 bfd_vma memaddr;
1058 unsigned long int word;
1059 struct disassemble_info *info;
1060{
1061 register const struct mips_opcode *op;
b34976b6 1062 static bfd_boolean init = 0;
252b5132
RH
1063 static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
1064
1065 /* Build a hash table to shorten the search time. */
1066 if (! init)
1067 {
1068 unsigned int i;
1069
1070 for (i = 0; i <= OP_MASK_OP; i++)
1071 {
1072 for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
1073 {
1074 if (op->pinfo == INSN_MACRO)
1075 continue;
1076 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
1077 {
1078 mips_hash[i] = op;
1079 break;
1080 }
1081 }
7f6621cd 1082 }
252b5132
RH
1083
1084 init = 1;
1085 }
1086
aa5f19f2 1087 info->bytes_per_chunk = INSNLEN;
252b5132 1088 info->display_endian = info->endian;
9bb28706
CD
1089 info->insn_info_valid = 1;
1090 info->branch_delay_insns = 0;
def7143b 1091 info->data_size = 0;
9bb28706
CD
1092 info->insn_type = dis_nonbranch;
1093 info->target = 0;
1094 info->target2 = 0;
252b5132
RH
1095
1096 op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
1097 if (op != NULL)
1098 {
1099 for (; op < &mips_opcodes[NUMOPCODES]; op++)
1100 {
1101 if (op->pinfo != INSN_MACRO && (word & op->mask) == op->match)
1102 {
1103 register const char *d;
2bd7f1f3 1104
3396de36 1105 /* We always allow to disassemble the jalx instruction. */
640c0ccd 1106 if (! OPCODE_IS_MEMBER (op, mips_isa, mips_processor)
3396de36 1107 && strcmp (op->name, "jalx"))
252b5132
RH
1108 continue;
1109
9bb28706
CD
1110 /* Figure out instruction type and branch delay information. */
1111 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
1112 {
1113 if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
1114 info->insn_type = dis_jsr;
1115 else
1116 info->insn_type = dis_branch;
1117 info->branch_delay_insns = 1;
1118 }
1119 else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
1120 | INSN_COND_BRANCH_LIKELY)) != 0)
1121 {
1122 if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
1123 info->insn_type = dis_condjsr;
1124 else
1125 info->insn_type = dis_condbranch;
1126 info->branch_delay_insns = 1;
1127 }
1128 else if ((op->pinfo & (INSN_STORE_MEMORY
1129 | INSN_LOAD_MEMORY_DELAY)) != 0)
1130 info->insn_type = dis_dref;
1131
252b5132
RH
1132 (*info->fprintf_func) (info->stream, "%s", op->name);
1133
1134 d = op->args;
1135 if (d != NULL && *d != '\0')
1136 {
7f6621cd 1137 (*info->fprintf_func) (info->stream, "\t");
794ac9d0 1138 print_insn_args (d, word, memaddr, info);
252b5132
RH
1139 }
1140
aa5f19f2 1141 return INSNLEN;
252b5132
RH
1142 }
1143 }
1144 }
1145
1146 /* Handle undefined instructions. */
9bb28706 1147 info->insn_type = dis_noninsn;
252b5132 1148 (*info->fprintf_func) (info->stream, "0x%x", word);
aa5f19f2 1149 return INSNLEN;
252b5132 1150}
aa5f19f2 1151\f
252b5132
RH
1152/* In an environment where we do not know the symbol type of the
1153 instruction we are forced to assume that the low order bit of the
1154 instructions' address may mark it as a mips16 instruction. If we
1155 are single stepping, or the pc is within the disassembled function,
1156 this works. Otherwise, we need a clue. Sometimes. */
1157
aa5f19f2
NC
1158static int
1159_print_insn_mips (memaddr, info, endianness)
252b5132
RH
1160 bfd_vma memaddr;
1161 struct disassemble_info *info;
aa5f19f2 1162 enum bfd_endian endianness;
252b5132 1163{
aa5f19f2 1164 bfd_byte buffer[INSNLEN];
252b5132
RH
1165 int status;
1166
640c0ccd
CD
1167 set_default_mips_dis_options (info);
1168 parse_mips_dis_options (info->disassembler_options);
1169
252b5132
RH
1170#if 1
1171 /* FIXME: If odd address, this is CLEARLY a mips 16 instruction. */
1172 /* Only a few tools will work this way. */
1173 if (memaddr & 0x01)
1174 return print_insn_mips16 (memaddr, info);
e93d7199 1175#endif
252b5132
RH
1176
1177#if SYMTAB_AVAILABLE
53f32ea5 1178 if (info->mach == bfd_mach_mips16
252b5132
RH
1179 || (info->flavour == bfd_target_elf_flavour
1180 && info->symbols != NULL
1181 && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
1182 == STO_MIPS16)))
1183 return print_insn_mips16 (memaddr, info);
e93d7199 1184#endif
252b5132 1185
aa5f19f2 1186 status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
252b5132 1187 if (status == 0)
aa5f19f2
NC
1188 {
1189 unsigned long insn;
1190
1191 if (endianness == BFD_ENDIAN_BIG)
7f6621cd 1192 insn = (unsigned long) bfd_getb32 (buffer);
aa5f19f2
NC
1193 else
1194 insn = (unsigned long) bfd_getl32 (buffer);
1195
1196 return print_insn_mips (memaddr, insn, info);
1197 }
252b5132
RH
1198 else
1199 {
1200 (*info->memory_error_func) (status, memaddr, info);
1201 return -1;
1202 }
1203}
1204
1205int
aa5f19f2 1206print_insn_big_mips (memaddr, info)
252b5132
RH
1207 bfd_vma memaddr;
1208 struct disassemble_info *info;
1209{
aa5f19f2
NC
1210 return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
1211}
252b5132 1212
aa5f19f2
NC
1213int
1214print_insn_little_mips (memaddr, info)
1215 bfd_vma memaddr;
1216 struct disassemble_info *info;
1217{
1218 return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
252b5132
RH
1219}
1220\f
1221/* Disassemble mips16 instructions. */
1222
1223static int
1224print_insn_mips16 (memaddr, info)
1225 bfd_vma memaddr;
1226 struct disassemble_info *info;
1227{
1228 int status;
1229 bfd_byte buffer[2];
1230 int length;
1231 int insn;
b34976b6 1232 bfd_boolean use_extend;
252b5132
RH
1233 int extend = 0;
1234 const struct mips_opcode *op, *opend;
1235
1236 info->bytes_per_chunk = 2;
1237 info->display_endian = info->endian;
252b5132
RH
1238 info->insn_info_valid = 1;
1239 info->branch_delay_insns = 0;
1240 info->data_size = 0;
1241 info->insn_type = dis_nonbranch;
1242 info->target = 0;
1243 info->target2 = 0;
1244
1245 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
1246 if (status != 0)
1247 {
1248 (*info->memory_error_func) (status, memaddr, info);
1249 return -1;
1250 }
1251
1252 length = 2;
1253
1254 if (info->endian == BFD_ENDIAN_BIG)
1255 insn = bfd_getb16 (buffer);
1256 else
1257 insn = bfd_getl16 (buffer);
1258
1259 /* Handle the extend opcode specially. */
b34976b6 1260 use_extend = FALSE;
252b5132
RH
1261 if ((insn & 0xf800) == 0xf000)
1262 {
b34976b6 1263 use_extend = TRUE;
252b5132
RH
1264 extend = insn & 0x7ff;
1265
1266 memaddr += 2;
1267
1268 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
1269 if (status != 0)
1270 {
1271 (*info->fprintf_func) (info->stream, "extend 0x%x",
1272 (unsigned int) extend);
1273 (*info->memory_error_func) (status, memaddr, info);
1274 return -1;
1275 }
1276
1277 if (info->endian == BFD_ENDIAN_BIG)
1278 insn = bfd_getb16 (buffer);
1279 else
1280 insn = bfd_getl16 (buffer);
1281
1282 /* Check for an extend opcode followed by an extend opcode. */
1283 if ((insn & 0xf800) == 0xf000)
1284 {
1285 (*info->fprintf_func) (info->stream, "extend 0x%x",
1286 (unsigned int) extend);
1287 info->insn_type = dis_noninsn;
1288 return length;
1289 }
1290
1291 length += 2;
1292 }
1293
1294 /* FIXME: Should probably use a hash table on the major opcode here. */
1295
1296 opend = mips16_opcodes + bfd_mips16_num_opcodes;
1297 for (op = mips16_opcodes; op < opend; op++)
1298 {
1299 if (op->pinfo != INSN_MACRO && (insn & op->mask) == op->match)
1300 {
1301 const char *s;
1302
1303 if (strchr (op->args, 'a') != NULL)
1304 {
1305 if (use_extend)
1306 {
1307 (*info->fprintf_func) (info->stream, "extend 0x%x",
1308 (unsigned int) extend);
1309 info->insn_type = dis_noninsn;
1310 return length - 2;
1311 }
1312
b34976b6 1313 use_extend = FALSE;
252b5132
RH
1314
1315 memaddr += 2;
1316
1317 status = (*info->read_memory_func) (memaddr, buffer, 2,
1318 info);
1319 if (status == 0)
1320 {
b34976b6 1321 use_extend = TRUE;
252b5132
RH
1322 if (info->endian == BFD_ENDIAN_BIG)
1323 extend = bfd_getb16 (buffer);
1324 else
1325 extend = bfd_getl16 (buffer);
1326 length += 2;
1327 }
1328 }
1329
1330 (*info->fprintf_func) (info->stream, "%s", op->name);
1331 if (op->args[0] != '\0')
1332 (*info->fprintf_func) (info->stream, "\t");
1333
1334 for (s = op->args; *s != '\0'; s++)
1335 {
1336 if (*s == ','
1337 && s[1] == 'w'
1338 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
1339 == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
1340 {
1341 /* Skip the register and the comma. */
1342 ++s;
1343 continue;
1344 }
1345 if (*s == ','
1346 && s[1] == 'v'
1347 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
1348 == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
1349 {
1350 /* Skip the register and the comma. */
1351 ++s;
1352 continue;
1353 }
1354 print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
1355 info);
1356 }
1357
1358 if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
1359 {
1360 info->branch_delay_insns = 1;
1361 if (info->insn_type != dis_jsr)
1362 info->insn_type = dis_branch;
1363 }
1364
1365 return length;
1366 }
1367 }
1368
1369 if (use_extend)
1370 (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
1371 (*info->fprintf_func) (info->stream, "0x%x", insn);
1372 info->insn_type = dis_noninsn;
1373
1374 return length;
1375}
1376
1377/* Disassemble an operand for a mips16 instruction. */
1378
1379static void
1380print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info)
aa5f19f2 1381 char type;
252b5132
RH
1382 const struct mips_opcode *op;
1383 int l;
b34976b6 1384 bfd_boolean use_extend;
252b5132
RH
1385 int extend;
1386 bfd_vma memaddr;
1387 struct disassemble_info *info;
1388{
1389 switch (type)
1390 {
1391 case ',':
1392 case '(':
1393 case ')':
1394 (*info->fprintf_func) (info->stream, "%c", type);
1395 break;
1396
1397 case 'y':
1398 case 'w':
aa5f19f2 1399 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
1400 mips16_reg_names[((l >> MIPS16OP_SH_RY)
1401 & MIPS16OP_MASK_RY)]);
1402 break;
1403
1404 case 'x':
1405 case 'v':
aa5f19f2 1406 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
1407 mips16_reg_names[((l >> MIPS16OP_SH_RX)
1408 & MIPS16OP_MASK_RX)]);
1409 break;
1410
1411 case 'z':
aa5f19f2 1412 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
1413 mips16_reg_names[((l >> MIPS16OP_SH_RZ)
1414 & MIPS16OP_MASK_RZ)]);
1415 break;
1416
1417 case 'Z':
aa5f19f2 1418 (*info->fprintf_func) (info->stream, "%s",
252b5132
RH
1419 mips16_reg_names[((l >> MIPS16OP_SH_MOVE32Z)
1420 & MIPS16OP_MASK_MOVE32Z)]);
1421 break;
1422
1423 case '0':
640c0ccd 1424 (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]);
252b5132
RH
1425 break;
1426
1427 case 'S':
640c0ccd 1428 (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[29]);
252b5132
RH
1429 break;
1430
1431 case 'P':
1432 (*info->fprintf_func) (info->stream, "$pc");
1433 break;
1434
1435 case 'R':
640c0ccd 1436 (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[31]);
252b5132
RH
1437 break;
1438
1439 case 'X':
aa5f19f2 1440 (*info->fprintf_func) (info->stream, "%s",
640c0ccd
CD
1441 mips_gpr_names[((l >> MIPS16OP_SH_REGR32)
1442 & MIPS16OP_MASK_REGR32)]);
252b5132
RH
1443 break;
1444
1445 case 'Y':
aa5f19f2 1446 (*info->fprintf_func) (info->stream, "%s",
640c0ccd 1447 mips_gpr_names[MIPS16OP_EXTRACT_REG32R (l)]);
252b5132
RH
1448 break;
1449
1450 case '<':
1451 case '>':
1452 case '[':
1453 case ']':
1454 case '4':
1455 case '5':
1456 case 'H':
1457 case 'W':
1458 case 'D':
1459 case 'j':
1460 case '6':
1461 case '8':
1462 case 'V':
1463 case 'C':
1464 case 'U':
1465 case 'k':
1466 case 'K':
1467 case 'p':
1468 case 'q':
1469 case 'A':
1470 case 'B':
1471 case 'E':
1472 {
1473 int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
1474
1475 shift = 0;
1476 signedp = 0;
1477 extbits = 16;
1478 pcrel = 0;
1479 extu = 0;
1480 branch = 0;
1481 switch (type)
1482 {
1483 case '<':
1484 nbits = 3;
1485 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
1486 extbits = 5;
1487 extu = 1;
1488 break;
1489 case '>':
1490 nbits = 3;
1491 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
1492 extbits = 5;
1493 extu = 1;
1494 break;
1495 case '[':
1496 nbits = 3;
1497 immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
1498 extbits = 6;
1499 extu = 1;
1500 break;
1501 case ']':
1502 nbits = 3;
1503 immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
1504 extbits = 6;
1505 extu = 1;
1506 break;
1507 case '4':
1508 nbits = 4;
1509 immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
1510 signedp = 1;
1511 extbits = 15;
1512 break;
1513 case '5':
1514 nbits = 5;
1515 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1516 info->insn_type = dis_dref;
1517 info->data_size = 1;
1518 break;
1519 case 'H':
1520 nbits = 5;
1521 shift = 1;
1522 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1523 info->insn_type = dis_dref;
1524 info->data_size = 2;
1525 break;
1526 case 'W':
1527 nbits = 5;
1528 shift = 2;
1529 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1530 if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
1531 && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
1532 {
1533 info->insn_type = dis_dref;
1534 info->data_size = 4;
1535 }
1536 break;
1537 case 'D':
1538 nbits = 5;
1539 shift = 3;
1540 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1541 info->insn_type = dis_dref;
1542 info->data_size = 8;
1543 break;
1544 case 'j':
1545 nbits = 5;
1546 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1547 signedp = 1;
1548 break;
1549 case '6':
1550 nbits = 6;
1551 immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1552 break;
1553 case '8':
1554 nbits = 8;
1555 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1556 break;
1557 case 'V':
1558 nbits = 8;
1559 shift = 2;
1560 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1561 /* FIXME: This might be lw, or it might be addiu to $sp or
1562 $pc. We assume it's load. */
1563 info->insn_type = dis_dref;
1564 info->data_size = 4;
1565 break;
1566 case 'C':
1567 nbits = 8;
1568 shift = 3;
1569 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1570 info->insn_type = dis_dref;
1571 info->data_size = 8;
1572 break;
1573 case 'U':
1574 nbits = 8;
1575 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1576 extu = 1;
1577 break;
1578 case 'k':
1579 nbits = 8;
1580 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1581 signedp = 1;
1582 break;
1583 case 'K':
1584 nbits = 8;
1585 shift = 3;
1586 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1587 signedp = 1;
1588 break;
1589 case 'p':
1590 nbits = 8;
1591 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1592 signedp = 1;
1593 pcrel = 1;
1594 branch = 1;
1595 info->insn_type = dis_condbranch;
1596 break;
1597 case 'q':
1598 nbits = 11;
1599 immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
1600 signedp = 1;
1601 pcrel = 1;
1602 branch = 1;
1603 info->insn_type = dis_branch;
1604 break;
1605 case 'A':
1606 nbits = 8;
1607 shift = 2;
1608 immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
1609 pcrel = 1;
1610 /* FIXME: This can be lw or la. We assume it is lw. */
1611 info->insn_type = dis_dref;
1612 info->data_size = 4;
1613 break;
1614 case 'B':
1615 nbits = 5;
1616 shift = 3;
1617 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1618 pcrel = 1;
1619 info->insn_type = dis_dref;
1620 info->data_size = 8;
1621 break;
1622 case 'E':
1623 nbits = 5;
1624 shift = 2;
1625 immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
1626 pcrel = 1;
1627 break;
1628 default:
1629 abort ();
1630 }
1631
1632 if (! use_extend)
1633 {
1634 if (signedp && immed >= (1 << (nbits - 1)))
1635 immed -= 1 << nbits;
1636 immed <<= shift;
1637 if ((type == '<' || type == '>' || type == '[' || type == ']')
1638 && immed == 0)
1639 immed = 8;
1640 }
1641 else
1642 {
1643 if (extbits == 16)
1644 immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
1645 else if (extbits == 15)
1646 immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
1647 else
1648 immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
1649 immed &= (1 << extbits) - 1;
1650 if (! extu && immed >= (1 << (extbits - 1)))
1651 immed -= 1 << extbits;
1652 }
1653
1654 if (! pcrel)
1655 (*info->fprintf_func) (info->stream, "%d", immed);
1656 else
1657 {
1658 bfd_vma baseaddr;
252b5132
RH
1659
1660 if (branch)
1661 {
1662 immed *= 2;
1663 baseaddr = memaddr + 2;
1664 }
1665 else if (use_extend)
1666 baseaddr = memaddr - 2;
1667 else
1668 {
1669 int status;
1670 bfd_byte buffer[2];
1671
1672 baseaddr = memaddr;
1673
1674 /* If this instruction is in the delay slot of a jr
1675 instruction, the base address is the address of the
1676 jr instruction. If it is in the delay slot of jalr
1677 instruction, the base address is the address of the
1678 jalr instruction. This test is unreliable: we have
1679 no way of knowing whether the previous word is
1680 instruction or data. */
1681 status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
1682 info);
1683 if (status == 0
1684 && (((info->endian == BFD_ENDIAN_BIG
1685 ? bfd_getb16 (buffer)
1686 : bfd_getl16 (buffer))
1687 & 0xf800) == 0x1800))
1688 baseaddr = memaddr - 4;
1689 else
1690 {
1691 status = (*info->read_memory_func) (memaddr - 2, buffer,
1692 2, info);
1693 if (status == 0
1694 && (((info->endian == BFD_ENDIAN_BIG
1695 ? bfd_getb16 (buffer)
1696 : bfd_getl16 (buffer))
1697 & 0xf81f) == 0xe800))
1698 baseaddr = memaddr - 2;
1699 }
1700 }
9bb28706
CD
1701 info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
1702 (*info->print_address_func) (info->target, info);
252b5132
RH
1703 }
1704 }
1705 break;
1706
1707 case 'a':
1708 if (! use_extend)
1709 extend = 0;
1710 l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
9bb28706
CD
1711 info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
1712 (*info->print_address_func) (info->target, info);
252b5132 1713 info->insn_type = dis_jsr;
252b5132
RH
1714 info->branch_delay_insns = 1;
1715 break;
1716
1717 case 'l':
1718 case 'L':
1719 {
1720 int need_comma, amask, smask;
1721
1722 need_comma = 0;
1723
1724 l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
1725
1726 amask = (l >> 3) & 7;
1727
1728 if (amask > 0 && amask < 5)
1729 {
640c0ccd 1730 (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]);
252b5132 1731 if (amask > 1)
aa5f19f2 1732 (*info->fprintf_func) (info->stream, "-%s",
640c0ccd 1733 mips_gpr_names[amask + 3]);
252b5132
RH
1734 need_comma = 1;
1735 }
1736
1737 smask = (l >> 1) & 3;
1738 if (smask == 3)
1739 {
1740 (*info->fprintf_func) (info->stream, "%s??",
1741 need_comma ? "," : "");
1742 need_comma = 1;
1743 }
1744 else if (smask > 0)
1745 {
aa5f19f2 1746 (*info->fprintf_func) (info->stream, "%s%s",
252b5132 1747 need_comma ? "," : "",
640c0ccd 1748 mips_gpr_names[16]);
252b5132 1749 if (smask > 1)
aa5f19f2 1750 (*info->fprintf_func) (info->stream, "-%s",
640c0ccd 1751 mips_gpr_names[smask + 15]);
252b5132
RH
1752 need_comma = 1;
1753 }
1754
1755 if (l & 1)
1756 {
aa5f19f2 1757 (*info->fprintf_func) (info->stream, "%s%s",
252b5132 1758 need_comma ? "," : "",
640c0ccd 1759 mips_gpr_names[31]);
252b5132
RH
1760 need_comma = 1;
1761 }
1762
1763 if (amask == 5 || amask == 6)
1764 {
1765 (*info->fprintf_func) (info->stream, "%s$f0",
1766 need_comma ? "," : "");
1767 if (amask == 6)
1768 (*info->fprintf_func) (info->stream, "-$f1");
1769 }
1770 }
1771 break;
1772
1773 default:
aa5f19f2
NC
1774 /* xgettext:c-format */
1775 (*info->fprintf_func)
1776 (info->stream,
1777 _("# internal disassembler error, unrecognised modifier (%c)"),
1778 type);
252b5132
RH
1779 abort ();
1780 }
1781}
640c0ccd
CD
1782
1783void
1784print_mips_disassembler_options (stream)
1785 FILE *stream;
1786{
4a9a3c54 1787 unsigned int i;
640c0ccd
CD
1788
1789 fprintf (stream, _("\n\
1790The following MIPS specific disassembler options are supported for use\n\
1791with the -M switch (multiple options should be separated by commas):\n"));
1792
1793 fprintf (stream, _("\n\
1794 gpr-names=ABI Print GPR names according to specified ABI.\n\
1795 Default: based on binary being disassembled.\n"));
1796
1797 fprintf (stream, _("\n\
1798 fpr-names=ABI Print FPR names according to specified ABI.\n\
1799 Default: numeric.\n"));
1800
1801 fprintf (stream, _("\n\
1802 cp0-names=ARCH Print CP0 register names according to\n\
1803 specified architecture.\n\
1804 Default: based on binary being disassembled.\n"));
1805
af7ee8bf
CD
1806 fprintf (stream, _("\n\
1807 hwr-names=ARCH Print HWR names according to specified \n\
1808 architecture.\n\
1809 Default: based on binary being disassembled.\n"));
1810
640c0ccd
CD
1811 fprintf (stream, _("\n\
1812 reg-names=ABI Print GPR and FPR names according to\n\
1813 specified ABI.\n"));
1814
1815 fprintf (stream, _("\n\
af7ee8bf 1816 reg-names=ARCH Print CP0 register and HWR names according to\n\
640c0ccd
CD
1817 specified architecture.\n"));
1818
1819 fprintf (stream, _("\n\
1820 For the options above, the following values are supported for \"ABI\":\n\
1821 "));
4a9a3c54 1822 for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
640c0ccd
CD
1823 fprintf (stream, " %s", mips_abi_choices[i].name);
1824 fprintf (stream, _("\n"));
1825
1826 fprintf (stream, _("\n\
1827 For the options above, The following values are supported for \"ARCH\":\n\
1828 "));
4a9a3c54 1829 for (i = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
640c0ccd
CD
1830 if (*mips_arch_choices[i].name != '\0')
1831 fprintf (stream, " %s", mips_arch_choices[i].name);
1832 fprintf (stream, _("\n"));
1833
1834 fprintf (stream, _("\n"));
1835}
This page took 0.326828 seconds and 4 git commands to generate.