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