Coverage Report

Created: 2023-08-28 06:23

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