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