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