Coverage Report

Created: 2026-07-12 09:22

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