arc-dis.c revision 1.1.1.3 1 1.1 christos /* Instruction printing code for the ARC.
2 1.1.1.3 christos Copyright (C) 1994-2016 Free Software Foundation, Inc.
3 1.1.1.3 christos
4 1.1.1.3 christos Contributed by Claudiu Zissulescu (claziss (at) synopsys.com)
5 1.1 christos
6 1.1 christos This file is part of libopcodes.
7 1.1 christos
8 1.1 christos This library is free software; you can redistribute it and/or modify
9 1.1 christos it under the terms of the GNU General Public License as published by
10 1.1 christos the Free Software Foundation; either version 3, or (at your option)
11 1.1 christos any later version.
12 1.1 christos
13 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
14 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 1.1 christos License for more details.
17 1.1 christos
18 1.1 christos You should have received a copy of the GNU General Public License
19 1.1 christos along with this program; if not, write to the Free Software
20 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 1.1 christos MA 02110-1301, USA. */
22 1.1 christos
23 1.1 christos #include "sysdep.h"
24 1.1.1.3 christos #include <stdio.h>
25 1.1.1.3 christos #include <assert.h>
26 1.1 christos #include "dis-asm.h"
27 1.1 christos #include "opcode/arc.h"
28 1.1 christos #include "elf/arc.h"
29 1.1 christos #include "arc-dis.h"
30 1.1 christos #include "arc-ext.h"
31 1.1.1.3 christos #include "elf-bfd.h"
32 1.1.1.3 christos #include "libiberty.h"
33 1.1.1.3 christos #include "opintl.h"
34 1.1 christos
35 1.1.1.3 christos /* Structure used to iterate over, and extract the values for, operands of
36 1.1.1.3 christos an opcode. */
37 1.1.1.3 christos
38 1.1.1.3 christos struct arc_operand_iterator
39 1.1.1.3 christos {
40 1.1.1.3 christos enum
41 1.1.1.3 christos {
42 1.1.1.3 christos OPERAND_ITERATOR_STANDARD,
43 1.1.1.3 christos OPERAND_ITERATOR_LONG
44 1.1.1.3 christos } mode;
45 1.1.1.3 christos
46 1.1.1.3 christos /* The array of 32-bit values that make up this instruction. All
47 1.1.1.3 christos required values have been pre-loaded into this array during the
48 1.1.1.3 christos find_format call. */
49 1.1.1.3 christos unsigned *insn;
50 1.1.1.3 christos
51 1.1.1.3 christos union
52 1.1.1.3 christos {
53 1.1.1.3 christos struct
54 1.1.1.3 christos {
55 1.1.1.3 christos /* The opcode this iterator is operating on. */
56 1.1.1.3 christos const struct arc_opcode *opcode;
57 1.1.1.3 christos
58 1.1.1.3 christos /* The index into the opcodes operand index list. */
59 1.1.1.3 christos const unsigned char *opidx;
60 1.1.1.3 christos } standard;
61 1.1.1.3 christos
62 1.1.1.3 christos struct
63 1.1.1.3 christos {
64 1.1.1.3 christos /* The long instruction opcode this iterator is operating on. */
65 1.1.1.3 christos const struct arc_long_opcode *long_opcode;
66 1.1.1.3 christos
67 1.1.1.3 christos /* Two indexes into the opcodes operand index lists. */
68 1.1.1.3 christos const unsigned char *opidx_base, *opidx_limm;
69 1.1.1.3 christos } long_insn;
70 1.1.1.3 christos } state;
71 1.1.1.3 christos };
72 1.1.1.3 christos
73 1.1.1.3 christos /* Globals variables. */
74 1.1.1.3 christos
75 1.1.1.3 christos static const char * const regnames[64] =
76 1.1.1.3 christos {
77 1.1.1.3 christos "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
78 1.1.1.3 christos "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
79 1.1.1.3 christos "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
80 1.1.1.3 christos "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
81 1.1.1.3 christos
82 1.1.1.3 christos "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
83 1.1.1.3 christos "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
84 1.1.1.3 christos "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
85 1.1.1.3 christos "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
86 1.1.1.3 christos };
87 1.1.1.3 christos
88 1.1.1.3 christos static const char * const addrtypenames[ARC_NUM_ADDRTYPES] =
89 1.1.1.3 christos {
90 1.1.1.3 christos "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd",
91 1.1.1.3 christos "cd", "cbd", "cjid", "clbd", "cm", "csd", "cxa", "cxd"
92 1.1.1.3 christos };
93 1.1 christos
94 1.1.1.3 christos static int addrtypenames_max = ARC_NUM_ADDRTYPES - 1;
95 1.1 christos
96 1.1.1.3 christos static const char * const addrtypeunknown = "unknown";
97 1.1.1.3 christos
98 1.1.1.3 christos /* This structure keeps track which instruction class(es)
99 1.1.1.3 christos should be ignored durring disassembling. */
100 1.1.1.3 christos
101 1.1.1.3 christos typedef struct skipclass
102 1.1 christos {
103 1.1.1.3 christos insn_class_t insn_class;
104 1.1.1.3 christos insn_subclass_t subclass;
105 1.1.1.3 christos struct skipclass *nxt;
106 1.1.1.3 christos } skipclass_t, *linkclass;
107 1.1.1.3 christos
108 1.1.1.3 christos /* Intial classes of instructions to be consider first when
109 1.1.1.3 christos disassembling. */
110 1.1.1.3 christos static linkclass decodelist = NULL;
111 1.1.1.3 christos
112 1.1.1.3 christos /* Macros section. */
113 1.1.1.3 christos
114 1.1.1.3 christos #ifdef DEBUG
115 1.1.1.3 christos # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
116 1.1.1.3 christos #else
117 1.1.1.3 christos # define pr_debug(fmt, args...)
118 1.1.1.3 christos #endif
119 1.1.1.3 christos
120 1.1.1.3 christos #define ARRANGE_ENDIAN(info, buf) \
121 1.1.1.3 christos (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \
122 1.1.1.3 christos : bfd_getb32 (buf))
123 1.1 christos
124 1.1.1.3 christos #define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \
125 1.1.1.3 christos (s + (sizeof (word) * 8 - 1 - e)))
126 1.1 christos #define OPCODE(word) (BITS ((word), 27, 31))
127 1.1 christos
128 1.1.1.3 christos #define OPCODE_AC(word) (BITS ((word), 11, 15))
129 1.1 christos
130 1.1.1.3 christos /* Functions implementation. */
131 1.1 christos
132 1.1.1.3 christos /* Return TRUE when two classes are not opcode conflicting. */
133 1.1 christos
134 1.1.1.3 christos static bfd_boolean
135 1.1.1.3 christos is_compatible_p (insn_class_t classA,
136 1.1.1.3 christos insn_subclass_t sclassA,
137 1.1.1.3 christos insn_class_t classB,
138 1.1.1.3 christos insn_subclass_t sclassB)
139 1.1 christos {
140 1.1.1.3 christos if (classA == DSP && sclassB == DPX)
141 1.1.1.3 christos return FALSE;
142 1.1.1.3 christos if (sclassA == DPX && classB == DSP)
143 1.1.1.3 christos return FALSE;
144 1.1.1.3 christos return TRUE;
145 1.1 christos }
146 1.1 christos
147 1.1.1.3 christos /* Add a new element to the decode list. */
148 1.1.1.3 christos
149 1.1.1.3 christos static void
150 1.1.1.3 christos add_to_decodelist (insn_class_t insn_class,
151 1.1.1.3 christos insn_subclass_t subclass)
152 1.1 christos {
153 1.1.1.3 christos linkclass t = (linkclass) xmalloc (sizeof (skipclass_t));
154 1.1.1.3 christos
155 1.1.1.3 christos t->insn_class = insn_class;
156 1.1.1.3 christos t->subclass = subclass;
157 1.1.1.3 christos t->nxt = decodelist;
158 1.1.1.3 christos decodelist = t;
159 1.1 christos }
160 1.1 christos
161 1.1.1.3 christos /* Return TRUE if we need to skip the opcode from being
162 1.1.1.3 christos disassembled. */
163 1.1.1.3 christos
164 1.1.1.3 christos static bfd_boolean
165 1.1.1.3 christos skip_this_opcode (const struct arc_opcode * opcode,
166 1.1.1.3 christos struct disassemble_info * info)
167 1.1 christos {
168 1.1.1.3 christos linkclass t = decodelist;
169 1.1.1.3 christos bfd_boolean addme = TRUE;
170 1.1 christos
171 1.1.1.3 christos /* Check opcode for major 0x06, return if it is not in. */
172 1.1.1.3 christos if (OPCODE (opcode->opcode) != 0x06)
173 1.1.1.3 christos return FALSE;
174 1.1.1.3 christos
175 1.1.1.3 christos while (t != NULL
176 1.1.1.3 christos && is_compatible_p (t->insn_class, t->subclass,
177 1.1.1.3 christos opcode->insn_class, opcode->subclass))
178 1.1.1.3 christos {
179 1.1.1.3 christos if ((t->insn_class == opcode->insn_class)
180 1.1.1.3 christos && (t->subclass == opcode->subclass))
181 1.1.1.3 christos addme = FALSE;
182 1.1.1.3 christos t = t->nxt;
183 1.1.1.3 christos }
184 1.1.1.3 christos
185 1.1.1.3 christos /* If we found an incompatibility then we must skip. */
186 1.1.1.3 christos if (t != NULL)
187 1.1.1.3 christos return TRUE;
188 1.1.1.3 christos
189 1.1.1.3 christos /* Even if we do not precisely know the if the right mnemonics
190 1.1.1.3 christos is correctly displayed, keep the disassmbled code class
191 1.1.1.3 christos consistent. */
192 1.1.1.3 christos if (addme)
193 1.1.1.3 christos {
194 1.1.1.3 christos switch (opcode->insn_class)
195 1.1.1.3 christos {
196 1.1.1.3 christos case DSP:
197 1.1.1.3 christos case FLOAT:
198 1.1.1.3 christos /* Add to the conflict list only the classes which
199 1.1.1.3 christos counts. */
200 1.1.1.3 christos add_to_decodelist (opcode->insn_class, opcode->subclass);
201 1.1.1.3 christos /* Warn if we have to decode an opcode and no preferred
202 1.1.1.3 christos classes have been chosen. */
203 1.1.1.3 christos info->fprintf_func (info->stream, _("\n\
204 1.1.1.3 christos Warning: disassembly may be wrong due to guessed opcode class choice.\n\
205 1.1.1.3 christos Use -M<class[,class]> to select the correct opcode class(es).\n\t\t\t\t"));
206 1.1.1.3 christos break;
207 1.1.1.3 christos default:
208 1.1.1.3 christos break;
209 1.1.1.3 christos }
210 1.1.1.3 christos }
211 1.1.1.3 christos return FALSE;
212 1.1 christos }
213 1.1 christos
214 1.1.1.3 christos static bfd_vma
215 1.1.1.3 christos bfd_getm32 (unsigned int data)
216 1.1 christos {
217 1.1.1.3 christos bfd_vma value = 0;
218 1.1.1.3 christos
219 1.1.1.3 christos value = ((data & 0xff00) | (data & 0xff)) << 16;
220 1.1.1.3 christos value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
221 1.1.1.3 christos return value;
222 1.1 christos }
223 1.1 christos
224 1.1.1.3 christos static bfd_boolean
225 1.1.1.3 christos special_flag_p (const char *opname,
226 1.1.1.3 christos const char *flgname)
227 1.1 christos {
228 1.1.1.3 christos const struct arc_flag_special *flg_spec;
229 1.1.1.3 christos unsigned i, j, flgidx;
230 1.1 christos
231 1.1.1.3 christos for (i = 0; i < arc_num_flag_special; i++)
232 1.1 christos {
233 1.1.1.3 christos flg_spec = &arc_flag_special_cases[i];
234 1.1.1.3 christos
235 1.1.1.3 christos if (strcmp (opname, flg_spec->name))
236 1.1.1.3 christos continue;
237 1.1.1.3 christos
238 1.1.1.3 christos /* Found potential special case instruction. */
239 1.1.1.3 christos for (j=0;; ++j)
240 1.1.1.3 christos {
241 1.1.1.3 christos flgidx = flg_spec->flags[j];
242 1.1.1.3 christos if (flgidx == 0)
243 1.1.1.3 christos break; /* End of the array. */
244 1.1 christos
245 1.1.1.3 christos if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
246 1.1.1.3 christos return TRUE;
247 1.1.1.3 christos }
248 1.1 christos }
249 1.1.1.3 christos return FALSE;
250 1.1 christos }
251 1.1 christos
252 1.1.1.3 christos /* Find opcode from ARC_TABLE given the instruction described by INSN and
253 1.1.1.3 christos INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */
254 1.1.1.3 christos
255 1.1.1.3 christos static const struct arc_opcode *
256 1.1.1.3 christos find_format_from_table (struct disassemble_info *info,
257 1.1.1.3 christos const struct arc_opcode *arc_table,
258 1.1.1.3 christos unsigned *insn,
259 1.1.1.3 christos unsigned int insn_len,
260 1.1.1.3 christos unsigned isa_mask,
261 1.1.1.3 christos bfd_boolean *has_limm,
262 1.1.1.3 christos bfd_boolean overlaps)
263 1.1 christos {
264 1.1.1.3 christos unsigned int i = 0;
265 1.1.1.3 christos const struct arc_opcode *opcode = NULL;
266 1.1.1.3 christos const unsigned char *opidx;
267 1.1.1.3 christos const unsigned char *flgidx;
268 1.1.1.3 christos
269 1.1.1.3 christos do
270 1.1.1.3 christos {
271 1.1.1.3 christos bfd_boolean invalid = FALSE;
272 1.1.1.3 christos
273 1.1.1.3 christos opcode = &arc_table[i++];
274 1.1.1.3 christos
275 1.1.1.3 christos if (ARC_SHORT (opcode->mask) && (insn_len == 2))
276 1.1.1.3 christos {
277 1.1.1.3 christos if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
278 1.1.1.3 christos continue;
279 1.1.1.3 christos }
280 1.1.1.3 christos else if (!ARC_SHORT (opcode->mask) && (insn_len == 4))
281 1.1.1.3 christos {
282 1.1.1.3 christos if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
283 1.1.1.3 christos continue;
284 1.1.1.3 christos }
285 1.1.1.3 christos else
286 1.1.1.3 christos continue;
287 1.1.1.3 christos
288 1.1.1.3 christos if ((insn[0] ^ opcode->opcode) & opcode->mask)
289 1.1.1.3 christos continue;
290 1.1.1.3 christos
291 1.1.1.3 christos if (!(opcode->cpu & isa_mask))
292 1.1.1.3 christos continue;
293 1.1.1.3 christos
294 1.1.1.3 christos *has_limm = FALSE;
295 1.1.1.3 christos
296 1.1.1.3 christos /* Possible candidate, check the operands. */
297 1.1.1.3 christos for (opidx = opcode->operands; *opidx; opidx++)
298 1.1.1.3 christos {
299 1.1.1.3 christos int value;
300 1.1.1.3 christos const struct arc_operand *operand = &arc_operands[*opidx];
301 1.1.1.3 christos
302 1.1.1.3 christos if (operand->flags & ARC_OPERAND_FAKE)
303 1.1.1.3 christos continue;
304 1.1.1.3 christos
305 1.1.1.3 christos if (operand->extract)
306 1.1.1.3 christos value = (*operand->extract) (insn[0], &invalid);
307 1.1.1.3 christos else
308 1.1.1.3 christos value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
309 1.1.1.3 christos
310 1.1.1.3 christos /* Check for LIMM indicator. If it is there, then make sure
311 1.1.1.3 christos we pick the right format. */
312 1.1.1.3 christos if (operand->flags & ARC_OPERAND_IR
313 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_LIMM))
314 1.1 christos {
315 1.1.1.3 christos if ((value == 0x3E && insn_len == 4)
316 1.1.1.3 christos || (value == 0x1E && insn_len == 2))
317 1.1 christos {
318 1.1.1.3 christos invalid = TRUE;
319 1.1.1.3 christos break;
320 1.1 christos }
321 1.1 christos }
322 1.1 christos
323 1.1.1.3 christos if (operand->flags & ARC_OPERAND_LIMM
324 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_DUPLICATE))
325 1.1.1.3 christos *has_limm = TRUE;
326 1.1.1.3 christos }
327 1.1.1.3 christos
328 1.1.1.3 christos /* Check the flags. */
329 1.1.1.3 christos for (flgidx = opcode->flags; *flgidx; flgidx++)
330 1.1.1.3 christos {
331 1.1.1.3 christos /* Get a valid flag class. */
332 1.1.1.3 christos const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
333 1.1.1.3 christos const unsigned *flgopridx;
334 1.1.1.3 christos int foundA = 0, foundB = 0;
335 1.1.1.3 christos unsigned int value;
336 1.1 christos
337 1.1.1.3 christos /* Check first the extensions. */
338 1.1.1.3 christos if (cl_flags->flag_class & F_CLASS_EXTEND)
339 1.1 christos {
340 1.1.1.3 christos value = (insn[0] & 0x1F);
341 1.1.1.3 christos if (arcExtMap_condCodeName (value))
342 1.1.1.3 christos continue;
343 1.1 christos }
344 1.1.1.3 christos
345 1.1.1.3 christos for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
346 1.1 christos {
347 1.1.1.3 christos const struct arc_flag_operand *flg_operand =
348 1.1.1.3 christos &arc_flag_operands[*flgopridx];
349 1.1 christos
350 1.1.1.3 christos value = (insn[0] >> flg_operand->shift)
351 1.1.1.3 christos & ((1 << flg_operand->bits) - 1);
352 1.1.1.3 christos if (value == flg_operand->code)
353 1.1.1.3 christos foundA = 1;
354 1.1.1.3 christos if (value)
355 1.1.1.3 christos foundB = 1;
356 1.1 christos }
357 1.1.1.3 christos
358 1.1.1.3 christos if (!foundA && foundB)
359 1.1 christos {
360 1.1.1.3 christos invalid = TRUE;
361 1.1.1.3 christos break;
362 1.1.1.3 christos }
363 1.1.1.3 christos }
364 1.1 christos
365 1.1.1.3 christos if (invalid)
366 1.1.1.3 christos continue;
367 1.1 christos
368 1.1.1.3 christos if (insn_len == 4
369 1.1.1.3 christos && overlaps
370 1.1.1.3 christos && skip_this_opcode (opcode, info))
371 1.1.1.3 christos continue;
372 1.1 christos
373 1.1.1.3 christos /* The instruction is valid. */
374 1.1.1.3 christos return opcode;
375 1.1.1.3 christos }
376 1.1.1.3 christos while (opcode->mask);
377 1.1 christos
378 1.1.1.3 christos return NULL;
379 1.1.1.3 christos }
380 1.1 christos
381 1.1.1.3 christos /* Find long instructions matching values in INSN array. */
382 1.1 christos
383 1.1.1.3 christos static const struct arc_long_opcode *
384 1.1.1.3 christos find_format_long_instructions (unsigned *insn,
385 1.1.1.3 christos unsigned int *insn_len,
386 1.1.1.3 christos unsigned isa_mask,
387 1.1.1.3 christos bfd_vma memaddr,
388 1.1.1.3 christos struct disassemble_info *info)
389 1.1.1.3 christos {
390 1.1.1.3 christos unsigned int i;
391 1.1.1.3 christos unsigned limm = 0;
392 1.1.1.3 christos bfd_boolean limm_loaded = FALSE;
393 1.1.1.3 christos
394 1.1.1.3 christos for (i = 0; i < arc_num_long_opcodes; ++i)
395 1.1.1.3 christos {
396 1.1.1.3 christos bfd_byte buffer[4];
397 1.1.1.3 christos int status;
398 1.1.1.3 christos const struct arc_opcode *opcode;
399 1.1.1.3 christos
400 1.1.1.3 christos opcode = &arc_long_opcodes[i].base_opcode;
401 1.1.1.3 christos
402 1.1.1.3 christos if (ARC_SHORT (opcode->mask) && (*insn_len == 2))
403 1.1.1.3 christos {
404 1.1.1.3 christos if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
405 1.1.1.3 christos continue;
406 1.1.1.3 christos }
407 1.1.1.3 christos else if (!ARC_SHORT (opcode->mask) && (*insn_len == 4))
408 1.1.1.3 christos {
409 1.1.1.3 christos if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
410 1.1.1.3 christos continue;
411 1.1.1.3 christos }
412 1.1.1.3 christos else
413 1.1.1.3 christos continue;
414 1.1.1.3 christos
415 1.1.1.3 christos if ((insn[0] ^ opcode->opcode) & opcode->mask)
416 1.1.1.3 christos continue;
417 1.1.1.3 christos
418 1.1.1.3 christos if (!(opcode->cpu & isa_mask))
419 1.1.1.3 christos continue;
420 1.1.1.3 christos
421 1.1.1.3 christos if (!limm_loaded)
422 1.1.1.3 christos {
423 1.1.1.3 christos status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
424 1.1.1.3 christos 4, info);
425 1.1.1.3 christos if (status != 0)
426 1.1.1.3 christos return NULL;
427 1.1.1.3 christos
428 1.1.1.3 christos limm = ARRANGE_ENDIAN (info, buffer);
429 1.1.1.3 christos limm_loaded = TRUE;
430 1.1.1.3 christos }
431 1.1.1.3 christos
432 1.1.1.3 christos /* Check the second word using the mask and template. */
433 1.1.1.3 christos if ((limm & arc_long_opcodes[i].limm_mask)
434 1.1.1.3 christos != arc_long_opcodes[i].limm_template)
435 1.1.1.3 christos continue;
436 1.1.1.3 christos
437 1.1.1.3 christos (*insn_len) += 4;
438 1.1.1.3 christos insn[1] = limm;
439 1.1.1.3 christos return &arc_long_opcodes[i];
440 1.1.1.3 christos }
441 1.1.1.3 christos
442 1.1.1.3 christos return NULL;
443 1.1.1.3 christos }
444 1.1.1.3 christos
445 1.1.1.3 christos /* Find opcode for INSN, trying various different sources. The instruction
446 1.1.1.3 christos length in INSN_LEN will be updated if the instruction requires a LIMM
447 1.1.1.3 christos extension, and the additional values loaded into the INSN array (which
448 1.1.1.3 christos must be big enough).
449 1.1.1.3 christos
450 1.1.1.3 christos A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
451 1.1.1.3 christos initialised, ready to iterate over the operands of the found opcode.
452 1.1.1.3 christos
453 1.1.1.3 christos This function returns TRUE in almost all cases, FALSE is reserved to
454 1.1.1.3 christos indicate an error (failing to find an opcode is not an error) a
455 1.1.1.3 christos returned result of FALSE would indicate that the disassembler can't
456 1.1.1.3 christos continue.
457 1.1.1.3 christos
458 1.1.1.3 christos If no matching opcode is found then the returned result will be TRUE,
459 1.1.1.3 christos the value placed into OPCODE_RESULT will be NULL, ITER will be
460 1.1.1.3 christos undefined, and INSN_LEN will be unchanged.
461 1.1.1.3 christos
462 1.1.1.3 christos If a matching opcode is found, then the returned result will be TRUE,
463 1.1.1.3 christos the opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be
464 1.1.1.3 christos increased by 4 if the instruction requires a LIMM, and the LIMM value
465 1.1.1.3 christos will have been loaded into the INSN[1]. Finally, ITER will have been
466 1.1.1.3 christos initialised so that calls to OPERAND_ITERATOR_NEXT will iterate over
467 1.1.1.3 christos the opcode's operands. */
468 1.1.1.3 christos
469 1.1.1.3 christos static bfd_boolean
470 1.1.1.3 christos find_format (bfd_vma memaddr,
471 1.1.1.3 christos unsigned * insn,
472 1.1.1.3 christos unsigned int * insn_len,
473 1.1.1.3 christos unsigned isa_mask,
474 1.1.1.3 christos struct disassemble_info * info,
475 1.1.1.3 christos const struct arc_opcode ** opcode_result,
476 1.1.1.3 christos struct arc_operand_iterator * iter)
477 1.1.1.3 christos {
478 1.1.1.3 christos const struct arc_opcode *opcode = NULL;
479 1.1.1.3 christos bfd_boolean needs_limm;
480 1.1.1.3 christos const extInstruction_t *einsn;
481 1.1.1.3 christos
482 1.1.1.3 christos /* First, try the extension instructions. */
483 1.1.1.3 christos einsn = arcExtMap_insn (OPCODE (insn[0]), insn[0]);
484 1.1.1.3 christos if (einsn != NULL)
485 1.1.1.3 christos {
486 1.1.1.3 christos const char *errmsg = NULL;
487 1.1.1.3 christos
488 1.1.1.3 christos opcode = arcExtMap_genOpcode (einsn, isa_mask, &errmsg);
489 1.1.1.3 christos if (opcode == NULL)
490 1.1.1.3 christos {
491 1.1.1.3 christos (*info->fprintf_func) (info->stream, "\
492 1.1.1.3 christos An error occured while generating the extension instruction operations");
493 1.1.1.3 christos *opcode_result = NULL;
494 1.1.1.3 christos return FALSE;
495 1.1.1.3 christos }
496 1.1.1.3 christos
497 1.1.1.3 christos opcode = find_format_from_table (info, opcode, insn, *insn_len,
498 1.1.1.3 christos isa_mask, &needs_limm, FALSE);
499 1.1.1.3 christos }
500 1.1.1.3 christos
501 1.1.1.3 christos /* Then, try finding the first match in the opcode table. */
502 1.1.1.3 christos if (opcode == NULL)
503 1.1.1.3 christos opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
504 1.1.1.3 christos isa_mask, &needs_limm, TRUE);
505 1.1.1.3 christos
506 1.1.1.3 christos if (needs_limm && opcode != NULL)
507 1.1.1.3 christos {
508 1.1.1.3 christos bfd_byte buffer[4];
509 1.1.1.3 christos int status;
510 1.1.1.3 christos
511 1.1.1.3 christos status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
512 1.1.1.3 christos 4, info);
513 1.1.1.3 christos if (status != 0)
514 1.1.1.3 christos {
515 1.1.1.3 christos opcode = NULL;
516 1.1.1.3 christos }
517 1.1.1.3 christos else
518 1.1.1.3 christos {
519 1.1.1.3 christos insn[1] = ARRANGE_ENDIAN (info, buffer);
520 1.1.1.3 christos *insn_len += 4;
521 1.1.1.3 christos }
522 1.1.1.3 christos }
523 1.1.1.3 christos
524 1.1.1.3 christos if (opcode == NULL)
525 1.1.1.3 christos {
526 1.1.1.3 christos const struct arc_long_opcode *long_opcode;
527 1.1 christos
528 1.1.1.3 christos /* No instruction found yet, try the long instructions. */
529 1.1.1.3 christos long_opcode =
530 1.1.1.3 christos find_format_long_instructions (insn, insn_len, isa_mask,
531 1.1.1.3 christos memaddr, info);
532 1.1.1.3 christos
533 1.1.1.3 christos if (long_opcode != NULL)
534 1.1.1.3 christos {
535 1.1.1.3 christos iter->mode = OPERAND_ITERATOR_LONG;
536 1.1.1.3 christos iter->insn = insn;
537 1.1.1.3 christos iter->state.long_insn.long_opcode = long_opcode;
538 1.1.1.3 christos iter->state.long_insn.opidx_base =
539 1.1.1.3 christos long_opcode->base_opcode.operands;
540 1.1.1.3 christos iter->state.long_insn.opidx_limm =
541 1.1.1.3 christos long_opcode->operands;
542 1.1.1.3 christos opcode = &long_opcode->base_opcode;
543 1.1.1.3 christos }
544 1.1.1.3 christos }
545 1.1.1.3 christos else
546 1.1.1.3 christos {
547 1.1.1.3 christos iter->mode = OPERAND_ITERATOR_STANDARD;
548 1.1.1.3 christos iter->insn = insn;
549 1.1.1.3 christos iter->state.standard.opcode = opcode;
550 1.1.1.3 christos iter->state.standard.opidx = opcode->operands;
551 1.1.1.3 christos }
552 1.1 christos
553 1.1.1.3 christos *opcode_result = opcode;
554 1.1.1.3 christos return TRUE;
555 1.1 christos }
556 1.1 christos
557 1.1 christos static void
558 1.1.1.3 christos print_flags (const struct arc_opcode *opcode,
559 1.1.1.3 christos unsigned *insn,
560 1.1.1.3 christos struct disassemble_info *info)
561 1.1 christos {
562 1.1.1.3 christos const unsigned char *flgidx;
563 1.1.1.3 christos unsigned int value;
564 1.1.1.3 christos
565 1.1.1.3 christos /* Now extract and print the flags. */
566 1.1.1.3 christos for (flgidx = opcode->flags; *flgidx; flgidx++)
567 1.1 christos {
568 1.1.1.3 christos /* Get a valid flag class. */
569 1.1.1.3 christos const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
570 1.1.1.3 christos const unsigned *flgopridx;
571 1.1 christos
572 1.1.1.3 christos /* Check first the extensions. */
573 1.1.1.3 christos if (cl_flags->flag_class & F_CLASS_EXTEND)
574 1.1 christos {
575 1.1.1.3 christos const char *name;
576 1.1.1.3 christos value = (insn[0] & 0x1F);
577 1.1 christos
578 1.1.1.3 christos name = arcExtMap_condCodeName (value);
579 1.1.1.3 christos if (name)
580 1.1.1.3 christos {
581 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".%s", name);
582 1.1.1.3 christos continue;
583 1.1.1.3 christos }
584 1.1 christos }
585 1.1.1.3 christos
586 1.1.1.3 christos for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
587 1.1 christos {
588 1.1.1.3 christos const struct arc_flag_operand *flg_operand =
589 1.1.1.3 christos &arc_flag_operands[*flgopridx];
590 1.1.1.3 christos
591 1.1.1.3 christos if (!flg_operand->favail)
592 1.1.1.3 christos continue;
593 1.1.1.3 christos
594 1.1.1.3 christos value = (insn[0] >> flg_operand->shift)
595 1.1.1.3 christos & ((1 << flg_operand->bits) - 1);
596 1.1.1.3 christos if (value == flg_operand->code)
597 1.1.1.3 christos {
598 1.1.1.3 christos /* FIXME!: print correctly nt/t flag. */
599 1.1.1.3 christos if (!special_flag_p (opcode->name, flg_operand->name))
600 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".");
601 1.1.1.3 christos else if (info->insn_type == dis_dref)
602 1.1.1.3 christos {
603 1.1.1.3 christos switch (flg_operand->name[0])
604 1.1.1.3 christos {
605 1.1.1.3 christos case 'b':
606 1.1.1.3 christos info->data_size = 1;
607 1.1.1.3 christos break;
608 1.1.1.3 christos case 'h':
609 1.1.1.3 christos case 'w':
610 1.1.1.3 christos info->data_size = 2;
611 1.1.1.3 christos break;
612 1.1.1.3 christos default:
613 1.1.1.3 christos info->data_size = 4;
614 1.1.1.3 christos break;
615 1.1.1.3 christos }
616 1.1.1.3 christos }
617 1.1.1.3 christos if (flg_operand->name[0] == 'd'
618 1.1.1.3 christos && flg_operand->name[1] == 0)
619 1.1.1.3 christos info->branch_delay_insns = 1;
620 1.1.1.3 christos
621 1.1.1.3 christos /* Check if it is a conditional flag. */
622 1.1.1.3 christos if (cl_flags->flag_class & F_CLASS_COND)
623 1.1.1.3 christos {
624 1.1.1.3 christos if (info->insn_type == dis_jsr)
625 1.1.1.3 christos info->insn_type = dis_condjsr;
626 1.1.1.3 christos else if (info->insn_type == dis_branch)
627 1.1.1.3 christos info->insn_type = dis_condbranch;
628 1.1.1.3 christos }
629 1.1.1.3 christos
630 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
631 1.1.1.3 christos }
632 1.1 christos }
633 1.1 christos }
634 1.1 christos }
635 1.1 christos
636 1.1.1.3 christos static const char *
637 1.1.1.3 christos get_auxreg (const struct arc_opcode *opcode,
638 1.1.1.3 christos int value,
639 1.1.1.3 christos unsigned isa_mask)
640 1.1 christos {
641 1.1.1.3 christos const char *name;
642 1.1.1.3 christos unsigned int i;
643 1.1.1.3 christos const struct arc_aux_reg *auxr = &arc_aux_regs[0];
644 1.1.1.3 christos
645 1.1.1.3 christos if (opcode->insn_class != AUXREG)
646 1.1.1.3 christos return NULL;
647 1.1.1.3 christos
648 1.1.1.3 christos name = arcExtMap_auxRegName (value);
649 1.1.1.3 christos if (name)
650 1.1.1.3 christos return name;
651 1.1 christos
652 1.1.1.3 christos for (i = 0; i < arc_num_aux_regs; i++, auxr++)
653 1.1 christos {
654 1.1.1.3 christos if (!(auxr->cpu & isa_mask))
655 1.1.1.3 christos continue;
656 1.1 christos
657 1.1.1.3 christos if (auxr->subclass != NONE)
658 1.1.1.3 christos return NULL;
659 1.1 christos
660 1.1.1.3 christos if (auxr->address == value)
661 1.1.1.3 christos return auxr->name;
662 1.1.1.3 christos }
663 1.1.1.3 christos return NULL;
664 1.1.1.3 christos }
665 1.1 christos
666 1.1.1.3 christos /* Convert a value representing an address type to a string used to refer to
667 1.1.1.3 christos the address type in assembly code. */
668 1.1 christos
669 1.1.1.3 christos static const char *
670 1.1.1.3 christos get_addrtype (int value)
671 1.1.1.3 christos {
672 1.1.1.3 christos if (value < 0 || value > addrtypenames_max)
673 1.1.1.3 christos return addrtypeunknown;
674 1.1.1.3 christos
675 1.1.1.3 christos return addrtypenames[value];
676 1.1.1.3 christos }
677 1.1 christos
678 1.1.1.3 christos /* Calculate the instruction length for an instruction starting with MSB
679 1.1.1.3 christos and LSB, the most and least significant byte. The ISA_MASK is used to
680 1.1.1.3 christos filter the instructions considered to only those that are part of the
681 1.1.1.3 christos current architecture.
682 1.1 christos
683 1.1.1.3 christos The instruction lengths are calculated from the ARC_OPCODE table, and
684 1.1.1.3 christos cached for later use. */
685 1.1.1.3 christos
686 1.1.1.3 christos static unsigned int
687 1.1.1.3 christos arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
688 1.1.1.3 christos {
689 1.1.1.3 christos bfd_byte major_opcode = msb >> 3;
690 1.1.1.3 christos
691 1.1.1.3 christos switch (info->mach)
692 1.1 christos {
693 1.1.1.3 christos case bfd_mach_arc_arc700:
694 1.1.1.3 christos /* The nps400 extension set requires this special casing of the
695 1.1.1.3 christos instruction length calculation. Right now this is not causing any
696 1.1.1.3 christos problems as none of the known extensions overlap in opcode space,
697 1.1.1.3 christos but, if they ever do then we might need to start carrying
698 1.1.1.3 christos information around in the elf about which extensions are in use. */
699 1.1.1.3 christos if (major_opcode == 0xb)
700 1.1.1.3 christos {
701 1.1.1.3 christos bfd_byte minor_opcode = lsb & 0x1f;
702 1.1.1.3 christos
703 1.1.1.3 christos if (minor_opcode < 4)
704 1.1.1.3 christos return 2;
705 1.1.1.3 christos }
706 1.1.1.3 christos case bfd_mach_arc_arc600:
707 1.1.1.3 christos return (major_opcode > 0xb) ? 2 : 4;
708 1.1 christos break;
709 1.1.1.3 christos
710 1.1.1.3 christos case bfd_mach_arc_arcv2:
711 1.1.1.3 christos return (major_opcode > 0x7) ? 2 : 4;
712 1.1 christos break;
713 1.1.1.3 christos
714 1.1.1.3 christos default:
715 1.1.1.3 christos abort ();
716 1.1 christos }
717 1.1.1.3 christos }
718 1.1.1.3 christos
719 1.1.1.3 christos /* Extract and return the value of OPERAND from the instruction whose value
720 1.1.1.3 christos is held in the array INSN. */
721 1.1 christos
722 1.1.1.3 christos static int
723 1.1.1.3 christos extract_operand_value (const struct arc_operand *operand, unsigned *insn)
724 1.1.1.3 christos {
725 1.1.1.3 christos int value;
726 1.1 christos
727 1.1.1.3 christos /* Read the limm operand, if required. */
728 1.1.1.3 christos if (operand->flags & ARC_OPERAND_LIMM)
729 1.1.1.3 christos /* The second part of the instruction value will have been loaded as
730 1.1.1.3 christos part of the find_format call made earlier. */
731 1.1.1.3 christos value = insn[1];
732 1.1.1.3 christos else
733 1.1.1.3 christos {
734 1.1.1.3 christos if (operand->extract)
735 1.1.1.3 christos value = (*operand->extract) (insn[0], (int *) NULL);
736 1.1.1.3 christos else
737 1.1.1.3 christos {
738 1.1.1.3 christos if (operand->flags & ARC_OPERAND_ALIGNED32)
739 1.1.1.3 christos {
740 1.1.1.3 christos value = (insn[0] >> operand->shift)
741 1.1.1.3 christos & ((1 << (operand->bits - 2)) - 1);
742 1.1.1.3 christos value = value << 2;
743 1.1.1.3 christos }
744 1.1.1.3 christos else
745 1.1.1.3 christos {
746 1.1.1.3 christos value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
747 1.1.1.3 christos }
748 1.1.1.3 christos if (operand->flags & ARC_OPERAND_SIGNED)
749 1.1.1.3 christos {
750 1.1.1.3 christos int signbit = 1 << (operand->bits - 1);
751 1.1.1.3 christos value = (value ^ signbit) - signbit;
752 1.1.1.3 christos }
753 1.1.1.3 christos }
754 1.1.1.3 christos }
755 1.1 christos
756 1.1.1.3 christos return value;
757 1.1 christos }
758 1.1 christos
759 1.1.1.3 christos /* Find the next operand, and the operands value from ITER. Return TRUE if
760 1.1.1.3 christos there is another operand, otherwise return FALSE. If there is an
761 1.1.1.3 christos operand returned then the operand is placed into OPERAND, and the value
762 1.1.1.3 christos into VALUE. If there is no operand returned then OPERAND and VALUE are
763 1.1.1.3 christos unchanged. */
764 1.1.1.3 christos
765 1.1.1.3 christos static bfd_boolean
766 1.1.1.3 christos operand_iterator_next (struct arc_operand_iterator *iter,
767 1.1.1.3 christos const struct arc_operand **operand,
768 1.1.1.3 christos int *value)
769 1.1.1.3 christos {
770 1.1.1.3 christos if (iter->mode == OPERAND_ITERATOR_STANDARD)
771 1.1.1.3 christos {
772 1.1.1.3 christos if (*iter->state.standard.opidx == 0)
773 1.1.1.3 christos {
774 1.1.1.3 christos *operand = NULL;
775 1.1.1.3 christos return FALSE;
776 1.1.1.3 christos }
777 1.1.1.3 christos
778 1.1.1.3 christos *operand = &arc_operands[*iter->state.standard.opidx];
779 1.1.1.3 christos *value = extract_operand_value (*operand, iter->insn);
780 1.1.1.3 christos iter->state.standard.opidx++;
781 1.1.1.3 christos }
782 1.1.1.3 christos else
783 1.1.1.3 christos {
784 1.1.1.3 christos const struct arc_operand *operand_base, *operand_limm;
785 1.1.1.3 christos int value_base, value_limm;
786 1.1 christos
787 1.1.1.3 christos if (*iter->state.long_insn.opidx_limm == 0)
788 1.1.1.3 christos {
789 1.1.1.3 christos *operand = NULL;
790 1.1.1.3 christos return FALSE;
791 1.1.1.3 christos }
792 1.1.1.3 christos
793 1.1.1.3 christos operand_base = &arc_operands[*iter->state.long_insn.opidx_base];
794 1.1.1.3 christos operand_limm = &arc_operands[*iter->state.long_insn.opidx_limm];
795 1.1.1.3 christos
796 1.1.1.3 christos if (operand_base->flags & ARC_OPERAND_LIMM)
797 1.1.1.3 christos {
798 1.1.1.3 christos /* We've reached the end of the operand list. */
799 1.1.1.3 christos *operand = NULL;
800 1.1.1.3 christos return FALSE;
801 1.1.1.3 christos }
802 1.1.1.3 christos
803 1.1.1.3 christos value_base = value_limm = 0;
804 1.1.1.3 christos if (!(operand_limm->flags & ARC_OPERAND_IGNORE))
805 1.1.1.3 christos {
806 1.1.1.3 christos /* This should never happen. If it does then the use of
807 1.1.1.3 christos extract_operand_value below will access memory beyond
808 1.1.1.3 christos the insn array. */
809 1.1.1.3 christos assert ((operand_limm->flags & ARC_OPERAND_LIMM) == 0);
810 1.1.1.3 christos
811 1.1.1.3 christos *operand = operand_limm;
812 1.1.1.3 christos value_limm = extract_operand_value (*operand, &iter->insn[1]);
813 1.1.1.3 christos }
814 1.1.1.3 christos
815 1.1.1.3 christos if (!(operand_base->flags & ARC_OPERAND_IGNORE))
816 1.1.1.3 christos {
817 1.1.1.3 christos *operand = operand_base;
818 1.1.1.3 christos value_base = extract_operand_value (*operand, iter->insn);
819 1.1.1.3 christos }
820 1.1.1.3 christos
821 1.1.1.3 christos /* This is a bit of a fudge. There's no reason why simply ORing
822 1.1.1.3 christos together the two values is the right thing to do, however, for all
823 1.1.1.3 christos the cases we currently have, it is the right thing, so, for now,
824 1.1.1.3 christos I've put off solving the more complex problem. */
825 1.1.1.3 christos *value = value_base | value_limm;
826 1.1 christos
827 1.1.1.3 christos iter->state.long_insn.opidx_base++;
828 1.1.1.3 christos iter->state.long_insn.opidx_limm++;
829 1.1.1.3 christos }
830 1.1.1.3 christos return TRUE;
831 1.1.1.3 christos }
832 1.1.1.3 christos
833 1.1.1.3 christos /* Helper for parsing the options. */
834 1.1.1.3 christos
835 1.1.1.3 christos static void
836 1.1.1.3 christos parse_option (char *option)
837 1.1 christos {
838 1.1.1.3 christos if (CONST_STRNEQ (option, "dsp"))
839 1.1.1.3 christos add_to_decodelist (DSP, NONE);
840 1.1 christos
841 1.1.1.3 christos else if (CONST_STRNEQ (option, "spfp"))
842 1.1.1.3 christos add_to_decodelist (FLOAT, SPX);
843 1.1.1.3 christos
844 1.1.1.3 christos else if (CONST_STRNEQ (option, "dpfp"))
845 1.1.1.3 christos add_to_decodelist (FLOAT, DPX);
846 1.1.1.3 christos
847 1.1.1.3 christos else if (CONST_STRNEQ (option, "quarkse_em"))
848 1.1.1.3 christos add_to_decodelist (FLOAT, QUARKSE);
849 1.1.1.3 christos
850 1.1.1.3 christos else if (CONST_STRNEQ (option, "fpuda"))
851 1.1.1.3 christos add_to_decodelist (FLOAT, DPA);
852 1.1.1.3 christos
853 1.1.1.3 christos else if (CONST_STRNEQ (option, "fpud"))
854 1.1.1.3 christos {
855 1.1.1.3 christos add_to_decodelist (FLOAT, SP);
856 1.1.1.3 christos add_to_decodelist (FLOAT, CVT);
857 1.1.1.3 christos }
858 1.1.1.3 christos
859 1.1.1.3 christos else if (CONST_STRNEQ (option, "fpus"))
860 1.1.1.3 christos {
861 1.1.1.3 christos add_to_decodelist (FLOAT, DP);
862 1.1.1.3 christos add_to_decodelist (FLOAT, CVT);
863 1.1.1.3 christos }
864 1.1.1.3 christos else
865 1.1.1.3 christos fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
866 1.1.1.3 christos }
867 1.1.1.3 christos
868 1.1.1.3 christos /* Go over the options list and parse it. */
869 1.1.1.3 christos
870 1.1.1.3 christos static void
871 1.1.1.3 christos parse_disassembler_options (char *options)
872 1.1.1.3 christos {
873 1.1.1.3 christos if (options == NULL)
874 1.1.1.3 christos return;
875 1.1.1.3 christos
876 1.1.1.3 christos while (*options)
877 1.1.1.3 christos {
878 1.1.1.3 christos /* Skip empty options. */
879 1.1.1.3 christos if (*options == ',')
880 1.1 christos {
881 1.1.1.3 christos ++ options;
882 1.1.1.3 christos continue;
883 1.1 christos }
884 1.1.1.3 christos
885 1.1.1.3 christos parse_option (options);
886 1.1.1.3 christos
887 1.1.1.3 christos while (*options != ',' && *options != '\0')
888 1.1.1.3 christos ++ options;
889 1.1.1.3 christos }
890 1.1.1.3 christos }
891 1.1.1.3 christos
892 1.1.1.3 christos /* Disassemble ARC instructions. */
893 1.1.1.3 christos
894 1.1.1.3 christos static int
895 1.1.1.3 christos print_insn_arc (bfd_vma memaddr,
896 1.1.1.3 christos struct disassemble_info *info)
897 1.1.1.3 christos {
898 1.1.1.3 christos bfd_byte buffer[4];
899 1.1.1.3 christos unsigned int lowbyte, highbyte;
900 1.1.1.3 christos int status;
901 1.1.1.3 christos unsigned int insn_len;
902 1.1.1.3 christos unsigned insn[2] = { 0, 0 };
903 1.1.1.3 christos unsigned isa_mask;
904 1.1.1.3 christos const struct arc_opcode *opcode;
905 1.1.1.3 christos bfd_boolean need_comma;
906 1.1.1.3 christos bfd_boolean open_braket;
907 1.1.1.3 christos int size;
908 1.1.1.3 christos const struct arc_operand *operand;
909 1.1.1.3 christos int value;
910 1.1.1.3 christos struct arc_operand_iterator iter;
911 1.1.1.3 christos Elf_Internal_Ehdr *header = NULL;
912 1.1.1.3 christos
913 1.1.1.3 christos if (info->disassembler_options)
914 1.1.1.3 christos {
915 1.1.1.3 christos parse_disassembler_options (info->disassembler_options);
916 1.1.1.3 christos
917 1.1.1.3 christos /* Avoid repeated parsing of the options. */
918 1.1.1.3 christos info->disassembler_options = NULL;
919 1.1.1.3 christos }
920 1.1.1.3 christos
921 1.1.1.3 christos memset (&iter, 0, sizeof (iter));
922 1.1.1.3 christos lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
923 1.1.1.3 christos highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
924 1.1.1.3 christos
925 1.1.1.3 christos if (info->section && info->section->owner)
926 1.1.1.3 christos header = elf_elfheader (info->section->owner);
927 1.1.1.3 christos
928 1.1.1.3 christos switch (info->mach)
929 1.1.1.3 christos {
930 1.1.1.3 christos case bfd_mach_arc_arc700:
931 1.1.1.3 christos isa_mask = ARC_OPCODE_ARC700;
932 1.1 christos break;
933 1.1 christos
934 1.1.1.3 christos case bfd_mach_arc_arc600:
935 1.1.1.3 christos isa_mask = ARC_OPCODE_ARC600;
936 1.1.1.3 christos break;
937 1.1.1.3 christos
938 1.1.1.3 christos case bfd_mach_arc_arcv2:
939 1.1.1.3 christos default:
940 1.1.1.3 christos isa_mask = ARC_OPCODE_ARCv2EM;
941 1.1.1.3 christos if ((header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
942 1.1 christos {
943 1.1.1.3 christos isa_mask = ARC_OPCODE_ARCv2HS;
944 1.1.1.3 christos /* FPU instructions are not extensions for HS. */
945 1.1.1.3 christos add_to_decodelist (FLOAT, SP);
946 1.1.1.3 christos add_to_decodelist (FLOAT, DP);
947 1.1.1.3 christos add_to_decodelist (FLOAT, CVT);
948 1.1 christos }
949 1.1 christos break;
950 1.1.1.3 christos }
951 1.1 christos
952 1.1.1.3 christos /* This variable may be set by the instruction decoder. It suggests
953 1.1.1.3 christos the number of bytes objdump should display on a single line. If
954 1.1.1.3 christos the instruction decoder sets this, it should always set it to
955 1.1.1.3 christos the same value in order to get reasonable looking output. */
956 1.1.1.3 christos
957 1.1.1.3 christos info->bytes_per_line = 8;
958 1.1.1.3 christos
959 1.1.1.3 christos /* In the next lines, we set two info variables control the way
960 1.1.1.3 christos objdump displays the raw data. For example, if bytes_per_line is
961 1.1.1.3 christos 8 and bytes_per_chunk is 4, the output will look like this:
962 1.1.1.3 christos 00: 00000000 00000000
963 1.1.1.3 christos with the chunks displayed according to "display_endian". */
964 1.1 christos
965 1.1.1.3 christos if (info->section
966 1.1.1.3 christos && !(info->section->flags & SEC_CODE))
967 1.1.1.3 christos {
968 1.1.1.3 christos /* This is not a CODE section. */
969 1.1.1.3 christos switch (info->section->size)
970 1.1.1.3 christos {
971 1.1.1.3 christos case 1:
972 1.1.1.3 christos case 2:
973 1.1.1.3 christos case 4:
974 1.1.1.3 christos size = info->section->size;
975 1.1.1.3 christos break;
976 1.1 christos default:
977 1.1.1.3 christos size = (info->section->size & 0x01) ? 1 : 4;
978 1.1 christos break;
979 1.1 christos }
980 1.1.1.3 christos info->bytes_per_chunk = 1;
981 1.1.1.3 christos info->display_endian = info->endian;
982 1.1.1.3 christos }
983 1.1.1.3 christos else
984 1.1.1.3 christos {
985 1.1.1.3 christos size = 2;
986 1.1.1.3 christos info->bytes_per_chunk = 2;
987 1.1.1.3 christos info->display_endian = info->endian;
988 1.1.1.3 christos }
989 1.1 christos
990 1.1.1.3 christos /* Read the insn into a host word. */
991 1.1.1.3 christos status = (*info->read_memory_func) (memaddr, buffer, size, info);
992 1.1.1.3 christos if (status != 0)
993 1.1.1.3 christos {
994 1.1.1.3 christos (*info->memory_error_func) (status, memaddr, info);
995 1.1.1.3 christos return -1;
996 1.1.1.3 christos }
997 1.1 christos
998 1.1.1.3 christos if (info->section
999 1.1.1.3 christos && !(info->section->flags & SEC_CODE))
1000 1.1.1.3 christos {
1001 1.1.1.3 christos /* Data section. */
1002 1.1.1.3 christos unsigned long data;
1003 1.1 christos
1004 1.1.1.3 christos data = bfd_get_bits (buffer, size * 8,
1005 1.1.1.3 christos info->display_endian == BFD_ENDIAN_BIG);
1006 1.1.1.3 christos switch (size)
1007 1.1 christos {
1008 1.1.1.3 christos case 1:
1009 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
1010 1.1 christos break;
1011 1.1.1.3 christos case 2:
1012 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
1013 1.1 christos break;
1014 1.1.1.3 christos case 4:
1015 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
1016 1.1 christos break;
1017 1.1.1.3 christos default:
1018 1.1.1.3 christos abort ();
1019 1.1 christos }
1020 1.1.1.3 christos return size;
1021 1.1.1.3 christos }
1022 1.1 christos
1023 1.1.1.3 christos insn_len = arc_insn_length (buffer[lowbyte], buffer[highbyte], info);
1024 1.1.1.3 christos pr_debug ("instruction length = %d bytes\n", insn_len);
1025 1.1 christos
1026 1.1.1.3 christos switch (insn_len)
1027 1.1.1.3 christos {
1028 1.1.1.3 christos case 2:
1029 1.1.1.3 christos insn[0] = (buffer[lowbyte] << 8) | buffer[highbyte];
1030 1.1 christos break;
1031 1.1 christos
1032 1.1 christos default:
1033 1.1.1.3 christos /* An unknown instruction is treated as being length 4. This is
1034 1.1.1.3 christos possibly not the best solution, but matches the behaviour that was
1035 1.1.1.3 christos in place before the table based instruction length look-up was
1036 1.1.1.3 christos introduced. */
1037 1.1.1.3 christos case 4:
1038 1.1.1.3 christos /* This is a long instruction: Read the remaning 2 bytes. */
1039 1.1.1.3 christos status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
1040 1.1.1.3 christos if (status != 0)
1041 1.1 christos {
1042 1.1.1.3 christos (*info->memory_error_func) (status, memaddr + 2, info);
1043 1.1.1.3 christos return -1;
1044 1.1 christos }
1045 1.1.1.3 christos insn[0] = ARRANGE_ENDIAN (info, buffer);
1046 1.1 christos break;
1047 1.1 christos }
1048 1.1 christos
1049 1.1.1.3 christos /* Set some defaults for the insn info. */
1050 1.1.1.3 christos info->insn_info_valid = 1;
1051 1.1.1.3 christos info->branch_delay_insns = 0;
1052 1.1.1.3 christos info->data_size = 0;
1053 1.1.1.3 christos info->insn_type = dis_nonbranch;
1054 1.1.1.3 christos info->target = 0;
1055 1.1.1.3 christos info->target2 = 0;
1056 1.1.1.3 christos
1057 1.1.1.3 christos /* FIXME to be moved in dissasemble_init_for_target. */
1058 1.1.1.3 christos info->disassembler_needs_relocs = TRUE;
1059 1.1.1.3 christos
1060 1.1.1.3 christos /* Find the first match in the opcode table. */
1061 1.1.1.3 christos if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
1062 1.1.1.3 christos return -1;
1063 1.1.1.3 christos
1064 1.1.1.3 christos if (!opcode)
1065 1.1.1.3 christos {
1066 1.1.1.3 christos if (insn_len == 2)
1067 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
1068 1.1 christos else
1069 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
1070 1.1.1.3 christos
1071 1.1.1.3 christos info->insn_type = dis_noninsn;
1072 1.1.1.3 christos return insn_len;
1073 1.1.1.3 christos }
1074 1.1.1.3 christos
1075 1.1.1.3 christos /* Print the mnemonic. */
1076 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", opcode->name);
1077 1.1 christos
1078 1.1.1.3 christos /* Preselect the insn class. */
1079 1.1.1.3 christos switch (opcode->insn_class)
1080 1.1.1.3 christos {
1081 1.1.1.3 christos case BRANCH:
1082 1.1.1.3 christos case JUMP:
1083 1.1.1.3 christos if (!strncmp (opcode->name, "bl", 2)
1084 1.1.1.3 christos || !strncmp (opcode->name, "jl", 2))
1085 1.1.1.3 christos {
1086 1.1.1.3 christos if (opcode->subclass == COND)
1087 1.1.1.3 christos info->insn_type = dis_condjsr;
1088 1.1.1.3 christos else
1089 1.1.1.3 christos info->insn_type = dis_jsr;
1090 1.1 christos }
1091 1.1 christos else
1092 1.1 christos {
1093 1.1.1.3 christos if (opcode->subclass == COND)
1094 1.1.1.3 christos info->insn_type = dis_condbranch;
1095 1.1.1.3 christos else
1096 1.1.1.3 christos info->insn_type = dis_branch;
1097 1.1 christos }
1098 1.1 christos break;
1099 1.1.1.3 christos case MEMORY:
1100 1.1.1.3 christos info->insn_type = dis_dref; /* FIXME! DB indicates mov as memory! */
1101 1.1 christos break;
1102 1.1.1.3 christos default:
1103 1.1.1.3 christos info->insn_type = dis_nonbranch;
1104 1.1 christos break;
1105 1.1.1.3 christos }
1106 1.1 christos
1107 1.1.1.3 christos pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode);
1108 1.1.1.3 christos
1109 1.1.1.3 christos print_flags (opcode, insn, info);
1110 1.1.1.3 christos
1111 1.1.1.3 christos if (opcode->operands[0] != 0)
1112 1.1.1.3 christos (*info->fprintf_func) (info->stream, "\t");
1113 1.1.1.3 christos
1114 1.1.1.3 christos need_comma = FALSE;
1115 1.1.1.3 christos open_braket = FALSE;
1116 1.1.1.3 christos
1117 1.1.1.3 christos /* Now extract and print the operands. */
1118 1.1.1.3 christos operand = NULL;
1119 1.1.1.3 christos while (operand_iterator_next (&iter, &operand, &value))
1120 1.1.1.3 christos {
1121 1.1.1.3 christos if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1122 1.1 christos {
1123 1.1.1.3 christos (*info->fprintf_func) (info->stream, "]");
1124 1.1.1.3 christos open_braket = FALSE;
1125 1.1.1.3 christos continue;
1126 1.1 christos }
1127 1.1 christos
1128 1.1.1.3 christos /* Only take input from real operands. */
1129 1.1.1.3 christos if (ARC_OPERAND_IS_FAKE (operand))
1130 1.1.1.3 christos continue;
1131 1.1 christos
1132 1.1.1.3 christos if ((operand->flags & ARC_OPERAND_IGNORE)
1133 1.1.1.3 christos && (operand->flags & ARC_OPERAND_IR)
1134 1.1.1.3 christos && value == -1)
1135 1.1.1.3 christos continue;
1136 1.1 christos
1137 1.1.1.3 christos if (operand->flags & ARC_OPERAND_COLON)
1138 1.1.1.3 christos {
1139 1.1.1.3 christos (*info->fprintf_func) (info->stream, ":");
1140 1.1.1.3 christos continue;
1141 1.1.1.3 christos }
1142 1.1 christos
1143 1.1.1.3 christos if (need_comma)
1144 1.1.1.3 christos (*info->fprintf_func) (info->stream, ",");
1145 1.1 christos
1146 1.1.1.3 christos if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1147 1.1 christos {
1148 1.1.1.3 christos (*info->fprintf_func) (info->stream, "[");
1149 1.1.1.3 christos open_braket = TRUE;
1150 1.1.1.3 christos need_comma = FALSE;
1151 1.1.1.3 christos continue;
1152 1.1 christos }
1153 1.1.1.3 christos
1154 1.1.1.3 christos need_comma = TRUE;
1155 1.1.1.3 christos
1156 1.1.1.3 christos /* Print the operand as directed by the flags. */
1157 1.1.1.3 christos if (operand->flags & ARC_OPERAND_IR)
1158 1.1 christos {
1159 1.1.1.3 christos const char *rname;
1160 1.1.1.3 christos
1161 1.1.1.3 christos assert (value >=0 && value < 64);
1162 1.1.1.3 christos rname = arcExtMap_coreRegName (value);
1163 1.1.1.3 christos if (!rname)
1164 1.1.1.3 christos rname = regnames[value];
1165 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", rname);
1166 1.1.1.3 christos if (operand->flags & ARC_OPERAND_TRUNCATE)
1167 1.1 christos {
1168 1.1.1.3 christos rname = arcExtMap_coreRegName (value + 1);
1169 1.1.1.3 christos if (!rname)
1170 1.1.1.3 christos rname = regnames[value + 1];
1171 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", rname);
1172 1.1 christos }
1173 1.1 christos }
1174 1.1.1.3 christos else if (operand->flags & ARC_OPERAND_LIMM)
1175 1.1.1.3 christos {
1176 1.1.1.3 christos const char *rname = get_auxreg (opcode, value, isa_mask);
1177 1.1 christos
1178 1.1.1.3 christos if (rname && open_braket)
1179 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", rname);
1180 1.1.1.3 christos else
1181 1.1.1.3 christos {
1182 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%#x", value);
1183 1.1.1.3 christos if (info->insn_type == dis_branch
1184 1.1.1.3 christos || info->insn_type == dis_jsr)
1185 1.1.1.3 christos info->target = (bfd_vma) value;
1186 1.1.1.3 christos }
1187 1.1.1.3 christos }
1188 1.1.1.3 christos else if (operand->flags & ARC_OPERAND_PCREL)
1189 1.1.1.3 christos {
1190 1.1.1.3 christos /* PCL relative. */
1191 1.1.1.3 christos if (info->flags & INSN_HAS_RELOC)
1192 1.1.1.3 christos memaddr = 0;
1193 1.1.1.3 christos (*info->print_address_func) ((memaddr & ~3) + value, info);
1194 1.1 christos
1195 1.1.1.3 christos info->target = (bfd_vma) (memaddr & ~3) + value;
1196 1.1.1.3 christos }
1197 1.1.1.3 christos else if (operand->flags & ARC_OPERAND_SIGNED)
1198 1.1 christos {
1199 1.1.1.3 christos const char *rname = get_auxreg (opcode, value, isa_mask);
1200 1.1.1.3 christos if (rname && open_braket)
1201 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", rname);
1202 1.1.1.3 christos else
1203 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%d", value);
1204 1.1 christos }
1205 1.1.1.3 christos else if (operand->flags & ARC_OPERAND_ADDRTYPE)
1206 1.1.1.3 christos {
1207 1.1.1.3 christos const char *addrtype = get_addrtype (value);
1208 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", addrtype);
1209 1.1.1.3 christos /* A colon follow an address type. */
1210 1.1.1.3 christos need_comma = FALSE;
1211 1.1.1.3 christos }
1212 1.1 christos else
1213 1.1 christos {
1214 1.1.1.3 christos if (operand->flags & ARC_OPERAND_TRUNCATE
1215 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_ALIGNED32)
1216 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_ALIGNED16)
1217 1.1.1.3 christos && value > 0 && value <= 14)
1218 1.1.1.3 christos (*info->fprintf_func) (info->stream, "r13-%s",
1219 1.1.1.3 christos regnames[13 + value - 1]);
1220 1.1.1.3 christos else
1221 1.1 christos {
1222 1.1.1.3 christos const char *rname = get_auxreg (opcode, value, isa_mask);
1223 1.1.1.3 christos if (rname && open_braket)
1224 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", rname);
1225 1.1.1.3 christos else
1226 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%#x", value);
1227 1.1 christos }
1228 1.1 christos }
1229 1.1 christos }
1230 1.1 christos
1231 1.1.1.3 christos return insn_len;
1232 1.1 christos }
1233 1.1 christos
1234 1.1 christos
1235 1.1.1.3 christos disassembler_ftype
1236 1.1.1.3 christos arc_get_disassembler (bfd *abfd)
1237 1.1 christos {
1238 1.1.1.3 christos /* Read the extenssion insns and registers, if any. */
1239 1.1.1.3 christos build_ARC_extmap (abfd);
1240 1.1.1.3 christos #ifdef DEBUG
1241 1.1.1.3 christos dump_ARC_extmap ();
1242 1.1.1.3 christos #endif
1243 1.1 christos
1244 1.1.1.3 christos return print_insn_arc;
1245 1.1 christos }
1246 1.1 christos
1247 1.1.1.3 christos /* Disassemble ARC instructions. Used by debugger. */
1248 1.1 christos
1249 1.1.1.3 christos struct arcDisState
1250 1.1.1.3 christos arcAnalyzeInstr (bfd_vma memaddr,
1251 1.1.1.3 christos struct disassemble_info *info)
1252 1.1 christos {
1253 1.1.1.3 christos struct arcDisState ret;
1254 1.1.1.3 christos memset (&ret, 0, sizeof (struct arcDisState));
1255 1.1 christos
1256 1.1.1.3 christos ret.instructionLen = print_insn_arc (memaddr, info);
1257 1.1 christos
1258 1.1.1.3 christos #if 0
1259 1.1.1.3 christos ret.words[0] = insn[0];
1260 1.1.1.3 christos ret.words[1] = insn[1];
1261 1.1.1.3 christos ret._this = &ret;
1262 1.1.1.3 christos ret.coreRegName = _coreRegName;
1263 1.1.1.3 christos ret.auxRegName = _auxRegName;
1264 1.1.1.3 christos ret.condCodeName = _condCodeName;
1265 1.1.1.3 christos ret.instName = _instName;
1266 1.1.1.3 christos #endif
1267 1.1 christos
1268 1.1.1.3 christos return ret;
1269 1.1.1.3 christos }
1270 1.1 christos
1271 1.1.1.3 christos void
1272 1.1.1.3 christos print_arc_disassembler_options (FILE *stream)
1273 1.1 christos {
1274 1.1.1.3 christos fprintf (stream, _("\n\
1275 1.1.1.3 christos The following ARC specific disassembler options are supported for use \n\
1276 1.1.1.3 christos with -M switch (multiple options should be separated by commas):\n"));
1277 1.1.1.3 christos
1278 1.1.1.3 christos fprintf (stream, _("\
1279 1.1.1.3 christos dsp Recognize DSP instructions.\n"));
1280 1.1.1.3 christos fprintf (stream, _("\
1281 1.1.1.3 christos spfp Recognize FPX SP instructions.\n"));
1282 1.1.1.3 christos fprintf (stream, _("\
1283 1.1.1.3 christos dpfp Recognize FPX DP instructions.\n"));
1284 1.1.1.3 christos fprintf (stream, _("\
1285 1.1.1.3 christos quarkse_em Recognize FPU QuarkSE-EM instructions.\n"));
1286 1.1.1.3 christos fprintf (stream, _("\
1287 1.1.1.3 christos fpuda Recognize double assist FPU instructions.\n"));
1288 1.1.1.3 christos fprintf (stream, _("\
1289 1.1.1.3 christos fpus Recognize single precision FPU instructions.\n"));
1290 1.1.1.3 christos fprintf (stream, _("\
1291 1.1.1.3 christos fpud Recognize double precision FPU instructions.\n"));
1292 1.1 christos }
1293 1.1 christos
1294 1.1 christos
1295 1.1.1.3 christos /* Local variables:
1296 1.1.1.3 christos eval: (c-set-style "gnu")
1297 1.1.1.3 christos indent-tabs-mode: t
1298 1.1.1.3 christos End: */
1299