mips-dis.c revision 1.1.1.9 1 1.1 christos /* Print mips instructions for GDB, the GNU debugger, or for objdump.
2 1.1.1.9 christos Copyright (C) 1989-2022 Free Software Foundation, Inc.
3 1.1 christos Contributed by Nobuyuki Hikichi(hikichi (at) sra.co.jp).
4 1.1 christos
5 1.1 christos This file is part of the GNU opcodes library.
6 1.1 christos
7 1.1 christos This library is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3, or (at your option)
10 1.1 christos any later version.
11 1.1 christos
12 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
13 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 1.1 christos License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; if not, write to the Free Software
19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 1.1 christos MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos #include "sysdep.h"
23 1.1.1.7 christos #include "disassemble.h"
24 1.1 christos #include "libiberty.h"
25 1.1 christos #include "opcode/mips.h"
26 1.1 christos #include "opintl.h"
27 1.1.1.8 christos #include "elf-bfd.h"
28 1.1.1.8 christos #include "elf/mips.h"
29 1.1.1.8 christos #include "elfxx-mips.h"
30 1.1 christos
31 1.1 christos /* FIXME: These are needed to figure out if the code is mips16 or
32 1.1 christos not. The low bit of the address is often a good indicator. No
33 1.1 christos symbol table is available when this code runs out in an embedded
34 1.1 christos system as when it is used for disassembler support in a monitor. */
35 1.1 christos
36 1.1 christos #if !defined(EMBEDDED_ENV)
37 1.1 christos #define SYMTAB_AVAILABLE 1
38 1.1 christos #endif
39 1.1 christos
40 1.1 christos /* Mips instructions are at maximum this many bytes long. */
41 1.1 christos #define INSNLEN 4
42 1.1 christos
43 1.1 christos
44 1.1 christos /* FIXME: These should be shared with gdb somehow. */
46 1.1 christos
47 1.1 christos struct mips_cp0sel_name
48 1.1 christos {
49 1.1 christos unsigned int cp0reg;
50 1.1 christos unsigned int sel;
51 1.1 christos const char * const name;
52 1.1 christos };
53 1.1 christos
54 1.1 christos static const char * const mips_gpr_names_numeric[32] =
55 1.1 christos {
56 1.1 christos "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
57 1.1 christos "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
58 1.1 christos "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
59 1.1 christos "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
60 1.1 christos };
61 1.1 christos
62 1.1 christos static const char * const mips_gpr_names_oldabi[32] =
63 1.1 christos {
64 1.1 christos "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
65 1.1 christos "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
66 1.1 christos "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
67 1.1 christos "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
68 1.1 christos };
69 1.1 christos
70 1.1 christos static const char * const mips_gpr_names_newabi[32] =
71 1.1 christos {
72 1.1 christos "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
73 1.1 christos "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
74 1.1 christos "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
75 1.1 christos "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
76 1.1 christos };
77 1.1 christos
78 1.1 christos static const char * const mips_fpr_names_numeric[32] =
79 1.1 christos {
80 1.1 christos "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
81 1.1 christos "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
82 1.1 christos "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
83 1.1 christos "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
84 1.1 christos };
85 1.1 christos
86 1.1 christos static const char * const mips_fpr_names_32[32] =
87 1.1 christos {
88 1.1 christos "fv0", "fv0f", "fv1", "fv1f", "ft0", "ft0f", "ft1", "ft1f",
89 1.1 christos "ft2", "ft2f", "ft3", "ft3f", "fa0", "fa0f", "fa1", "fa1f",
90 1.1 christos "ft4", "ft4f", "ft5", "ft5f", "fs0", "fs0f", "fs1", "fs1f",
91 1.1 christos "fs2", "fs2f", "fs3", "fs3f", "fs4", "fs4f", "fs5", "fs5f"
92 1.1 christos };
93 1.1 christos
94 1.1 christos static const char * const mips_fpr_names_n32[32] =
95 1.1 christos {
96 1.1 christos "fv0", "ft14", "fv1", "ft15", "ft0", "ft1", "ft2", "ft3",
97 1.1 christos "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
98 1.1 christos "fa4", "fa5", "fa6", "fa7", "fs0", "ft8", "fs1", "ft9",
99 1.1 christos "fs2", "ft10", "fs3", "ft11", "fs4", "ft12", "fs5", "ft13"
100 1.1 christos };
101 1.1 christos
102 1.1 christos static const char * const mips_fpr_names_64[32] =
103 1.1 christos {
104 1.1 christos "fv0", "ft12", "fv1", "ft13", "ft0", "ft1", "ft2", "ft3",
105 1.1 christos "ft4", "ft5", "ft6", "ft7", "fa0", "fa1", "fa2", "fa3",
106 1.1 christos "fa4", "fa5", "fa6", "fa7", "ft8", "ft9", "ft10", "ft11",
107 1.1 christos "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7"
108 1.1 christos };
109 1.1 christos
110 1.1 christos static const char * const mips_cp0_names_numeric[32] =
111 1.1 christos {
112 1.1 christos "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
113 1.1 christos "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
114 1.1 christos "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
115 1.1 christos "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
116 1.1 christos };
117 1.1.1.3 christos
118 1.1.1.3 christos static const char * const mips_cp1_names_numeric[32] =
119 1.1.1.3 christos {
120 1.1.1.3 christos "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
121 1.1.1.3 christos "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
122 1.1.1.3 christos "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
123 1.1.1.3 christos "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
124 1.1.1.3 christos };
125 1.1.1.9 christos
126 1.1.1.9 christos static const char * const mips_cp0_names_r3900[32] =
127 1.1.1.9 christos {
128 1.1.1.9 christos "$0", "$1", "$2", "c0_config",
129 1.1.1.9 christos "$4", "$5", "$6", "c0_cache",
130 1.1.1.9 christos "c0_badvaddr", "$9", "$10", "$11",
131 1.1.1.9 christos "c0_sr", "c0_cause", "c0_epc", "c0_prid",
132 1.1.1.9 christos "c0_debug", "c0_depc", "$18", "$19",
133 1.1.1.9 christos "$20", "$21", "$22", "$23",
134 1.1.1.9 christos "$24", "$25", "$26", "$27",
135 1.1.1.9 christos "$28", "$29", "$30", "$31",
136 1.1.1.9 christos };
137 1.1 christos
138 1.1 christos static const char * const mips_cp0_names_r3000[32] =
139 1.1 christos {
140 1.1 christos "c0_index", "c0_random", "c0_entrylo", "$3",
141 1.1 christos "c0_context", "$5", "$6", "$7",
142 1.1 christos "c0_badvaddr", "$9", "c0_entryhi", "$11",
143 1.1 christos "c0_sr", "c0_cause", "c0_epc", "c0_prid",
144 1.1 christos "$16", "$17", "$18", "$19",
145 1.1 christos "$20", "$21", "$22", "$23",
146 1.1 christos "$24", "$25", "$26", "$27",
147 1.1 christos "$28", "$29", "$30", "$31",
148 1.1 christos };
149 1.1 christos
150 1.1 christos static const char * const mips_cp0_names_r4000[32] =
151 1.1 christos {
152 1.1 christos "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
153 1.1 christos "c0_context", "c0_pagemask", "c0_wired", "$7",
154 1.1 christos "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
155 1.1 christos "c0_sr", "c0_cause", "c0_epc", "c0_prid",
156 1.1 christos "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
157 1.1 christos "c0_xcontext", "$21", "$22", "$23",
158 1.1 christos "$24", "$25", "c0_ecc", "c0_cacheerr",
159 1.1 christos "c0_taglo", "c0_taghi", "c0_errorepc", "$31",
160 1.1 christos };
161 1.1.1.2 christos
162 1.1.1.2 christos static const char * const mips_cp0_names_r5900[32] =
163 1.1.1.2 christos {
164 1.1.1.2 christos "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
165 1.1.1.2 christos "c0_context", "c0_pagemask", "c0_wired", "$7",
166 1.1.1.2 christos "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
167 1.1.1.2 christos "c0_sr", "c0_cause", "c0_epc", "c0_prid",
168 1.1.1.2 christos "c0_config", "$17", "$18", "$19",
169 1.1.1.2 christos "$20", "$21", "$22", "c0_badpaddr",
170 1.1.1.2 christos "c0_depc", "c0_perfcnt", "$26", "$27",
171 1.1.1.2 christos "c0_taglo", "c0_taghi", "c0_errorepc", "$31"
172 1.1.1.2 christos };
173 1.1 christos
174 1.1 christos static const char * const mips_cp0_names_mips3264[32] =
175 1.1 christos {
176 1.1 christos "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
177 1.1 christos "c0_context", "c0_pagemask", "c0_wired", "$7",
178 1.1 christos "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
179 1.1 christos "c0_status", "c0_cause", "c0_epc", "c0_prid",
180 1.1 christos "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
181 1.1 christos "c0_xcontext", "$21", "$22", "c0_debug",
182 1.1 christos "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
183 1.1 christos "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
184 1.1 christos };
185 1.1.1.9 christos
186 1.1.1.9 christos static const char * const mips_cp1_names_mips[32] =
187 1.1.1.9 christos {
188 1.1.1.9 christos "c1_fir", "$1", "$2", "$3",
189 1.1.1.9 christos "$4", "$5", "$6", "$7",
190 1.1.1.9 christos "$8", "$9", "$10", "$11",
191 1.1.1.9 christos "$12", "$13", "$14", "$15",
192 1.1.1.9 christos "$16", "$17", "$18", "$19",
193 1.1.1.9 christos "$20", "$21", "$22", "$23",
194 1.1.1.9 christos "$24", "$25", "$26", "$27",
195 1.1.1.9 christos "$28", "$29", "$30", "c1_fcsr"
196 1.1.1.9 christos };
197 1.1.1.3 christos
198 1.1.1.3 christos static const char * const mips_cp1_names_mips3264[32] =
199 1.1.1.3 christos {
200 1.1.1.3 christos "c1_fir", "c1_ufr", "$2", "$3",
201 1.1.1.3 christos "c1_unfr", "$5", "$6", "$7",
202 1.1.1.3 christos "$8", "$9", "$10", "$11",
203 1.1.1.3 christos "$12", "$13", "$14", "$15",
204 1.1.1.3 christos "$16", "$17", "$18", "$19",
205 1.1.1.3 christos "$20", "$21", "$22", "$23",
206 1.1.1.3 christos "$24", "c1_fccr", "c1_fexr", "$27",
207 1.1.1.3 christos "c1_fenr", "$29", "$30", "c1_fcsr"
208 1.1.1.3 christos };
209 1.1 christos
210 1.1 christos static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] =
211 1.1 christos {
212 1.1 christos { 16, 1, "c0_config1" },
213 1.1 christos { 16, 2, "c0_config2" },
214 1.1 christos { 16, 3, "c0_config3" },
215 1.1 christos { 18, 1, "c0_watchlo,1" },
216 1.1 christos { 18, 2, "c0_watchlo,2" },
217 1.1 christos { 18, 3, "c0_watchlo,3" },
218 1.1 christos { 18, 4, "c0_watchlo,4" },
219 1.1 christos { 18, 5, "c0_watchlo,5" },
220 1.1 christos { 18, 6, "c0_watchlo,6" },
221 1.1 christos { 18, 7, "c0_watchlo,7" },
222 1.1 christos { 19, 1, "c0_watchhi,1" },
223 1.1 christos { 19, 2, "c0_watchhi,2" },
224 1.1 christos { 19, 3, "c0_watchhi,3" },
225 1.1 christos { 19, 4, "c0_watchhi,4" },
226 1.1 christos { 19, 5, "c0_watchhi,5" },
227 1.1 christos { 19, 6, "c0_watchhi,6" },
228 1.1 christos { 19, 7, "c0_watchhi,7" },
229 1.1 christos { 25, 1, "c0_perfcnt,1" },
230 1.1 christos { 25, 2, "c0_perfcnt,2" },
231 1.1 christos { 25, 3, "c0_perfcnt,3" },
232 1.1 christos { 25, 4, "c0_perfcnt,4" },
233 1.1 christos { 25, 5, "c0_perfcnt,5" },
234 1.1 christos { 25, 6, "c0_perfcnt,6" },
235 1.1 christos { 25, 7, "c0_perfcnt,7" },
236 1.1 christos { 27, 1, "c0_cacheerr,1" },
237 1.1 christos { 27, 2, "c0_cacheerr,2" },
238 1.1 christos { 27, 3, "c0_cacheerr,3" },
239 1.1 christos { 28, 1, "c0_datalo" },
240 1.1 christos { 29, 1, "c0_datahi" }
241 1.1 christos };
242 1.1 christos
243 1.1 christos static const char * const mips_cp0_names_mips3264r2[32] =
244 1.1 christos {
245 1.1 christos "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
246 1.1 christos "c0_context", "c0_pagemask", "c0_wired", "c0_hwrena",
247 1.1 christos "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
248 1.1 christos "c0_status", "c0_cause", "c0_epc", "c0_prid",
249 1.1 christos "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
250 1.1 christos "c0_xcontext", "$21", "$22", "c0_debug",
251 1.1 christos "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr",
252 1.1 christos "c0_taglo", "c0_taghi", "c0_errorepc", "c0_desave",
253 1.1 christos };
254 1.1 christos
255 1.1 christos static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] =
256 1.1 christos {
257 1.1 christos { 4, 1, "c0_contextconfig" },
258 1.1 christos { 0, 1, "c0_mvpcontrol" },
259 1.1 christos { 0, 2, "c0_mvpconf0" },
260 1.1 christos { 0, 3, "c0_mvpconf1" },
261 1.1 christos { 1, 1, "c0_vpecontrol" },
262 1.1 christos { 1, 2, "c0_vpeconf0" },
263 1.1 christos { 1, 3, "c0_vpeconf1" },
264 1.1 christos { 1, 4, "c0_yqmask" },
265 1.1 christos { 1, 5, "c0_vpeschedule" },
266 1.1 christos { 1, 6, "c0_vpeschefback" },
267 1.1 christos { 2, 1, "c0_tcstatus" },
268 1.1 christos { 2, 2, "c0_tcbind" },
269 1.1 christos { 2, 3, "c0_tcrestart" },
270 1.1 christos { 2, 4, "c0_tchalt" },
271 1.1 christos { 2, 5, "c0_tccontext" },
272 1.1 christos { 2, 6, "c0_tcschedule" },
273 1.1 christos { 2, 7, "c0_tcschefback" },
274 1.1 christos { 5, 1, "c0_pagegrain" },
275 1.1 christos { 6, 1, "c0_srsconf0" },
276 1.1 christos { 6, 2, "c0_srsconf1" },
277 1.1 christos { 6, 3, "c0_srsconf2" },
278 1.1 christos { 6, 4, "c0_srsconf3" },
279 1.1 christos { 6, 5, "c0_srsconf4" },
280 1.1 christos { 12, 1, "c0_intctl" },
281 1.1 christos { 12, 2, "c0_srsctl" },
282 1.1 christos { 12, 3, "c0_srsmap" },
283 1.1 christos { 15, 1, "c0_ebase" },
284 1.1 christos { 16, 1, "c0_config1" },
285 1.1 christos { 16, 2, "c0_config2" },
286 1.1 christos { 16, 3, "c0_config3" },
287 1.1 christos { 18, 1, "c0_watchlo,1" },
288 1.1 christos { 18, 2, "c0_watchlo,2" },
289 1.1 christos { 18, 3, "c0_watchlo,3" },
290 1.1 christos { 18, 4, "c0_watchlo,4" },
291 1.1 christos { 18, 5, "c0_watchlo,5" },
292 1.1 christos { 18, 6, "c0_watchlo,6" },
293 1.1 christos { 18, 7, "c0_watchlo,7" },
294 1.1 christos { 19, 1, "c0_watchhi,1" },
295 1.1 christos { 19, 2, "c0_watchhi,2" },
296 1.1 christos { 19, 3, "c0_watchhi,3" },
297 1.1 christos { 19, 4, "c0_watchhi,4" },
298 1.1 christos { 19, 5, "c0_watchhi,5" },
299 1.1 christos { 19, 6, "c0_watchhi,6" },
300 1.1 christos { 19, 7, "c0_watchhi,7" },
301 1.1 christos { 23, 1, "c0_tracecontrol" },
302 1.1 christos { 23, 2, "c0_tracecontrol2" },
303 1.1 christos { 23, 3, "c0_usertracedata" },
304 1.1 christos { 23, 4, "c0_tracebpc" },
305 1.1 christos { 25, 1, "c0_perfcnt,1" },
306 1.1 christos { 25, 2, "c0_perfcnt,2" },
307 1.1 christos { 25, 3, "c0_perfcnt,3" },
308 1.1 christos { 25, 4, "c0_perfcnt,4" },
309 1.1 christos { 25, 5, "c0_perfcnt,5" },
310 1.1 christos { 25, 6, "c0_perfcnt,6" },
311 1.1 christos { 25, 7, "c0_perfcnt,7" },
312 1.1 christos { 27, 1, "c0_cacheerr,1" },
313 1.1 christos { 27, 2, "c0_cacheerr,2" },
314 1.1 christos { 27, 3, "c0_cacheerr,3" },
315 1.1 christos { 28, 1, "c0_datalo" },
316 1.1 christos { 28, 2, "c0_taglo1" },
317 1.1 christos { 28, 3, "c0_datalo1" },
318 1.1 christos { 28, 4, "c0_taglo2" },
319 1.1 christos { 28, 5, "c0_datalo2" },
320 1.1 christos { 28, 6, "c0_taglo3" },
321 1.1 christos { 28, 7, "c0_datalo3" },
322 1.1 christos { 29, 1, "c0_datahi" },
323 1.1 christos { 29, 2, "c0_taghi1" },
324 1.1 christos { 29, 3, "c0_datahi1" },
325 1.1 christos { 29, 4, "c0_taghi2" },
326 1.1 christos { 29, 5, "c0_datahi2" },
327 1.1 christos { 29, 6, "c0_taghi3" },
328 1.1 christos { 29, 7, "c0_datahi3" },
329 1.1 christos };
330 1.1 christos
331 1.1 christos /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods. */
332 1.1 christos static const char * const mips_cp0_names_sb1[32] =
333 1.1 christos {
334 1.1 christos "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
335 1.1 christos "c0_context", "c0_pagemask", "c0_wired", "$7",
336 1.1 christos "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
337 1.1 christos "c0_status", "c0_cause", "c0_epc", "c0_prid",
338 1.1 christos "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
339 1.1 christos "c0_xcontext", "$21", "$22", "c0_debug",
340 1.1 christos "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
341 1.1 christos "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
342 1.1 christos };
343 1.1 christos
344 1.1 christos static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] =
345 1.1 christos {
346 1.1 christos { 16, 1, "c0_config1" },
347 1.1 christos { 18, 1, "c0_watchlo,1" },
348 1.1 christos { 19, 1, "c0_watchhi,1" },
349 1.1 christos { 22, 0, "c0_perftrace" },
350 1.1 christos { 23, 3, "c0_edebug" },
351 1.1 christos { 25, 1, "c0_perfcnt,1" },
352 1.1 christos { 25, 2, "c0_perfcnt,2" },
353 1.1 christos { 25, 3, "c0_perfcnt,3" },
354 1.1 christos { 25, 4, "c0_perfcnt,4" },
355 1.1 christos { 25, 5, "c0_perfcnt,5" },
356 1.1 christos { 25, 6, "c0_perfcnt,6" },
357 1.1 christos { 25, 7, "c0_perfcnt,7" },
358 1.1 christos { 26, 1, "c0_buserr_pa" },
359 1.1 christos { 27, 1, "c0_cacheerr_d" },
360 1.1 christos { 27, 3, "c0_cacheerr_d_pa" },
361 1.1 christos { 28, 1, "c0_datalo_i" },
362 1.1 christos { 28, 2, "c0_taglo_d" },
363 1.1 christos { 28, 3, "c0_datalo_d" },
364 1.1 christos { 29, 1, "c0_datahi_i" },
365 1.1 christos { 29, 2, "c0_taghi_d" },
366 1.1 christos { 29, 3, "c0_datahi_d" },
367 1.1 christos };
368 1.1 christos
369 1.1 christos /* Xlr cop0 register names. */
370 1.1 christos static const char * const mips_cp0_names_xlr[32] = {
371 1.1 christos "c0_index", "c0_random", "c0_entrylo0", "c0_entrylo1",
372 1.1 christos "c0_context", "c0_pagemask", "c0_wired", "$7",
373 1.1 christos "c0_badvaddr", "c0_count", "c0_entryhi", "c0_compare",
374 1.1 christos "c0_status", "c0_cause", "c0_epc", "c0_prid",
375 1.1 christos "c0_config", "c0_lladdr", "c0_watchlo", "c0_watchhi",
376 1.1 christos "c0_xcontext", "$21", "$22", "c0_debug",
377 1.1 christos "c0_depc", "c0_perfcnt", "c0_errctl", "c0_cacheerr_i",
378 1.1 christos "c0_taglo_i", "c0_taghi_i", "c0_errorepc", "c0_desave",
379 1.1 christos };
380 1.1 christos
381 1.1 christos /* XLR's CP0 Select Registers. */
382 1.1 christos
383 1.1 christos static const struct mips_cp0sel_name mips_cp0sel_names_xlr[] = {
384 1.1 christos { 9, 6, "c0_extintreq" },
385 1.1 christos { 9, 7, "c0_extintmask" },
386 1.1 christos { 15, 1, "c0_ebase" },
387 1.1 christos { 16, 1, "c0_config1" },
388 1.1 christos { 16, 2, "c0_config2" },
389 1.1 christos { 16, 3, "c0_config3" },
390 1.1 christos { 16, 7, "c0_procid2" },
391 1.1 christos { 18, 1, "c0_watchlo,1" },
392 1.1 christos { 18, 2, "c0_watchlo,2" },
393 1.1 christos { 18, 3, "c0_watchlo,3" },
394 1.1 christos { 18, 4, "c0_watchlo,4" },
395 1.1 christos { 18, 5, "c0_watchlo,5" },
396 1.1 christos { 18, 6, "c0_watchlo,6" },
397 1.1 christos { 18, 7, "c0_watchlo,7" },
398 1.1 christos { 19, 1, "c0_watchhi,1" },
399 1.1 christos { 19, 2, "c0_watchhi,2" },
400 1.1 christos { 19, 3, "c0_watchhi,3" },
401 1.1 christos { 19, 4, "c0_watchhi,4" },
402 1.1 christos { 19, 5, "c0_watchhi,5" },
403 1.1 christos { 19, 6, "c0_watchhi,6" },
404 1.1 christos { 19, 7, "c0_watchhi,7" },
405 1.1 christos { 25, 1, "c0_perfcnt,1" },
406 1.1 christos { 25, 2, "c0_perfcnt,2" },
407 1.1 christos { 25, 3, "c0_perfcnt,3" },
408 1.1 christos { 25, 4, "c0_perfcnt,4" },
409 1.1 christos { 25, 5, "c0_perfcnt,5" },
410 1.1 christos { 25, 6, "c0_perfcnt,6" },
411 1.1 christos { 25, 7, "c0_perfcnt,7" },
412 1.1 christos { 27, 1, "c0_cacheerr,1" },
413 1.1 christos { 27, 2, "c0_cacheerr,2" },
414 1.1 christos { 27, 3, "c0_cacheerr,3" },
415 1.1 christos { 28, 1, "c0_datalo" },
416 1.1 christos { 29, 1, "c0_datahi" }
417 1.1 christos };
418 1.1 christos
419 1.1 christos static const char * const mips_hwr_names_numeric[32] =
420 1.1 christos {
421 1.1 christos "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
422 1.1 christos "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
423 1.1 christos "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
424 1.1 christos "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
425 1.1 christos };
426 1.1 christos
427 1.1 christos static const char * const mips_hwr_names_mips3264r2[32] =
428 1.1 christos {
429 1.1 christos "hwr_cpunum", "hwr_synci_step", "hwr_cc", "hwr_ccres",
430 1.1 christos "$4", "$5", "$6", "$7",
431 1.1 christos "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
432 1.1 christos "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
433 1.1 christos "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
434 1.1 christos };
435 1.1.1.3 christos
436 1.1.1.3 christos static const char * const msa_control_names[32] =
437 1.1.1.3 christos {
438 1.1.1.3 christos "msa_ir", "msa_csr", "msa_access", "msa_save",
439 1.1.1.3 christos "msa_modify", "msa_request", "msa_map", "msa_unmap",
440 1.1.1.3 christos "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
441 1.1.1.3 christos "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
442 1.1.1.3 christos "$24", "$25", "$26", "$27", "$28", "$29", "$30", "$31"
443 1.1.1.3 christos };
444 1.1 christos
445 1.1 christos struct mips_abi_choice
446 1.1 christos {
447 1.1 christos const char * name;
448 1.1 christos const char * const *gpr_names;
449 1.1 christos const char * const *fpr_names;
450 1.1 christos };
451 1.1 christos
452 1.1 christos struct mips_abi_choice mips_abi_choices[] =
453 1.1 christos {
454 1.1 christos { "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric },
455 1.1 christos { "32", mips_gpr_names_oldabi, mips_fpr_names_32 },
456 1.1 christos { "n32", mips_gpr_names_newabi, mips_fpr_names_n32 },
457 1.1 christos { "64", mips_gpr_names_newabi, mips_fpr_names_64 },
458 1.1 christos };
459 1.1 christos
460 1.1 christos struct mips_arch_choice
461 1.1 christos {
462 1.1 christos const char *name;
463 1.1 christos int bfd_mach_valid;
464 1.1 christos unsigned long bfd_mach;
465 1.1 christos int processor;
466 1.1.1.3 christos int isa;
467 1.1 christos int ase;
468 1.1 christos const char * const *cp0_names;
469 1.1 christos const struct mips_cp0sel_name *cp0sel_names;
470 1.1.1.3 christos unsigned int cp0sel_names_len;
471 1.1 christos const char * const *cp1_names;
472 1.1 christos const char * const *hwr_names;
473 1.1 christos };
474 1.1 christos
475 1.1 christos const struct mips_arch_choice mips_arch_choices[] =
476 1.1.1.3 christos {
477 1.1.1.3 christos { "numeric", 0, 0, 0, 0, 0,
478 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
479 1.1 christos mips_hwr_names_numeric },
480 1.1.1.3 christos
481 1.1.1.9 christos { "r3000", 1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1, 0,
482 1.1.1.3 christos mips_cp0_names_r3000, NULL, 0, mips_cp1_names_mips,
483 1.1.1.3 christos mips_hwr_names_numeric },
484 1.1.1.9 christos { "r3900", 1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1, 0,
485 1.1.1.3 christos mips_cp0_names_r3900, NULL, 0, mips_cp1_names_numeric,
486 1.1.1.3 christos mips_hwr_names_numeric },
487 1.1.1.9 christos { "r4000", 1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3, 0,
488 1.1.1.3 christos mips_cp0_names_r4000, NULL, 0, mips_cp1_names_mips,
489 1.1.1.3 christos mips_hwr_names_numeric },
490 1.1.1.9 christos { "r4010", 1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2, 0,
491 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
492 1.1.1.3 christos mips_hwr_names_numeric },
493 1.1.1.9 christos { "vr4100", 1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3, 0,
494 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
495 1.1.1.3 christos mips_hwr_names_numeric },
496 1.1.1.9 christos { "vr4111", 1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3, 0,
497 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
498 1.1.1.3 christos mips_hwr_names_numeric },
499 1.1.1.9 christos { "vr4120", 1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3, 0,
500 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
501 1.1.1.3 christos mips_hwr_names_numeric },
502 1.1.1.9 christos { "r4300", 1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3, 0,
503 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
504 1.1.1.3 christos mips_hwr_names_numeric },
505 1.1.1.9 christos { "r4400", 1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3, 0,
506 1.1.1.3 christos mips_cp0_names_r4000, NULL, 0, mips_cp1_names_mips,
507 1.1.1.3 christos mips_hwr_names_numeric },
508 1.1.1.9 christos { "r4600", 1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3, 0,
509 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
510 1.1.1.3 christos mips_hwr_names_numeric },
511 1.1.1.9 christos { "r4650", 1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3, 0,
512 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
513 1.1.1.3 christos mips_hwr_names_numeric },
514 1.1.1.9 christos { "r5000", 1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4, 0,
515 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
516 1.1.1.3 christos mips_hwr_names_numeric },
517 1.1.1.9 christos { "vr5400", 1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4, 0,
518 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
519 1.1.1.3 christos mips_hwr_names_numeric },
520 1.1.1.9 christos { "vr5500", 1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4, 0,
521 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
522 1.1.1.3 christos mips_hwr_names_numeric },
523 1.1.1.9 christos { "r5900", 1, bfd_mach_mips5900, CPU_R5900, ISA_MIPS3, 0,
524 1.1.1.3 christos mips_cp0_names_r5900, NULL, 0, mips_cp1_names_mips,
525 1.1.1.3 christos mips_hwr_names_numeric },
526 1.1.1.9 christos { "r6000", 1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2, 0,
527 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
528 1.1.1.3 christos mips_hwr_names_numeric },
529 1.1.1.9 christos { "rm7000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
530 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
531 1.1.1.3 christos mips_hwr_names_numeric },
532 1.1.1.9 christos { "rm9000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
533 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
534 1.1.1.3 christos mips_hwr_names_numeric },
535 1.1.1.9 christos { "r8000", 1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4, 0,
536 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
537 1.1.1.3 christos mips_hwr_names_numeric },
538 1.1.1.9 christos { "r10000", 1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4, 0,
539 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
540 1.1.1.3 christos mips_hwr_names_numeric },
541 1.1.1.9 christos { "r12000", 1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4, 0,
542 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
543 1.1.1.3 christos mips_hwr_names_numeric },
544 1.1.1.9 christos { "r14000", 1, bfd_mach_mips14000, CPU_R14000, ISA_MIPS4, 0,
545 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
546 1.1.1.3 christos mips_hwr_names_numeric },
547 1.1.1.9 christos { "r16000", 1, bfd_mach_mips16000, CPU_R16000, ISA_MIPS4, 0,
548 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
549 1.1.1.3 christos mips_hwr_names_numeric },
550 1.1.1.9 christos { "mips5", 1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5, 0,
551 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips,
552 1.1 christos mips_hwr_names_numeric },
553 1.1 christos
554 1.1 christos /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
555 1.1 christos Note that MIPS-3D and MDMX are not applicable to MIPS32. (See
556 1.1 christos _MIPS32 Architecture For Programmers Volume I: Introduction to the
557 1.1 christos MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
558 1.1 christos page 1. */
559 1.1.1.3 christos { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32,
560 1.1 christos ISA_MIPS32, ASE_SMARTMIPS,
561 1.1 christos mips_cp0_names_mips3264,
562 1.1.1.3 christos mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
563 1.1 christos mips_cp1_names_mips3264, mips_hwr_names_numeric },
564 1.1 christos
565 1.1.1.3 christos { "mips32r2", 1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
566 1.1.1.3 christos ISA_MIPS32R2,
567 1.1.1.4 christos (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
568 1.1.1.4 christos | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
569 1.1.1.4 christos mips_cp0_names_mips3264r2,
570 1.1.1.4 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
571 1.1.1.4 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
572 1.1.1.4 christos
573 1.1.1.4 christos { "mips32r3", 1, bfd_mach_mipsisa32r3, CPU_MIPS32R3,
574 1.1.1.4 christos ISA_MIPS32R3,
575 1.1.1.4 christos (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
576 1.1.1.4 christos | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
577 1.1.1.4 christos mips_cp0_names_mips3264r2,
578 1.1.1.4 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
579 1.1.1.4 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
580 1.1.1.4 christos
581 1.1.1.4 christos { "mips32r5", 1, bfd_mach_mipsisa32r5, CPU_MIPS32R5,
582 1.1.1.4 christos ISA_MIPS32R5,
583 1.1.1.4 christos (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
584 1.1.1.4 christos | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
585 1.1.1.4 christos mips_cp0_names_mips3264r2,
586 1.1.1.4 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
587 1.1.1.4 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
588 1.1.1.4 christos
589 1.1.1.4 christos { "mips32r6", 1, bfd_mach_mipsisa32r6, CPU_MIPS32R6,
590 1.1.1.4 christos ISA_MIPS32R6,
591 1.1.1.7 christos (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_XPA | ASE_MCU | ASE_MT | ASE_DSP
592 1.1 christos | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC | ASE_GINV),
593 1.1 christos mips_cp0_names_mips3264r2,
594 1.1.1.3 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
595 1.1 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
596 1.1 christos
597 1.1 christos /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs. */
598 1.1.1.3 christos { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64,
599 1.1 christos ISA_MIPS64, ASE_MIPS3D | ASE_MDMX,
600 1.1 christos mips_cp0_names_mips3264,
601 1.1.1.3 christos mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
602 1.1 christos mips_cp1_names_mips3264, mips_hwr_names_numeric },
603 1.1 christos
604 1.1.1.3 christos { "mips64r2", 1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
605 1.1.1.3 christos ISA_MIPS64R2,
606 1.1.1.4 christos (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
607 1.1.1.4 christos | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
608 1.1.1.4 christos mips_cp0_names_mips3264r2,
609 1.1.1.4 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
610 1.1.1.4 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
611 1.1.1.4 christos
612 1.1.1.4 christos { "mips64r3", 1, bfd_mach_mipsisa64r3, CPU_MIPS64R3,
613 1.1.1.4 christos ISA_MIPS64R3,
614 1.1.1.4 christos (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
615 1.1.1.4 christos | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
616 1.1.1.4 christos mips_cp0_names_mips3264r2,
617 1.1.1.4 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
618 1.1.1.4 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
619 1.1.1.4 christos
620 1.1.1.4 christos { "mips64r5", 1, bfd_mach_mipsisa64r5, CPU_MIPS64R5,
621 1.1.1.4 christos ISA_MIPS64R5,
622 1.1.1.4 christos (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
623 1.1.1.4 christos | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
624 1.1.1.4 christos mips_cp0_names_mips3264r2,
625 1.1.1.4 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
626 1.1.1.4 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
627 1.1.1.4 christos
628 1.1.1.4 christos { "mips64r6", 1, bfd_mach_mipsisa64r6, CPU_MIPS64R6,
629 1.1.1.4 christos ISA_MIPS64R6,
630 1.1.1.7 christos (ASE_EVA | ASE_MSA | ASE_MSA64 | ASE_XPA | ASE_VIRT | ASE_VIRT64
631 1.1.1.7 christos | ASE_MCU | ASE_MT | ASE_DSP | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC
632 1.1.1.7 christos | ASE_CRC64 | ASE_GINV),
633 1.1.1.7 christos mips_cp0_names_mips3264r2,
634 1.1.1.7 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
635 1.1.1.7 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
636 1.1.1.7 christos
637 1.1.1.7 christos { "interaptiv-mr2", 1, bfd_mach_mips_interaptiv_mr2, CPU_INTERAPTIV_MR2,
638 1.1.1.7 christos ISA_MIPS32R3,
639 1.1 christos ASE_MT | ASE_EVA | ASE_DSP | ASE_DSPR2 | ASE_MIPS16E2 | ASE_MIPS16E2_MT,
640 1.1 christos mips_cp0_names_mips3264r2,
641 1.1.1.3 christos mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
642 1.1 christos mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
643 1.1 christos
644 1.1.1.3 christos { "sb1", 1, bfd_mach_mips_sb1, CPU_SB1,
645 1.1 christos ISA_MIPS64 | INSN_SB1, ASE_MIPS3D,
646 1.1 christos mips_cp0_names_sb1,
647 1.1.1.3 christos mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
648 1.1 christos mips_cp1_names_mips3264, mips_hwr_names_numeric },
649 1.1 christos
650 1.1.1.3 christos { "loongson2e", 1, bfd_mach_mips_loongson_2e, CPU_LOONGSON_2E,
651 1.1.1.9 christos ISA_MIPS3 | INSN_LOONGSON_2E, 0, mips_cp0_names_numeric,
652 1.1 christos NULL, 0, mips_cp1_names_mips, mips_hwr_names_numeric },
653 1.1 christos
654 1.1.1.7 christos { "loongson2f", 1, bfd_mach_mips_loongson_2f, CPU_LOONGSON_2F,
655 1.1.1.9 christos ISA_MIPS3 | INSN_LOONGSON_2F, ASE_LOONGSON_MMI, mips_cp0_names_numeric,
656 1.1 christos NULL, 0, mips_cp1_names_mips, mips_hwr_names_numeric },
657 1.1.1.7 christos
658 1.1.1.7 christos /* The loongson3a is an alias of gs464 for compatibility */
659 1.1.1.7 christos { "loongson3a", 1, bfd_mach_mips_gs464, CPU_GS464,
660 1.1.1.7 christos ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
661 1.1.1.7 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
662 1.1.1.7 christos mips_hwr_names_numeric },
663 1.1.1.7 christos
664 1.1.1.7 christos { "gs464", 1, bfd_mach_mips_gs464, CPU_GS464,
665 1.1.1.7 christos ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
666 1.1.1.7 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
667 1.1.1.7 christos mips_hwr_names_numeric },
668 1.1.1.7 christos
669 1.1.1.7 christos { "gs464e", 1, bfd_mach_mips_gs464e, CPU_GS464E,
670 1.1.1.7 christos ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
671 1.1.1.7 christos | ASE_LOONGSON_EXT2, mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
672 1.1.1.7 christos mips_hwr_names_numeric },
673 1.1.1.9 christos
674 1.1.1.7 christos { "gs264e", 1, bfd_mach_mips_gs264e, CPU_GS264E,
675 1.1.1.7 christos ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
676 1.1.1.7 christos | ASE_LOONGSON_EXT2 | ASE_MSA | ASE_MSA64, mips_cp0_names_numeric, NULL,
677 1.1 christos 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
678 1.1 christos
679 1.1.1.3 christos { "octeon", 1, bfd_mach_mips_octeon, CPU_OCTEON,
680 1.1.1.3 christos ISA_MIPS64R2 | INSN_OCTEON, 0, mips_cp0_names_numeric, NULL, 0,
681 1.1 christos mips_cp1_names_mips3264, mips_hwr_names_numeric },
682 1.1.1.2 christos
683 1.1.1.3 christos { "octeon+", 1, bfd_mach_mips_octeonp, CPU_OCTEONP,
684 1.1.1.3 christos ISA_MIPS64R2 | INSN_OCTEONP, 0, mips_cp0_names_numeric,
685 1.1.1.2 christos NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
686 1.1.1.2 christos
687 1.1.1.3 christos { "octeon2", 1, bfd_mach_mips_octeon2, CPU_OCTEON2,
688 1.1.1.3 christos ISA_MIPS64R2 | INSN_OCTEON2, 0, mips_cp0_names_numeric,
689 1.1.1.2 christos NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
690 1.1.1.4 christos
691 1.1.1.4 christos { "octeon3", 1, bfd_mach_mips_octeon3, CPU_OCTEON3,
692 1.1.1.4 christos ISA_MIPS64R5 | INSN_OCTEON3, ASE_VIRT | ASE_VIRT64,
693 1.1.1.4 christos mips_cp0_names_numeric,
694 1.1.1.4 christos NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
695 1.1 christos
696 1.1.1.3 christos { "xlr", 1, bfd_mach_mips_xlr, CPU_XLR,
697 1.1 christos ISA_MIPS64 | INSN_XLR, 0,
698 1.1 christos mips_cp0_names_xlr,
699 1.1.1.3 christos mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
700 1.1 christos mips_cp1_names_mips3264, mips_hwr_names_numeric },
701 1.1.1.2 christos
702 1.1.1.2 christos /* XLP is mostly like XLR, with the prominent exception it is being
703 1.1.1.2 christos MIPS64R2. */
704 1.1.1.3 christos { "xlp", 1, bfd_mach_mips_xlr, CPU_XLR,
705 1.1.1.2 christos ISA_MIPS64R2 | INSN_XLR, 0,
706 1.1.1.2 christos mips_cp0_names_xlr,
707 1.1.1.3 christos mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
708 1.1.1.2 christos mips_cp1_names_mips3264, mips_hwr_names_numeric },
709 1.1 christos
710 1.1 christos /* This entry, mips16, is here only for ISA/processor selection; do
711 1.1.1.7 christos not print its name. */
712 1.1.1.7 christos { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS64,
713 1.1.1.3 christos ASE_MIPS16E2 | ASE_MIPS16E2_MT,
714 1.1.1.3 christos mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
715 1.1 christos mips_hwr_names_numeric },
716 1.1 christos };
717 1.1 christos
718 1.1 christos /* ISA and processor type to disassemble for, and register names to use.
719 1.1 christos set_default_mips_dis_options and parse_mips_dis_options fill in these
720 1.1 christos values. */
721 1.1 christos static int mips_processor;
722 1.1.1.3 christos static int mips_isa;
723 1.1.1.2 christos static int mips_ase;
724 1.1 christos static int micromips_ase;
725 1.1 christos static const char * const *mips_gpr_names;
726 1.1 christos static const char * const *mips_fpr_names;
727 1.1 christos static const char * const *mips_cp0_names;
728 1.1 christos static const struct mips_cp0sel_name *mips_cp0sel_names;
729 1.1.1.3 christos static int mips_cp0sel_names_len;
730 1.1 christos static const char * const *mips_cp1_names;
731 1.1 christos static const char * const *mips_hwr_names;
732 1.1 christos
733 1.1 christos /* Other options */
734 1.1 christos static int no_aliases; /* If set disassemble as most general inst. */
735 1.1 christos
736 1.1 christos static const struct mips_abi_choice *
738 1.1 christos choose_abi_by_name (const char *name, unsigned int namelen)
739 1.1 christos {
740 1.1 christos const struct mips_abi_choice *c;
741 1.1 christos unsigned int i;
742 1.1 christos
743 1.1 christos for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++)
744 1.1 christos if (strncmp (mips_abi_choices[i].name, name, namelen) == 0
745 1.1 christos && strlen (mips_abi_choices[i].name) == namelen)
746 1.1 christos c = &mips_abi_choices[i];
747 1.1 christos
748 1.1 christos return c;
749 1.1 christos }
750 1.1 christos
751 1.1 christos static const struct mips_arch_choice *
752 1.1 christos choose_arch_by_name (const char *name, unsigned int namelen)
753 1.1 christos {
754 1.1 christos const struct mips_arch_choice *c = NULL;
755 1.1 christos unsigned int i;
756 1.1 christos
757 1.1 christos for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
758 1.1 christos if (strncmp (mips_arch_choices[i].name, name, namelen) == 0
759 1.1 christos && strlen (mips_arch_choices[i].name) == namelen)
760 1.1 christos c = &mips_arch_choices[i];
761 1.1 christos
762 1.1 christos return c;
763 1.1 christos }
764 1.1 christos
765 1.1 christos static const struct mips_arch_choice *
766 1.1 christos choose_arch_by_number (unsigned long mach)
767 1.1 christos {
768 1.1 christos static unsigned long hint_bfd_mach;
769 1.1 christos static const struct mips_arch_choice *hint_arch_choice;
770 1.1 christos const struct mips_arch_choice *c;
771 1.1 christos unsigned int i;
772 1.1 christos
773 1.1 christos /* We optimize this because even if the user specifies no
774 1.1 christos flags, this will be done for every instruction! */
775 1.1 christos if (hint_bfd_mach == mach
776 1.1 christos && hint_arch_choice != NULL
777 1.1 christos && hint_arch_choice->bfd_mach == hint_bfd_mach)
778 1.1 christos return hint_arch_choice;
779 1.1 christos
780 1.1 christos for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
781 1.1 christos {
782 1.1 christos if (mips_arch_choices[i].bfd_mach_valid
783 1.1 christos && mips_arch_choices[i].bfd_mach == mach)
784 1.1 christos {
785 1.1 christos c = &mips_arch_choices[i];
786 1.1 christos hint_bfd_mach = mach;
787 1.1 christos hint_arch_choice = c;
788 1.1 christos }
789 1.1 christos }
790 1.1 christos return c;
791 1.1 christos }
792 1.1 christos
793 1.1 christos /* Check if the object uses NewABI conventions. */
794 1.1 christos
795 1.1 christos static int
796 1.1 christos is_newabi (Elf_Internal_Ehdr *header)
797 1.1 christos {
798 1.1 christos /* There are no old-style ABIs which use 64-bit ELF. */
799 1.1 christos if (header->e_ident[EI_CLASS] == ELFCLASS64)
800 1.1 christos return 1;
801 1.1 christos
802 1.1 christos /* If a 32-bit ELF file, n32 is a new-style ABI. */
803 1.1 christos if ((header->e_flags & EF_MIPS_ABI2) != 0)
804 1.1 christos return 1;
805 1.1 christos
806 1.1 christos return 0;
807 1.1.1.2 christos }
808 1.1.1.2 christos
809 1.1.1.2 christos /* Check if the object has microMIPS ASE code. */
810 1.1.1.2 christos
811 1.1.1.2 christos static int
812 1.1.1.2 christos is_micromips (Elf_Internal_Ehdr *header)
813 1.1.1.2 christos {
814 1.1.1.2 christos if ((header->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0)
815 1.1.1.2 christos return 1;
816 1.1.1.2 christos
817 1.1.1.2 christos return 0;
818 1.1.1.6 christos }
819 1.1.1.6 christos
820 1.1.1.6 christos /* Convert ASE flags from .MIPS.abiflags to internal values. */
821 1.1.1.6 christos
822 1.1.1.6 christos static unsigned long
823 1.1.1.6 christos mips_convert_abiflags_ases (unsigned long afl_ases)
824 1.1.1.6 christos {
825 1.1.1.6 christos unsigned long opcode_ases = 0;
826 1.1.1.6 christos
827 1.1.1.6 christos if (afl_ases & AFL_ASE_DSP)
828 1.1.1.6 christos opcode_ases |= ASE_DSP;
829 1.1.1.6 christos if (afl_ases & AFL_ASE_DSPR2)
830 1.1.1.6 christos opcode_ases |= ASE_DSPR2;
831 1.1.1.6 christos if (afl_ases & AFL_ASE_EVA)
832 1.1.1.6 christos opcode_ases |= ASE_EVA;
833 1.1.1.6 christos if (afl_ases & AFL_ASE_MCU)
834 1.1.1.6 christos opcode_ases |= ASE_MCU;
835 1.1.1.6 christos if (afl_ases & AFL_ASE_MDMX)
836 1.1.1.6 christos opcode_ases |= ASE_MDMX;
837 1.1.1.6 christos if (afl_ases & AFL_ASE_MIPS3D)
838 1.1.1.6 christos opcode_ases |= ASE_MIPS3D;
839 1.1.1.6 christos if (afl_ases & AFL_ASE_MT)
840 1.1.1.6 christos opcode_ases |= ASE_MT;
841 1.1.1.6 christos if (afl_ases & AFL_ASE_SMARTMIPS)
842 1.1.1.6 christos opcode_ases |= ASE_SMARTMIPS;
843 1.1.1.6 christos if (afl_ases & AFL_ASE_VIRT)
844 1.1.1.6 christos opcode_ases |= ASE_VIRT;
845 1.1.1.6 christos if (afl_ases & AFL_ASE_MSA)
846 1.1.1.6 christos opcode_ases |= ASE_MSA;
847 1.1.1.6 christos if (afl_ases & AFL_ASE_XPA)
848 1.1.1.6 christos opcode_ases |= ASE_XPA;
849 1.1.1.7 christos if (afl_ases & AFL_ASE_DSPR3)
850 1.1.1.7 christos opcode_ases |= ASE_DSPR3;
851 1.1.1.6 christos if (afl_ases & AFL_ASE_MIPS16E2)
852 1.1.1.6 christos opcode_ases |= ASE_MIPS16E2;
853 1.1.1.6 christos return opcode_ases;
854 1.1.1.7 christos }
855 1.1.1.7 christos
856 1.1.1.7 christos /* Calculate combination ASE flags from regular ASE flags. */
857 1.1.1.8 christos
858 1.1.1.7 christos static unsigned long
859 1.1.1.7 christos mips_calculate_combination_ases (int opcode_isa, unsigned long opcode_ases)
860 1.1.1.7 christos {
861 1.1.1.7 christos unsigned long combination_ases = 0;
862 1.1.1.7 christos
863 1.1.1.7 christos if ((opcode_ases & (ASE_XPA | ASE_VIRT)) == (ASE_XPA | ASE_VIRT))
864 1.1.1.7 christos combination_ases |= ASE_XPA_VIRT;
865 1.1.1.8 christos if ((opcode_ases & (ASE_MIPS16E2 | ASE_MT)) == (ASE_MIPS16E2 | ASE_MT))
866 1.1.1.8 christos combination_ases |= ASE_MIPS16E2_MT;
867 1.1.1.8 christos if ((opcode_ases & ASE_EVA)
868 1.1.1.8 christos && ((opcode_isa & INSN_ISA_MASK) == ISA_MIPS64R6
869 1.1.1.7 christos || (opcode_isa & INSN_ISA_MASK) == ISA_MIPS32R6))
870 1.1.1.7 christos combination_ases |= ASE_EVA_R6;
871 1.1.1.7 christos return combination_ases;
872 1.1 christos }
873 1.1 christos
874 1.1 christos static void
875 1.1 christos set_default_mips_dis_options (struct disassemble_info *info)
876 1.1 christos {
877 1.1.1.2 christos const struct mips_arch_choice *chosen_arch;
878 1.1.1.2 christos
879 1.1.1.2 christos /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
880 1.1 christos is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
881 1.1.1.2 christos CP0 register, and HWR names. */
882 1.1.1.2 christos mips_isa = ISA_MIPS3;
883 1.1.1.3 christos mips_processor = CPU_R3000;
884 1.1 christos micromips_ase = 0;
885 1.1 christos mips_ase = 0;
886 1.1 christos mips_gpr_names = mips_gpr_names_oldabi;
887 1.1 christos mips_fpr_names = mips_fpr_names_numeric;
888 1.1 christos mips_cp0_names = mips_cp0_names_numeric;
889 1.1.1.3 christos mips_cp0sel_names = NULL;
890 1.1 christos mips_cp0sel_names_len = 0;
891 1.1 christos mips_cp1_names = mips_cp1_names_numeric;
892 1.1 christos mips_hwr_names = mips_hwr_names_numeric;
893 1.1 christos no_aliases = 0;
894 1.1 christos
895 1.1 christos /* Set ISA, architecture, and cp0 register names as best we can. */
896 1.1 christos #if ! SYMTAB_AVAILABLE
897 1.1 christos /* This is running out on a target machine, not in a host tool.
898 1.1 christos FIXME: Where does mips_target_info come from? */
899 1.1.1.3 christos target_processor = mips_target_info.processor;
900 1.1 christos mips_isa = mips_target_info.isa;
901 1.1 christos mips_ase = mips_target_info.ase;
902 1.1 christos #else
903 1.1 christos chosen_arch = choose_arch_by_number (info->mach);
904 1.1 christos if (chosen_arch != NULL)
905 1.1 christos {
906 1.1.1.3 christos mips_processor = chosen_arch->processor;
907 1.1 christos mips_isa = chosen_arch->isa;
908 1.1 christos mips_ase = chosen_arch->ase;
909 1.1 christos mips_cp0_names = chosen_arch->cp0_names;
910 1.1.1.3 christos mips_cp0sel_names = chosen_arch->cp0sel_names;
911 1.1 christos mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
912 1.1 christos mips_cp1_names = chosen_arch->cp1_names;
913 1.1.1.6 christos mips_hwr_names = chosen_arch->hwr_names;
914 1.1.1.6 christos }
915 1.1.1.6 christos
916 1.1.1.6 christos /* Update settings according to the ELF file header flags. */
917 1.1.1.6 christos if (info->flavour == bfd_target_elf_flavour && info->section != NULL)
918 1.1.1.6 christos {
919 1.1.1.6 christos struct bfd *abfd = info->section->owner;
920 1.1.1.6 christos Elf_Internal_Ehdr *header = elf_elfheader (abfd);
921 1.1.1.6 christos Elf_Internal_ABIFlags_v0 *abiflags = NULL;
922 1.1.1.6 christos
923 1.1.1.6 christos /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
924 1.1.1.6 christos because we won't then have a MIPS/ELF BFD, however we need
925 1.1.1.6 christos to guard against a link error in a `--enable-targets=...'
926 1.1.1.6 christos configuration with a 32-bit host where the MIPS target is
927 1.1.1.6 christos a secondary, or with MIPS/ECOFF configurations. */
928 1.1.1.6 christos #ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
929 1.1.1.6 christos abiflags = bfd_mips_elf_get_abiflags (abfd);
930 1.1.1.6 christos #endif
931 1.1.1.6 christos /* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
932 1.1.1.6 christos if (is_newabi (header))
933 1.1.1.6 christos mips_gpr_names = mips_gpr_names_newabi;
934 1.1.1.6 christos /* If a microMIPS binary, then don't use MIPS16 bindings. */
935 1.1.1.6 christos micromips_ase = is_micromips (header);
936 1.1.1.6 christos /* OR in any extra ASE flags set in ELF file structures. */
937 1.1.1.6 christos if (abiflags)
938 1.1.1.6 christos mips_ase |= mips_convert_abiflags_ases (abiflags->ases);
939 1.1.1.6 christos else if (header->e_flags & EF_MIPS_ARCH_ASE_MDMX)
940 1.1 christos mips_ase |= ASE_MDMX;
941 1.1.1.8 christos }
942 1.1 christos #endif
943 1.1 christos mips_ase |= mips_calculate_combination_ases (mips_isa, mips_ase);
944 1.1.1.7 christos }
945 1.1.1.7 christos
946 1.1.1.3 christos /* Parse an ASE disassembler option and set the corresponding global
947 1.1.1.9 christos ASE flag(s). Return TRUE if successful, FALSE otherwise. */
948 1.1.1.7 christos
949 1.1.1.7 christos static bool
950 1.1.1.9 christos parse_mips_ase_option (const char *option)
951 1.1.1.3 christos {
952 1.1.1.3 christos if (startswith (option, "msa"))
953 1.1.1.4 christos {
954 1.1.1.4 christos mips_ase |= ASE_MSA;
955 1.1.1.4 christos if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R2
956 1.1.1.4 christos || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R3
957 1.1.1.3 christos || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R5
958 1.1.1.9 christos || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6)
959 1.1.1.3 christos mips_ase |= ASE_MSA64;
960 1.1.1.3 christos return true;
961 1.1.1.9 christos }
962 1.1.1.3 christos
963 1.1.1.3 christos if (startswith (option, "virt"))
964 1.1.1.4 christos {
965 1.1.1.4 christos mips_ase |= ASE_VIRT;
966 1.1.1.4 christos if (mips_isa & ISA_MIPS64R2
967 1.1.1.4 christos || mips_isa & ISA_MIPS64R3
968 1.1.1.3 christos || mips_isa & ISA_MIPS64R5
969 1.1.1.9 christos || mips_isa & ISA_MIPS64R6)
970 1.1.1.3 christos mips_ase |= ASE_VIRT64;
971 1.1.1.4 christos return true;
972 1.1.1.9 christos }
973 1.1.1.4 christos
974 1.1.1.4 christos if (startswith (option, "xpa"))
975 1.1.1.9 christos {
976 1.1.1.7 christos mips_ase |= ASE_XPA;
977 1.1.1.7 christos return true;
978 1.1.1.9 christos }
979 1.1.1.7 christos
980 1.1.1.7 christos if (startswith (option, "ginv"))
981 1.1.1.9 christos {
982 1.1.1.7 christos mips_ase |= ASE_GINV;
983 1.1.1.7 christos return true;
984 1.1.1.9 christos }
985 1.1.1.7 christos
986 1.1.1.7 christos if (startswith (option, "loongson-mmi"))
987 1.1.1.9 christos {
988 1.1.1.7 christos mips_ase |= ASE_LOONGSON_MMI;
989 1.1.1.7 christos return true;
990 1.1.1.9 christos }
991 1.1.1.7 christos
992 1.1.1.7 christos if (startswith (option, "loongson-cam"))
993 1.1.1.9 christos {
994 1.1.1.7 christos mips_ase |= ASE_LOONGSON_CAM;
995 1.1.1.7 christos return true;
996 1.1.1.7 christos }
997 1.1.1.9 christos
998 1.1.1.7 christos /* Put here for match ext2 frist */
999 1.1.1.7 christos if (startswith (option, "loongson-ext2"))
1000 1.1.1.9 christos {
1001 1.1.1.7 christos mips_ase |= ASE_LOONGSON_EXT2;
1002 1.1.1.7 christos return true;
1003 1.1.1.9 christos }
1004 1.1.1.7 christos
1005 1.1.1.7 christos if (startswith (option, "loongson-ext"))
1006 1.1.1.9 christos {
1007 1.1.1.7 christos mips_ase |= ASE_LOONGSON_EXT;
1008 1.1.1.7 christos return true;
1009 1.1.1.9 christos }
1010 1.1.1.7 christos
1011 1.1.1.7 christos return false;
1012 1.1.1.7 christos }
1013 1.1.1.7 christos
1014 1.1.1.7 christos static void
1015 1.1.1.7 christos parse_mips_dis_option (const char *option, unsigned int len)
1016 1.1.1.7 christos {
1017 1.1.1.7 christos unsigned int i, optionlen, vallen;
1018 1.1.1.7 christos const char *val;
1019 1.1.1.7 christos const struct mips_abi_choice *chosen_abi;
1020 1.1.1.7 christos const struct mips_arch_choice *chosen_arch;
1021 1.1.1.9 christos
1022 1.1.1.7 christos /* Try to match options that are simple flags */
1023 1.1.1.7 christos if (startswith (option, "no-aliases"))
1024 1.1.1.4 christos {
1025 1.1.1.4 christos no_aliases = 1;
1026 1.1.1.5 christos return;
1027 1.1.1.7 christos }
1028 1.1.1.7 christos
1029 1.1.1.8 christos if (parse_mips_ase_option (option))
1030 1.1.1.7 christos {
1031 1.1.1.7 christos mips_ase |= mips_calculate_combination_ases (mips_isa, mips_ase);
1032 1.1.1.5 christos return;
1033 1.1 christos }
1034 1.1 christos
1035 1.1 christos /* Look for the = that delimits the end of the option name. */
1036 1.1 christos for (i = 0; i < len; i++)
1037 1.1 christos if (option[i] == '=')
1038 1.1 christos break;
1039 1.1 christos
1040 1.1 christos if (i == 0) /* Invalid option: no name before '='. */
1041 1.1 christos return;
1042 1.1 christos if (i == len) /* Invalid option: no '='. */
1043 1.1 christos return;
1044 1.1 christos if (i == (len - 1)) /* Invalid option: no value after '='. */
1045 1.1 christos return;
1046 1.1 christos
1047 1.1 christos optionlen = i;
1048 1.1 christos val = option + (optionlen + 1);
1049 1.1 christos vallen = len - (optionlen + 1);
1050 1.1 christos
1051 1.1 christos if (strncmp ("gpr-names", option, optionlen) == 0
1052 1.1 christos && strlen ("gpr-names") == optionlen)
1053 1.1 christos {
1054 1.1 christos chosen_abi = choose_abi_by_name (val, vallen);
1055 1.1 christos if (chosen_abi != NULL)
1056 1.1 christos mips_gpr_names = chosen_abi->gpr_names;
1057 1.1 christos return;
1058 1.1 christos }
1059 1.1 christos
1060 1.1 christos if (strncmp ("fpr-names", option, optionlen) == 0
1061 1.1 christos && strlen ("fpr-names") == optionlen)
1062 1.1 christos {
1063 1.1 christos chosen_abi = choose_abi_by_name (val, vallen);
1064 1.1 christos if (chosen_abi != NULL)
1065 1.1 christos mips_fpr_names = chosen_abi->fpr_names;
1066 1.1 christos return;
1067 1.1 christos }
1068 1.1 christos
1069 1.1 christos if (strncmp ("cp0-names", option, optionlen) == 0
1070 1.1 christos && strlen ("cp0-names") == optionlen)
1071 1.1 christos {
1072 1.1 christos chosen_arch = choose_arch_by_name (val, vallen);
1073 1.1 christos if (chosen_arch != NULL)
1074 1.1 christos {
1075 1.1 christos mips_cp0_names = chosen_arch->cp0_names;
1076 1.1 christos mips_cp0sel_names = chosen_arch->cp0sel_names;
1077 1.1 christos mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
1078 1.1 christos }
1079 1.1 christos return;
1080 1.1.1.3 christos }
1081 1.1.1.3 christos
1082 1.1.1.3 christos if (strncmp ("cp1-names", option, optionlen) == 0
1083 1.1.1.3 christos && strlen ("cp1-names") == optionlen)
1084 1.1.1.3 christos {
1085 1.1.1.3 christos chosen_arch = choose_arch_by_name (val, vallen);
1086 1.1.1.3 christos if (chosen_arch != NULL)
1087 1.1.1.3 christos mips_cp1_names = chosen_arch->cp1_names;
1088 1.1.1.3 christos return;
1089 1.1 christos }
1090 1.1 christos
1091 1.1 christos if (strncmp ("hwr-names", option, optionlen) == 0
1092 1.1 christos && strlen ("hwr-names") == optionlen)
1093 1.1 christos {
1094 1.1 christos chosen_arch = choose_arch_by_name (val, vallen);
1095 1.1 christos if (chosen_arch != NULL)
1096 1.1 christos mips_hwr_names = chosen_arch->hwr_names;
1097 1.1 christos return;
1098 1.1 christos }
1099 1.1 christos
1100 1.1 christos if (strncmp ("reg-names", option, optionlen) == 0
1101 1.1 christos && strlen ("reg-names") == optionlen)
1102 1.1 christos {
1103 1.1 christos /* We check both ABI and ARCH here unconditionally, so
1104 1.1 christos that "numeric" will do the desirable thing: select
1105 1.1 christos numeric register names for all registers. Other than
1106 1.1 christos that, a given name probably won't match both. */
1107 1.1 christos chosen_abi = choose_abi_by_name (val, vallen);
1108 1.1 christos if (chosen_abi != NULL)
1109 1.1 christos {
1110 1.1 christos mips_gpr_names = chosen_abi->gpr_names;
1111 1.1 christos mips_fpr_names = chosen_abi->fpr_names;
1112 1.1 christos }
1113 1.1 christos chosen_arch = choose_arch_by_name (val, vallen);
1114 1.1 christos if (chosen_arch != NULL)
1115 1.1 christos {
1116 1.1 christos mips_cp0_names = chosen_arch->cp0_names;
1117 1.1.1.3 christos mips_cp0sel_names = chosen_arch->cp0sel_names;
1118 1.1 christos mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
1119 1.1 christos mips_cp1_names = chosen_arch->cp1_names;
1120 1.1 christos mips_hwr_names = chosen_arch->hwr_names;
1121 1.1 christos }
1122 1.1 christos return;
1123 1.1 christos }
1124 1.1 christos
1125 1.1 christos /* Invalid option. */
1126 1.1 christos }
1127 1.1 christos
1128 1.1 christos static void
1129 1.1 christos parse_mips_dis_options (const char *options)
1130 1.1 christos {
1131 1.1 christos const char *option_end;
1132 1.1 christos
1133 1.1 christos if (options == NULL)
1134 1.1 christos return;
1135 1.1 christos
1136 1.1 christos while (*options != '\0')
1137 1.1 christos {
1138 1.1 christos /* Skip empty options. */
1139 1.1 christos if (*options == ',')
1140 1.1 christos {
1141 1.1 christos options++;
1142 1.1 christos continue;
1143 1.1 christos }
1144 1.1 christos
1145 1.1 christos /* We know that *options is neither NUL or a comma. */
1146 1.1 christos option_end = options + 1;
1147 1.1 christos while (*option_end != ',' && *option_end != '\0')
1148 1.1 christos option_end++;
1149 1.1 christos
1150 1.1 christos parse_mips_dis_option (options, option_end - options);
1151 1.1 christos
1152 1.1 christos /* Go on to the next one. If option_end points to a comma, it
1153 1.1 christos will be skipped above. */
1154 1.1 christos options = option_end;
1155 1.1 christos }
1156 1.1 christos }
1157 1.1 christos
1158 1.1 christos static const struct mips_cp0sel_name *
1159 1.1 christos lookup_mips_cp0sel_name (const struct mips_cp0sel_name *names,
1160 1.1 christos unsigned int len,
1161 1.1 christos unsigned int cp0reg,
1162 1.1 christos unsigned int sel)
1163 1.1 christos {
1164 1.1 christos unsigned int i;
1165 1.1 christos
1166 1.1 christos for (i = 0; i < len; i++)
1167 1.1 christos if (names[i].cp0reg == cp0reg && names[i].sel == sel)
1168 1.1 christos return &names[i];
1169 1.1.1.3 christos return NULL;
1170 1.1.1.3 christos }
1171 1.1 christos
1172 1.1 christos /* Print register REGNO, of type TYPE, for instruction OPCODE. */
1173 1.1.1.3 christos
1174 1.1.1.3 christos static void
1175 1.1 christos print_reg (struct disassemble_info *info, const struct mips_opcode *opcode,
1176 1.1.1.9 christos enum mips_reg_operand_type type, int regno)
1177 1.1.1.9 christos {
1178 1.1.1.3 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1179 1.1 christos
1180 1.1.1.3 christos switch (type)
1181 1.1.1.9 christos {
1182 1.1.1.9 christos case OP_REG_GP:
1183 1.1.1.3 christos infprintf (info->stream, dis_style_register, "%s",
1184 1.1 christos mips_gpr_names[regno]);
1185 1.1.1.3 christos break;
1186 1.1.1.9 christos
1187 1.1.1.9 christos case OP_REG_FP:
1188 1.1.1.3 christos infprintf (info->stream, dis_style_register, "%s",
1189 1.1 christos mips_fpr_names[regno]);
1190 1.1.1.3 christos break;
1191 1.1.1.3 christos
1192 1.1.1.9 christos case OP_REG_CCC:
1193 1.1.1.3 christos if (opcode->pinfo & (FP_D | FP_S))
1194 1.1.1.9 christos infprintf (info->stream, dis_style_register, "$fcc%d", regno);
1195 1.1.1.3 christos else
1196 1.1 christos infprintf (info->stream, dis_style_register, "$cc%d", regno);
1197 1.1.1.3 christos break;
1198 1.1.1.3 christos
1199 1.1.1.9 christos case OP_REG_VEC:
1200 1.1.1.3 christos if (opcode->membership & INSN_5400)
1201 1.1.1.9 christos infprintf (info->stream, dis_style_register, "$f%d", regno);
1202 1.1.1.3 christos else
1203 1.1 christos infprintf (info->stream, dis_style_register, "$v%d", regno);
1204 1.1.1.3 christos break;
1205 1.1.1.9 christos
1206 1.1.1.3 christos case OP_REG_ACC:
1207 1.1 christos infprintf (info->stream, dis_style_register, "$ac%d", regno);
1208 1.1.1.3 christos break;
1209 1.1.1.3 christos
1210 1.1.1.9 christos case OP_REG_COPRO:
1211 1.1.1.3 christos if (opcode->name[strlen (opcode->name) - 1] == '0')
1212 1.1.1.9 christos infprintf (info->stream, dis_style_register, "%s", mips_cp0_names[regno]);
1213 1.1.1.9 christos else
1214 1.1.1.9 christos infprintf (info->stream, dis_style_register, "$%d", regno);
1215 1.1.1.9 christos break;
1216 1.1.1.9 christos
1217 1.1.1.9 christos case OP_REG_CONTROL:
1218 1.1.1.9 christos if (opcode->name[strlen (opcode->name) - 1] == '1')
1219 1.1.1.9 christos infprintf (info->stream, dis_style_register, "%s", mips_cp1_names[regno]);
1220 1.1.1.3 christos else
1221 1.1 christos infprintf (info->stream, dis_style_register, "$%d", regno);
1222 1.1.1.3 christos break;
1223 1.1.1.9 christos
1224 1.1.1.3 christos case OP_REG_HW:
1225 1.1 christos infprintf (info->stream, dis_style_register, "%s", mips_hwr_names[regno]);
1226 1.1.1.3 christos break;
1227 1.1.1.9 christos
1228 1.1.1.3 christos case OP_REG_VF:
1229 1.1 christos infprintf (info->stream, dis_style_register, "$vf%d", regno);
1230 1.1.1.3 christos break;
1231 1.1.1.9 christos
1232 1.1.1.3 christos case OP_REG_VI:
1233 1.1 christos infprintf (info->stream, dis_style_register, "$vi%d", regno);
1234 1.1.1.3 christos break;
1235 1.1.1.9 christos
1236 1.1.1.3 christos case OP_REG_R5900_I:
1237 1.1 christos infprintf (info->stream, dis_style_register, "$I");
1238 1.1.1.3 christos break;
1239 1.1.1.9 christos
1240 1.1.1.3 christos case OP_REG_R5900_Q:
1241 1.1 christos infprintf (info->stream, dis_style_register, "$Q");
1242 1.1.1.3 christos break;
1243 1.1.1.9 christos
1244 1.1.1.3 christos case OP_REG_R5900_R:
1245 1.1 christos infprintf (info->stream, dis_style_register, "$R");
1246 1.1.1.3 christos break;
1247 1.1.1.9 christos
1248 1.1.1.3 christos case OP_REG_R5900_ACC:
1249 1.1 christos infprintf (info->stream, dis_style_register, "$ACC");
1250 1.1.1.3 christos break;
1251 1.1.1.9 christos
1252 1.1.1.3 christos case OP_REG_MSA:
1253 1.1 christos infprintf (info->stream, dis_style_register, "$w%d", regno);
1254 1.1.1.3 christos break;
1255 1.1.1.9 christos
1256 1.1.1.9 christos case OP_REG_MSA_CTRL:
1257 1.1.1.3 christos infprintf (info->stream, dis_style_register, "%s",
1258 1.1 christos msa_control_names[regno]);
1259 1.1.1.3 christos break;
1260 1.1.1.3 christos
1261 1.1.1.3 christos }
1262 1.1.1.3 christos }
1263 1.1.1.3 christos
1264 1.1.1.3 christos /* Used to track the state carried over from previous operands in
1266 1.1.1.3 christos an instruction. */
1267 1.1.1.3 christos struct mips_print_arg_state {
1268 1.1 christos /* The value of the last OP_INT seen. We only use this for OP_MSB,
1269 1.1.1.3 christos where the value is known to be unsigned and small. */
1270 1.1.1.3 christos unsigned int last_int;
1271 1.1.1.3 christos
1272 1.1.1.3 christos /* The type and number of the last OP_REG seen. We only use this for
1273 1.1.1.4 christos OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG. */
1274 1.1.1.4 christos enum mips_reg_operand_type last_reg_type;
1275 1.1.1.3 christos unsigned int last_regno;
1276 1.1 christos unsigned int dest_regno;
1277 1.1.1.3 christos unsigned int seen_dest;
1278 1.1 christos };
1279 1.1.1.3 christos
1280 1.1.1.3 christos /* Initialize STATE for the start of an instruction. */
1281 1.1.1.3 christos
1282 1.1.1.3 christos static inline void
1283 1.1.1.3 christos init_print_arg_state (struct mips_print_arg_state *state)
1284 1.1.1.2 christos {
1285 1.1.1.3 christos memset (state, 0, sizeof (*state));
1286 1.1.1.3 christos }
1287 1.1.1.2 christos
1288 1.1.1.3 christos /* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
1289 1.1.1.3 christos whose value is given by UVAL. */
1290 1.1.1.9 christos
1291 1.1.1.9 christos static void
1292 1.1.1.3 christos print_vu0_channel (struct disassemble_info *info,
1293 1.1.1.9 christos const struct mips_operand *operand, unsigned int uval,
1294 1.1.1.9 christos enum disassembler_style style)
1295 1.1.1.3 christos {
1296 1.1.1.9 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1297 1.1.1.3 christos
1298 1.1.1.3 christos if (operand->size == 4)
1299 1.1.1.3 christos infprintf (info->stream, style, "%s%s%s%s",
1300 1.1.1.3 christos uval & 8 ? "x" : "",
1301 1.1.1.3 christos uval & 4 ? "y" : "",
1302 1.1.1.9 christos uval & 2 ? "z" : "",
1303 1.1.1.3 christos uval & 1 ? "w" : "");
1304 1.1.1.3 christos else if (operand->size == 2)
1305 1.1.1.3 christos infprintf (info->stream, style, "%c", "xyzw"[uval]);
1306 1.1 christos else
1307 1.1.1.4 christos abort ();
1308 1.1.1.4 christos }
1309 1.1.1.4 christos
1310 1.1.1.4 christos /* Record information about a register operand. */
1311 1.1.1.4 christos
1312 1.1.1.4 christos static void
1313 1.1.1.4 christos mips_seen_register (struct mips_print_arg_state *state,
1314 1.1.1.4 christos unsigned int regno,
1315 1.1.1.4 christos enum mips_reg_operand_type reg_type)
1316 1.1.1.4 christos {
1317 1.1.1.4 christos state->last_reg_type = reg_type;
1318 1.1.1.4 christos state->last_regno = regno;
1319 1.1.1.4 christos
1320 1.1.1.4 christos if (!state->seen_dest)
1321 1.1.1.4 christos {
1322 1.1.1.4 christos state->seen_dest = 1;
1323 1.1.1.4 christos state->dest_regno = regno;
1324 1.1.1.7 christos }
1325 1.1.1.7 christos }
1326 1.1.1.7 christos
1327 1.1.1.7 christos /* Print SAVE/RESTORE instruction operands according to the argument
1328 1.1.1.7 christos register mask AMASK, the number of static registers saved NSREG,
1329 1.1.1.7 christos the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
1330 1.1.1.7 christos and the frame size FRAME_SIZE. */
1331 1.1.1.7 christos
1332 1.1.1.7 christos static void
1333 1.1.1.7 christos mips_print_save_restore (struct disassemble_info *info, unsigned int amask,
1334 1.1.1.7 christos unsigned int nsreg, unsigned int ra,
1335 1.1.1.9 christos unsigned int s0, unsigned int s1,
1336 1.1.1.7 christos unsigned int frame_size)
1337 1.1.1.7 christos {
1338 1.1.1.7 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1339 1.1.1.7 christos unsigned int nargs, nstatics, smask, i, j;
1340 1.1.1.7 christos void *is = info->stream;
1341 1.1.1.7 christos const char *sep;
1342 1.1.1.7 christos
1343 1.1.1.7 christos if (amask == MIPS_SVRS_ALL_ARGS)
1344 1.1.1.7 christos {
1345 1.1.1.7 christos nargs = 4;
1346 1.1.1.7 christos nstatics = 0;
1347 1.1.1.7 christos }
1348 1.1.1.7 christos else if (amask == MIPS_SVRS_ALL_STATICS)
1349 1.1.1.7 christos {
1350 1.1.1.7 christos nargs = 0;
1351 1.1.1.7 christos nstatics = 4;
1352 1.1.1.7 christos }
1353 1.1.1.7 christos else
1354 1.1.1.7 christos {
1355 1.1.1.7 christos nargs = amask >> 2;
1356 1.1.1.7 christos nstatics = amask & 3;
1357 1.1.1.7 christos }
1358 1.1.1.7 christos
1359 1.1.1.9 christos sep = "";
1360 1.1.1.7 christos if (nargs > 0)
1361 1.1.1.9 christos {
1362 1.1.1.7 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[4]);
1363 1.1.1.7 christos if (nargs > 1)
1364 1.1.1.7 christos infprintf (is, dis_style_register, "-%s", mips_gpr_names[4 + nargs - 1]);
1365 1.1.1.9 christos sep = ",";
1366 1.1.1.9 christos }
1367 1.1.1.7 christos
1368 1.1.1.7 christos infprintf (is, dis_style_text, "%s", sep);
1369 1.1.1.9 christos infprintf (is, dis_style_immediate, "%d", frame_size);
1370 1.1.1.9 christos
1371 1.1.1.9 christos if (ra) /* $ra */
1372 1.1.1.9 christos {
1373 1.1.1.7 christos infprintf (is, dis_style_text, ",");
1374 1.1.1.7 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[31]);
1375 1.1.1.7 christos }
1376 1.1.1.7 christos
1377 1.1.1.7 christos smask = 0;
1378 1.1.1.7 christos if (s0) /* $s0 */
1379 1.1.1.7 christos smask |= 1 << 0;
1380 1.1.1.7 christos if (s1) /* $s1 */
1381 1.1.1.7 christos smask |= 1 << 1;
1382 1.1.1.7 christos if (nsreg > 0) /* $s2-$s8 */
1383 1.1.1.7 christos smask |= ((1 << nsreg) - 1) << 2;
1384 1.1.1.7 christos
1385 1.1.1.9 christos for (i = 0; i < 9; i++)
1386 1.1.1.9 christos if (smask & (1 << i))
1387 1.1.1.9 christos {
1388 1.1.1.7 christos infprintf (is, dis_style_text, ",");
1389 1.1.1.7 christos infprintf (is, dis_style_register, "%s",
1390 1.1.1.7 christos mips_gpr_names[i == 8 ? 30 : (16 + i)]);
1391 1.1.1.7 christos /* Skip over string of set bits. */
1392 1.1.1.9 christos for (j = i; smask & (2 << j); j++)
1393 1.1.1.9 christos continue;
1394 1.1.1.9 christos if (j > i)
1395 1.1.1.9 christos {
1396 1.1.1.9 christos infprintf (is, dis_style_text, "-");
1397 1.1.1.7 christos infprintf (is, dis_style_register, "%s",
1398 1.1.1.7 christos mips_gpr_names[j == 8 ? 30 : (16 + j)]);
1399 1.1.1.7 christos }
1400 1.1.1.7 christos i = j + 1;
1401 1.1.1.9 christos }
1402 1.1.1.9 christos /* Statics $ax - $a3. */
1403 1.1.1.9 christos if (nstatics == 1)
1404 1.1.1.9 christos {
1405 1.1.1.7 christos infprintf (is, dis_style_text, ",");
1406 1.1.1.9 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[7]);
1407 1.1.1.9 christos }
1408 1.1.1.9 christos else if (nstatics > 0)
1409 1.1.1.9 christos {
1410 1.1.1.9 christos infprintf (is, dis_style_text, ",");
1411 1.1.1.9 christos infprintf (is, dis_style_register, "%s",
1412 1.1.1.9 christos mips_gpr_names[7 - nstatics + 1]);
1413 1.1.1.7 christos infprintf (is, dis_style_text, "-");
1414 1.1.1.7 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[7]);
1415 1.1.1.7 christos }
1416 1.1.1.3 christos }
1417 1.1.1.3 christos
1418 1.1.1.3 christos
1419 1.1 christos /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
1420 1.1.1.3 christos UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
1421 1.1.1.3 christos the base address for OP_PCREL operands. */
1422 1.1.1.3 christos
1423 1.1.1.3 christos static void
1424 1.1.1.3 christos print_insn_arg (struct disassemble_info *info,
1425 1.1.1.3 christos struct mips_print_arg_state *state,
1426 1.1.1.3 christos const struct mips_opcode *opcode,
1427 1.1.1.3 christos const struct mips_operand *operand,
1428 1.1.1.9 christos bfd_vma base_pc,
1429 1.1.1.3 christos unsigned int uval)
1430 1.1 christos {
1431 1.1.1.3 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1432 1.1.1.3 christos void *is = info->stream;
1433 1.1.1.3 christos
1434 1.1.1.3 christos switch (operand->type)
1435 1.1.1.3 christos {
1436 1.1 christos case OP_INT:
1437 1.1.1.3 christos {
1438 1.1.1.3 christos const struct mips_int_operand *int_op;
1439 1.1.1.3 christos
1440 1.1.1.3 christos int_op = (const struct mips_int_operand *) operand;
1441 1.1.1.9 christos uval = mips_decode_int_operand (int_op, uval);
1442 1.1.1.3 christos state->last_int = uval;
1443 1.1.1.9 christos if (int_op->print_hex)
1444 1.1.1.3 christos infprintf (is, dis_style_immediate, "0x%x", uval);
1445 1.1.1.3 christos else
1446 1.1 christos infprintf (is, dis_style_immediate, "%d", uval);
1447 1.1.1.3 christos }
1448 1.1.1.3 christos break;
1449 1.1.1.3 christos
1450 1.1 christos case OP_MAPPED_INT:
1451 1.1.1.3 christos {
1452 1.1.1.3 christos const struct mips_mapped_int_operand *mint_op;
1453 1.1.1.3 christos
1454 1.1.1.3 christos mint_op = (const struct mips_mapped_int_operand *) operand;
1455 1.1.1.9 christos uval = mint_op->int_map[uval];
1456 1.1.1.3 christos state->last_int = uval;
1457 1.1.1.9 christos if (mint_op->print_hex)
1458 1.1.1.3 christos infprintf (is, dis_style_immediate, "0x%x", uval);
1459 1.1.1.3 christos else
1460 1.1 christos infprintf (is, dis_style_immediate, "%d", uval);
1461 1.1.1.3 christos }
1462 1.1.1.3 christos break;
1463 1.1.1.3 christos
1464 1.1 christos case OP_MSB:
1465 1.1.1.3 christos {
1466 1.1.1.3 christos const struct mips_msb_operand *msb_op;
1467 1.1.1.3 christos
1468 1.1.1.3 christos msb_op = (const struct mips_msb_operand *) operand;
1469 1.1.1.9 christos uval += msb_op->bias;
1470 1.1.1.3 christos if (msb_op->add_lsb)
1471 1.1.1.3 christos uval -= state->last_int;
1472 1.1 christos infprintf (is, dis_style_immediate, "0x%x", uval);
1473 1.1.1.3 christos }
1474 1.1.1.3 christos break;
1475 1.1.1.3 christos
1476 1.1.1.3 christos case OP_REG:
1477 1.1 christos case OP_OPTIONAL_REG:
1478 1.1.1.3 christos {
1479 1.1.1.3 christos const struct mips_reg_operand *reg_op;
1480 1.1.1.3 christos
1481 1.1 christos reg_op = (const struct mips_reg_operand *) operand;
1482 1.1.1.4 christos uval = mips_decode_reg_operand (reg_op, uval);
1483 1.1.1.3 christos print_reg (info, opcode, reg_op->reg_type, uval);
1484 1.1.1.3 christos
1485 1.1 christos mips_seen_register (state, uval, reg_op->reg_type);
1486 1.1.1.3 christos }
1487 1.1.1.3 christos break;
1488 1.1.1.3 christos
1489 1.1 christos case OP_REG_PAIR:
1490 1.1.1.3 christos {
1491 1.1.1.3 christos const struct mips_reg_pair_operand *pair_op;
1492 1.1.1.3 christos
1493 1.1.1.9 christos pair_op = (const struct mips_reg_pair_operand *) operand;
1494 1.1.1.3 christos print_reg (info, opcode, pair_op->reg_type,
1495 1.1.1.3 christos pair_op->reg1_map[uval]);
1496 1.1.1.3 christos infprintf (is, dis_style_text, ",");
1497 1.1.1.3 christos print_reg (info, opcode, pair_op->reg_type,
1498 1.1 christos pair_op->reg2_map[uval]);
1499 1.1.1.3 christos }
1500 1.1.1.3 christos break;
1501 1.1.1.3 christos
1502 1.1 christos case OP_PCREL:
1503 1.1.1.3 christos {
1504 1.1.1.3 christos const struct mips_pcrel_operand *pcrel_op;
1505 1.1 christos
1506 1.1.1.7 christos pcrel_op = (const struct mips_pcrel_operand *) operand;
1507 1.1.1.7 christos info->target = mips_decode_pcrel_operand (pcrel_op, base_pc, uval);
1508 1.1.1.7 christos
1509 1.1.1.7 christos /* For jumps and branches clear the ISA bit except for
1510 1.1.1.3 christos the GDB disassembler. */
1511 1.1 christos if (pcrel_op->include_isa_bit
1512 1.1.1.3 christos && info->flavour != bfd_target_unknown_flavour)
1513 1.1.1.3 christos info->target &= -2;
1514 1.1.1.3 christos
1515 1.1.1.2 christos (*info->print_address_func) (info->target, info);
1516 1.1.1.3 christos }
1517 1.1.1.9 christos break;
1518 1.1.1.3 christos
1519 1.1 christos case OP_PERF_REG:
1520 1.1.1.3 christos infprintf (is, dis_style_register, "%d", uval);
1521 1.1.1.3 christos break;
1522 1.1.1.3 christos
1523 1.1 christos case OP_ADDIUSP_INT:
1524 1.1.1.3 christos {
1525 1.1.1.3 christos int sval;
1526 1.1.1.3 christos
1527 1.1.1.9 christos sval = mips_signed_operand (operand, uval) * 4;
1528 1.1.1.3 christos if (sval >= -8 && sval < 8)
1529 1.1.1.3 christos sval ^= 0x400;
1530 1.1 christos infprintf (is, dis_style_immediate, "%d", sval);
1531 1.1.1.3 christos break;
1532 1.1.1.3 christos }
1533 1.1.1.3 christos
1534 1.1 christos case OP_CLO_CLZ_DEST:
1535 1.1.1.3 christos {
1536 1.1.1.3 christos unsigned int reg1, reg2;
1537 1.1.1.3 christos
1538 1.1.1.3 christos reg1 = uval & 31;
1539 1.1.1.9 christos reg2 = uval >> 5;
1540 1.1.1.3 christos /* If one is zero use the other. */
1541 1.1.1.9 christos if (reg1 == reg2 || reg2 == 0)
1542 1.1.1.3 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[reg1]);
1543 1.1.1.9 christos else if (reg1 == 0)
1544 1.1.1.9 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[reg2]);
1545 1.1.1.9 christos else
1546 1.1.1.9 christos {
1547 1.1.1.9 christos /* Bogus, result depends on processor. */
1548 1.1.1.9 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[reg1]);
1549 1.1.1.3 christos infprintf (is, dis_style_text, " or ");
1550 1.1.1.3 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[reg2]);
1551 1.1 christos }
1552 1.1.1.4 christos }
1553 1.1.1.4 christos break;
1554 1.1.1.4 christos
1555 1.1.1.4 christos case OP_SAME_RS_RT:
1556 1.1.1.4 christos case OP_CHECK_PREV:
1557 1.1.1.4 christos case OP_NON_ZERO_REG:
1558 1.1.1.4 christos {
1559 1.1.1.4 christos print_reg (info, opcode, OP_REG_GP, uval & 31);
1560 1.1.1.4 christos mips_seen_register (state, uval, OP_REG_GP);
1561 1.1.1.3 christos }
1562 1.1.1.3 christos break;
1563 1.1.1.3 christos
1564 1.1.1.3 christos case OP_LWM_SWM_LIST:
1565 1.1.1.9 christos if (operand->size == 2)
1566 1.1.1.9 christos {
1567 1.1.1.9 christos if (uval == 0)
1568 1.1.1.9 christos {
1569 1.1.1.9 christos infprintf (is, dis_style_register, "%s",
1570 1.1.1.9 christos mips_gpr_names[16]);
1571 1.1.1.9 christos infprintf (is, dis_style_text, ",");
1572 1.1.1.3 christos infprintf (is, dis_style_register, "%s",
1573 1.1.1.9 christos mips_gpr_names[31]);
1574 1.1.1.9 christos }
1575 1.1.1.9 christos else
1576 1.1.1.9 christos {
1577 1.1.1.9 christos infprintf (is, dis_style_register, "%s",
1578 1.1.1.9 christos mips_gpr_names[16]);
1579 1.1.1.9 christos infprintf (is, dis_style_text, "-");
1580 1.1.1.9 christos infprintf (is, dis_style_register, "%s",
1581 1.1.1.9 christos mips_gpr_names[16 + uval]);
1582 1.1.1.9 christos infprintf (is, dis_style_text, ",");
1583 1.1.1.3 christos infprintf (is, dis_style_register, "%s",
1584 1.1.1.3 christos mips_gpr_names[31]);
1585 1.1.1.3 christos }
1586 1.1.1.3 christos }
1587 1.1 christos else
1588 1.1.1.3 christos {
1589 1.1.1.3 christos int s_reg_encode;
1590 1.1.1.3 christos
1591 1.1.1.3 christos s_reg_encode = uval & 0xf;
1592 1.1.1.9 christos if (s_reg_encode != 0)
1593 1.1.1.3 christos {
1594 1.1.1.9 christos if (s_reg_encode == 1)
1595 1.1.1.9 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[16]);
1596 1.1.1.9 christos else if (s_reg_encode < 9)
1597 1.1.1.9 christos {
1598 1.1.1.9 christos infprintf (is, dis_style_register, "%s",
1599 1.1.1.9 christos mips_gpr_names[16]);
1600 1.1.1.9 christos infprintf (is, dis_style_text, "-");
1601 1.1.1.3 christos infprintf (is, dis_style_register, "%s",
1602 1.1.1.9 christos mips_gpr_names[15 + s_reg_encode]);
1603 1.1.1.9 christos }
1604 1.1.1.9 christos else if (s_reg_encode == 9)
1605 1.1.1.9 christos {
1606 1.1.1.9 christos infprintf (is, dis_style_register, "%s",
1607 1.1.1.9 christos mips_gpr_names[16]);
1608 1.1.1.9 christos infprintf (is, dis_style_text, "-");
1609 1.1.1.9 christos infprintf (is, dis_style_register, "%s",
1610 1.1.1.9 christos mips_gpr_names[23]);
1611 1.1.1.9 christos infprintf (is, dis_style_text, ",");
1612 1.1.1.3 christos infprintf (is, dis_style_register, "%s",
1613 1.1.1.9 christos mips_gpr_names[30]);
1614 1.1.1.3 christos }
1615 1.1 christos else
1616 1.1.1.3 christos infprintf (is, dis_style_text, "UNKNOWN");
1617 1.1.1.3 christos }
1618 1.1.1.3 christos
1619 1.1.1.9 christos if (uval & 0x10) /* For ra. */
1620 1.1.1.3 christos {
1621 1.1.1.9 christos if (s_reg_encode == 0)
1622 1.1.1.9 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[31]);
1623 1.1.1.9 christos else
1624 1.1.1.9 christos {
1625 1.1.1.9 christos infprintf (is, dis_style_text, ",");
1626 1.1.1.3 christos infprintf (is, dis_style_register, "%s",
1627 1.1.1.3 christos mips_gpr_names[31]);
1628 1.1.1.3 christos }
1629 1.1 christos }
1630 1.1.1.3 christos }
1631 1.1.1.3 christos break;
1632 1.1.1.3 christos
1633 1.1.1.3 christos case OP_ENTRY_EXIT_LIST:
1634 1.1 christos {
1635 1.1.1.3 christos const char *sep;
1636 1.1.1.3 christos unsigned int amask, smask;
1637 1.1.1.3 christos
1638 1.1.1.3 christos sep = "";
1639 1.1.1.9 christos amask = (uval >> 3) & 7;
1640 1.1.1.3 christos if (amask > 0 && amask < 5)
1641 1.1.1.9 christos {
1642 1.1.1.9 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[4]);
1643 1.1.1.9 christos if (amask > 1)
1644 1.1.1.9 christos {
1645 1.1.1.9 christos infprintf (is, dis_style_text, "-");
1646 1.1.1.3 christos infprintf (is, dis_style_register, "%s",
1647 1.1.1.3 christos mips_gpr_names[amask + 3]);
1648 1.1 christos }
1649 1.1.1.3 christos sep = ",";
1650 1.1.1.3 christos }
1651 1.1.1.3 christos
1652 1.1.1.9 christos smask = (uval >> 1) & 3;
1653 1.1.1.3 christos if (smask == 3)
1654 1.1.1.3 christos {
1655 1.1.1.3 christos infprintf (is, dis_style_text, "%s??", sep);
1656 1.1.1.3 christos sep = ",";
1657 1.1.1.9 christos }
1658 1.1.1.9 christos else if (smask > 0)
1659 1.1.1.3 christos {
1660 1.1.1.9 christos infprintf (is, dis_style_text, "%s", sep);
1661 1.1.1.9 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[16]);
1662 1.1.1.9 christos if (smask > 1)
1663 1.1.1.9 christos {
1664 1.1.1.9 christos infprintf (is, dis_style_text, "-");
1665 1.1.1.3 christos infprintf (is, dis_style_register, "%s",
1666 1.1.1.3 christos mips_gpr_names[smask + 15]);
1667 1.1 christos }
1668 1.1.1.3 christos sep = ",";
1669 1.1.1.3 christos }
1670 1.1.1.9 christos
1671 1.1.1.9 christos if (uval & 1)
1672 1.1.1.3 christos {
1673 1.1.1.3 christos infprintf (is, dis_style_text, "%s", sep);
1674 1.1 christos infprintf (is, dis_style_register, "%s", mips_gpr_names[31]);
1675 1.1.1.3 christos sep = ",";
1676 1.1.1.3 christos }
1677 1.1.1.9 christos
1678 1.1.1.9 christos if (amask == 5 || amask == 6)
1679 1.1.1.3 christos {
1680 1.1.1.9 christos infprintf (is, dis_style_text, "%s", sep);
1681 1.1.1.9 christos infprintf (is, dis_style_register, "%s", mips_fpr_names[0]);
1682 1.1.1.9 christos if (amask == 6)
1683 1.1.1.9 christos {
1684 1.1.1.3 christos infprintf (is, dis_style_text, "-");
1685 1.1.1.3 christos infprintf (is, dis_style_register, "%s", mips_fpr_names[1]);
1686 1.1.1.3 christos }
1687 1.1 christos }
1688 1.1.1.3 christos }
1689 1.1.1.7 christos break;
1690 1.1.1.3 christos
1691 1.1 christos case OP_SAVE_RESTORE_LIST:
1692 1.1.1.3 christos /* Should be handled by the caller due to complex behavior. */
1693 1.1.1.3 christos abort ();
1694 1.1.1.3 christos
1695 1.1 christos case OP_MDMX_IMM_REG:
1696 1.1.1.3 christos {
1697 1.1.1.3 christos unsigned int vsel;
1698 1.1.1.3 christos
1699 1.1.1.3 christos vsel = uval >> 5;
1700 1.1.1.3 christos uval &= 31;
1701 1.1 christos if ((vsel & 0x10) == 0)
1702 1.1.1.3 christos {
1703 1.1.1.3 christos int fmt;
1704 1.1.1.3 christos
1705 1.1.1.3 christos vsel &= 0x0f;
1706 1.1.1.3 christos for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
1707 1.1.1.9 christos if ((vsel & 1) == 0)
1708 1.1.1.9 christos break;
1709 1.1.1.9 christos print_reg (info, opcode, OP_REG_VEC, uval);
1710 1.1.1.3 christos infprintf (is, dis_style_text, "[");
1711 1.1.1.3 christos infprintf (is, dis_style_immediate, "%d", vsel >> 1);
1712 1.1.1.3 christos infprintf (is, dis_style_text, "]");
1713 1.1.1.3 christos }
1714 1.1.1.9 christos else if ((vsel & 0x08) == 0)
1715 1.1.1.3 christos print_reg (info, opcode, OP_REG_VEC, uval);
1716 1.1.1.3 christos else
1717 1.1 christos infprintf (is, dis_style_immediate, "0x%x", uval);
1718 1.1.1.3 christos }
1719 1.1.1.3 christos break;
1720 1.1.1.3 christos
1721 1.1 christos case OP_REPEAT_PREV_REG:
1722 1.1.1.3 christos print_reg (info, opcode, state->last_reg_type, state->last_regno);
1723 1.1.1.4 christos break;
1724 1.1.1.4 christos
1725 1.1 christos case OP_REPEAT_DEST_REG:
1726 1.1.1.3 christos print_reg (info, opcode, state->last_reg_type, state->dest_regno);
1727 1.1.1.9 christos break;
1728 1.1.1.3 christos
1729 1.1 christos case OP_PC:
1730 1.1.1.7 christos infprintf (is, dis_style_register, "$pc");
1731 1.1.1.7 christos break;
1732 1.1.1.7 christos
1733 1.1.1.7 christos case OP_REG28:
1734 1.1.1.3 christos print_reg (info, opcode, OP_REG_GP, 28);
1735 1.1.1.3 christos break;
1736 1.1.1.9 christos
1737 1.1.1.3 christos case OP_VU0_SUFFIX:
1738 1.1 christos case OP_VU0_MATCH_SUFFIX:
1739 1.1.1.3 christos print_vu0_channel (info, operand, uval, dis_style_register);
1740 1.1.1.9 christos break;
1741 1.1.1.9 christos
1742 1.1.1.9 christos case OP_IMM_INDEX:
1743 1.1.1.3 christos infprintf (is, dis_style_text, "[");
1744 1.1 christos infprintf (is, dis_style_immediate, "%d", uval);
1745 1.1.1.3 christos infprintf (is, dis_style_text, "]");
1746 1.1.1.9 christos break;
1747 1.1.1.3 christos
1748 1.1.1.9 christos case OP_REG_INDEX:
1749 1.1.1.3 christos infprintf (is, dis_style_text, "[");
1750 1.1.1.3 christos print_reg (info, opcode, OP_REG_GP, uval);
1751 1.1.1.3 christos infprintf (is, dis_style_text, "]");
1752 1.1 christos break;
1753 1.1.1.4 christos }
1754 1.1.1.4 christos }
1755 1.1.1.4 christos
1756 1.1.1.9 christos /* Validate the arguments for INSN, which is described by OPCODE.
1757 1.1.1.4 christos Use DECODE_OPERAND to get the encoding of each operand. */
1758 1.1.1.4 christos
1759 1.1.1.4 christos static bool
1760 1.1.1.4 christos validate_insn_args (const struct mips_opcode *opcode,
1761 1.1.1.4 christos const struct mips_operand *(*decode_operand) (const char *),
1762 1.1.1.4 christos unsigned int insn)
1763 1.1.1.4 christos {
1764 1.1.1.4 christos struct mips_print_arg_state state;
1765 1.1.1.4 christos const struct mips_operand *operand;
1766 1.1.1.4 christos const char *s;
1767 1.1.1.4 christos unsigned int uval;
1768 1.1.1.4 christos
1769 1.1.1.4 christos init_print_arg_state (&state);
1770 1.1.1.4 christos for (s = opcode->args; *s; ++s)
1771 1.1.1.4 christos {
1772 1.1.1.4 christos switch (*s)
1773 1.1.1.4 christos {
1774 1.1.1.4 christos case ',':
1775 1.1.1.4 christos case '(':
1776 1.1.1.4 christos case ')':
1777 1.1.1.4 christos break;
1778 1.1.1.4 christos
1779 1.1.1.4 christos case '#':
1780 1.1.1.4 christos ++s;
1781 1.1.1.4 christos break;
1782 1.1.1.4 christos
1783 1.1.1.4 christos default:
1784 1.1.1.4 christos operand = decode_operand (s);
1785 1.1.1.4 christos
1786 1.1.1.4 christos if (operand)
1787 1.1.1.4 christos {
1788 1.1.1.4 christos uval = mips_extract_operand (operand, insn);
1789 1.1.1.4 christos switch (operand->type)
1790 1.1.1.4 christos {
1791 1.1.1.4 christos case OP_REG:
1792 1.1.1.4 christos case OP_OPTIONAL_REG:
1793 1.1.1.4 christos {
1794 1.1.1.4 christos const struct mips_reg_operand *reg_op;
1795 1.1.1.4 christos
1796 1.1.1.4 christos reg_op = (const struct mips_reg_operand *) operand;
1797 1.1.1.4 christos uval = mips_decode_reg_operand (reg_op, uval);
1798 1.1.1.4 christos mips_seen_register (&state, uval, reg_op->reg_type);
1799 1.1.1.4 christos }
1800 1.1.1.4 christos break;
1801 1.1.1.4 christos
1802 1.1.1.4 christos case OP_SAME_RS_RT:
1803 1.1.1.4 christos {
1804 1.1.1.4 christos unsigned int reg1, reg2;
1805 1.1.1.4 christos
1806 1.1.1.4 christos reg1 = uval & 31;
1807 1.1.1.9 christos reg2 = uval >> 5;
1808 1.1.1.4 christos
1809 1.1.1.4 christos if (reg1 != reg2 || reg1 == 0)
1810 1.1.1.4 christos return false;
1811 1.1.1.4 christos }
1812 1.1.1.4 christos break;
1813 1.1.1.4 christos
1814 1.1.1.4 christos case OP_CHECK_PREV:
1815 1.1.1.4 christos {
1816 1.1.1.4 christos const struct mips_check_prev_operand *prev_op;
1817 1.1.1.4 christos
1818 1.1.1.9 christos prev_op = (const struct mips_check_prev_operand *) operand;
1819 1.1.1.4 christos
1820 1.1.1.4 christos if (!prev_op->zero_ok && uval == 0)
1821 1.1.1.4 christos return false;
1822 1.1.1.4 christos
1823 1.1.1.4 christos if (((prev_op->less_than_ok && uval < state.last_regno)
1824 1.1.1.4 christos || (prev_op->greater_than_ok && uval > state.last_regno)
1825 1.1.1.9 christos || (prev_op->equal_ok && uval == state.last_regno)))
1826 1.1.1.4 christos break;
1827 1.1.1.4 christos
1828 1.1.1.4 christos return false;
1829 1.1.1.4 christos }
1830 1.1.1.4 christos
1831 1.1.1.9 christos case OP_NON_ZERO_REG:
1832 1.1.1.4 christos {
1833 1.1.1.4 christos if (uval == 0)
1834 1.1.1.4 christos return false;
1835 1.1.1.4 christos }
1836 1.1.1.4 christos break;
1837 1.1.1.4 christos
1838 1.1.1.4 christos case OP_INT:
1839 1.1.1.4 christos case OP_MAPPED_INT:
1840 1.1.1.4 christos case OP_MSB:
1841 1.1.1.4 christos case OP_REG_PAIR:
1842 1.1.1.4 christos case OP_PCREL:
1843 1.1.1.4 christos case OP_PERF_REG:
1844 1.1.1.4 christos case OP_ADDIUSP_INT:
1845 1.1.1.4 christos case OP_CLO_CLZ_DEST:
1846 1.1.1.4 christos case OP_LWM_SWM_LIST:
1847 1.1.1.4 christos case OP_ENTRY_EXIT_LIST:
1848 1.1.1.4 christos case OP_MDMX_IMM_REG:
1849 1.1.1.7 christos case OP_REPEAT_PREV_REG:
1850 1.1.1.4 christos case OP_REPEAT_DEST_REG:
1851 1.1.1.4 christos case OP_PC:
1852 1.1.1.4 christos case OP_REG28:
1853 1.1.1.4 christos case OP_VU0_SUFFIX:
1854 1.1.1.4 christos case OP_VU0_MATCH_SUFFIX:
1855 1.1.1.7 christos case OP_IMM_INDEX:
1856 1.1.1.4 christos case OP_REG_INDEX:
1857 1.1.1.4 christos case OP_SAVE_RESTORE_LIST:
1858 1.1.1.4 christos break;
1859 1.1.1.4 christos }
1860 1.1.1.4 christos }
1861 1.1.1.4 christos if (*s == 'm' || *s == '+' || *s == '-')
1862 1.1.1.9 christos ++s;
1863 1.1.1.4 christos }
1864 1.1.1.4 christos }
1865 1.1.1.3 christos return true;
1866 1.1.1.3 christos }
1867 1.1.1.4 christos
1868 1.1.1.4 christos /* Print the arguments for INSN, which is described by OPCODE.
1869 1.1 christos Use DECODE_OPERAND to get the encoding of each operand. Use BASE_PC
1870 1.1.1.3 christos as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
1871 1.1.1.3 christos operand is for a branch or jump. */
1872 1.1.1.3 christos
1873 1.1.1.3 christos static void
1874 1.1.1.4 christos print_insn_args (struct disassemble_info *info,
1875 1.1.1.3 christos const struct mips_opcode *opcode,
1876 1.1.1.9 christos const struct mips_operand *(*decode_operand) (const char *),
1877 1.1.1.3 christos unsigned int insn, bfd_vma insn_pc, unsigned int length)
1878 1.1.1.3 christos {
1879 1.1.1.3 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1880 1.1.1.3 christos void *is = info->stream;
1881 1.1 christos struct mips_print_arg_state state;
1882 1.1.1.3 christos const struct mips_operand *operand;
1883 1.1.1.3 christos const char *s;
1884 1.1.1.3 christos
1885 1.1.1.3 christos init_print_arg_state (&state);
1886 1.1.1.3 christos for (s = opcode->args; *s; ++s)
1887 1.1.1.3 christos {
1888 1.1.1.3 christos switch (*s)
1889 1.1.1.3 christos {
1890 1.1.1.9 christos case ',':
1891 1.1 christos case '(':
1892 1.1 christos case ')':
1893 1.1.1.3 christos infprintf (is, dis_style_text, "%c", *s);
1894 1.1.1.3 christos break;
1895 1.1.1.9 christos
1896 1.1 christos case '#':
1897 1.1 christos ++s;
1898 1.1 christos infprintf (is, dis_style_text, "%c%c", *s, *s);
1899 1.1.1.3 christos break;
1900 1.1.1.3 christos
1901 1.1.1.3 christos default:
1902 1.1.1.3 christos operand = decode_operand (s);
1903 1.1.1.9 christos if (!operand)
1904 1.1.1.3 christos {
1905 1.1.1.3 christos /* xgettext:c-format */
1906 1.1.1.3 christos infprintf (is, dis_style_text,
1907 1.1.1.3 christos _("# internal error, undefined operand in `%s %s'"),
1908 1.1.1.7 christos opcode->name, opcode->args);
1909 1.1.1.7 christos return;
1910 1.1.1.3 christos }
1911 1.1.1.7 christos
1912 1.1.1.7 christos if (operand->type == OP_SAVE_RESTORE_LIST)
1913 1.1.1.7 christos {
1914 1.1.1.7 christos /* Handle this case here because of the complex behavior. */
1915 1.1.1.7 christos unsigned int amask = (insn >> 15) & 0xf;
1916 1.1.1.7 christos unsigned int nsreg = (insn >> 23) & 0x7;
1917 1.1.1.7 christos unsigned int ra = insn & 0x1000; /* $ra */
1918 1.1.1.7 christos unsigned int s0 = insn & 0x800; /* $s0 */
1919 1.1.1.7 christos unsigned int s1 = insn & 0x400; /* $s1 */
1920 1.1.1.7 christos unsigned int frame_size = (((insn >> 15) & 0xf0)
1921 1.1.1.7 christos | ((insn >> 6) & 0x0f)) * 8;
1922 1.1.1.7 christos mips_print_save_restore (info, amask, nsreg, ra, s0, s1,
1923 1.1.1.7 christos frame_size);
1924 1.1.1.7 christos }
1925 1.1.1.7 christos else if (operand->type == OP_REG
1926 1.1.1.7 christos && s[1] == ','
1927 1.1.1.7 christos && s[2] == 'H'
1928 1.1.1.3 christos && opcode->name[strlen (opcode->name) - 1] == '0')
1929 1.1.1.3 christos {
1930 1.1.1.3 christos /* Coprocessor register 0 with sel field. */
1931 1.1.1.3 christos const struct mips_cp0sel_name *n;
1932 1.1.1.3 christos unsigned int reg, sel;
1933 1.1.1.3 christos
1934 1.1.1.3 christos reg = mips_extract_operand (operand, insn);
1935 1.1.1.3 christos s += 2;
1936 1.1.1.3 christos operand = decode_operand (s);
1937 1.1.1.3 christos sel = mips_extract_operand (operand, insn);
1938 1.1.1.3 christos
1939 1.1.1.3 christos /* CP0 register including 'sel' code for mftc0, to be
1940 1.1.1.3 christos printed textually if known. If not known, print both
1941 1.1.1.3 christos CP0 register name and sel numerically since CP0 register
1942 1.1.1.3 christos with sel 0 may have a name unrelated to register being
1943 1.1.1.3 christos printed. */
1944 1.1.1.3 christos n = lookup_mips_cp0sel_name (mips_cp0sel_names,
1945 1.1.1.9 christos mips_cp0sel_names_len,
1946 1.1.1.3 christos reg, sel);
1947 1.1.1.9 christos if (n != NULL)
1948 1.1.1.9 christos infprintf (is, dis_style_register, "%s", n->name);
1949 1.1.1.9 christos else
1950 1.1.1.9 christos {
1951 1.1.1.9 christos infprintf (is, dis_style_register, "$%d", reg);
1952 1.1.1.3 christos infprintf (is, dis_style_text, ",");
1953 1.1.1.3 christos infprintf (is, dis_style_immediate, "%d", sel);
1954 1.1.1.4 christos }
1955 1.1.1.4 christos }
1956 1.1.1.4 christos else
1957 1.1.1.4 christos {
1958 1.1.1.4 christos bfd_vma base_pc = insn_pc;
1959 1.1.1.4 christos
1960 1.1.1.4 christos /* Adjust the PC relative base so that branch/jump insns use
1961 1.1.1.4 christos the following PC as the base but genuinely PC relative
1962 1.1.1.4 christos operands use the current PC. */
1963 1.1.1.4 christos if (operand->type == OP_PCREL)
1964 1.1.1.4 christos {
1965 1.1.1.4 christos const struct mips_pcrel_operand *pcrel_op;
1966 1.1.1.4 christos
1967 1.1.1.4 christos pcrel_op = (const struct mips_pcrel_operand *) operand;
1968 1.1.1.4 christos /* The include_isa_bit flag is sufficient to distinguish
1969 1.1.1.4 christos branch/jump from other PC relative operands. */
1970 1.1.1.4 christos if (pcrel_op->include_isa_bit)
1971 1.1.1.4 christos base_pc += length;
1972 1.1.1.4 christos }
1973 1.1.1.4 christos
1974 1.1.1.4 christos print_insn_arg (info, &state, opcode, operand, base_pc,
1975 1.1.1.3 christos mips_extract_operand (operand, insn));
1976 1.1.1.3 christos }
1977 1.1 christos if (*s == 'm' || *s == '+' || *s == '-')
1978 1.1 christos ++s;
1979 1.1 christos break;
1980 1.1 christos }
1981 1.1 christos }
1982 1.1 christos }
1983 1.1 christos
1984 1.1 christos /* Print the mips instruction at address MEMADDR in debugged memory,
1986 1.1 christos on using INFO. Returns length of the instruction, in bytes, which is
1987 1.1 christos always INSNLEN. BIGENDIAN must be 1 if this is big-endian code, 0 if
1988 1.1.1.2 christos this is little-endian code. */
1989 1.1 christos
1990 1.1 christos static int
1991 1.1.1.3 christos print_insn_mips (bfd_vma memaddr,
1992 1.1.1.3 christos int word,
1993 1.1.1.2 christos struct disassemble_info *info)
1994 1.1.1.9 christos {
1995 1.1 christos #define GET_OP(insn, field) \
1996 1.1.1.9 christos (((insn) >> OP_SH_##field) & OP_MASK_##field)
1997 1.1.1.2 christos static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
1998 1.1 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
1999 1.1 christos const struct mips_opcode *op;
2000 1.1 christos static bool init = 0;
2001 1.1 christos void *is = info->stream;
2002 1.1 christos
2003 1.1 christos /* Build a hash table to shorten the search time. */
2004 1.1 christos if (! init)
2005 1.1 christos {
2006 1.1 christos unsigned int i;
2007 1.1 christos
2008 1.1 christos for (i = 0; i <= OP_MASK_OP; i++)
2009 1.1 christos {
2010 1.1 christos for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
2011 1.1.1.2 christos {
2012 1.1 christos if (op->pinfo == INSN_MACRO
2013 1.1 christos || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
2014 1.1 christos continue;
2015 1.1 christos if (i == GET_OP (op->match, OP))
2016 1.1 christos {
2017 1.1 christos mips_hash[i] = op;
2018 1.1 christos break;
2019 1.1 christos }
2020 1.1 christos }
2021 1.1 christos }
2022 1.1 christos
2023 1.1 christos init = 1;
2024 1.1 christos }
2025 1.1 christos
2026 1.1 christos info->bytes_per_chunk = INSNLEN;
2027 1.1 christos info->display_endian = info->endian;
2028 1.1 christos info->insn_info_valid = 1;
2029 1.1 christos info->branch_delay_insns = 0;
2030 1.1 christos info->data_size = 0;
2031 1.1.1.2 christos info->insn_type = dis_nonbranch;
2032 1.1 christos info->target = 0;
2033 1.1 christos info->target2 = 0;
2034 1.1 christos
2035 1.1 christos op = mips_hash[GET_OP (word, OP)];
2036 1.1.1.5 christos if (op != NULL)
2037 1.1 christos {
2038 1.1 christos for (; op < &mips_opcodes[NUMOPCODES]; op++)
2039 1.1 christos {
2040 1.1.1.4 christos if (op->pinfo != INSN_MACRO
2041 1.1.1.3 christos && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
2042 1.1.1.4 christos && (word & op->mask) == op->match)
2043 1.1.1.4 christos {
2044 1.1.1.4 christos /* We always disassemble the jalx instruction, except for MIPS r6. */
2045 1.1 christos if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
2046 1.1 christos && (strcmp (op->name, "jalx")
2047 1.1 christos || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6
2048 1.1 christos || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6))
2049 1.1 christos continue;
2050 1.1.1.3 christos
2051 1.1 christos /* Figure out instruction type and branch delay information. */
2052 1.1 christos if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
2053 1.1 christos {
2054 1.1 christos if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
2055 1.1 christos info->insn_type = dis_jsr;
2056 1.1 christos else
2057 1.1 christos info->insn_type = dis_branch;
2058 1.1 christos info->branch_delay_insns = 1;
2059 1.1 christos }
2060 1.1 christos else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
2061 1.1 christos | INSN_COND_BRANCH_LIKELY)) != 0)
2062 1.1 christos {
2063 1.1 christos if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2064 1.1 christos info->insn_type = dis_condjsr;
2065 1.1 christos else
2066 1.1.1.3 christos info->insn_type = dis_condbranch;
2067 1.1 christos info->branch_delay_insns = 1;
2068 1.1 christos }
2069 1.1.1.4 christos else if ((op->pinfo & (INSN_STORE_MEMORY
2070 1.1.1.4 christos | INSN_LOAD_MEMORY)) != 0)
2071 1.1.1.4 christos info->insn_type = dis_dref;
2072 1.1.1.9 christos
2073 1.1.1.3 christos if (!validate_insn_args (op, decode_mips_operand, word))
2074 1.1.1.3 christos continue;
2075 1.1.1.3 christos
2076 1.1.1.3 christos infprintf (is, dis_style_mnemonic, "%s", op->name);
2077 1.1.1.9 christos if (op->pinfo2 & INSN2_VU0_CHANNEL_SUFFIX)
2078 1.1.1.3 christos {
2079 1.1.1.9 christos unsigned int uval;
2080 1.1.1.9 christos
2081 1.1.1.3 christos infprintf (is, dis_style_mnemonic, ".");
2082 1.1 christos uval = mips_extract_operand (&mips_vu0_channel_mask, word);
2083 1.1.1.3 christos print_vu0_channel (info, &mips_vu0_channel_mask, uval,
2084 1.1 christos dis_style_mnemonic);
2085 1.1.1.9 christos }
2086 1.1.1.3 christos
2087 1.1.1.4 christos if (op->args[0])
2088 1.1 christos {
2089 1.1 christos infprintf (is, dis_style_text, "\t");
2090 1.1 christos print_insn_args (info, op, decode_mips_operand, word,
2091 1.1 christos memaddr, 4);
2092 1.1 christos }
2093 1.1 christos
2094 1.1.1.2 christos return INSNLEN;
2095 1.1 christos }
2096 1.1 christos }
2097 1.1 christos }
2098 1.1.1.9 christos #undef GET_OP
2099 1.1.1.9 christos
2100 1.1.1.9 christos /* Handle undefined instructions. */
2101 1.1 christos info->insn_type = dis_noninsn;
2102 1.1 christos infprintf (is, dis_style_assembler_directive, ".word");
2103 1.1 christos infprintf (is, dis_style_text, "\t");
2104 1.1 christos infprintf (is, dis_style_immediate, "0x%x", word);
2105 1.1 christos return INSNLEN;
2106 1.1 christos }
2107 1.1.1.3 christos
2108 1.1.1.3 christos /* Disassemble an operand for a mips16 instruction. */
2110 1.1.1.3 christos
2111 1.1.1.9 christos static void
2112 1.1.1.9 christos print_mips16_insn_arg (struct disassemble_info *info,
2113 1.1 christos struct mips_print_arg_state *state,
2114 1.1.1.9 christos const struct mips_opcode *opcode,
2115 1.1.1.2 christos char type, bfd_vma memaddr,
2116 1.1.1.3 christos unsigned insn, bool use_extend,
2117 1.1.1.6 christos unsigned extend, bool is_offset)
2118 1.1.1.3 christos {
2119 1.1.1.3 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
2120 1.1.1.3 christos void *is = info->stream;
2121 1.1.1.3 christos const struct mips_operand *operand, *ext_operand;
2122 1.1.1.3 christos unsigned short ext_size;
2123 1.1.1.2 christos unsigned int uval;
2124 1.1 christos bfd_vma baseaddr;
2125 1.1 christos
2126 1.1 christos if (!use_extend)
2127 1.1 christos extend = 0;
2128 1.1 christos
2129 1.1.1.9 christos switch (type)
2130 1.1 christos {
2131 1.1 christos case ',':
2132 1.1.1.3 christos case '(':
2133 1.1.1.9 christos case ')':
2134 1.1.1.3 christos infprintf (is, dis_style_text, "%c", type);
2135 1.1.1.3 christos break;
2136 1.1.1.3 christos
2137 1.1.1.9 christos default:
2138 1.1.1.3 christos operand = decode_mips16_operand (type, false);
2139 1.1.1.3 christos if (!operand)
2140 1.1.1.3 christos {
2141 1.1 christos /* xgettext:c-format */
2142 1.1.1.3 christos infprintf (is, dis_style_text, _("# internal error, undefined operand in `%s %s'"),
2143 1.1.1.3 christos opcode->name, opcode->args);
2144 1.1.1.6 christos return;
2145 1.1.1.3 christos }
2146 1.1.1.7 christos
2147 1.1.1.7 christos if (operand->type == OP_SAVE_RESTORE_LIST)
2148 1.1.1.7 christos {
2149 1.1.1.7 christos /* Handle this case here because of the complex interaction
2150 1.1.1.7 christos with the EXTEND opcode. */
2151 1.1.1.7 christos unsigned int amask = extend & 0xf;
2152 1.1.1.3 christos unsigned int nsreg = (extend >> 8) & 0x7;
2153 1.1.1.3 christos unsigned int ra = insn & 0x40; /* $ra */
2154 1.1.1.7 christos unsigned int s0 = insn & 0x20; /* $s0 */
2155 1.1.1.3 christos unsigned int s1 = insn & 0x10; /* $s1 */
2156 1.1.1.3 christos unsigned int frame_size = ((extend & 0xf0) | (insn & 0x0f)) * 8;
2157 1.1 christos if (frame_size == 0 && !use_extend)
2158 1.1.1.3 christos frame_size = 128;
2159 1.1.1.3 christos mips_print_save_restore (info, amask, nsreg, ra, s0, s1, frame_size);
2160 1.1.1.3 christos break;
2161 1.1 christos }
2162 1.1.1.3 christos
2163 1.1.1.3 christos if (is_offset && operand->type == OP_INT)
2164 1.1.1.3 christos {
2165 1.1.1.3 christos const struct mips_int_operand *int_op;
2166 1.1 christos
2167 1.1.1.6 christos int_op = (const struct mips_int_operand *) operand;
2168 1.1.1.6 christos info->insn_type = dis_dref;
2169 1.1.1.3 christos info->data_size = 1 << int_op->shift;
2170 1.1.1.9 christos }
2171 1.1.1.7 christos
2172 1.1.1.7 christos ext_size = 0;
2173 1.1.1.7 christos if (use_extend)
2174 1.1.1.3 christos {
2175 1.1.1.6 christos ext_operand = decode_mips16_operand (type, true);
2176 1.1.1.6 christos if (ext_operand != operand
2177 1.1.1.3 christos || (operand->type == OP_INT && operand->lsb == 0
2178 1.1.1.3 christos && mips_opcode_32bit_p (opcode)))
2179 1.1.1.6 christos {
2180 1.1.1.6 christos ext_size = ext_operand->size;
2181 1.1.1.7 christos operand = ext_operand;
2182 1.1.1.6 christos }
2183 1.1.1.6 christos }
2184 1.1.1.6 christos if (operand->size == 26)
2185 1.1.1.6 christos uval = ((extend & 0x1f) << 21) | ((extend & 0x3e0) << 11) | insn;
2186 1.1.1.6 christos else if (ext_size == 16 || ext_size == 9)
2187 1.1.1.6 christos uval = ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
2188 1.1.1.6 christos else if (ext_size == 15)
2189 1.1.1.7 christos uval = ((extend & 0xf) << 11) | (extend & 0x7f0) | (insn & 0xf);
2190 1.1.1.7 christos else if (ext_size == 6)
2191 1.1 christos uval = ((extend >> 6) & 0x1f) | (extend & 0x20);
2192 1.1.1.3 christos else
2193 1.1.1.3 christos uval = mips_extract_operand (operand, (extend << 16) | insn);
2194 1.1.1.3 christos if (ext_size == 9)
2195 1.1.1.3 christos uval &= (1U << ext_size) - 1;
2196 1.1 christos
2197 1.1.1.3 christos baseaddr = memaddr + 2;
2198 1.1.1.3 christos if (operand->type == OP_PCREL)
2199 1.1.1.3 christos {
2200 1.1.1.3 christos const struct mips_pcrel_operand *pcrel_op;
2201 1.1.1.6 christos
2202 1.1.1.6 christos pcrel_op = (const struct mips_pcrel_operand *) operand;
2203 1.1.1.3 christos if (!pcrel_op->include_isa_bit && use_extend)
2204 1.1.1.6 christos baseaddr = memaddr - 2;
2205 1.1.1.6 christos else if (!pcrel_op->include_isa_bit)
2206 1.1.1.6 christos {
2207 1.1.1.6 christos bfd_byte buffer[2];
2208 1.1.1.6 christos
2209 1.1.1.6 christos /* If this instruction is in the delay slot of a JAL/JALX
2210 1.1.1.6 christos instruction, the base address is the address of the
2211 1.1.1.6 christos JAL/JALX instruction. If it is in the delay slot of
2212 1.1.1.6 christos a JR/JALR instruction, the base address is the address
2213 1.1.1.6 christos of the JR/JALR instruction. This test is unreliable:
2214 1.1.1.6 christos we have no way of knowing whether the previous word is
2215 1.1.1.6 christos instruction or data. */
2216 1.1.1.6 christos if (info->read_memory_func (memaddr - 4, buffer, 2, info) == 0
2217 1.1.1.6 christos && (((info->endian == BFD_ENDIAN_BIG
2218 1.1.1.6 christos ? bfd_getb16 (buffer)
2219 1.1.1.6 christos : bfd_getl16 (buffer))
2220 1.1.1.6 christos & 0xf800) == 0x1800))
2221 1.1.1.6 christos baseaddr = memaddr - 4;
2222 1.1.1.6 christos else if (info->read_memory_func (memaddr - 2, buffer, 2,
2223 1.1.1.6 christos info) == 0
2224 1.1.1.6 christos && (((info->endian == BFD_ENDIAN_BIG
2225 1.1.1.6 christos ? bfd_getb16 (buffer)
2226 1.1.1.6 christos : bfd_getl16 (buffer))
2227 1.1.1.6 christos & 0xf89f) == 0xe800)
2228 1.1.1.6 christos && (((info->endian == BFD_ENDIAN_BIG
2229 1.1.1.6 christos ? bfd_getb16 (buffer)
2230 1.1.1.6 christos : bfd_getl16 (buffer))
2231 1.1.1.3 christos & 0x0060) != 0x0060))
2232 1.1 christos baseaddr = memaddr - 2;
2233 1.1.1.3 christos else
2234 1.1 christos baseaddr = memaddr;
2235 1.1.1.3 christos }
2236 1.1.1.3 christos }
2237 1.1 christos
2238 1.1 christos print_insn_arg (info, state, opcode, operand, baseaddr + 1, uval);
2239 1.1.1.3 christos break;
2240 1.1.1.3 christos }
2241 1.1.1.3 christos }
2242 1.1.1.3 christos
2243 1.1.1.9 christos
2244 1.1.1.3 christos /* Check if the given address is the last word of a MIPS16 PLT entry.
2245 1.1.1.3 christos This word is data and depending on the value it may interfere with
2246 1.1.1.3 christos disassembly of further PLT entries. We make use of the fact PLT
2247 1.1.1.3 christos symbols are marked BSF_SYNTHETIC. */
2248 1.1.1.3 christos static bool
2249 1.1.1.3 christos is_mips16_plt_tail (struct disassemble_info *info, bfd_vma addr)
2250 1.1.1.9 christos {
2251 1.1 christos if (info->symbols
2252 1.1.1.9 christos && info->symbols[0]
2253 1.1 christos && (info->symbols[0]->flags & BSF_SYNTHETIC)
2254 1.1 christos && addr == bfd_asymbol_value (info->symbols[0]) + 12)
2255 1.1.1.6 christos return true;
2256 1.1.1.6 christos
2257 1.1.1.6 christos return false;
2258 1.1.1.6 christos }
2259 1.1.1.6 christos
2260 1.1.1.6 christos /* Whether none, a 32-bit or a 16-bit instruction match has been done. */
2261 1.1.1.6 christos
2262 1.1.1.6 christos enum match_kind
2263 1.1.1.6 christos {
2264 1.1 christos MATCH_NONE,
2265 1.1 christos MATCH_FULL,
2266 1.1 christos MATCH_SHORT
2267 1.1 christos };
2268 1.1 christos
2269 1.1.1.9 christos /* Disassemble mips16 instructions. */
2270 1.1 christos
2271 1.1.1.3 christos static int
2272 1.1 christos print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
2273 1.1.1.3 christos {
2274 1.1.1.2 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
2275 1.1.1.9 christos int status;
2276 1.1.1.9 christos bfd_byte buffer[4];
2277 1.1.1.6 christos const struct mips_opcode *op, *opend;
2278 1.1.1.6 christos struct mips_print_arg_state state;
2279 1.1.1.6 christos void *is = info->stream;
2280 1.1 christos bool have_second;
2281 1.1 christos bool extend_only;
2282 1.1 christos unsigned int second;
2283 1.1 christos unsigned int first;
2284 1.1 christos unsigned int full;
2285 1.1 christos
2286 1.1 christos info->bytes_per_chunk = 2;
2287 1.1 christos info->display_endian = info->endian;
2288 1.1 christos info->insn_info_valid = 1;
2289 1.1.1.3 christos info->branch_delay_insns = 0;
2290 1.1.1.3 christos info->data_size = 0;
2291 1.1.1.3 christos info->target = 0;
2292 1.1.1.3 christos info->target2 = 0;
2293 1.1.1.3 christos
2294 1.1.1.3 christos #define GET_OP(insn, field) \
2295 1.1.1.3 christos (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
2296 1.1.1.3 christos /* Decode PLT entry's GOT slot address word. */
2297 1.1.1.3 christos if (is_mips16_plt_tail (info, memaddr))
2298 1.1.1.3 christos {
2299 1.1.1.3 christos info->insn_type = dis_noninsn;
2300 1.1.1.3 christos status = (*info->read_memory_func) (memaddr, buffer, 4, info);
2301 1.1.1.3 christos if (status == 0)
2302 1.1.1.3 christos {
2303 1.1.1.3 christos unsigned int gotslot;
2304 1.1.1.9 christos
2305 1.1.1.9 christos if (info->endian == BFD_ENDIAN_BIG)
2306 1.1.1.9 christos gotslot = bfd_getb32 (buffer);
2307 1.1.1.3 christos else
2308 1.1.1.3 christos gotslot = bfd_getl32 (buffer);
2309 1.1.1.3 christos infprintf (is, dis_style_assembler_directive, ".word");
2310 1.1.1.3 christos infprintf (is, dis_style_text, "\t");
2311 1.1.1.3 christos infprintf (is, dis_style_immediate, "0x%x", gotslot);
2312 1.1.1.3 christos
2313 1.1.1.3 christos return 4;
2314 1.1.1.3 christos }
2315 1.1.1.3 christos }
2316 1.1 christos else
2317 1.1 christos {
2318 1.1 christos info->insn_type = dis_nonbranch;
2319 1.1 christos status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2320 1.1 christos }
2321 1.1 christos if (status != 0)
2322 1.1.1.9 christos {
2323 1.1.1.7 christos (*info->memory_error_func) (status, memaddr, info);
2324 1.1 christos return -1;
2325 1.1.1.6 christos }
2326 1.1 christos
2327 1.1.1.6 christos extend_only = false;
2328 1.1 christos
2329 1.1.1.6 christos if (info->endian == BFD_ENDIAN_BIG)
2330 1.1.1.6 christos first = bfd_getb16 (buffer);
2331 1.1 christos else
2332 1.1.1.9 christos first = bfd_getl16 (buffer);
2333 1.1 christos
2334 1.1.1.6 christos status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2335 1.1 christos if (status == 0)
2336 1.1.1.6 christos {
2337 1.1.1.6 christos have_second = true;
2338 1.1.1.6 christos if (info->endian == BFD_ENDIAN_BIG)
2339 1.1.1.6 christos second = bfd_getb16 (buffer);
2340 1.1.1.6 christos else
2341 1.1.1.9 christos second = bfd_getl16 (buffer);
2342 1.1.1.6 christos full = (first << 16) | second;
2343 1.1.1.6 christos }
2344 1.1 christos else
2345 1.1 christos {
2346 1.1 christos have_second = false;
2347 1.1 christos second = 0;
2348 1.1 christos full = first;
2349 1.1 christos }
2350 1.1 christos
2351 1.1.1.6 christos /* FIXME: Should probably use a hash table on the major opcode here. */
2352 1.1 christos
2353 1.1.1.6 christos opend = mips16_opcodes + bfd_mips16_num_opcodes;
2354 1.1.1.6 christos for (op = mips16_opcodes; op < opend; op++)
2355 1.1 christos {
2356 1.1.1.6 christos enum match_kind match;
2357 1.1.1.6 christos
2358 1.1.1.6 christos if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor))
2359 1.1.1.6 christos continue;
2360 1.1.1.6 christos
2361 1.1.1.6 christos if (op->pinfo == INSN_MACRO
2362 1.1.1.6 christos || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
2363 1.1.1.6 christos match = MATCH_NONE;
2364 1.1.1.6 christos else if (mips_opcode_32bit_p (op))
2365 1.1.1.6 christos {
2366 1.1.1.6 christos if (have_second
2367 1.1.1.6 christos && (full & op->mask) == op->match)
2368 1.1.1.6 christos match = MATCH_FULL;
2369 1.1.1.6 christos else
2370 1.1.1.6 christos match = MATCH_NONE;
2371 1.1.1.6 christos }
2372 1.1.1.6 christos else if ((first & op->mask) == op->match)
2373 1.1.1.6 christos {
2374 1.1.1.6 christos match = MATCH_SHORT;
2375 1.1.1.7 christos second = 0;
2376 1.1.1.6 christos full = first;
2377 1.1.1.7 christos }
2378 1.1.1.7 christos else if ((first & 0xf800) == 0xf000
2379 1.1.1.7 christos && have_second
2380 1.1.1.7 christos && !extend_only
2381 1.1.1.9 christos && (second & op->mask) == op->match)
2382 1.1.1.7 christos {
2383 1.1.1.7 christos if (op->pinfo2 & INSN2_SHORT_ONLY)
2384 1.1.1.7 christos {
2385 1.1.1.7 christos match = MATCH_NONE;
2386 1.1.1.6 christos extend_only = true;
2387 1.1.1.6 christos }
2388 1.1 christos else
2389 1.1.1.6 christos match = MATCH_FULL;
2390 1.1.1.6 christos }
2391 1.1.1.6 christos else
2392 1.1 christos match = MATCH_NONE;
2393 1.1.1.9 christos
2394 1.1 christos if (match != MATCH_NONE)
2395 1.1.1.9 christos {
2396 1.1 christos const char *s;
2397 1.1.1.3 christos
2398 1.1 christos infprintf (is, dis_style_mnemonic, "%s", op->name);
2399 1.1 christos if (op->args[0] != '\0')
2400 1.1 christos infprintf (is, dis_style_text, "\t");
2401 1.1 christos
2402 1.1.1.6 christos init_print_arg_state (&state);
2403 1.1 christos for (s = op->args; *s != '\0'; s++)
2404 1.1 christos {
2405 1.1 christos if (*s == ','
2406 1.1 christos && s[1] == 'w'
2407 1.1 christos && GET_OP (full, RX) == GET_OP (full, RY))
2408 1.1 christos {
2409 1.1 christos /* Skip the register and the comma. */
2410 1.1.1.6 christos ++s;
2411 1.1 christos continue;
2412 1.1 christos }
2413 1.1 christos if (*s == ','
2414 1.1 christos && s[1] == 'v'
2415 1.1 christos && GET_OP (full, RZ) == GET_OP (full, RX))
2416 1.1.1.7 christos {
2417 1.1.1.7 christos /* Skip the register and the comma. */
2418 1.1.1.7 christos ++s;
2419 1.1.1.7 christos continue;
2420 1.1.1.6 christos }
2421 1.1.1.7 christos if (s[0] == 'N'
2422 1.1.1.7 christos && s[1] == ','
2423 1.1.1.7 christos && s[2] == 'O'
2424 1.1.1.7 christos && op->name[strlen (op->name) - 1] == '0')
2425 1.1.1.7 christos {
2426 1.1.1.9 christos /* Coprocessor register 0 with sel field. */
2427 1.1.1.7 christos const struct mips_cp0sel_name *n;
2428 1.1.1.7 christos const struct mips_operand *operand;
2429 1.1.1.9 christos unsigned int reg, sel;
2430 1.1.1.7 christos
2431 1.1.1.7 christos operand = decode_mips16_operand (*s, true);
2432 1.1.1.7 christos reg = mips_extract_operand (operand, (first << 16) | second);
2433 1.1.1.7 christos s += 2;
2434 1.1.1.7 christos operand = decode_mips16_operand (*s, true);
2435 1.1.1.7 christos sel = mips_extract_operand (operand, (first << 16) | second);
2436 1.1.1.7 christos
2437 1.1.1.7 christos /* CP0 register including 'sel' code for mftc0, to be
2438 1.1.1.7 christos printed textually if known. If not known, print both
2439 1.1.1.7 christos CP0 register name and sel numerically since CP0 register
2440 1.1.1.7 christos with sel 0 may have a name unrelated to register being
2441 1.1.1.9 christos printed. */
2442 1.1.1.7 christos n = lookup_mips_cp0sel_name (mips_cp0sel_names,
2443 1.1.1.9 christos mips_cp0sel_names_len,
2444 1.1.1.9 christos reg, sel);
2445 1.1.1.9 christos if (n != NULL)
2446 1.1.1.9 christos infprintf (is, dis_style_register, "%s", n->name);
2447 1.1.1.9 christos else
2448 1.1.1.6 christos {
2449 1.1.1.7 christos infprintf (is, dis_style_register, "$%d", reg);
2450 1.1.1.7 christos infprintf (is, dis_style_text, ",");
2451 1.1.1.7 christos infprintf (is, dis_style_immediate, "%d", sel);
2452 1.1.1.7 christos }
2453 1.1.1.7 christos }
2454 1.1.1.9 christos else
2455 1.1.1.7 christos switch (match)
2456 1.1.1.7 christos {
2457 1.1.1.7 christos case MATCH_FULL:
2458 1.1.1.9 christos print_mips16_insn_arg (info, &state, op, *s, memaddr + 2,
2459 1.1.1.7 christos second, true, first, s[1] == '(');
2460 1.1.1.7 christos break;
2461 1.1.1.7 christos case MATCH_SHORT:
2462 1.1.1.7 christos print_mips16_insn_arg (info, &state, op, *s, memaddr,
2463 1.1 christos first, false, 0, s[1] == '(');
2464 1.1 christos break;
2465 1.1 christos case MATCH_NONE: /* Stop the compiler complaining. */
2466 1.1 christos break;
2467 1.1 christos }
2468 1.1.1.3 christos }
2469 1.1.1.3 christos
2470 1.1 christos /* Figure out branch instruction type and delay slot information. */
2471 1.1 christos if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
2472 1.1 christos info->branch_delay_insns = 1;
2473 1.1 christos if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0
2474 1.1 christos || (op->pinfo2 & INSN2_UNCOND_BRANCH) != 0)
2475 1.1 christos {
2476 1.1.1.3 christos if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2477 1.1 christos info->insn_type = dis_jsr;
2478 1.1 christos else
2479 1.1.1.6 christos info->insn_type = dis_branch;
2480 1.1 christos }
2481 1.1 christos else if ((op->pinfo2 & INSN2_COND_BRANCH) != 0)
2482 1.1.1.2 christos info->insn_type = dis_condbranch;
2483 1.1 christos
2484 1.1.1.9 christos return match == MATCH_FULL ? 4 : 2;
2485 1.1.1.9 christos }
2486 1.1.1.9 christos }
2487 1.1.1.2 christos #undef GET_OP
2488 1.1.1.2 christos
2489 1.1.1.6 christos infprintf (is, dis_style_assembler_directive, ".short");
2490 1.1.1.2 christos infprintf (is, dis_style_text, "\t");
2491 1.1.1.2 christos infprintf (is, dis_style_immediate, "0x%x", first);
2492 1.1.1.2 christos info->insn_type = dis_noninsn;
2493 1.1.1.2 christos
2494 1.1.1.2 christos return 2;
2495 1.1.1.2 christos }
2496 1.1.1.2 christos
2497 1.1.1.9 christos /* Disassemble microMIPS instructions. */
2498 1.1.1.2 christos
2499 1.1.1.2 christos static int
2500 1.1.1.2 christos print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
2501 1.1.1.3 christos {
2502 1.1.1.3 christos const fprintf_styled_ftype infprintf = info->fprintf_styled_func;
2503 1.1.1.2 christos const struct mips_opcode *op, *opend;
2504 1.1.1.3 christos void *is = info->stream;
2505 1.1.1.2 christos bfd_byte buffer[2];
2506 1.1.1.2 christos unsigned int higher;
2507 1.1.1.2 christos unsigned int length;
2508 1.1.1.2 christos int status;
2509 1.1.1.2 christos unsigned int insn;
2510 1.1.1.2 christos
2511 1.1.1.2 christos info->bytes_per_chunk = 2;
2512 1.1.1.2 christos info->display_endian = info->endian;
2513 1.1.1.2 christos info->insn_info_valid = 1;
2514 1.1.1.2 christos info->branch_delay_insns = 0;
2515 1.1.1.2 christos info->data_size = 0;
2516 1.1.1.2 christos info->insn_type = dis_nonbranch;
2517 1.1.1.2 christos info->target = 0;
2518 1.1.1.2 christos info->target2 = 0;
2519 1.1.1.2 christos
2520 1.1.1.2 christos status = (*info->read_memory_func) (memaddr, buffer, 2, info);
2521 1.1.1.2 christos if (status != 0)
2522 1.1.1.2 christos {
2523 1.1.1.2 christos (*info->memory_error_func) (status, memaddr, info);
2524 1.1.1.2 christos return -1;
2525 1.1.1.2 christos }
2526 1.1.1.2 christos
2527 1.1.1.2 christos length = 2;
2528 1.1.1.2 christos
2529 1.1.1.5 christos if (info->endian == BFD_ENDIAN_BIG)
2530 1.1.1.2 christos insn = bfd_getb16 (buffer);
2531 1.1.1.2 christos else
2532 1.1.1.2 christos insn = bfd_getl16 (buffer);
2533 1.1.1.2 christos
2534 1.1.1.2 christos if ((insn & 0x1c00) == 0x0000 || (insn & 0x1000) == 0x1000)
2535 1.1.1.2 christos {
2536 1.1.1.2 christos /* This is a 32-bit microMIPS instruction. */
2537 1.1.1.9 christos higher = insn;
2538 1.1.1.2 christos
2539 1.1.1.2 christos status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
2540 1.1.1.2 christos if (status != 0)
2541 1.1.1.2 christos {
2542 1.1.1.2 christos infprintf (is, dis_style_text, "micromips 0x%x", higher);
2543 1.1.1.2 christos (*info->memory_error_func) (status, memaddr + 2, info);
2544 1.1.1.2 christos return -1;
2545 1.1.1.2 christos }
2546 1.1.1.2 christos
2547 1.1.1.2 christos if (info->endian == BFD_ENDIAN_BIG)
2548 1.1.1.2 christos insn = bfd_getb16 (buffer);
2549 1.1.1.2 christos else
2550 1.1.1.2 christos insn = bfd_getl16 (buffer);
2551 1.1.1.2 christos
2552 1.1.1.2 christos insn = insn | (higher << 16);
2553 1.1.1.2 christos
2554 1.1.1.2 christos length += 2;
2555 1.1.1.2 christos }
2556 1.1.1.2 christos
2557 1.1.1.2 christos /* FIXME: Should probably use a hash table on the major opcode here. */
2558 1.1.1.2 christos
2559 1.1.1.2 christos opend = micromips_opcodes + bfd_micromips_num_opcodes;
2560 1.1.1.2 christos for (op = micromips_opcodes; op < opend; op++)
2561 1.1.1.2 christos {
2562 1.1.1.2 christos if (op->pinfo != INSN_MACRO
2563 1.1.1.4 christos && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
2564 1.1.1.4 christos && (insn & op->mask) == op->match
2565 1.1.1.4 christos && ((length == 2 && (op->mask & 0xffff0000) == 0)
2566 1.1.1.9 christos || (length == 4 && (op->mask & 0xffff0000) != 0)))
2567 1.1.1.2 christos {
2568 1.1.1.3 christos if (!validate_insn_args (op, decode_micromips_operand, insn))
2569 1.1.1.2 christos continue;
2570 1.1.1.9 christos
2571 1.1.1.3 christos infprintf (is, dis_style_mnemonic, "%s", op->name);
2572 1.1.1.4 christos
2573 1.1.1.2 christos if (op->args[0])
2574 1.1.1.2 christos {
2575 1.1.1.2 christos infprintf (is, dis_style_text, "\t");
2576 1.1.1.2 christos print_insn_args (info, op, decode_micromips_operand, insn,
2577 1.1.1.2 christos memaddr + 1, length);
2578 1.1.1.2 christos }
2579 1.1.1.2 christos
2580 1.1.1.2 christos /* Figure out instruction type and branch delay information. */
2581 1.1.1.2 christos if ((op->pinfo
2582 1.1.1.3 christos & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY)) != 0)
2583 1.1.1.2 christos info->branch_delay_insns = 1;
2584 1.1.1.2 christos if (((op->pinfo & INSN_UNCOND_BRANCH_DELAY)
2585 1.1.1.2 christos | (op->pinfo2 & INSN2_UNCOND_BRANCH)) != 0)
2586 1.1.1.2 christos {
2587 1.1.1.2 christos if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
2588 1.1.1.2 christos info->insn_type = dis_jsr;
2589 1.1.1.2 christos else
2590 1.1.1.2 christos info->insn_type = dis_branch;
2591 1.1.1.2 christos }
2592 1.1.1.2 christos else if (((op->pinfo & INSN_COND_BRANCH_DELAY)
2593 1.1.1.2 christos | (op->pinfo2 & INSN2_COND_BRANCH)) != 0)
2594 1.1.1.2 christos {
2595 1.1.1.2 christos if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
2596 1.1.1.3 christos info->insn_type = dis_condjsr;
2597 1.1.1.2 christos else
2598 1.1.1.2 christos info->insn_type = dis_condbranch;
2599 1.1.1.2 christos }
2600 1.1.1.2 christos else if ((op->pinfo
2601 1.1.1.2 christos & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY)) != 0)
2602 1.1.1.2 christos info->insn_type = dis_dref;
2603 1.1.1.9 christos
2604 1.1.1.9 christos return length;
2605 1.1.1.9 christos }
2606 1.1.1.9 christos }
2607 1.1.1.9 christos
2608 1.1.1.9 christos if (length == 2)
2609 1.1 christos infprintf (is, dis_style_assembler_directive, ".short");
2610 1.1 christos else
2611 1.1 christos infprintf (is, dis_style_assembler_directive, ".word");
2612 1.1 christos infprintf (is, dis_style_text, "\t");
2613 1.1 christos infprintf (is, dis_style_immediate, "0x%x", insn);
2614 1.1.1.2 christos info->insn_type = dis_noninsn;
2615 1.1.1.5 christos
2616 1.1.1.5 christos return length;
2617 1.1.1.5 christos }
2618 1.1.1.5 christos
2619 1.1.1.5 christos /* Return 1 if a symbol associated with the location being disassembled
2620 1.1.1.5 christos indicates a compressed mode, either MIPS16 or microMIPS, according to
2621 1.1.1.2 christos MICROMIPS_P. We iterate over all the symbols at the address being
2622 1.1.1.9 christos considered assuming if at least one of them indicates code compression,
2623 1.1.1.9 christos then such code has been genuinely produced here (other symbols could
2624 1.1.1.2 christos have been derived from function symbols defined elsewhere or could
2625 1.1.1.2 christos define data). Otherwise, return 0. */
2626 1.1.1.3 christos
2627 1.1.1.2 christos static bool
2628 1.1.1.3 christos is_compressed_mode_p (struct disassemble_info *info, bool micromips_p)
2629 1.1.1.3 christos {
2630 1.1.1.5 christos int i;
2631 1.1.1.3 christos int l;
2632 1.1.1.5 christos
2633 1.1.1.3 christos for (i = info->symtab_pos, l = i + info->num_symbols; i < l; i++)
2634 1.1.1.3 christos if (((info->symtab[i])->flags & BSF_SYNTHETIC) != 0
2635 1.1.1.3 christos && ((!micromips_p
2636 1.1.1.3 christos && ELF_ST_IS_MIPS16 ((*info->symbols)->udata.i))
2637 1.1.1.3 christos || (micromips_p
2638 1.1.1.3 christos && ELF_ST_IS_MICROMIPS ((*info->symbols)->udata.i))))
2639 1.1.1.5 christos return 1;
2640 1.1.1.3 christos else if (bfd_asymbol_flavour (info->symtab[i]) == bfd_target_elf_flavour
2641 1.1.1.5 christos && info->symtab[i]->section == info->section)
2642 1.1.1.3 christos {
2643 1.1.1.3 christos elf_symbol_type *symbol = (elf_symbol_type *) info->symtab[i];
2644 1.1.1.3 christos if ((!micromips_p
2645 1.1.1.2 christos && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
2646 1.1.1.2 christos || (micromips_p
2647 1.1.1.2 christos && ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
2648 1.1.1.2 christos return 1;
2649 1.1 christos }
2650 1.1 christos
2651 1.1 christos return 0;
2652 1.1 christos }
2653 1.1 christos
2654 1.1 christos /* In an environment where we do not know the symbol type of the
2655 1.1 christos instruction we are forced to assume that the low order bit of the
2656 1.1 christos instructions' address may mark it as a mips16 instruction. If we
2657 1.1 christos are single stepping, or the pc is within the disassembled function,
2658 1.1 christos this works. Otherwise, we need a clue. Sometimes. */
2659 1.1 christos
2660 1.1 christos static int
2661 1.1 christos _print_insn_mips (bfd_vma memaddr,
2662 1.1 christos struct disassemble_info *info,
2663 1.1 christos enum bfd_endian endianness)
2664 1.1 christos {
2665 1.1 christos bfd_byte buffer[INSNLEN];
2666 1.1.1.2 christos int status;
2667 1.1.1.2 christos
2668 1.1.1.2 christos set_default_mips_dis_options (info);
2669 1.1.1.2 christos parse_mips_dis_options (info->disassembler_options);
2670 1.1.1.2 christos
2671 1.1 christos if (info->mach == bfd_mach_mips16)
2672 1.1.1.2 christos return print_insn_mips16 (memaddr, info);
2673 1.1 christos if (info->mach == bfd_mach_mips_micromips)
2674 1.1 christos return print_insn_micromips (memaddr, info);
2675 1.1.1.5 christos
2676 1.1.1.5 christos #if 1
2677 1.1.1.5 christos /* FIXME: If odd address, this is CLEARLY a compressed instruction. */
2678 1.1.1.5 christos /* Only a few tools will work this way. */
2679 1.1.1.5 christos if (memaddr & 0x01)
2680 1.1.1.5 christos {
2681 1.1 christos if (micromips_ase)
2682 1.1 christos return print_insn_micromips (memaddr, info);
2683 1.1 christos else
2684 1.1.1.9 christos return print_insn_mips16 (memaddr, info);
2685 1.1.1.5 christos }
2686 1.1.1.9 christos #endif
2687 1.1.1.5 christos
2688 1.1 christos #if SYMTAB_AVAILABLE
2689 1.1 christos if (is_compressed_mode_p (info, true))
2690 1.1 christos return print_insn_micromips (memaddr, info);
2691 1.1 christos if (is_compressed_mode_p (info, false))
2692 1.1 christos return print_insn_mips16 (memaddr, info);
2693 1.1.1.2 christos #endif
2694 1.1 christos
2695 1.1 christos status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
2696 1.1.1.2 christos if (status == 0)
2697 1.1 christos {
2698 1.1.1.2 christos int insn;
2699 1.1 christos
2700 1.1 christos if (endianness == BFD_ENDIAN_BIG)
2701 1.1 christos insn = bfd_getb32 (buffer);
2702 1.1 christos else
2703 1.1 christos insn = bfd_getl32 (buffer);
2704 1.1 christos
2705 1.1 christos return print_insn_mips (memaddr, insn, info);
2706 1.1 christos }
2707 1.1 christos else
2708 1.1 christos {
2709 1.1 christos (*info->memory_error_func) (status, memaddr, info);
2710 1.1 christos return -1;
2711 1.1 christos }
2712 1.1 christos }
2713 1.1 christos
2714 1.1 christos int
2715 1.1 christos print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info)
2716 1.1 christos {
2717 1.1 christos return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
2718 1.1 christos }
2719 1.1 christos
2720 1.1 christos int
2721 1.1.1.7 christos print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info)
2722 1.1.1.7 christos {
2723 1.1.1.7 christos return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
2724 1.1.1.7 christos }
2725 1.1.1.7 christos
2726 1.1.1.7 christos /* Indices into option argument vector for options accepting an argument.
2728 1.1.1.7 christos Use MIPS_OPTION_ARG_NONE for options accepting no argument. */
2729 1.1.1.7 christos typedef enum
2730 1.1.1.7 christos {
2731 1.1.1.7 christos MIPS_OPTION_ARG_NONE = -1,
2732 1.1.1.7 christos MIPS_OPTION_ARG_ABI,
2733 1.1.1.7 christos MIPS_OPTION_ARG_ARCH,
2734 1.1.1.7 christos MIPS_OPTION_ARG_SIZE
2735 1.1.1.7 christos } mips_option_arg_t;
2736 1.1.1.7 christos
2737 1.1.1.7 christos /* Valid MIPS disassembler options. */
2738 1.1.1.7 christos static struct
2739 1.1.1.7 christos {
2740 1.1.1.7 christos const char *name;
2741 1.1.1.7 christos const char *description;
2742 1.1.1.7 christos mips_option_arg_t arg;
2743 1.1.1.7 christos } mips_options[] =
2744 1.1.1.7 christos {
2745 1.1.1.7 christos { "no-aliases", N_("Use canonical instruction forms.\n"),
2746 1.1.1.7 christos MIPS_OPTION_ARG_NONE },
2747 1.1.1.7 christos { "msa", N_("Recognize MSA instructions.\n"),
2748 1.1.1.7 christos MIPS_OPTION_ARG_NONE },
2749 1.1.1.7 christos { "virt", N_("Recognize the virtualization ASE instructions.\n"),
2750 1.1.1.7 christos MIPS_OPTION_ARG_NONE },
2751 1.1.1.7 christos { "xpa", N_("Recognize the eXtended Physical Address (XPA) ASE\n\
2752 1.1.1.7 christos instructions.\n"),
2753 1.1.1.7 christos MIPS_OPTION_ARG_NONE },
2754 1.1.1.7 christos { "ginv", N_("Recognize the Global INValidate (GINV) ASE "
2755 1.1.1.7 christos "instructions.\n"),
2756 1.1.1.7 christos MIPS_OPTION_ARG_NONE },
2757 1.1.1.7 christos { "loongson-mmi",
2758 1.1.1.7 christos N_("Recognize the Loongson MultiMedia extensions "
2759 1.1.1.7 christos "Instructions (MMI) ASE instructions.\n"),
2760 1.1.1.7 christos MIPS_OPTION_ARG_NONE },
2761 1.1.1.7 christos { "loongson-cam",
2762 1.1.1.7 christos N_("Recognize the Loongson Content Address Memory (CAM) "
2763 1.1.1.7 christos " instructions.\n"),
2764 1.1.1.7 christos MIPS_OPTION_ARG_NONE },
2765 1.1.1.7 christos { "loongson-ext",
2766 1.1.1.7 christos N_("Recognize the Loongson EXTensions (EXT) "
2767 1.1.1.7 christos " instructions.\n"),
2768 1.1.1.7 christos MIPS_OPTION_ARG_NONE },
2769 1.1.1.7 christos { "loongson-ext2",
2770 1.1.1.7 christos N_("Recognize the Loongson EXTensions R2 (EXT2) "
2771 1.1.1.7 christos " instructions.\n"),
2772 1.1.1.7 christos MIPS_OPTION_ARG_NONE },
2773 1.1.1.7 christos { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
2774 1.1.1.7 christos Default: based on binary being disassembled.\n"),
2775 1.1.1.7 christos MIPS_OPTION_ARG_ABI },
2776 1.1.1.7 christos { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
2777 1.1.1.7 christos Default: numeric.\n"),
2778 1.1.1.7 christos MIPS_OPTION_ARG_ABI },
2779 1.1.1.7 christos { "cp0-names=", N_("Print CP0 register names according to specified "
2780 1.1.1.7 christos "architecture.\n\
2781 1.1.1.7 christos Default: based on binary being disassembled.\n"),
2782 1.1.1.7 christos MIPS_OPTION_ARG_ARCH },
2783 1.1.1.7 christos { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
2784 1.1.1.7 christos Default: based on binary being disassembled.\n"),
2785 1.1.1.7 christos MIPS_OPTION_ARG_ARCH },
2786 1.1.1.7 christos { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
2787 1.1.1.7 christos MIPS_OPTION_ARG_ABI },
2788 1.1.1.7 christos { "reg-names=", N_("Print CP0 register and HWR names according to "
2789 1.1.1.7 christos "specified\n\
2790 1.1.1.7 christos architecture."),
2791 1.1.1.7 christos MIPS_OPTION_ARG_ARCH }
2792 1.1.1.7 christos };
2793 1.1.1.7 christos
2794 1.1.1.7 christos /* Build the structure representing valid MIPS disassembler options.
2795 1.1.1.7 christos This is done dynamically for maintenance ease purpose; a static
2796 1.1.1.7 christos initializer would be unreadable. */
2797 1.1.1.7 christos
2798 1.1.1.7 christos const disasm_options_and_args_t *
2799 1.1.1.7 christos disassembler_options_mips (void)
2800 1.1.1.7 christos {
2801 1.1.1.7 christos static disasm_options_and_args_t *opts_and_args;
2802 1.1.1.7 christos
2803 1.1.1.7 christos if (opts_and_args == NULL)
2804 1.1.1.7 christos {
2805 1.1.1.7 christos size_t num_options = ARRAY_SIZE (mips_options);
2806 1.1.1.7 christos size_t num_args = MIPS_OPTION_ARG_SIZE;
2807 1.1.1.7 christos disasm_option_arg_t *args;
2808 1.1.1.7 christos disasm_options_t *opts;
2809 1.1.1.7 christos size_t i;
2810 1.1.1.7 christos size_t j;
2811 1.1.1.7 christos
2812 1.1.1.7 christos args = XNEWVEC (disasm_option_arg_t, num_args + 1);
2813 1.1.1.7 christos
2814 1.1.1.7 christos args[MIPS_OPTION_ARG_ABI].name = "ABI";
2815 1.1.1.7 christos args[MIPS_OPTION_ARG_ABI].values
2816 1.1.1.7 christos = XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices) + 1);
2817 1.1.1.7 christos for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
2818 1.1.1.7 christos args[MIPS_OPTION_ARG_ABI].values[i] = mips_abi_choices[i].name;
2819 1.1.1.7 christos /* The array we return must be NULL terminated. */
2820 1.1.1.7 christos args[MIPS_OPTION_ARG_ABI].values[i] = NULL;
2821 1.1.1.7 christos
2822 1.1.1.7 christos args[MIPS_OPTION_ARG_ARCH].name = "ARCH";
2823 1.1.1.7 christos args[MIPS_OPTION_ARG_ARCH].values
2824 1.1.1.7 christos = XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices) + 1);
2825 1.1.1.7 christos for (i = 0, j = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
2826 1.1.1.7 christos if (*mips_arch_choices[i].name != '\0')
2827 1.1.1.7 christos args[MIPS_OPTION_ARG_ARCH].values[j++] = mips_arch_choices[i].name;
2828 1.1.1.7 christos /* The array we return must be NULL terminated. */
2829 1.1.1.7 christos args[MIPS_OPTION_ARG_ARCH].values[j] = NULL;
2830 1.1.1.7 christos
2831 1.1.1.7 christos /* The array we return must be NULL terminated. */
2832 1.1.1.7 christos args[MIPS_OPTION_ARG_SIZE].name = NULL;
2833 1.1.1.7 christos args[MIPS_OPTION_ARG_SIZE].values = NULL;
2834 1.1.1.7 christos
2835 1.1.1.7 christos opts_and_args = XNEW (disasm_options_and_args_t);
2836 1.1.1.7 christos opts_and_args->args = args;
2837 1.1.1.7 christos
2838 1.1.1.7 christos opts = &opts_and_args->options;
2839 1.1.1.7 christos opts->name = XNEWVEC (const char *, num_options + 1);
2840 1.1.1.7 christos opts->description = XNEWVEC (const char *, num_options + 1);
2841 1.1.1.7 christos opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1);
2842 1.1.1.7 christos for (i = 0; i < num_options; i++)
2843 1.1.1.7 christos {
2844 1.1.1.7 christos opts->name[i] = mips_options[i].name;
2845 1.1.1.7 christos opts->description[i] = _(mips_options[i].description);
2846 1.1.1.7 christos if (mips_options[i].arg != MIPS_OPTION_ARG_NONE)
2847 1.1.1.7 christos opts->arg[i] = &args[mips_options[i].arg];
2848 1.1.1.7 christos else
2849 1.1.1.7 christos opts->arg[i] = NULL;
2850 1.1.1.7 christos }
2851 1.1.1.7 christos /* The array we return must be NULL terminated. */
2852 1.1.1.7 christos opts->name[i] = NULL;
2853 1.1.1.7 christos opts->description[i] = NULL;
2854 1.1 christos opts->arg[i] = NULL;
2855 1.1 christos }
2856 1.1 christos
2857 1.1.1.7 christos return opts_and_args;
2858 1.1.1.7 christos }
2859 1.1.1.7 christos
2860 1.1.1.7 christos void
2861 1.1.1.7 christos print_mips_disassembler_options (FILE *stream)
2862 1.1.1.7 christos {
2863 1.1.1.7 christos const disasm_options_and_args_t *opts_and_args;
2864 1.1.1.7 christos const disasm_option_arg_t *args;
2865 1.1.1.7 christos const disasm_options_t *opts;
2866 1.1.1.7 christos size_t max_len = 0;
2867 1.1 christos size_t i;
2868 1.1 christos size_t j;
2869 1.1 christos
2870 1.1.1.7 christos opts_and_args = disassembler_options_mips ();
2871 1.1.1.4 christos opts = &opts_and_args->options;
2872 1.1.1.7 christos args = opts_and_args->args;
2873 1.1.1.7 christos
2874 1.1.1.7 christos fprintf (stream, _("\n\
2875 1.1.1.7 christos The following MIPS specific disassembler options are supported for use\n\
2876 1.1 christos with the -M switch (multiple options should be separated by commas):\n\n"));
2877 1.1.1.7 christos
2878 1.1.1.7 christos /* Compute the length of the longest option name. */
2879 1.1.1.7 christos for (i = 0; opts->name[i] != NULL; i++)
2880 1.1.1.7 christos {
2881 1.1.1.7 christos size_t len = strlen (opts->name[i]);
2882 1.1 christos
2883 1.1.1.7 christos if (opts->arg[i] != NULL)
2884 1.1.1.7 christos len += strlen (opts->arg[i]->name);
2885 1.1.1.7 christos if (max_len < len)
2886 1.1.1.7 christos max_len = len;
2887 1.1.1.7 christos }
2888 1.1.1.7 christos
2889 1.1.1.7 christos for (i = 0, max_len++; opts->name[i] != NULL; i++)
2890 1.1.1.7 christos {
2891 1.1 christos fprintf (stream, " %s", opts->name[i]);
2892 1.1.1.7 christos if (opts->arg[i] != NULL)
2893 1.1.1.7 christos fprintf (stream, "%s", opts->arg[i]->name);
2894 1.1.1.7 christos if (opts->description[i] != NULL)
2895 1.1.1.7 christos {
2896 1.1.1.7 christos size_t len = strlen (opts->name[i]);
2897 1.1.1.7 christos
2898 1.1.1.7 christos if (opts->arg[i] != NULL)
2899 1.1 christos len += strlen (opts->arg[i]->name);
2900 1.1.1.7 christos fprintf (stream,
2901 1.1.1.7 christos "%*c %s", (int) (max_len - len), ' ', opts->description[i]);
2902 1.1.1.9 christos }
2903 1.1.1.9 christos fprintf (stream, _("\n"));
2904 1.1.1.7 christos }
2905 1.1.1.7 christos
2906 1.1.1.7 christos for (i = 0; args[i].name != NULL; i++)
2907 1.1.1.7 christos {
2908 1.1.1.7 christos if (args[i].values == NULL)
2909 1.1.1.7 christos continue;
2910 1.1.1.7 christos fprintf (stream, _("\n\
2911 1.1 christos For the options above, the following values are supported for \"%s\":\n "),
2912 1.1 christos args[i].name);
2913 1.1 christos for (j = 0; args[i].values[j] != NULL; j++)
2914 fprintf (stream, " %s", args[i].values[j]);
2915 fprintf (stream, _("\n"));
2916 }
2917
2918 fprintf (stream, _("\n"));
2919 }
2920