arc-dis.c revision 1.1.1.5 1 1.1 christos /* Instruction printing code for the ARC.
2 1.1.1.5 christos Copyright (C) 1994-2019 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.4 christos /* The complete instruction value to extract operands from. */
41 1.1.1.4 christos unsigned long long insn;
42 1.1.1.3 christos
43 1.1.1.4 christos /* The LIMM if this is being tracked separately. This field is only
44 1.1.1.4 christos valid if we find the LIMM operand in the operand list. */
45 1.1.1.4 christos unsigned limm;
46 1.1.1.3 christos
47 1.1.1.4 christos /* The opcode this iterator is operating on. */
48 1.1.1.4 christos const struct arc_opcode *opcode;
49 1.1.1.3 christos
50 1.1.1.4 christos /* The index into the opcodes operand index list. */
51 1.1.1.4 christos const unsigned char *opidx;
52 1.1.1.4 christos };
53 1.1.1.3 christos
54 1.1.1.4 christos /* A private data used by ARC decoder. */
55 1.1.1.4 christos struct arc_disassemble_info
56 1.1.1.4 christos {
57 1.1.1.4 christos /* The current disassembled arc opcode. */
58 1.1.1.4 christos const struct arc_opcode *opcode;
59 1.1.1.3 christos
60 1.1.1.4 christos /* Instruction length w/o limm field. */
61 1.1.1.4 christos unsigned insn_len;
62 1.1.1.4 christos
63 1.1.1.4 christos /* TRUE if we have limm. */
64 1.1.1.4 christos bfd_boolean limm_p;
65 1.1.1.4 christos
66 1.1.1.4 christos /* LIMM value, if exists. */
67 1.1.1.4 christos unsigned limm;
68 1.1.1.4 christos
69 1.1.1.4 christos /* Condition code, if exists. */
70 1.1.1.4 christos unsigned condition_code;
71 1.1.1.4 christos
72 1.1.1.4 christos /* Writeback mode. */
73 1.1.1.4 christos unsigned writeback_mode;
74 1.1.1.4 christos
75 1.1.1.4 christos /* Number of operands. */
76 1.1.1.4 christos unsigned operands_count;
77 1.1.1.4 christos
78 1.1.1.4 christos struct arc_insn_operand operands[MAX_INSN_ARGS];
79 1.1.1.3 christos };
80 1.1.1.3 christos
81 1.1.1.3 christos /* Globals variables. */
82 1.1.1.3 christos
83 1.1.1.3 christos static const char * const regnames[64] =
84 1.1.1.3 christos {
85 1.1.1.3 christos "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
86 1.1.1.3 christos "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
87 1.1.1.3 christos "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
88 1.1.1.3 christos "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
89 1.1.1.3 christos
90 1.1.1.3 christos "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
91 1.1.1.3 christos "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
92 1.1.1.3 christos "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
93 1.1.1.3 christos "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
94 1.1.1.3 christos };
95 1.1.1.3 christos
96 1.1.1.3 christos static const char * const addrtypenames[ARC_NUM_ADDRTYPES] =
97 1.1.1.3 christos {
98 1.1.1.3 christos "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd",
99 1.1.1.3 christos "cd", "cbd", "cjid", "clbd", "cm", "csd", "cxa", "cxd"
100 1.1.1.3 christos };
101 1.1 christos
102 1.1.1.3 christos static int addrtypenames_max = ARC_NUM_ADDRTYPES - 1;
103 1.1 christos
104 1.1.1.3 christos static const char * const addrtypeunknown = "unknown";
105 1.1.1.3 christos
106 1.1.1.3 christos /* This structure keeps track which instruction class(es)
107 1.1.1.3 christos should be ignored durring disassembling. */
108 1.1.1.3 christos
109 1.1.1.3 christos typedef struct skipclass
110 1.1 christos {
111 1.1.1.3 christos insn_class_t insn_class;
112 1.1.1.3 christos insn_subclass_t subclass;
113 1.1.1.3 christos struct skipclass *nxt;
114 1.1.1.3 christos } skipclass_t, *linkclass;
115 1.1.1.3 christos
116 1.1.1.3 christos /* Intial classes of instructions to be consider first when
117 1.1.1.3 christos disassembling. */
118 1.1.1.3 christos static linkclass decodelist = NULL;
119 1.1.1.3 christos
120 1.1.1.5 christos /* ISA mask value enforced via disassembler info options. ARC_OPCODE_NONE
121 1.1.1.5 christos value means that no CPU is enforced. */
122 1.1.1.5 christos
123 1.1.1.5 christos static unsigned enforced_isa_mask = ARC_OPCODE_NONE;
124 1.1.1.5 christos
125 1.1.1.5 christos /* True if we want to print using only hex numbers. */
126 1.1.1.5 christos static bfd_boolean print_hex = FALSE;
127 1.1.1.5 christos
128 1.1.1.3 christos /* Macros section. */
129 1.1.1.3 christos
130 1.1.1.3 christos #ifdef DEBUG
131 1.1.1.3 christos # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
132 1.1.1.3 christos #else
133 1.1.1.3 christos # define pr_debug(fmt, args...)
134 1.1.1.3 christos #endif
135 1.1.1.3 christos
136 1.1.1.3 christos #define ARRANGE_ENDIAN(info, buf) \
137 1.1.1.3 christos (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \
138 1.1.1.3 christos : bfd_getb32 (buf))
139 1.1 christos
140 1.1.1.3 christos #define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \
141 1.1.1.3 christos (s + (sizeof (word) * 8 - 1 - e)))
142 1.1.1.4 christos #define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31))
143 1.1 christos
144 1.1.1.3 christos /* Functions implementation. */
145 1.1 christos
146 1.1.1.4 christos /* Initialize private data. */
147 1.1.1.3 christos static bfd_boolean
148 1.1.1.4 christos init_arc_disasm_info (struct disassemble_info *info)
149 1.1 christos {
150 1.1.1.4 christos struct arc_disassemble_info *arc_infop
151 1.1.1.4 christos = calloc (sizeof (*arc_infop), 1);
152 1.1.1.4 christos
153 1.1.1.4 christos if (arc_infop == NULL)
154 1.1.1.3 christos return FALSE;
155 1.1.1.4 christos
156 1.1.1.4 christos info->private_data = arc_infop;
157 1.1.1.3 christos return TRUE;
158 1.1 christos }
159 1.1 christos
160 1.1.1.3 christos /* Add a new element to the decode list. */
161 1.1.1.3 christos
162 1.1.1.3 christos static void
163 1.1.1.3 christos add_to_decodelist (insn_class_t insn_class,
164 1.1.1.3 christos insn_subclass_t subclass)
165 1.1 christos {
166 1.1.1.3 christos linkclass t = (linkclass) xmalloc (sizeof (skipclass_t));
167 1.1.1.3 christos
168 1.1.1.3 christos t->insn_class = insn_class;
169 1.1.1.3 christos t->subclass = subclass;
170 1.1.1.3 christos t->nxt = decodelist;
171 1.1.1.3 christos decodelist = t;
172 1.1 christos }
173 1.1 christos
174 1.1.1.3 christos /* Return TRUE if we need to skip the opcode from being
175 1.1.1.3 christos disassembled. */
176 1.1.1.3 christos
177 1.1.1.3 christos static bfd_boolean
178 1.1.1.4 christos skip_this_opcode (const struct arc_opcode *opcode)
179 1.1 christos {
180 1.1.1.3 christos linkclass t = decodelist;
181 1.1 christos
182 1.1.1.3 christos /* Check opcode for major 0x06, return if it is not in. */
183 1.1.1.4 christos if (arc_opcode_len (opcode) == 4
184 1.1.1.4 christos && OPCODE_32BIT_INSN (opcode->opcode) != 0x06)
185 1.1.1.3 christos return FALSE;
186 1.1.1.3 christos
187 1.1.1.4 christos /* or not a known truble class. */
188 1.1.1.4 christos switch (opcode->insn_class)
189 1.1.1.4 christos {
190 1.1.1.4 christos case FLOAT:
191 1.1.1.4 christos case DSP:
192 1.1.1.5 christos case ARITH:
193 1.1.1.4 christos break;
194 1.1.1.4 christos default:
195 1.1.1.4 christos return FALSE;
196 1.1.1.4 christos }
197 1.1.1.4 christos
198 1.1.1.4 christos while (t != NULL)
199 1.1.1.3 christos {
200 1.1.1.3 christos if ((t->insn_class == opcode->insn_class)
201 1.1.1.3 christos && (t->subclass == opcode->subclass))
202 1.1.1.4 christos return FALSE;
203 1.1.1.3 christos t = t->nxt;
204 1.1.1.3 christos }
205 1.1.1.3 christos
206 1.1.1.4 christos return TRUE;
207 1.1 christos }
208 1.1 christos
209 1.1.1.3 christos static bfd_vma
210 1.1.1.3 christos bfd_getm32 (unsigned int data)
211 1.1 christos {
212 1.1.1.3 christos bfd_vma value = 0;
213 1.1.1.3 christos
214 1.1.1.3 christos value = ((data & 0xff00) | (data & 0xff)) << 16;
215 1.1.1.3 christos value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
216 1.1.1.3 christos return value;
217 1.1 christos }
218 1.1 christos
219 1.1.1.3 christos static bfd_boolean
220 1.1.1.3 christos special_flag_p (const char *opname,
221 1.1.1.3 christos const char *flgname)
222 1.1 christos {
223 1.1.1.3 christos const struct arc_flag_special *flg_spec;
224 1.1.1.3 christos unsigned i, j, flgidx;
225 1.1 christos
226 1.1.1.3 christos for (i = 0; i < arc_num_flag_special; i++)
227 1.1 christos {
228 1.1.1.3 christos flg_spec = &arc_flag_special_cases[i];
229 1.1.1.3 christos
230 1.1.1.3 christos if (strcmp (opname, flg_spec->name))
231 1.1.1.3 christos continue;
232 1.1.1.3 christos
233 1.1.1.3 christos /* Found potential special case instruction. */
234 1.1.1.3 christos for (j=0;; ++j)
235 1.1.1.3 christos {
236 1.1.1.3 christos flgidx = flg_spec->flags[j];
237 1.1.1.3 christos if (flgidx == 0)
238 1.1.1.3 christos break; /* End of the array. */
239 1.1 christos
240 1.1.1.3 christos if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
241 1.1.1.3 christos return TRUE;
242 1.1.1.3 christos }
243 1.1 christos }
244 1.1.1.3 christos return FALSE;
245 1.1 christos }
246 1.1 christos
247 1.1.1.3 christos /* Find opcode from ARC_TABLE given the instruction described by INSN and
248 1.1.1.3 christos INSNLEN. The ISA_MASK restricts the possible matches in ARC_TABLE. */
249 1.1.1.3 christos
250 1.1.1.3 christos static const struct arc_opcode *
251 1.1.1.3 christos find_format_from_table (struct disassemble_info *info,
252 1.1.1.3 christos const struct arc_opcode *arc_table,
253 1.1.1.4 christos unsigned long long insn,
254 1.1.1.3 christos unsigned int insn_len,
255 1.1.1.3 christos unsigned isa_mask,
256 1.1.1.3 christos bfd_boolean *has_limm,
257 1.1.1.3 christos bfd_boolean overlaps)
258 1.1 christos {
259 1.1.1.3 christos unsigned int i = 0;
260 1.1.1.3 christos const struct arc_opcode *opcode = NULL;
261 1.1.1.4 christos const struct arc_opcode *t_op = NULL;
262 1.1.1.3 christos const unsigned char *opidx;
263 1.1.1.3 christos const unsigned char *flgidx;
264 1.1.1.4 christos bfd_boolean warn_p = FALSE;
265 1.1.1.3 christos
266 1.1.1.3 christos do
267 1.1.1.3 christos {
268 1.1.1.3 christos bfd_boolean invalid = FALSE;
269 1.1.1.3 christos
270 1.1.1.3 christos opcode = &arc_table[i++];
271 1.1.1.3 christos
272 1.1.1.4 christos if (!(opcode->cpu & isa_mask))
273 1.1.1.3 christos continue;
274 1.1.1.3 christos
275 1.1.1.4 christos if (arc_opcode_len (opcode) != (int) insn_len)
276 1.1.1.3 christos continue;
277 1.1.1.3 christos
278 1.1.1.4 christos if ((insn & opcode->mask) != opcode->opcode)
279 1.1.1.3 christos continue;
280 1.1.1.3 christos
281 1.1.1.3 christos *has_limm = FALSE;
282 1.1.1.3 christos
283 1.1.1.3 christos /* Possible candidate, check the operands. */
284 1.1.1.3 christos for (opidx = opcode->operands; *opidx; opidx++)
285 1.1.1.3 christos {
286 1.1.1.4 christos int value, limmind;
287 1.1.1.3 christos const struct arc_operand *operand = &arc_operands[*opidx];
288 1.1.1.3 christos
289 1.1.1.3 christos if (operand->flags & ARC_OPERAND_FAKE)
290 1.1.1.3 christos continue;
291 1.1.1.3 christos
292 1.1.1.3 christos if (operand->extract)
293 1.1.1.4 christos value = (*operand->extract) (insn, &invalid);
294 1.1.1.3 christos else
295 1.1.1.4 christos value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
296 1.1.1.3 christos
297 1.1.1.3 christos /* Check for LIMM indicator. If it is there, then make sure
298 1.1.1.3 christos we pick the right format. */
299 1.1.1.4 christos limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E;
300 1.1.1.3 christos if (operand->flags & ARC_OPERAND_IR
301 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_LIMM))
302 1.1 christos {
303 1.1.1.3 christos if ((value == 0x3E && insn_len == 4)
304 1.1.1.4 christos || (value == limmind && insn_len == 2))
305 1.1 christos {
306 1.1.1.3 christos invalid = TRUE;
307 1.1.1.3 christos break;
308 1.1 christos }
309 1.1 christos }
310 1.1 christos
311 1.1.1.3 christos if (operand->flags & ARC_OPERAND_LIMM
312 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_DUPLICATE))
313 1.1.1.3 christos *has_limm = TRUE;
314 1.1.1.3 christos }
315 1.1.1.3 christos
316 1.1.1.3 christos /* Check the flags. */
317 1.1.1.3 christos for (flgidx = opcode->flags; *flgidx; flgidx++)
318 1.1.1.3 christos {
319 1.1.1.3 christos /* Get a valid flag class. */
320 1.1.1.3 christos const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
321 1.1.1.3 christos const unsigned *flgopridx;
322 1.1.1.3 christos int foundA = 0, foundB = 0;
323 1.1.1.3 christos unsigned int value;
324 1.1 christos
325 1.1.1.3 christos /* Check first the extensions. */
326 1.1.1.3 christos if (cl_flags->flag_class & F_CLASS_EXTEND)
327 1.1 christos {
328 1.1.1.4 christos value = (insn & 0x1F);
329 1.1.1.3 christos if (arcExtMap_condCodeName (value))
330 1.1.1.3 christos continue;
331 1.1 christos }
332 1.1.1.3 christos
333 1.1.1.4 christos /* Check for the implicit flags. */
334 1.1.1.4 christos if (cl_flags->flag_class & F_CLASS_IMPLICIT)
335 1.1.1.4 christos continue;
336 1.1.1.4 christos
337 1.1.1.3 christos for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
338 1.1 christos {
339 1.1.1.3 christos const struct arc_flag_operand *flg_operand =
340 1.1.1.3 christos &arc_flag_operands[*flgopridx];
341 1.1 christos
342 1.1.1.4 christos value = (insn >> flg_operand->shift)
343 1.1.1.3 christos & ((1 << flg_operand->bits) - 1);
344 1.1.1.3 christos if (value == flg_operand->code)
345 1.1.1.3 christos foundA = 1;
346 1.1.1.3 christos if (value)
347 1.1.1.3 christos foundB = 1;
348 1.1 christos }
349 1.1.1.3 christos
350 1.1.1.3 christos if (!foundA && foundB)
351 1.1 christos {
352 1.1.1.3 christos invalid = TRUE;
353 1.1.1.3 christos break;
354 1.1.1.3 christos }
355 1.1.1.3 christos }
356 1.1 christos
357 1.1.1.3 christos if (invalid)
358 1.1.1.3 christos continue;
359 1.1 christos
360 1.1.1.3 christos if (insn_len == 4
361 1.1.1.4 christos && overlaps)
362 1.1.1.4 christos {
363 1.1.1.4 christos warn_p = TRUE;
364 1.1.1.4 christos t_op = opcode;
365 1.1.1.4 christos if (skip_this_opcode (opcode))
366 1.1.1.4 christos continue;
367 1.1.1.4 christos }
368 1.1 christos
369 1.1.1.3 christos /* The instruction is valid. */
370 1.1.1.3 christos return opcode;
371 1.1.1.3 christos }
372 1.1.1.3 christos while (opcode->mask);
373 1.1 christos
374 1.1.1.4 christos if (warn_p)
375 1.1.1.3 christos {
376 1.1.1.4 christos info->fprintf_func (info->stream,
377 1.1.1.4 christos _("\nWarning: disassembly may be wrong due to "
378 1.1.1.4 christos "guessed opcode class choice.\n"
379 1.1.1.4 christos "Use -M<class[,class]> to select the correct "
380 1.1.1.4 christos "opcode class(es).\n\t\t\t\t"));
381 1.1.1.4 christos return t_op;
382 1.1.1.3 christos }
383 1.1.1.3 christos
384 1.1.1.3 christos return NULL;
385 1.1.1.3 christos }
386 1.1.1.3 christos
387 1.1.1.3 christos /* Find opcode for INSN, trying various different sources. The instruction
388 1.1.1.3 christos length in INSN_LEN will be updated if the instruction requires a LIMM
389 1.1.1.4 christos extension.
390 1.1.1.3 christos
391 1.1.1.3 christos A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
392 1.1.1.4 christos initialised, ready to iterate over the operands of the found opcode. If
393 1.1.1.4 christos the found opcode requires a LIMM then the LIMM value will be loaded into a
394 1.1.1.4 christos field of ITER.
395 1.1.1.3 christos
396 1.1.1.3 christos This function returns TRUE in almost all cases, FALSE is reserved to
397 1.1.1.4 christos indicate an error (failing to find an opcode is not an error) a returned
398 1.1.1.4 christos result of FALSE would indicate that the disassembler can't continue.
399 1.1.1.4 christos
400 1.1.1.4 christos If no matching opcode is found then the returned result will be TRUE, the
401 1.1.1.4 christos value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and
402 1.1.1.4 christos INSN_LEN will be unchanged.
403 1.1.1.4 christos
404 1.1.1.4 christos If a matching opcode is found, then the returned result will be TRUE, the
405 1.1.1.4 christos opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by
406 1.1.1.4 christos 4 if the instruction requires a LIMM, and the LIMM value will have been
407 1.1.1.4 christos loaded into a field of ITER. Finally, ITER will have been initialised so
408 1.1.1.4 christos that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's
409 1.1.1.4 christos operands. */
410 1.1.1.3 christos
411 1.1.1.3 christos static bfd_boolean
412 1.1.1.3 christos find_format (bfd_vma memaddr,
413 1.1.1.4 christos unsigned long long insn,
414 1.1.1.3 christos unsigned int * insn_len,
415 1.1.1.3 christos unsigned isa_mask,
416 1.1.1.3 christos struct disassemble_info * info,
417 1.1.1.3 christos const struct arc_opcode ** opcode_result,
418 1.1.1.3 christos struct arc_operand_iterator * iter)
419 1.1.1.3 christos {
420 1.1.1.3 christos const struct arc_opcode *opcode = NULL;
421 1.1.1.3 christos bfd_boolean needs_limm;
422 1.1.1.4 christos const extInstruction_t *einsn, *i;
423 1.1.1.4 christos unsigned limm = 0;
424 1.1.1.4 christos struct arc_disassemble_info *arc_infop = info->private_data;
425 1.1.1.3 christos
426 1.1.1.3 christos /* First, try the extension instructions. */
427 1.1.1.4 christos if (*insn_len == 4)
428 1.1.1.3 christos {
429 1.1.1.4 christos einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn);
430 1.1.1.4 christos for (i = einsn; (i != NULL) && (opcode == NULL); i = i->next)
431 1.1.1.3 christos {
432 1.1.1.4 christos const char *errmsg = NULL;
433 1.1.1.4 christos
434 1.1.1.4 christos opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg);
435 1.1.1.4 christos if (opcode == NULL)
436 1.1.1.4 christos {
437 1.1.1.4 christos (*info->fprintf_func) (info->stream, "\
438 1.1.1.3 christos An error occured while generating the extension instruction operations");
439 1.1.1.4 christos *opcode_result = NULL;
440 1.1.1.4 christos return FALSE;
441 1.1.1.4 christos }
442 1.1.1.3 christos
443 1.1.1.4 christos opcode = find_format_from_table (info, opcode, insn, *insn_len,
444 1.1.1.4 christos isa_mask, &needs_limm, FALSE);
445 1.1.1.4 christos }
446 1.1.1.3 christos }
447 1.1.1.3 christos
448 1.1.1.3 christos /* Then, try finding the first match in the opcode table. */
449 1.1.1.3 christos if (opcode == NULL)
450 1.1.1.3 christos opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
451 1.1.1.3 christos isa_mask, &needs_limm, TRUE);
452 1.1.1.3 christos
453 1.1.1.3 christos if (needs_limm && opcode != NULL)
454 1.1.1.3 christos {
455 1.1.1.3 christos bfd_byte buffer[4];
456 1.1.1.3 christos int status;
457 1.1.1.3 christos
458 1.1.1.3 christos status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
459 1.1.1.3 christos 4, info);
460 1.1.1.3 christos if (status != 0)
461 1.1.1.3 christos {
462 1.1.1.3 christos opcode = NULL;
463 1.1.1.3 christos }
464 1.1.1.3 christos else
465 1.1.1.3 christos {
466 1.1.1.4 christos limm = ARRANGE_ENDIAN (info, buffer);
467 1.1.1.3 christos *insn_len += 4;
468 1.1.1.3 christos }
469 1.1.1.3 christos }
470 1.1.1.3 christos
471 1.1.1.4 christos if (opcode != NULL)
472 1.1.1.3 christos {
473 1.1.1.3 christos iter->insn = insn;
474 1.1.1.4 christos iter->limm = limm;
475 1.1.1.4 christos iter->opcode = opcode;
476 1.1.1.4 christos iter->opidx = opcode->operands;
477 1.1.1.3 christos }
478 1.1 christos
479 1.1.1.3 christos *opcode_result = opcode;
480 1.1.1.4 christos
481 1.1.1.4 christos /* Update private data. */
482 1.1.1.4 christos arc_infop->opcode = opcode;
483 1.1.1.4 christos arc_infop->limm = (needs_limm) ? limm : 0;
484 1.1.1.4 christos arc_infop->limm_p = needs_limm;
485 1.1.1.4 christos
486 1.1.1.3 christos return TRUE;
487 1.1 christos }
488 1.1 christos
489 1.1 christos static void
490 1.1.1.3 christos print_flags (const struct arc_opcode *opcode,
491 1.1.1.4 christos unsigned long long *insn,
492 1.1.1.3 christos struct disassemble_info *info)
493 1.1 christos {
494 1.1.1.3 christos const unsigned char *flgidx;
495 1.1.1.3 christos unsigned int value;
496 1.1.1.4 christos struct arc_disassemble_info *arc_infop = info->private_data;
497 1.1.1.3 christos
498 1.1.1.3 christos /* Now extract and print the flags. */
499 1.1.1.3 christos for (flgidx = opcode->flags; *flgidx; flgidx++)
500 1.1 christos {
501 1.1.1.3 christos /* Get a valid flag class. */
502 1.1.1.3 christos const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
503 1.1.1.3 christos const unsigned *flgopridx;
504 1.1 christos
505 1.1.1.3 christos /* Check first the extensions. */
506 1.1.1.3 christos if (cl_flags->flag_class & F_CLASS_EXTEND)
507 1.1 christos {
508 1.1.1.3 christos const char *name;
509 1.1.1.3 christos value = (insn[0] & 0x1F);
510 1.1 christos
511 1.1.1.3 christos name = arcExtMap_condCodeName (value);
512 1.1.1.3 christos if (name)
513 1.1.1.3 christos {
514 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".%s", name);
515 1.1.1.3 christos continue;
516 1.1.1.3 christos }
517 1.1 christos }
518 1.1.1.3 christos
519 1.1.1.3 christos for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
520 1.1 christos {
521 1.1.1.3 christos const struct arc_flag_operand *flg_operand =
522 1.1.1.3 christos &arc_flag_operands[*flgopridx];
523 1.1.1.3 christos
524 1.1.1.4 christos /* Implicit flags are only used for the insn decoder. */
525 1.1.1.4 christos if (cl_flags->flag_class & F_CLASS_IMPLICIT)
526 1.1.1.4 christos {
527 1.1.1.4 christos if (cl_flags->flag_class & F_CLASS_COND)
528 1.1.1.4 christos arc_infop->condition_code = flg_operand->code;
529 1.1.1.4 christos else if (cl_flags->flag_class & F_CLASS_WB)
530 1.1.1.4 christos arc_infop->writeback_mode = flg_operand->code;
531 1.1.1.4 christos else if (cl_flags->flag_class & F_CLASS_ZZ)
532 1.1.1.4 christos info->data_size = flg_operand->code;
533 1.1.1.4 christos continue;
534 1.1.1.4 christos }
535 1.1.1.4 christos
536 1.1.1.3 christos if (!flg_operand->favail)
537 1.1.1.3 christos continue;
538 1.1.1.3 christos
539 1.1.1.3 christos value = (insn[0] >> flg_operand->shift)
540 1.1.1.3 christos & ((1 << flg_operand->bits) - 1);
541 1.1.1.3 christos if (value == flg_operand->code)
542 1.1.1.3 christos {
543 1.1.1.3 christos /* FIXME!: print correctly nt/t flag. */
544 1.1.1.3 christos if (!special_flag_p (opcode->name, flg_operand->name))
545 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".");
546 1.1.1.3 christos else if (info->insn_type == dis_dref)
547 1.1.1.3 christos {
548 1.1.1.3 christos switch (flg_operand->name[0])
549 1.1.1.3 christos {
550 1.1.1.3 christos case 'b':
551 1.1.1.3 christos info->data_size = 1;
552 1.1.1.3 christos break;
553 1.1.1.3 christos case 'h':
554 1.1.1.3 christos case 'w':
555 1.1.1.3 christos info->data_size = 2;
556 1.1.1.3 christos break;
557 1.1.1.3 christos default:
558 1.1.1.3 christos info->data_size = 4;
559 1.1.1.3 christos break;
560 1.1.1.3 christos }
561 1.1.1.3 christos }
562 1.1.1.3 christos if (flg_operand->name[0] == 'd'
563 1.1.1.3 christos && flg_operand->name[1] == 0)
564 1.1.1.3 christos info->branch_delay_insns = 1;
565 1.1.1.3 christos
566 1.1.1.3 christos /* Check if it is a conditional flag. */
567 1.1.1.3 christos if (cl_flags->flag_class & F_CLASS_COND)
568 1.1.1.3 christos {
569 1.1.1.3 christos if (info->insn_type == dis_jsr)
570 1.1.1.3 christos info->insn_type = dis_condjsr;
571 1.1.1.3 christos else if (info->insn_type == dis_branch)
572 1.1.1.3 christos info->insn_type = dis_condbranch;
573 1.1.1.4 christos arc_infop->condition_code = flg_operand->code;
574 1.1.1.3 christos }
575 1.1.1.3 christos
576 1.1.1.4 christos /* Check for the write back modes. */
577 1.1.1.4 christos if (cl_flags->flag_class & F_CLASS_WB)
578 1.1.1.4 christos arc_infop->writeback_mode = flg_operand->code;
579 1.1.1.4 christos
580 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
581 1.1.1.3 christos }
582 1.1 christos }
583 1.1 christos }
584 1.1 christos }
585 1.1 christos
586 1.1.1.3 christos static const char *
587 1.1.1.3 christos get_auxreg (const struct arc_opcode *opcode,
588 1.1.1.3 christos int value,
589 1.1.1.3 christos unsigned isa_mask)
590 1.1 christos {
591 1.1.1.3 christos const char *name;
592 1.1.1.3 christos unsigned int i;
593 1.1.1.3 christos const struct arc_aux_reg *auxr = &arc_aux_regs[0];
594 1.1.1.3 christos
595 1.1.1.3 christos if (opcode->insn_class != AUXREG)
596 1.1.1.3 christos return NULL;
597 1.1.1.3 christos
598 1.1.1.3 christos name = arcExtMap_auxRegName (value);
599 1.1.1.3 christos if (name)
600 1.1.1.3 christos return name;
601 1.1 christos
602 1.1.1.3 christos for (i = 0; i < arc_num_aux_regs; i++, auxr++)
603 1.1 christos {
604 1.1.1.3 christos if (!(auxr->cpu & isa_mask))
605 1.1.1.3 christos continue;
606 1.1 christos
607 1.1.1.3 christos if (auxr->subclass != NONE)
608 1.1.1.3 christos return NULL;
609 1.1 christos
610 1.1.1.3 christos if (auxr->address == value)
611 1.1.1.3 christos return auxr->name;
612 1.1.1.3 christos }
613 1.1.1.3 christos return NULL;
614 1.1.1.3 christos }
615 1.1 christos
616 1.1.1.3 christos /* Convert a value representing an address type to a string used to refer to
617 1.1.1.3 christos the address type in assembly code. */
618 1.1 christos
619 1.1.1.3 christos static const char *
620 1.1.1.3 christos get_addrtype (int value)
621 1.1.1.3 christos {
622 1.1.1.3 christos if (value < 0 || value > addrtypenames_max)
623 1.1.1.3 christos return addrtypeunknown;
624 1.1.1.3 christos
625 1.1.1.3 christos return addrtypenames[value];
626 1.1.1.3 christos }
627 1.1 christos
628 1.1.1.3 christos /* Calculate the instruction length for an instruction starting with MSB
629 1.1.1.3 christos and LSB, the most and least significant byte. The ISA_MASK is used to
630 1.1.1.3 christos filter the instructions considered to only those that are part of the
631 1.1.1.3 christos current architecture.
632 1.1 christos
633 1.1.1.3 christos The instruction lengths are calculated from the ARC_OPCODE table, and
634 1.1.1.3 christos cached for later use. */
635 1.1.1.3 christos
636 1.1.1.3 christos static unsigned int
637 1.1.1.3 christos arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
638 1.1.1.3 christos {
639 1.1.1.3 christos bfd_byte major_opcode = msb >> 3;
640 1.1.1.3 christos
641 1.1.1.3 christos switch (info->mach)
642 1.1 christos {
643 1.1.1.3 christos case bfd_mach_arc_arc700:
644 1.1.1.3 christos /* The nps400 extension set requires this special casing of the
645 1.1.1.3 christos instruction length calculation. Right now this is not causing any
646 1.1.1.3 christos problems as none of the known extensions overlap in opcode space,
647 1.1.1.3 christos but, if they ever do then we might need to start carrying
648 1.1.1.3 christos information around in the elf about which extensions are in use. */
649 1.1.1.3 christos if (major_opcode == 0xb)
650 1.1.1.3 christos {
651 1.1.1.3 christos bfd_byte minor_opcode = lsb & 0x1f;
652 1.1.1.3 christos
653 1.1.1.4 christos if (minor_opcode < 4)
654 1.1.1.4 christos return 6;
655 1.1.1.4 christos else if (minor_opcode == 0x10 || minor_opcode == 0x11)
656 1.1.1.4 christos return 8;
657 1.1.1.3 christos }
658 1.1.1.4 christos if (major_opcode == 0xa)
659 1.1.1.4 christos {
660 1.1.1.4 christos return 8;
661 1.1.1.4 christos }
662 1.1.1.4 christos /* Fall through. */
663 1.1.1.3 christos case bfd_mach_arc_arc600:
664 1.1.1.3 christos return (major_opcode > 0xb) ? 2 : 4;
665 1.1 christos break;
666 1.1.1.3 christos
667 1.1.1.3 christos case bfd_mach_arc_arcv2:
668 1.1.1.3 christos return (major_opcode > 0x7) ? 2 : 4;
669 1.1 christos break;
670 1.1.1.3 christos
671 1.1.1.3 christos default:
672 1.1.1.3 christos abort ();
673 1.1 christos }
674 1.1.1.3 christos }
675 1.1.1.3 christos
676 1.1.1.3 christos /* Extract and return the value of OPERAND from the instruction whose value
677 1.1.1.3 christos is held in the array INSN. */
678 1.1 christos
679 1.1.1.3 christos static int
680 1.1.1.4 christos extract_operand_value (const struct arc_operand *operand,
681 1.1.1.4 christos unsigned long long insn,
682 1.1.1.4 christos unsigned limm)
683 1.1.1.3 christos {
684 1.1.1.3 christos int value;
685 1.1 christos
686 1.1.1.3 christos /* Read the limm operand, if required. */
687 1.1.1.3 christos if (operand->flags & ARC_OPERAND_LIMM)
688 1.1.1.3 christos /* The second part of the instruction value will have been loaded as
689 1.1.1.3 christos part of the find_format call made earlier. */
690 1.1.1.4 christos value = limm;
691 1.1.1.3 christos else
692 1.1.1.3 christos {
693 1.1.1.3 christos if (operand->extract)
694 1.1.1.4 christos value = (*operand->extract) (insn, (int *) NULL);
695 1.1.1.3 christos else
696 1.1.1.3 christos {
697 1.1.1.3 christos if (operand->flags & ARC_OPERAND_ALIGNED32)
698 1.1.1.3 christos {
699 1.1.1.4 christos value = (insn >> operand->shift)
700 1.1.1.3 christos & ((1 << (operand->bits - 2)) - 1);
701 1.1.1.3 christos value = value << 2;
702 1.1.1.3 christos }
703 1.1.1.3 christos else
704 1.1.1.3 christos {
705 1.1.1.4 christos value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
706 1.1.1.3 christos }
707 1.1.1.3 christos if (operand->flags & ARC_OPERAND_SIGNED)
708 1.1.1.3 christos {
709 1.1.1.3 christos int signbit = 1 << (operand->bits - 1);
710 1.1.1.3 christos value = (value ^ signbit) - signbit;
711 1.1.1.3 christos }
712 1.1.1.3 christos }
713 1.1.1.3 christos }
714 1.1 christos
715 1.1.1.3 christos return value;
716 1.1 christos }
717 1.1 christos
718 1.1.1.3 christos /* Find the next operand, and the operands value from ITER. Return TRUE if
719 1.1.1.3 christos there is another operand, otherwise return FALSE. If there is an
720 1.1.1.3 christos operand returned then the operand is placed into OPERAND, and the value
721 1.1.1.3 christos into VALUE. If there is no operand returned then OPERAND and VALUE are
722 1.1.1.3 christos unchanged. */
723 1.1.1.3 christos
724 1.1.1.3 christos static bfd_boolean
725 1.1.1.3 christos operand_iterator_next (struct arc_operand_iterator *iter,
726 1.1.1.3 christos const struct arc_operand **operand,
727 1.1.1.3 christos int *value)
728 1.1.1.3 christos {
729 1.1.1.4 christos if (*iter->opidx == 0)
730 1.1.1.3 christos {
731 1.1.1.4 christos *operand = NULL;
732 1.1.1.4 christos return FALSE;
733 1.1.1.3 christos }
734 1.1 christos
735 1.1.1.4 christos *operand = &arc_operands[*iter->opidx];
736 1.1.1.4 christos *value = extract_operand_value (*operand, iter->insn, iter->limm);
737 1.1.1.4 christos iter->opidx++;
738 1.1.1.3 christos
739 1.1.1.3 christos return TRUE;
740 1.1.1.3 christos }
741 1.1.1.3 christos
742 1.1.1.3 christos /* Helper for parsing the options. */
743 1.1.1.3 christos
744 1.1.1.3 christos static void
745 1.1.1.4 christos parse_option (const char *option)
746 1.1 christos {
747 1.1.1.5 christos if (disassembler_options_cmp (option, "dsp") == 0)
748 1.1.1.3 christos add_to_decodelist (DSP, NONE);
749 1.1 christos
750 1.1.1.5 christos else if (disassembler_options_cmp (option, "spfp") == 0)
751 1.1.1.3 christos add_to_decodelist (FLOAT, SPX);
752 1.1.1.3 christos
753 1.1.1.5 christos else if (disassembler_options_cmp (option, "dpfp") == 0)
754 1.1.1.3 christos add_to_decodelist (FLOAT, DPX);
755 1.1.1.3 christos
756 1.1.1.5 christos else if (disassembler_options_cmp (option, "quarkse_em") == 0)
757 1.1.1.4 christos {
758 1.1.1.4 christos add_to_decodelist (FLOAT, DPX);
759 1.1.1.4 christos add_to_decodelist (FLOAT, SPX);
760 1.1.1.5 christos add_to_decodelist (FLOAT, QUARKSE1);
761 1.1.1.5 christos add_to_decodelist (FLOAT, QUARKSE2);
762 1.1.1.4 christos }
763 1.1.1.3 christos
764 1.1.1.5 christos else if (disassembler_options_cmp (option, "fpuda") == 0)
765 1.1.1.3 christos add_to_decodelist (FLOAT, DPA);
766 1.1.1.3 christos
767 1.1.1.5 christos else if (disassembler_options_cmp (option, "fpus") == 0)
768 1.1.1.3 christos {
769 1.1.1.3 christos add_to_decodelist (FLOAT, SP);
770 1.1.1.3 christos add_to_decodelist (FLOAT, CVT);
771 1.1.1.3 christos }
772 1.1.1.3 christos
773 1.1.1.5 christos else if (disassembler_options_cmp (option, "fpud") == 0)
774 1.1.1.3 christos {
775 1.1.1.3 christos add_to_decodelist (FLOAT, DP);
776 1.1.1.3 christos add_to_decodelist (FLOAT, CVT);
777 1.1.1.3 christos }
778 1.1.1.5 christos else if (CONST_STRNEQ (option, "hex"))
779 1.1.1.5 christos print_hex = TRUE;
780 1.1.1.3 christos else
781 1.1.1.5 christos /* xgettext:c-format */
782 1.1.1.5 christos opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
783 1.1.1.3 christos }
784 1.1.1.3 christos
785 1.1.1.5 christos #define ARC_CPU_TYPE_A6xx(NAME,EXTRA) \
786 1.1.1.5 christos { #NAME, ARC_OPCODE_ARC600, "ARC600" }
787 1.1.1.5 christos #define ARC_CPU_TYPE_A7xx(NAME,EXTRA) \
788 1.1.1.5 christos { #NAME, ARC_OPCODE_ARC700, "ARC700" }
789 1.1.1.5 christos #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA) \
790 1.1.1.5 christos { #NAME, ARC_OPCODE_ARCv2EM, "ARC EM" }
791 1.1.1.5 christos #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA) \
792 1.1.1.5 christos { #NAME, ARC_OPCODE_ARCv2HS, "ARC HS" }
793 1.1.1.5 christos #define ARC_CPU_TYPE_NONE \
794 1.1.1.5 christos { 0, 0, 0 }
795 1.1.1.3 christos
796 1.1.1.5 christos /* A table of CPU names and opcode sets. */
797 1.1.1.5 christos static const struct cpu_type
798 1.1.1.3 christos {
799 1.1.1.5 christos const char *name;
800 1.1.1.5 christos unsigned flags;
801 1.1.1.5 christos const char *isa;
802 1.1.1.5 christos }
803 1.1.1.5 christos cpu_types[] =
804 1.1.1.5 christos {
805 1.1.1.5 christos #include "elf/arc-cpu.def"
806 1.1.1.5 christos };
807 1.1.1.5 christos
808 1.1.1.5 christos /* Helper for parsing the CPU options. Accept any of the ARC architectures
809 1.1.1.5 christos values. OPTION should be a value passed to cpu=. */
810 1.1.1.5 christos
811 1.1.1.5 christos static unsigned
812 1.1.1.5 christos parse_cpu_option (const char *option)
813 1.1.1.5 christos {
814 1.1.1.5 christos int i;
815 1.1.1.3 christos
816 1.1.1.5 christos for (i = 0; cpu_types[i].name; ++i)
817 1.1.1.3 christos {
818 1.1.1.5 christos if (!disassembler_options_cmp (cpu_types[i].name, option))
819 1.1 christos {
820 1.1.1.5 christos return cpu_types[i].flags;
821 1.1 christos }
822 1.1.1.5 christos }
823 1.1.1.3 christos
824 1.1.1.5 christos /* xgettext:c-format */
825 1.1.1.5 christos opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option);
826 1.1.1.5 christos return ARC_OPCODE_NONE;
827 1.1.1.5 christos }
828 1.1.1.5 christos
829 1.1.1.5 christos /* Go over the options list and parse it. */
830 1.1.1.3 christos
831 1.1.1.5 christos static void
832 1.1.1.5 christos parse_disassembler_options (const char *options)
833 1.1.1.5 christos {
834 1.1.1.5 christos const char *option;
835 1.1.1.5 christos
836 1.1.1.5 christos if (options == NULL)
837 1.1.1.5 christos return;
838 1.1.1.5 christos
839 1.1.1.5 christos /* Disassembler might be reused for difference CPU's, and cpu option set for
840 1.1.1.5 christos the first one shouldn't be applied to second (which might not have
841 1.1.1.5 christos explicit cpu in its options. Therefore it is required to reset enforced
842 1.1.1.5 christos CPU when new options are being parsed. */
843 1.1.1.5 christos enforced_isa_mask = ARC_OPCODE_NONE;
844 1.1.1.5 christos
845 1.1.1.5 christos FOR_EACH_DISASSEMBLER_OPTION (option, options)
846 1.1.1.5 christos {
847 1.1.1.5 christos /* A CPU option? Cannot use STRING_COMMA_LEN because strncmp is also a
848 1.1.1.5 christos preprocessor macro. */
849 1.1.1.5 christos if (strncmp (option, "cpu=", 4) == 0)
850 1.1.1.5 christos /* Strip leading `cpu=`. */
851 1.1.1.5 christos enforced_isa_mask = parse_cpu_option (option + 4);
852 1.1.1.5 christos else
853 1.1.1.5 christos parse_option (option);
854 1.1.1.3 christos }
855 1.1.1.3 christos }
856 1.1.1.3 christos
857 1.1.1.4 christos /* Return the instruction type for an instruction described by OPCODE. */
858 1.1.1.4 christos
859 1.1.1.4 christos static enum dis_insn_type
860 1.1.1.4 christos arc_opcode_to_insn_type (const struct arc_opcode *opcode)
861 1.1.1.4 christos {
862 1.1.1.4 christos enum dis_insn_type insn_type;
863 1.1.1.4 christos
864 1.1.1.4 christos switch (opcode->insn_class)
865 1.1.1.4 christos {
866 1.1.1.4 christos case BRANCH:
867 1.1.1.4 christos case BBIT0:
868 1.1.1.4 christos case BBIT1:
869 1.1.1.4 christos case BI:
870 1.1.1.4 christos case BIH:
871 1.1.1.4 christos case BRCC:
872 1.1.1.4 christos case EI:
873 1.1.1.4 christos case JLI:
874 1.1.1.4 christos case JUMP:
875 1.1.1.4 christos case LOOP:
876 1.1.1.4 christos if (!strncmp (opcode->name, "bl", 2)
877 1.1.1.4 christos || !strncmp (opcode->name, "jl", 2))
878 1.1.1.4 christos {
879 1.1.1.4 christos if (opcode->subclass == COND)
880 1.1.1.4 christos insn_type = dis_condjsr;
881 1.1.1.4 christos else
882 1.1.1.4 christos insn_type = dis_jsr;
883 1.1.1.4 christos }
884 1.1.1.4 christos else
885 1.1.1.4 christos {
886 1.1.1.4 christos if (opcode->subclass == COND)
887 1.1.1.4 christos insn_type = dis_condbranch;
888 1.1.1.4 christos else
889 1.1.1.4 christos insn_type = dis_branch;
890 1.1.1.4 christos }
891 1.1.1.4 christos break;
892 1.1.1.4 christos case LOAD:
893 1.1.1.4 christos case STORE:
894 1.1.1.4 christos case MEMORY:
895 1.1.1.4 christos case ENTER:
896 1.1.1.4 christos case PUSH:
897 1.1.1.4 christos case POP:
898 1.1.1.4 christos insn_type = dis_dref;
899 1.1.1.4 christos break;
900 1.1.1.4 christos case LEAVE:
901 1.1.1.4 christos insn_type = dis_branch;
902 1.1.1.4 christos break;
903 1.1.1.4 christos default:
904 1.1.1.4 christos insn_type = dis_nonbranch;
905 1.1.1.4 christos break;
906 1.1.1.4 christos }
907 1.1.1.4 christos
908 1.1.1.4 christos return insn_type;
909 1.1.1.4 christos }
910 1.1.1.4 christos
911 1.1.1.3 christos /* Disassemble ARC instructions. */
912 1.1.1.3 christos
913 1.1.1.3 christos static int
914 1.1.1.3 christos print_insn_arc (bfd_vma memaddr,
915 1.1.1.3 christos struct disassemble_info *info)
916 1.1.1.3 christos {
917 1.1.1.4 christos bfd_byte buffer[8];
918 1.1.1.4 christos unsigned int highbyte, lowbyte;
919 1.1.1.3 christos int status;
920 1.1.1.3 christos unsigned int insn_len;
921 1.1.1.4 christos unsigned long long insn = 0;
922 1.1.1.5 christos unsigned isa_mask = ARC_OPCODE_NONE;
923 1.1.1.3 christos const struct arc_opcode *opcode;
924 1.1.1.3 christos bfd_boolean need_comma;
925 1.1.1.3 christos bfd_boolean open_braket;
926 1.1.1.3 christos int size;
927 1.1.1.3 christos const struct arc_operand *operand;
928 1.1.1.5 christos int value, vpcl;
929 1.1.1.3 christos struct arc_operand_iterator iter;
930 1.1.1.4 christos struct arc_disassemble_info *arc_infop;
931 1.1.1.5 christos bfd_boolean rpcl = FALSE, rset = FALSE;
932 1.1.1.3 christos
933 1.1.1.3 christos if (info->disassembler_options)
934 1.1.1.3 christos {
935 1.1.1.3 christos parse_disassembler_options (info->disassembler_options);
936 1.1.1.3 christos
937 1.1.1.3 christos /* Avoid repeated parsing of the options. */
938 1.1.1.3 christos info->disassembler_options = NULL;
939 1.1.1.3 christos }
940 1.1.1.3 christos
941 1.1.1.4 christos if (info->private_data == NULL && !init_arc_disasm_info (info))
942 1.1.1.4 christos return -1;
943 1.1.1.4 christos
944 1.1.1.3 christos memset (&iter, 0, sizeof (iter));
945 1.1.1.4 christos highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
946 1.1.1.4 christos lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
947 1.1.1.3 christos
948 1.1.1.5 christos /* Figure out CPU type, unless it was enforced via disassembler options. */
949 1.1.1.5 christos if (enforced_isa_mask == ARC_OPCODE_NONE)
950 1.1.1.3 christos {
951 1.1.1.5 christos Elf_Internal_Ehdr *header = NULL;
952 1.1 christos
953 1.1.1.5 christos if (info->section && info->section->owner)
954 1.1.1.5 christos header = elf_elfheader (info->section->owner);
955 1.1.1.3 christos
956 1.1.1.5 christos switch (info->mach)
957 1.1.1.5 christos {
958 1.1.1.5 christos case bfd_mach_arc_arc700:
959 1.1.1.5 christos isa_mask = ARC_OPCODE_ARC700;
960 1.1.1.5 christos break;
961 1.1.1.5 christos
962 1.1.1.5 christos case bfd_mach_arc_arc600:
963 1.1.1.5 christos isa_mask = ARC_OPCODE_ARC600;
964 1.1.1.5 christos break;
965 1.1.1.5 christos
966 1.1.1.5 christos case bfd_mach_arc_arcv2:
967 1.1.1.5 christos default:
968 1.1.1.5 christos isa_mask = ARC_OPCODE_ARCv2EM;
969 1.1.1.5 christos /* TODO: Perhaps remove definition of header since it is only used at
970 1.1.1.5 christos this location. */
971 1.1.1.5 christos if (header != NULL
972 1.1.1.5 christos && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
973 1.1.1.5 christos isa_mask = ARC_OPCODE_ARCv2HS;
974 1.1.1.5 christos break;
975 1.1 christos }
976 1.1.1.5 christos }
977 1.1.1.5 christos else
978 1.1.1.5 christos isa_mask = enforced_isa_mask;
979 1.1.1.5 christos
980 1.1.1.5 christos if (isa_mask == ARC_OPCODE_ARCv2HS)
981 1.1.1.5 christos {
982 1.1.1.5 christos /* FPU instructions are not extensions for HS. */
983 1.1.1.5 christos add_to_decodelist (FLOAT, SP);
984 1.1.1.5 christos add_to_decodelist (FLOAT, DP);
985 1.1.1.5 christos add_to_decodelist (FLOAT, CVT);
986 1.1.1.3 christos }
987 1.1 christos
988 1.1.1.3 christos /* This variable may be set by the instruction decoder. It suggests
989 1.1.1.3 christos the number of bytes objdump should display on a single line. If
990 1.1.1.3 christos the instruction decoder sets this, it should always set it to
991 1.1.1.3 christos the same value in order to get reasonable looking output. */
992 1.1.1.3 christos
993 1.1.1.3 christos info->bytes_per_line = 8;
994 1.1.1.3 christos
995 1.1.1.3 christos /* In the next lines, we set two info variables control the way
996 1.1.1.3 christos objdump displays the raw data. For example, if bytes_per_line is
997 1.1.1.3 christos 8 and bytes_per_chunk is 4, the output will look like this:
998 1.1.1.3 christos 00: 00000000 00000000
999 1.1.1.3 christos with the chunks displayed according to "display_endian". */
1000 1.1 christos
1001 1.1.1.3 christos if (info->section
1002 1.1.1.3 christos && !(info->section->flags & SEC_CODE))
1003 1.1.1.3 christos {
1004 1.1.1.3 christos /* This is not a CODE section. */
1005 1.1.1.3 christos switch (info->section->size)
1006 1.1.1.3 christos {
1007 1.1.1.3 christos case 1:
1008 1.1.1.3 christos case 2:
1009 1.1.1.3 christos case 4:
1010 1.1.1.3 christos size = info->section->size;
1011 1.1.1.3 christos break;
1012 1.1 christos default:
1013 1.1.1.3 christos size = (info->section->size & 0x01) ? 1 : 4;
1014 1.1 christos break;
1015 1.1 christos }
1016 1.1.1.3 christos info->bytes_per_chunk = 1;
1017 1.1.1.3 christos info->display_endian = info->endian;
1018 1.1.1.3 christos }
1019 1.1.1.3 christos else
1020 1.1.1.3 christos {
1021 1.1.1.3 christos size = 2;
1022 1.1.1.3 christos info->bytes_per_chunk = 2;
1023 1.1.1.3 christos info->display_endian = info->endian;
1024 1.1.1.3 christos }
1025 1.1 christos
1026 1.1.1.3 christos /* Read the insn into a host word. */
1027 1.1.1.3 christos status = (*info->read_memory_func) (memaddr, buffer, size, info);
1028 1.1.1.5 christos
1029 1.1.1.3 christos if (status != 0)
1030 1.1.1.3 christos {
1031 1.1.1.3 christos (*info->memory_error_func) (status, memaddr, info);
1032 1.1.1.3 christos return -1;
1033 1.1.1.3 christos }
1034 1.1 christos
1035 1.1.1.3 christos if (info->section
1036 1.1.1.3 christos && !(info->section->flags & SEC_CODE))
1037 1.1.1.3 christos {
1038 1.1.1.3 christos /* Data section. */
1039 1.1.1.3 christos unsigned long data;
1040 1.1 christos
1041 1.1.1.3 christos data = bfd_get_bits (buffer, size * 8,
1042 1.1.1.3 christos info->display_endian == BFD_ENDIAN_BIG);
1043 1.1.1.3 christos switch (size)
1044 1.1 christos {
1045 1.1.1.3 christos case 1:
1046 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
1047 1.1 christos break;
1048 1.1.1.3 christos case 2:
1049 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
1050 1.1 christos break;
1051 1.1.1.3 christos case 4:
1052 1.1.1.3 christos (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
1053 1.1 christos break;
1054 1.1.1.3 christos default:
1055 1.1.1.3 christos abort ();
1056 1.1 christos }
1057 1.1.1.3 christos return size;
1058 1.1.1.3 christos }
1059 1.1 christos
1060 1.1.1.4 christos insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
1061 1.1.1.3 christos pr_debug ("instruction length = %d bytes\n", insn_len);
1062 1.1.1.4 christos arc_infop = info->private_data;
1063 1.1.1.4 christos arc_infop->insn_len = insn_len;
1064 1.1 christos
1065 1.1.1.3 christos switch (insn_len)
1066 1.1.1.3 christos {
1067 1.1.1.3 christos case 2:
1068 1.1.1.4 christos insn = (buffer[highbyte] << 8) | buffer[lowbyte];
1069 1.1 christos break;
1070 1.1 christos
1071 1.1.1.3 christos case 4:
1072 1.1.1.4 christos {
1073 1.1.1.4 christos /* This is a long instruction: Read the remaning 2 bytes. */
1074 1.1.1.4 christos status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
1075 1.1.1.4 christos if (status != 0)
1076 1.1.1.4 christos {
1077 1.1.1.4 christos (*info->memory_error_func) (status, memaddr + 2, info);
1078 1.1.1.4 christos return -1;
1079 1.1.1.4 christos }
1080 1.1.1.4 christos insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
1081 1.1.1.4 christos }
1082 1.1.1.4 christos break;
1083 1.1.1.4 christos
1084 1.1.1.4 christos case 6:
1085 1.1.1.4 christos {
1086 1.1.1.4 christos status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
1087 1.1.1.4 christos if (status != 0)
1088 1.1.1.4 christos {
1089 1.1.1.4 christos (*info->memory_error_func) (status, memaddr + 2, info);
1090 1.1.1.4 christos return -1;
1091 1.1.1.4 christos }
1092 1.1.1.4 christos insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
1093 1.1.1.4 christos insn |= ((unsigned long long) buffer[highbyte] << 40)
1094 1.1.1.4 christos | ((unsigned long long) buffer[lowbyte] << 32);
1095 1.1.1.4 christos }
1096 1.1 christos break;
1097 1.1.1.4 christos
1098 1.1.1.4 christos case 8:
1099 1.1.1.4 christos {
1100 1.1.1.4 christos status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
1101 1.1.1.4 christos if (status != 0)
1102 1.1.1.4 christos {
1103 1.1.1.4 christos (*info->memory_error_func) (status, memaddr + 2, info);
1104 1.1.1.4 christos return -1;
1105 1.1.1.4 christos }
1106 1.1.1.4 christos insn =
1107 1.1.1.4 christos ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
1108 1.1.1.4 christos | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
1109 1.1.1.4 christos }
1110 1.1.1.4 christos break;
1111 1.1.1.4 christos
1112 1.1.1.4 christos default:
1113 1.1.1.4 christos /* There is no instruction whose length is not 2, 4, 6, or 8. */
1114 1.1.1.4 christos abort ();
1115 1.1 christos }
1116 1.1 christos
1117 1.1.1.4 christos pr_debug ("instruction value = %llx\n", insn);
1118 1.1.1.4 christos
1119 1.1.1.3 christos /* Set some defaults for the insn info. */
1120 1.1.1.3 christos info->insn_info_valid = 1;
1121 1.1.1.3 christos info->branch_delay_insns = 0;
1122 1.1.1.4 christos info->data_size = 4;
1123 1.1.1.3 christos info->insn_type = dis_nonbranch;
1124 1.1.1.3 christos info->target = 0;
1125 1.1.1.3 christos info->target2 = 0;
1126 1.1.1.3 christos
1127 1.1.1.3 christos /* FIXME to be moved in dissasemble_init_for_target. */
1128 1.1.1.3 christos info->disassembler_needs_relocs = TRUE;
1129 1.1.1.3 christos
1130 1.1.1.3 christos /* Find the first match in the opcode table. */
1131 1.1.1.3 christos if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
1132 1.1.1.3 christos return -1;
1133 1.1.1.3 christos
1134 1.1.1.3 christos if (!opcode)
1135 1.1.1.3 christos {
1136 1.1.1.4 christos switch (insn_len)
1137 1.1.1.4 christos {
1138 1.1.1.4 christos case 2:
1139 1.1.1.5 christos (*info->fprintf_func) (info->stream, ".shor\t%#04llx",
1140 1.1.1.4 christos insn & 0xffff);
1141 1.1.1.4 christos break;
1142 1.1.1.4 christos case 4:
1143 1.1.1.5 christos (*info->fprintf_func) (info->stream, ".word\t%#08llx",
1144 1.1.1.4 christos insn & 0xffffffff);
1145 1.1.1.4 christos break;
1146 1.1.1.4 christos case 6:
1147 1.1.1.5 christos (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1148 1.1.1.4 christos insn & 0xffffffff);
1149 1.1.1.5 christos (*info->fprintf_func) (info->stream, ".long\t%#04llx",
1150 1.1.1.4 christos (insn >> 32) & 0xffff);
1151 1.1.1.4 christos break;
1152 1.1.1.4 christos case 8:
1153 1.1.1.5 christos (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1154 1.1.1.4 christos insn & 0xffffffff);
1155 1.1.1.5 christos (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1156 1.1.1.4 christos insn >> 32);
1157 1.1.1.4 christos break;
1158 1.1.1.4 christos default:
1159 1.1.1.4 christos abort ();
1160 1.1.1.4 christos }
1161 1.1.1.3 christos
1162 1.1.1.3 christos info->insn_type = dis_noninsn;
1163 1.1.1.3 christos return insn_len;
1164 1.1.1.3 christos }
1165 1.1.1.3 christos
1166 1.1.1.3 christos /* Print the mnemonic. */
1167 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", opcode->name);
1168 1.1 christos
1169 1.1.1.3 christos /* Preselect the insn class. */
1170 1.1.1.4 christos info->insn_type = arc_opcode_to_insn_type (opcode);
1171 1.1 christos
1172 1.1.1.4 christos pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
1173 1.1.1.3 christos
1174 1.1.1.4 christos print_flags (opcode, &insn, info);
1175 1.1.1.3 christos
1176 1.1.1.3 christos if (opcode->operands[0] != 0)
1177 1.1.1.3 christos (*info->fprintf_func) (info->stream, "\t");
1178 1.1.1.3 christos
1179 1.1.1.3 christos need_comma = FALSE;
1180 1.1.1.3 christos open_braket = FALSE;
1181 1.1.1.4 christos arc_infop->operands_count = 0;
1182 1.1.1.3 christos
1183 1.1.1.3 christos /* Now extract and print the operands. */
1184 1.1.1.3 christos operand = NULL;
1185 1.1.1.5 christos vpcl = 0;
1186 1.1.1.3 christos while (operand_iterator_next (&iter, &operand, &value))
1187 1.1.1.3 christos {
1188 1.1.1.3 christos if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1189 1.1 christos {
1190 1.1.1.3 christos (*info->fprintf_func) (info->stream, "]");
1191 1.1.1.3 christos open_braket = FALSE;
1192 1.1.1.3 christos continue;
1193 1.1 christos }
1194 1.1 christos
1195 1.1.1.3 christos /* Only take input from real operands. */
1196 1.1.1.3 christos if (ARC_OPERAND_IS_FAKE (operand))
1197 1.1.1.3 christos continue;
1198 1.1 christos
1199 1.1.1.3 christos if ((operand->flags & ARC_OPERAND_IGNORE)
1200 1.1.1.3 christos && (operand->flags & ARC_OPERAND_IR)
1201 1.1.1.4 christos && value == -1)
1202 1.1.1.3 christos continue;
1203 1.1 christos
1204 1.1.1.3 christos if (operand->flags & ARC_OPERAND_COLON)
1205 1.1.1.4 christos {
1206 1.1.1.4 christos (*info->fprintf_func) (info->stream, ":");
1207 1.1.1.4 christos continue;
1208 1.1.1.4 christos }
1209 1.1 christos
1210 1.1.1.3 christos if (need_comma)
1211 1.1.1.3 christos (*info->fprintf_func) (info->stream, ",");
1212 1.1 christos
1213 1.1.1.3 christos if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1214 1.1 christos {
1215 1.1.1.3 christos (*info->fprintf_func) (info->stream, "[");
1216 1.1.1.3 christos open_braket = TRUE;
1217 1.1.1.3 christos need_comma = FALSE;
1218 1.1.1.3 christos continue;
1219 1.1 christos }
1220 1.1.1.3 christos
1221 1.1.1.3 christos need_comma = TRUE;
1222 1.1.1.3 christos
1223 1.1.1.5 christos if (operand->flags & ARC_OPERAND_PCREL)
1224 1.1.1.5 christos {
1225 1.1.1.5 christos rpcl = TRUE;
1226 1.1.1.5 christos vpcl = value;
1227 1.1.1.5 christos rset = TRUE;
1228 1.1.1.5 christos
1229 1.1.1.5 christos info->target = (bfd_vma) (memaddr & ~3) + value;
1230 1.1.1.5 christos }
1231 1.1.1.5 christos else if (!(operand->flags & ARC_OPERAND_IR))
1232 1.1.1.5 christos {
1233 1.1.1.5 christos vpcl = value;
1234 1.1.1.5 christos rset = TRUE;
1235 1.1.1.5 christos }
1236 1.1.1.5 christos
1237 1.1.1.3 christos /* Print the operand as directed by the flags. */
1238 1.1.1.3 christos if (operand->flags & ARC_OPERAND_IR)
1239 1.1 christos {
1240 1.1.1.3 christos const char *rname;
1241 1.1.1.3 christos
1242 1.1.1.3 christos assert (value >=0 && value < 64);
1243 1.1.1.3 christos rname = arcExtMap_coreRegName (value);
1244 1.1.1.3 christos if (!rname)
1245 1.1.1.3 christos rname = regnames[value];
1246 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", rname);
1247 1.1.1.3 christos if (operand->flags & ARC_OPERAND_TRUNCATE)
1248 1.1 christos {
1249 1.1.1.3 christos rname = arcExtMap_coreRegName (value + 1);
1250 1.1.1.3 christos if (!rname)
1251 1.1.1.3 christos rname = regnames[value + 1];
1252 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", rname);
1253 1.1 christos }
1254 1.1.1.5 christos if (value == 63)
1255 1.1.1.5 christos rpcl = TRUE;
1256 1.1.1.5 christos else
1257 1.1.1.5 christos rpcl = FALSE;
1258 1.1 christos }
1259 1.1.1.3 christos else if (operand->flags & ARC_OPERAND_LIMM)
1260 1.1.1.3 christos {
1261 1.1.1.3 christos const char *rname = get_auxreg (opcode, value, isa_mask);
1262 1.1 christos
1263 1.1.1.3 christos if (rname && open_braket)
1264 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", rname);
1265 1.1.1.3 christos else
1266 1.1.1.3 christos {
1267 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%#x", value);
1268 1.1.1.3 christos if (info->insn_type == dis_branch
1269 1.1.1.3 christos || info->insn_type == dis_jsr)
1270 1.1.1.3 christos info->target = (bfd_vma) value;
1271 1.1.1.3 christos }
1272 1.1.1.3 christos }
1273 1.1.1.3 christos else if (operand->flags & ARC_OPERAND_SIGNED)
1274 1.1 christos {
1275 1.1.1.3 christos const char *rname = get_auxreg (opcode, value, isa_mask);
1276 1.1.1.3 christos if (rname && open_braket)
1277 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", rname);
1278 1.1.1.3 christos else
1279 1.1.1.5 christos {
1280 1.1.1.5 christos if (print_hex)
1281 1.1.1.5 christos (*info->fprintf_func) (info->stream, "%#x", value);
1282 1.1.1.5 christos else
1283 1.1.1.5 christos (*info->fprintf_func) (info->stream, "%d", value);
1284 1.1.1.5 christos }
1285 1.1 christos }
1286 1.1.1.3 christos else if (operand->flags & ARC_OPERAND_ADDRTYPE)
1287 1.1.1.4 christos {
1288 1.1.1.4 christos const char *addrtype = get_addrtype (value);
1289 1.1.1.4 christos (*info->fprintf_func) (info->stream, "%s", addrtype);
1290 1.1.1.4 christos /* A colon follow an address type. */
1291 1.1.1.4 christos need_comma = FALSE;
1292 1.1.1.4 christos }
1293 1.1 christos else
1294 1.1 christos {
1295 1.1.1.3 christos if (operand->flags & ARC_OPERAND_TRUNCATE
1296 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_ALIGNED32)
1297 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_ALIGNED16)
1298 1.1.1.5 christos && value >= 0 && value <= 14)
1299 1.1.1.5 christos {
1300 1.1.1.5 christos /* Leave/Enter mnemonics. */
1301 1.1.1.5 christos switch (value)
1302 1.1.1.5 christos {
1303 1.1.1.5 christos case 0:
1304 1.1.1.5 christos need_comma = FALSE;
1305 1.1.1.5 christos break;
1306 1.1.1.5 christos case 1:
1307 1.1.1.5 christos (*info->fprintf_func) (info->stream, "r13");
1308 1.1.1.5 christos break;
1309 1.1.1.5 christos default:
1310 1.1.1.5 christos (*info->fprintf_func) (info->stream, "r13-%s",
1311 1.1.1.5 christos regnames[13 + value - 1]);
1312 1.1.1.5 christos break;
1313 1.1.1.5 christos }
1314 1.1.1.5 christos rpcl = FALSE;
1315 1.1.1.5 christos rset = FALSE;
1316 1.1.1.5 christos }
1317 1.1.1.3 christos else
1318 1.1 christos {
1319 1.1.1.3 christos const char *rname = get_auxreg (opcode, value, isa_mask);
1320 1.1.1.3 christos if (rname && open_braket)
1321 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%s", rname);
1322 1.1.1.3 christos else
1323 1.1.1.3 christos (*info->fprintf_func) (info->stream, "%#x", value);
1324 1.1 christos }
1325 1.1 christos }
1326 1.1.1.4 christos
1327 1.1.1.4 christos if (operand->flags & ARC_OPERAND_LIMM)
1328 1.1.1.4 christos {
1329 1.1.1.4 christos arc_infop->operands[arc_infop->operands_count].kind
1330 1.1.1.4 christos = ARC_OPERAND_KIND_LIMM;
1331 1.1.1.4 christos /* It is not important to have exactly the LIMM indicator
1332 1.1.1.4 christos here. */
1333 1.1.1.4 christos arc_infop->operands[arc_infop->operands_count].value = 63;
1334 1.1.1.4 christos }
1335 1.1.1.4 christos else
1336 1.1.1.4 christos {
1337 1.1.1.4 christos arc_infop->operands[arc_infop->operands_count].value = value;
1338 1.1.1.4 christos arc_infop->operands[arc_infop->operands_count].kind
1339 1.1.1.4 christos = (operand->flags & ARC_OPERAND_IR
1340 1.1.1.4 christos ? ARC_OPERAND_KIND_REG
1341 1.1.1.4 christos : ARC_OPERAND_KIND_SHIMM);
1342 1.1.1.4 christos }
1343 1.1.1.4 christos arc_infop->operands_count ++;
1344 1.1 christos }
1345 1.1 christos
1346 1.1.1.5 christos /* Pretty print extra info for pc-relative operands. */
1347 1.1.1.5 christos if (rpcl && rset)
1348 1.1.1.5 christos {
1349 1.1.1.5 christos if (info->flags & INSN_HAS_RELOC)
1350 1.1.1.5 christos /* If the instruction has a reloc associated with it, then the
1351 1.1.1.5 christos offset field in the instruction will actually be the addend
1352 1.1.1.5 christos for the reloc. (We are using REL type relocs). In such
1353 1.1.1.5 christos cases, we can ignore the pc when computing addresses, since
1354 1.1.1.5 christos the addend is not currently pc-relative. */
1355 1.1.1.5 christos memaddr = 0;
1356 1.1.1.5 christos
1357 1.1.1.5 christos (*info->fprintf_func) (info->stream, "\t;");
1358 1.1.1.5 christos (*info->print_address_func) ((memaddr & ~3) + vpcl, info);
1359 1.1.1.5 christos }
1360 1.1.1.5 christos
1361 1.1.1.3 christos return insn_len;
1362 1.1 christos }
1363 1.1 christos
1364 1.1 christos
1365 1.1.1.3 christos disassembler_ftype
1366 1.1.1.3 christos arc_get_disassembler (bfd *abfd)
1367 1.1 christos {
1368 1.1.1.4 christos /* BFD my be absent, if opcodes is invoked from the debugger that
1369 1.1.1.4 christos has connected to remote target and doesn't have an ELF file. */
1370 1.1.1.4 christos if (abfd != NULL)
1371 1.1.1.4 christos {
1372 1.1.1.4 christos /* Read the extension insns and registers, if any. */
1373 1.1.1.4 christos build_ARC_extmap (abfd);
1374 1.1.1.3 christos #ifdef DEBUG
1375 1.1.1.4 christos dump_ARC_extmap ();
1376 1.1.1.3 christos #endif
1377 1.1.1.4 christos }
1378 1.1 christos
1379 1.1.1.3 christos return print_insn_arc;
1380 1.1 christos }
1381 1.1 christos
1382 1.1.1.3 christos void
1383 1.1.1.3 christos print_arc_disassembler_options (FILE *stream)
1384 1.1 christos {
1385 1.1.1.5 christos int i;
1386 1.1.1.5 christos
1387 1.1.1.3 christos fprintf (stream, _("\n\
1388 1.1.1.3 christos The following ARC specific disassembler options are supported for use \n\
1389 1.1.1.3 christos with -M switch (multiple options should be separated by commas):\n"));
1390 1.1.1.3 christos
1391 1.1.1.5 christos /* cpu=... options. */
1392 1.1.1.5 christos for (i = 0; cpu_types[i].name; ++i)
1393 1.1.1.5 christos {
1394 1.1.1.5 christos /* As of now all value CPU values are less than 16 characters. */
1395 1.1.1.5 christos fprintf (stream, " cpu=%-16s\tEnforce %s ISA.\n",
1396 1.1.1.5 christos cpu_types[i].name, cpu_types[i].isa);
1397 1.1.1.5 christos }
1398 1.1.1.5 christos
1399 1.1.1.3 christos fprintf (stream, _("\
1400 1.1.1.3 christos dsp Recognize DSP instructions.\n"));
1401 1.1.1.3 christos fprintf (stream, _("\
1402 1.1.1.3 christos spfp Recognize FPX SP instructions.\n"));
1403 1.1.1.3 christos fprintf (stream, _("\
1404 1.1.1.3 christos dpfp Recognize FPX DP instructions.\n"));
1405 1.1.1.3 christos fprintf (stream, _("\
1406 1.1.1.3 christos quarkse_em Recognize FPU QuarkSE-EM instructions.\n"));
1407 1.1.1.3 christos fprintf (stream, _("\
1408 1.1.1.3 christos fpuda Recognize double assist FPU instructions.\n"));
1409 1.1.1.3 christos fprintf (stream, _("\
1410 1.1.1.3 christos fpus Recognize single precision FPU instructions.\n"));
1411 1.1.1.3 christos fprintf (stream, _("\
1412 1.1.1.3 christos fpud Recognize double precision FPU instructions.\n"));
1413 1.1.1.5 christos fprintf (stream, _("\
1414 1.1.1.5 christos hex Use only hexadecimal number to print immediates.\n"));
1415 1.1 christos }
1416 1.1 christos
1417 1.1.1.4 christos void arc_insn_decode (bfd_vma addr,
1418 1.1.1.4 christos struct disassemble_info *info,
1419 1.1.1.4 christos disassembler_ftype disasm_func,
1420 1.1.1.4 christos struct arc_instruction *insn)
1421 1.1.1.4 christos {
1422 1.1.1.4 christos const struct arc_opcode *opcode;
1423 1.1.1.4 christos struct arc_disassemble_info *arc_infop;
1424 1.1.1.4 christos
1425 1.1.1.4 christos /* Ensure that insn would be in the reset state. */
1426 1.1.1.4 christos memset (insn, 0, sizeof (struct arc_instruction));
1427 1.1.1.4 christos
1428 1.1.1.4 christos /* There was an error when disassembling, for example memory read error. */
1429 1.1.1.4 christos if (disasm_func (addr, info) < 0)
1430 1.1.1.4 christos {
1431 1.1.1.4 christos insn->valid = FALSE;
1432 1.1.1.4 christos return;
1433 1.1.1.4 christos }
1434 1.1.1.4 christos
1435 1.1.1.4 christos assert (info->private_data != NULL);
1436 1.1.1.4 christos arc_infop = info->private_data;
1437 1.1.1.4 christos
1438 1.1.1.4 christos insn->length = arc_infop->insn_len;;
1439 1.1.1.4 christos insn->address = addr;
1440 1.1.1.4 christos
1441 1.1.1.4 christos /* Quick exit if memory at this address is not an instruction. */
1442 1.1.1.4 christos if (info->insn_type == dis_noninsn)
1443 1.1.1.4 christos {
1444 1.1.1.4 christos insn->valid = FALSE;
1445 1.1.1.4 christos return;
1446 1.1.1.4 christos }
1447 1.1.1.4 christos
1448 1.1.1.4 christos insn->valid = TRUE;
1449 1.1.1.4 christos
1450 1.1.1.4 christos opcode = (const struct arc_opcode *) arc_infop->opcode;
1451 1.1.1.4 christos insn->insn_class = opcode->insn_class;
1452 1.1.1.4 christos insn->limm_value = arc_infop->limm;
1453 1.1.1.4 christos insn->limm_p = arc_infop->limm_p;
1454 1.1.1.4 christos
1455 1.1.1.4 christos insn->is_control_flow = (info->insn_type == dis_branch
1456 1.1.1.4 christos || info->insn_type == dis_condbranch
1457 1.1.1.4 christos || info->insn_type == dis_jsr
1458 1.1.1.4 christos || info->insn_type == dis_condjsr);
1459 1.1.1.4 christos
1460 1.1.1.4 christos insn->has_delay_slot = info->branch_delay_insns;
1461 1.1.1.4 christos insn->writeback_mode
1462 1.1.1.4 christos = (enum arc_ldst_writeback_mode) arc_infop->writeback_mode;
1463 1.1.1.4 christos insn->data_size_mode = info->data_size;
1464 1.1.1.4 christos insn->condition_code = arc_infop->condition_code;
1465 1.1.1.4 christos memcpy (insn->operands, arc_infop->operands,
1466 1.1.1.4 christos sizeof (struct arc_insn_operand) * MAX_INSN_ARGS);
1467 1.1.1.4 christos insn->operands_count = arc_infop->operands_count;
1468 1.1.1.4 christos }
1469 1.1 christos
1470 1.1.1.3 christos /* Local variables:
1471 1.1.1.3 christos eval: (c-set-style "gnu")
1472 1.1.1.3 christos indent-tabs-mode: t
1473 1.1.1.3 christos End: */
1474