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