Coverage Report

Created: 2023-08-28 06:23

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