Coverage Report

Created: 2025-06-24 06:45

/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-2025 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
265k
  (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf))  \
129
265k
   : bfd_getb32 (buf))
130
131
611k
#define BITS(word,s,e)  (((word) >> (s)) & ((1ull << ((e) - (s)) << 1) - 1))
132
611k
#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.15k
{
140
3.15k
  struct arc_disassemble_info *arc_infop = calloc (1, sizeof (*arc_infop));
141
142
3.15k
  info->private_data = arc_infop;
143
3.15k
  return arc_infop != NULL;
144
3.15k
}
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
2.57k
{
153
2.57k
  unsigned int i;
154
7.93k
  for (i = 0; i < arc_infop->decode_count; i++)
155
6.55k
    if (arc_infop->decode[i].insn_class == insn_class
156
6.55k
  && arc_infop->decode[i].subclass == subclass)
157
1.19k
      return;
158
159
1.38k
  assert (i < MAX_DECODES);
160
1.38k
  arc_infop->decode[i].insn_class = insn_class;
161
1.38k
  arc_infop->decode[i].subclass = subclass;
162
1.38k
  arc_infop->decode_count = i + 1;
163
1.38k
}
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
192k
{
171
  /* Check opcode for major 0x06, return if it is not in.  */
172
192k
  if (arc_opcode_len (opcode) == 4
173
192k
      && (OPCODE_32BIT_INSN (opcode->opcode) != 0x06
174
    /* Can be an APEX extensions.  */
175
192k
    && OPCODE_32BIT_INSN (opcode->opcode) != 0x07))
176
172k
    return false;
177
178
  /* or not a known truble class.  */
179
19.2k
  switch (opcode->insn_class)
180
19.2k
    {
181
10.8k
    case FLOAT:
182
14.5k
    case DSP:
183
16.2k
    case ARITH:
184
16.9k
    case MPY:
185
16.9k
      break;
186
2.30k
    default:
187
2.30k
      return false;
188
19.2k
    }
189
190
16.9k
  struct arc_disassemble_info *arc_infop = info->private_data;
191
20.3k
  for (unsigned int i = 0; i < arc_infop->decode_count; i++)
192
4.01k
    if (arc_infop->decode[i].insn_class == opcode->insn_class
193
4.01k
  && arc_infop->decode[i].subclass == opcode->subclass)
194
611
      return false;
195
196
16.3k
  return true;
197
16.9k
}
198
199
static bfd_vma
200
bfd_getm32 (unsigned int data)
201
240k
{
202
240k
  bfd_vma value = 0;
203
204
240k
  value = ((data & 0xff00) | (data & 0xff)) << 16;
205
240k
  value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
206
240k
  return value;
207
240k
}
208
209
static bool
210
special_flag_p (const char *opname,
211
    const char *flgname)
212
128k
{
213
128k
  const struct arc_flag_special *flg_spec;
214
128k
  unsigned i, j, flgidx;
215
216
1.11M
  for (i = 0; i < arc_num_flag_special; i++)
217
1.01M
    {
218
1.01M
      flg_spec = &arc_flag_special_cases[i];
219
220
1.01M
      if (strcmp (opname, flg_spec->name))
221
925k
  continue;
222
223
      /* Found potential special case instruction.  */
224
1.16M
      for (j=0;; ++j)
225
1.25M
  {
226
1.25M
    flgidx = flg_spec->flags[j];
227
1.25M
    if (flgidx == 0)
228
57.5k
      break; /* End of the array.  */
229
230
1.19M
    if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
231
31.0k
      return true;
232
1.19M
  }
233
88.6k
    }
234
97.8k
  return false;
235
128k
}
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
597k
{
249
597k
  unsigned int i = 0;
250
597k
  const struct arc_opcode *opcode = NULL;
251
597k
  const struct arc_opcode *t_op = NULL;
252
597k
  const unsigned char *opidx;
253
597k
  const unsigned char *flgidx;
254
597k
  bool warn_p = false;
255
256
597k
  do
257
1.74G
    {
258
1.74G
      bool invalid = false;
259
260
1.74G
      opcode = &arc_table[i++];
261
262
1.74G
      if (!(opcode->cpu & isa_mask))
263
841M
  continue;
264
265
908M
      if (arc_opcode_len (opcode) != (int) insn_len)
266
501M
  continue;
267
268
406M
      if ((insn & opcode->mask) != opcode->opcode)
269
406M
  continue;
270
271
561k
      *has_limm = false;
272
273
      /* Possible candidate, check the operands.  */
274
2.29M
      for (opidx = opcode->operands; *opidx; opidx++)
275
1.74M
  {
276
1.74M
    int value, limmind;
277
1.74M
    const struct arc_operand *operand = &arc_operands[*opidx];
278
279
1.74M
    if (operand->flags & ARC_OPERAND_FAKE)
280
382k
      continue;
281
282
1.36M
    if (operand->extract)
283
1.14M
      value = (*operand->extract) (insn, &invalid);
284
212k
    else
285
212k
      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.36M
    limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E;
290
1.36M
    if (operand->flags & ARC_OPERAND_IR
291
1.36M
        && !(operand->flags & ARC_OPERAND_LIMM))
292
758k
      {
293
758k
        if ((value == 0x3E && insn_len == 4)
294
758k
      || (value == limmind && insn_len == 2))
295
12.9k
    {
296
12.9k
      invalid = true;
297
12.9k
      break;
298
12.9k
    }
299
758k
      }
300
301
1.34M
    if (operand->flags & ARC_OPERAND_LIMM
302
1.34M
        && !(operand->flags & ARC_OPERAND_DUPLICATE))
303
8.09k
      *has_limm = true;
304
1.34M
  }
305
306
      /* Check the flags.  */
307
992k
      for (flgidx = opcode->flags; *flgidx; flgidx++)
308
439k
  {
309
    /* Get a valid flag class.  */
310
439k
    const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
311
439k
    const unsigned *flgopridx;
312
439k
    int foundA = 0, foundB = 0;
313
439k
    unsigned int value;
314
315
    /* Check first the extensions.  */
316
439k
    if (cl_flags->flag_class & F_CLASS_EXTEND)
317
73.1k
      {
318
73.1k
        value = (insn & 0x1F);
319
73.1k
        if (arcExtMap_condCodeName (value))
320
0
    continue;
321
73.1k
      }
322
323
    /* Check for the implicit flags.  */
324
439k
    if (cl_flags->flag_class & F_CLASS_IMPLICIT)
325
99.5k
      continue;
326
327
3.04M
    for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
328
2.70M
      {
329
2.70M
        const struct arc_flag_operand *flg_operand =
330
2.70M
    &arc_flag_operands[*flgopridx];
331
332
2.70M
        value = (insn >> flg_operand->shift)
333
2.70M
    & ((1 << flg_operand->bits) - 1);
334
2.70M
        if (value == flg_operand->code)
335
388k
    foundA = 1;
336
2.70M
        if (value)
337
1.31M
    foundB = 1;
338
2.70M
      }
339
340
339k
    if (!foundA && foundB)
341
8.13k
      {
342
8.13k
        invalid = true;
343
8.13k
        break;
344
8.13k
      }
345
339k
  }
346
347
561k
      if (invalid)
348
27.1k
  continue;
349
350
534k
      if (insn_len == 4
351
534k
    && overlaps)
352
192k
  {
353
192k
    warn_p = true;
354
192k
    t_op = opcode;
355
192k
    if (skip_this_opcode (info, opcode))
356
16.3k
      continue;
357
192k
  }
358
359
      /* The instruction is valid.  */
360
518k
      return opcode;
361
534k
    }
362
1.74G
  while (opcode->mask);
363
364
79.0k
  if (warn_p)
365
13.4k
    {
366
13.4k
      info->fprintf_styled_func
367
13.4k
  (info->stream, dis_style_text,
368
13.4k
   _("\nWarning: disassembly may be wrong due to "
369
13.4k
     "guessed opcode class choice.\n"
370
13.4k
     "Use -M<class[,class]> to select the correct "
371
13.4k
     "opcode class(es).\n\t\t\t\t"));
372
13.4k
      return t_op;
373
13.4k
    }
374
375
65.5k
  return NULL;
376
79.0k
}
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
597k
{
411
597k
  const struct arc_opcode *opcode = NULL;
412
597k
  bool needs_limm = false;
413
597k
  const extInstruction_t *einsn, *i;
414
597k
  unsigned limm = 0;
415
597k
  struct arc_disassemble_info *arc_infop = info->private_data;
416
417
  /* First, try the extension instructions.  */
418
597k
  if (*insn_len == 4)
419
243k
    {
420
243k
      einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn);
421
243k
      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
243k
    }
440
441
  /* Then, try finding the first match in the opcode table.  */
442
597k
  if (opcode == NULL)
443
597k
    opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
444
597k
             isa_mask, &needs_limm, true);
445
446
597k
  if (opcode != NULL && needs_limm)
447
5.03k
    {
448
5.03k
      bfd_byte buffer[4];
449
5.03k
      int status;
450
451
5.03k
      status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
452
5.03k
                                          4, info);
453
5.03k
      if (status != 0)
454
142
        {
455
142
          opcode = NULL;
456
142
        }
457
4.89k
      else
458
4.89k
        {
459
4.89k
          limm = ARRANGE_ENDIAN (info, buffer);
460
4.89k
          *insn_len += 4;
461
4.89k
        }
462
5.03k
    }
463
464
597k
  if (opcode != NULL)
465
531k
    {
466
531k
      iter->insn = insn;
467
531k
      iter->limm = limm;
468
531k
      iter->opcode = opcode;
469
531k
      iter->opidx = opcode->operands;
470
531k
    }
471
472
597k
  *opcode_result = opcode;
473
474
  /* Update private data.  */
475
597k
  arc_infop->opcode = opcode;
476
597k
  arc_infop->limm = limm;
477
597k
  arc_infop->limm_p = needs_limm;
478
479
597k
  return true;
480
597k
}
481
482
static void
483
print_flags (const struct arc_opcode *opcode,
484
       unsigned long long *insn,
485
       struct disassemble_info *info)
486
531k
{
487
531k
  const unsigned char *flgidx;
488
531k
  unsigned int value;
489
531k
  struct arc_disassemble_info *arc_infop = info->private_data;
490
491
  /* Now extract and print the flags.  */
492
945k
  for (flgidx = opcode->flags; *flgidx; flgidx++)
493
414k
    {
494
      /* Get a valid flag class.  */
495
414k
      const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
496
414k
      const unsigned *flgopridx;
497
498
      /* Check first the extensions.  */
499
414k
      if (cl_flags->flag_class & F_CLASS_EXTEND)
500
70.1k
  {
501
70.1k
    const char *name;
502
70.1k
    value = (insn[0] & 0x1F);
503
504
70.1k
    name = arcExtMap_condCodeName (value);
505
70.1k
    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
70.1k
  }
512
513
3.08M
      for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
514
2.67M
  {
515
2.67M
    const struct arc_flag_operand *flg_operand =
516
2.67M
      &arc_flag_operands[*flgopridx];
517
518
    /* Implicit flags are only used for the insn decoder.  */
519
2.67M
    if (cl_flags->flag_class & F_CLASS_IMPLICIT)
520
99.4k
      {
521
99.4k
        if (cl_flags->flag_class & F_CLASS_COND)
522
32.0k
    arc_infop->condition_code = flg_operand->code;
523
67.3k
        else if (cl_flags->flag_class & F_CLASS_WB)
524
1.92k
    arc_infop->writeback_mode = flg_operand->code;
525
65.4k
        else if (cl_flags->flag_class & F_CLASS_ZZ)
526
65.4k
    info->data_size = flg_operand->code;
527
99.4k
        continue;
528
99.4k
      }
529
530
2.57M
    if (!flg_operand->favail)
531
988k
      continue;
532
533
1.58M
    value = (insn[0] >> flg_operand->shift)
534
1.58M
      & ((1 << flg_operand->bits) - 1);
535
1.58M
    if (value == flg_operand->code)
536
128k
      {
537
         /* FIXME!: print correctly nt/t flag.  */
538
128k
        if (!special_flag_p (opcode->name, flg_operand->name))
539
97.8k
    (*info->fprintf_styled_func) (info->stream,
540
97.8k
                dis_style_mnemonic, ".");
541
31.0k
        else if (info->insn_type == dis_dref)
542
13.3k
    {
543
13.3k
      switch (flg_operand->name[0])
544
13.3k
        {
545
5.08k
        case 'b':
546
5.08k
          info->data_size = 1;
547
5.08k
          break;
548
8.28k
        case 'h':
549
8.28k
        case 'w':
550
8.28k
          info->data_size = 2;
551
8.28k
          break;
552
0
        default:
553
0
          info->data_size = 4;
554
0
          break;
555
13.3k
        }
556
13.3k
    }
557
128k
        if (flg_operand->name[0] == 'd'
558
128k
      && flg_operand->name[1] == 0)
559
28.1k
    info->branch_delay_insns = 1;
560
561
        /* Check if it is a conditional flag.  */
562
128k
        if (cl_flags->flag_class & F_CLASS_COND)
563
21.2k
    {
564
21.2k
      if (info->insn_type == dis_jsr)
565
2.54k
        info->insn_type = dis_condjsr;
566
18.7k
      else if (info->insn_type == dis_branch)
567
15.2k
        info->insn_type = dis_condbranch;
568
21.2k
      arc_infop->condition_code = flg_operand->code;
569
21.2k
    }
570
571
        /* Check for the write back modes.  */
572
128k
        if (cl_flags->flag_class & F_CLASS_WB)
573
16.4k
    arc_infop->writeback_mode = flg_operand->code;
574
575
128k
        (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
576
128k
              "%s", flg_operand->name);
577
128k
      }
578
1.58M
  }
579
414k
    }
580
531k
}
581
582
static const char *
583
get_auxreg (const struct arc_opcode *opcode,
584
      int value,
585
      unsigned isa_mask)
586
547k
{
587
547k
  const char *name;
588
547k
  unsigned int i;
589
547k
  const struct arc_aux_reg *auxr = &arc_aux_regs[0];
590
591
547k
  if (opcode->insn_class != AUXREG)
592
542k
    return NULL;
593
594
5.75k
  name = arcExtMap_auxRegName (value);
595
5.75k
  if (name)
596
0
    return name;
597
598
896k
  for (i = 0; i < arc_num_aux_regs; i++, auxr++)
599
895k
    {
600
895k
      if (!(auxr->cpu & isa_mask))
601
343k
  continue;
602
603
552k
      if (auxr->subclass != NONE)
604
1.55k
  return NULL;
605
606
550k
      if (auxr->address == value)
607
3.25k
  return auxr->name;
608
550k
    }
609
942
  return NULL;
610
5.75k
}
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
3.32k
{
618
3.32k
  if (value >= ARC_NUM_ADDRTYPES)
619
0
    return "unknown";
620
621
3.32k
  return addrtypenames[value];
622
3.32k
}
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
597k
{
635
597k
  bfd_byte major_opcode = msb >> 3;
636
637
597k
  switch (info->mach)
638
597k
    {
639
300k
    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
300k
      if (major_opcode == 0xb)
646
15.1k
        {
647
15.1k
          bfd_byte minor_opcode = lsb & 0x1f;
648
649
15.1k
    if (minor_opcode < 4)
650
2.58k
      return 6;
651
12.5k
    else if (minor_opcode == 0x10 || minor_opcode == 0x11)
652
3.06k
      return 8;
653
15.1k
        }
654
294k
      if (major_opcode == 0xa)
655
4.58k
        {
656
4.58k
          return 8;
657
4.58k
        }
658
      /* Fall through.  */
659
315k
    case bfd_mach_arc_arc600:
660
315k
      return (major_opcode > 0xb) ? 2 : 4;
661
0
      break;
662
663
271k
    case bfd_mach_arc_arcv2:
664
271k
      return (major_opcode > 0x7) ? 2 : 4;
665
0
      break;
666
667
3
    default:
668
3
      return 0;
669
597k
    }
670
597k
}
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
1.61M
{
680
1.61M
  int value;
681
682
  /* Read the limm operand, if required.  */
683
1.61M
  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.98k
    value = limm;
687
1.61M
  else
688
1.61M
    {
689
1.61M
      if (operand->extract)
690
1.07M
  value = (*operand->extract) (insn, (bool *) NULL);
691
532k
      else
692
532k
        {
693
532k
          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
532k
          else
700
532k
            {
701
532k
              value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
702
532k
            }
703
532k
          if (operand->flags & ARC_OPERAND_SIGNED)
704
1.58k
            {
705
1.58k
              int signbit = 1 << (operand->bits - 1);
706
1.58k
              value = (value ^ signbit) - signbit;
707
1.58k
            }
708
532k
        }
709
1.61M
    }
710
711
1.61M
  return value;
712
1.61M
}
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.15M
{
725
2.15M
  if (*iter->opidx == 0)
726
531k
    {
727
531k
      *operand = NULL;
728
531k
      return false;
729
531k
    }
730
731
1.61M
  *operand = &arc_operands[*iter->opidx];
732
1.61M
  *value = extract_operand_value (*operand, iter->insn, iter->limm);
733
1.61M
  iter->opidx++;
734
735
1.61M
  return true;
736
2.15M
}
737
738
/* Helper for parsing the options.  */
739
740
static void
741
parse_option (struct arc_disassemble_info *arc_infop, const char *option)
742
8.22k
{
743
8.22k
  if (disassembler_options_cmp (option, "dsp") == 0)
744
284
    add_to_decode (arc_infop, DSP, NONE);
745
746
7.94k
  else if (disassembler_options_cmp (option, "spfp") == 0)
747
290
    add_to_decode (arc_infop, FLOAT, SPX);
748
749
7.65k
  else if (disassembler_options_cmp (option, "dpfp") == 0)
750
298
    add_to_decode (arc_infop, FLOAT, DPX);
751
752
7.35k
  else if (disassembler_options_cmp (option, "quarkse_em") == 0)
753
0
    {
754
0
      add_to_decode (arc_infop, FLOAT, DPX);
755
0
      add_to_decode (arc_infop, FLOAT, SPX);
756
0
      add_to_decode (arc_infop, FLOAT, QUARKSE1);
757
0
      add_to_decode (arc_infop, FLOAT, QUARKSE2);
758
0
    }
759
760
7.35k
  else if (disassembler_options_cmp (option, "fpuda") == 0)
761
222
    add_to_decode (arc_infop, FLOAT, DPA);
762
763
7.13k
  else if (disassembler_options_cmp (option, "nps400") == 0)
764
0
    {
765
0
      add_to_decode (arc_infop, ACL, NPS400);
766
0
      add_to_decode (arc_infop, ARITH, NPS400);
767
0
      add_to_decode (arc_infop, BITOP, NPS400);
768
0
      add_to_decode (arc_infop, BMU, NPS400);
769
0
      add_to_decode (arc_infop, CONTROL, NPS400);
770
0
      add_to_decode (arc_infop, DMA, NPS400);
771
0
      add_to_decode (arc_infop, DPI, NPS400);
772
0
      add_to_decode (arc_infop, MEMORY, NPS400);
773
0
      add_to_decode (arc_infop, MISC, NPS400);
774
0
      add_to_decode (arc_infop, NET, NPS400);
775
0
      add_to_decode (arc_infop, PMU, NPS400);
776
0
      add_to_decode (arc_infop, PROTOCOL_DECODE, NPS400);
777
0
      add_to_decode (arc_infop, ULTRAIP, NPS400);
778
0
    }
779
780
7.13k
  else if (disassembler_options_cmp (option, "fpus") == 0)
781
262
    {
782
262
      add_to_decode (arc_infop, FLOAT, SP);
783
262
      add_to_decode (arc_infop, FLOAT, CVT);
784
262
    }
785
786
6.87k
  else if (disassembler_options_cmp (option, "fpud") == 0)
787
200
    {
788
200
      add_to_decode (arc_infop, FLOAT, DP);
789
200
      add_to_decode (arc_infop, FLOAT, CVT);
790
200
    }
791
6.67k
  else if (startswith (option, "hex"))
792
192
    arc_infop->print_hex = true;
793
6.47k
  else
794
    /* xgettext:c-format */
795
6.47k
    opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
796
8.22k
}
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
536
{
827
536
  int i;
828
829
10.8k
  for (i = 0; cpu_types[i].name; ++i)
830
10.5k
    {
831
10.5k
      if (!disassembler_options_cmp (cpu_types[i].name, option))
832
244
  {
833
244
    return cpu_types[i].flags;
834
244
  }
835
10.5k
    }
836
837
  /* xgettext:c-format */
838
292
  opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option);
839
292
  return ARC_OPCODE_NONE;
840
536
}
841
842
/* Go over the options list and parse it.  */
843
844
static void
845
parse_disassembler_options (struct disassemble_info *info)
846
3.15k
{
847
3.15k
  struct arc_disassemble_info *arc_infop = info->private_data;
848
3.15k
  const char *option;
849
850
3.15k
  arc_infop->isa_mask = ARC_OPCODE_NONE;
851
852
3.15k
  FOR_EACH_DISASSEMBLER_OPTION (option, info->disassembler_options)
853
8.76k
    {
854
      /* A CPU option?  Cannot use STRING_COMMA_LEN because strncmp is also a
855
   preprocessor macro.  */
856
8.76k
      if (strncmp (option, "cpu=", 4) == 0)
857
  /* Strip leading `cpu=`.  */
858
536
  arc_infop->isa_mask = parse_cpu_option (option + 4);
859
8.22k
      else
860
8.22k
  parse_option (arc_infop, option);
861
8.76k
    }
862
863
  /* Figure out CPU type, unless it was enforced via disassembler options.  */
864
3.15k
  if (arc_infop->isa_mask == ARC_OPCODE_NONE)
865
2.97k
    {
866
2.97k
      switch (info->mach)
867
2.97k
  {
868
1.63k
  case bfd_mach_arc_arc700:
869
1.63k
    arc_infop->isa_mask = ARC_OPCODE_ARC700;
870
1.63k
    break;
871
872
222
  case bfd_mach_arc_arc600:
873
222
    arc_infop->isa_mask = ARC_OPCODE_ARC600;
874
222
    break;
875
876
998
  case bfd_mach_arc_arcv2:
877
1.11k
  default:
878
1.11k
    {
879
1.11k
      Elf_Internal_Ehdr *header = NULL;
880
881
1.11k
      if (info->section && info->section->owner)
882
9
        header = elf_elfheader (info->section->owner);
883
1.11k
      arc_infop->isa_mask = ARC_OPCODE_ARCv2EM;
884
1.11k
      if (header != NULL
885
1.11k
    && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
886
9
        arc_infop->isa_mask = ARC_OPCODE_ARCv2HS;
887
1.11k
    }
888
1.11k
    break;
889
2.97k
  }
890
2.97k
    }
891
892
3.15k
  if (arc_infop->isa_mask == ARC_OPCODE_ARCv2HS)
893
185
    {
894
      /* FPU instructions are not extensions for HS.  */
895
185
      add_to_decode (arc_infop, FLOAT, SP);
896
185
      add_to_decode (arc_infop, FLOAT, DP);
897
185
      add_to_decode (arc_infop, FLOAT, CVT);
898
185
    }
899
3.15k
}
900
901
/* Return the instruction type for an instruction described by OPCODE.  */
902
903
static enum dis_insn_type
904
arc_opcode_to_insn_type (const struct arc_opcode *opcode)
905
531k
{
906
531k
  enum dis_insn_type insn_type;
907
908
531k
  switch (opcode->insn_class)
909
531k
    {
910
167k
    case BRANCH:
911
169k
    case BBIT0:
912
171k
    case BBIT1:
913
172k
    case BI:
914
173k
    case BIH:
915
193k
    case BRCC:
916
193k
    case DBNZ:
917
200k
    case EI:
918
204k
    case JLI:
919
207k
    case JUMP:
920
208k
    case LOOP:
921
208k
      if (!strncmp (opcode->name, "bl", 2)
922
208k
    || !strncmp (opcode->name, "jl", 2))
923
75.3k
  {
924
75.3k
    if (opcode->subclass == COND)
925
2.26k
      insn_type = dis_condjsr;
926
73.0k
    else
927
73.0k
      insn_type = dis_jsr;
928
75.3k
  }
929
133k
      else
930
133k
  {
931
133k
    if (opcode->subclass == COND)
932
32.2k
      insn_type = dis_condbranch;
933
100k
    else
934
100k
      insn_type = dis_branch;
935
133k
  }
936
208k
      break;
937
108k
    case LOAD:
938
159k
    case STORE:
939
161k
    case MEMORY:
940
161k
    case ENTER:
941
162k
    case PUSH:
942
163k
    case POP:
943
163k
      insn_type = dis_dref;
944
163k
      break;
945
4.12k
    case LEAVE:
946
4.12k
      insn_type = dis_branch;
947
4.12k
      break;
948
155k
    default:
949
155k
      insn_type = dis_nonbranch;
950
155k
      break;
951
531k
    }
952
953
531k
  return insn_type;
954
531k
}
955
956
/* Disassemble ARC instructions.  */
957
958
static int
959
print_insn_arc (bfd_vma memaddr,
960
    struct disassemble_info *info)
961
598k
{
962
598k
  bfd_byte buffer[8];
963
598k
  unsigned int highbyte, lowbyte;
964
598k
  int status;
965
598k
  unsigned int insn_len;
966
598k
  unsigned long long insn = 0;
967
598k
  const struct arc_opcode *opcode;
968
598k
  bool need_comma;
969
598k
  bool open_braket;
970
598k
  int size;
971
598k
  const struct arc_operand *operand;
972
598k
  int value, vpcl;
973
598k
  struct arc_operand_iterator iter;
974
598k
  struct arc_disassemble_info *arc_infop;
975
598k
  bool rpcl = false, rset = false;
976
977
598k
  if (info->private_data == NULL)
978
3.15k
    {
979
3.15k
      if (!init_arc_disasm_info (info))
980
0
  return -1;
981
982
3.15k
      parse_disassembler_options (info);
983
3.15k
    }
984
985
598k
  memset (&iter, 0, sizeof (iter));
986
598k
  highbyte = info->endian == BFD_ENDIAN_LITTLE ? 1 : 0;
987
598k
  lowbyte = info->endian == BFD_ENDIAN_LITTLE ? 0 : 1;
988
989
  /* This variable may be set by the instruction decoder.  It suggests
990
     the number of bytes objdump should display on a single line.  If
991
     the instruction decoder sets this, it should always set it to
992
     the same value in order to get reasonable looking output.  */
993
598k
  info->bytes_per_line  = 8;
994
995
  /* In the next lines, we set two info variables control the way
996
     objdump displays the raw data.  For example, if bytes_per_line is
997
     8 and bytes_per_chunk is 4, the output will look like this:
998
     00:   00000000 00000000
999
     with the chunks displayed according to "display_endian".  */
1000
598k
  if (info->section
1001
598k
      && !(info->section->flags & SEC_CODE))
1002
113
    {
1003
      /* This is not a CODE section.  */
1004
113
      switch (info->section->size)
1005
113
  {
1006
0
  case 1:
1007
0
  case 2:
1008
0
  case 4:
1009
0
    size = info->section->size;
1010
0
    break;
1011
113
  default:
1012
113
    size = (info->section->size & 0x01) ? 1 : 4;
1013
113
    break;
1014
113
  }
1015
113
      info->bytes_per_chunk = 1;
1016
113
      info->display_endian = info->endian;
1017
113
    }
1018
598k
  else
1019
598k
    {
1020
598k
      size = 2;
1021
598k
      info->bytes_per_chunk = 2;
1022
598k
      info->display_endian = info->endian;
1023
598k
    }
1024
1025
  /* Read the insn into a host word.  */
1026
598k
  status = (*info->read_memory_func) (memaddr, buffer, size, info);
1027
1028
598k
  if (status != 0)
1029
605
    {
1030
605
      (*info->memory_error_func) (status, memaddr, info);
1031
605
      return -1;
1032
605
    }
1033
1034
597k
  if (info->section
1035
597k
      && !(info->section->flags & SEC_CODE))
1036
111
    {
1037
      /* Data section.  */
1038
111
      unsigned long data;
1039
1040
111
      data = bfd_get_bits (buffer, size * 8,
1041
111
         info->display_endian == BFD_ENDIAN_BIG);
1042
111
      switch (size)
1043
111
  {
1044
0
  case 1:
1045
0
    (*info->fprintf_styled_func) (info->stream,
1046
0
          dis_style_assembler_directive,
1047
0
          ".byte");
1048
0
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1049
0
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1050
0
          "0x%02lx", data);
1051
0
    break;
1052
0
  case 2:
1053
0
    (*info->fprintf_styled_func) (info->stream,
1054
0
          dis_style_assembler_directive,
1055
0
          ".short");
1056
0
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1057
0
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1058
0
          "0x%04lx", data);
1059
0
    break;
1060
111
  case 4:
1061
111
    (*info->fprintf_styled_func) (info->stream,
1062
111
          dis_style_assembler_directive,
1063
111
          ".word");
1064
111
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1065
111
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1066
111
          "0x%08lx", data);
1067
111
    break;
1068
0
  default:
1069
0
    return -1;
1070
111
  }
1071
111
      return size;
1072
111
    }
1073
1074
597k
  insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
1075
597k
  pr_debug ("instruction length = %d bytes\n", insn_len);
1076
597k
  if (insn_len == 0)
1077
3
    return -1;
1078
1079
597k
  arc_infop = info->private_data;
1080
597k
  arc_infop->insn_len = insn_len;
1081
1082
597k
  switch (insn_len)
1083
597k
    {
1084
343k
    case 2:
1085
343k
      insn = (buffer[highbyte] << 8) | buffer[lowbyte];
1086
343k
      break;
1087
1088
243k
    case 4:
1089
243k
      {
1090
  /* This is a long instruction: Read the remaning 2 bytes.  */
1091
243k
  status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
1092
243k
  if (status != 0)
1093
268
    {
1094
268
      (*info->memory_error_func) (status, memaddr + 2, info);
1095
268
      return -1;
1096
268
    }
1097
243k
  insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
1098
243k
      }
1099
0
      break;
1100
1101
2.58k
    case 6:
1102
2.58k
      {
1103
2.58k
  status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
1104
2.58k
  if (status != 0)
1105
30
    {
1106
30
      (*info->memory_error_func) (status, memaddr + 2, info);
1107
30
      return -1;
1108
30
    }
1109
2.55k
  insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
1110
2.55k
  insn |= ((unsigned long long) buffer[highbyte] << 40)
1111
2.55k
    | ((unsigned long long) buffer[lowbyte] << 32);
1112
2.55k
      }
1113
0
      break;
1114
1115
7.65k
    case 8:
1116
7.65k
      {
1117
7.65k
  status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
1118
7.65k
  if (status != 0)
1119
68
    {
1120
68
      (*info->memory_error_func) (status, memaddr + 2, info);
1121
68
      return -1;
1122
68
    }
1123
7.58k
  insn =
1124
7.58k
    ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
1125
7.58k
     | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
1126
7.58k
      }
1127
0
      break;
1128
1129
0
    default:
1130
      /* There is no instruction whose length is not 2, 4, 6, or 8.  */
1131
0
      return -1;
1132
597k
    }
1133
1134
597k
  pr_debug ("instruction value = %llx\n", insn);
1135
1136
  /* Set some defaults for the insn info.  */
1137
597k
  info->insn_info_valid    = 1;
1138
597k
  info->branch_delay_insns = 0;
1139
597k
  info->data_size    = 4;
1140
597k
  info->insn_type    = dis_nonbranch;
1141
597k
  info->target       = 0;
1142
597k
  info->target2      = 0;
1143
1144
  /* FIXME to be moved in dissasemble_init_for_target.  */
1145
597k
  info->disassembler_needs_relocs = true;
1146
1147
  /* Find the first match in the opcode table.  */
1148
597k
  if (!find_format (memaddr, insn, &insn_len, arc_infop->isa_mask, info,
1149
597k
        &opcode, &iter))
1150
0
    return -1;
1151
1152
597k
  if (!opcode)
1153
65.7k
    {
1154
65.7k
      switch (insn_len)
1155
65.7k
  {
1156
7.06k
  case 2:
1157
7.06k
    (*info->fprintf_styled_func) (info->stream,
1158
7.06k
          dis_style_assembler_directive,
1159
7.06k
          ".short");
1160
7.06k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1161
7.06k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1162
7.06k
          "0x%04llx", insn & 0xffff);
1163
7.06k
    break;
1164
1165
53.7k
  case 4:
1166
53.7k
    (*info->fprintf_styled_func) (info->stream,
1167
53.7k
          dis_style_assembler_directive,
1168
53.7k
          ".word");
1169
53.7k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1170
53.7k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1171
53.7k
          "0x%08llx", insn & 0xffffffff);
1172
53.7k
    break;
1173
1174
486
  case 6:
1175
486
    (*info->fprintf_styled_func) (info->stream,
1176
486
          dis_style_assembler_directive,
1177
486
          ".long");
1178
486
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1179
486
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1180
486
               "0x%08llx", insn & 0xffffffff);
1181
486
    (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
1182
486
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1183
486
          "0x%04llx", (insn >> 32) & 0xffff);
1184
486
    break;
1185
1186
4.38k
  case 8:
1187
4.38k
    (*info->fprintf_styled_func) (info->stream,
1188
4.38k
          dis_style_assembler_directive,
1189
4.38k
          ".long");
1190
4.38k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1191
4.38k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1192
4.38k
          "0x%08llx", insn & 0xffffffff);
1193
4.38k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
1194
4.38k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1195
4.38k
          "0x%08llx", (insn >> 32));
1196
4.38k
    break;
1197
1198
0
  default:
1199
0
    return -1;
1200
65.7k
  }
1201
1202
65.7k
      info->insn_type = dis_noninsn;
1203
65.7k
      return insn_len;
1204
65.7k
    }
1205
1206
  /* Print the mnemonic.  */
1207
531k
  (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
1208
531k
        "%s", opcode->name);
1209
1210
  /* Preselect the insn class.  */
1211
531k
  info->insn_type = arc_opcode_to_insn_type (opcode);
1212
1213
531k
  pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
1214
1215
531k
  print_flags (opcode, &insn, info);
1216
1217
531k
  if (opcode->operands[0] != 0)
1218
530k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1219
1220
531k
  need_comma = false;
1221
531k
  open_braket = false;
1222
531k
  arc_infop->operands_count = 0;
1223
1224
  /* Now extract and print the operands.  */
1225
531k
  operand = NULL;
1226
531k
  vpcl = 0;
1227
2.15M
  while (operand_iterator_next (&iter, &operand, &value))
1228
1.61M
    {
1229
1.61M
      if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1230
178k
  {
1231
178k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "]");
1232
178k
    open_braket = false;
1233
178k
    continue;
1234
178k
  }
1235
1236
      /* Only take input from real operands.  */
1237
1.44M
      if (ARC_OPERAND_IS_FAKE (operand))
1238
0
  continue;
1239
1240
1.44M
      if ((operand->flags & ARC_OPERAND_IGNORE)
1241
1.44M
    && (operand->flags & ARC_OPERAND_IR)
1242
1.44M
    && value == -1)
1243
8.54k
  continue;
1244
1245
1.43M
      if (operand->flags & ARC_OPERAND_COLON)
1246
3.32k
  {
1247
3.32k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, ":");
1248
3.32k
    continue;
1249
3.32k
  }
1250
1251
1.42M
      if (need_comma)
1252
715k
  (*info->fprintf_styled_func) (info->stream, dis_style_text,",");
1253
1254
1.42M
      if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1255
178k
  {
1256
178k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "[");
1257
178k
    open_braket = true;
1258
178k
    need_comma = false;
1259
178k
    continue;
1260
178k
  }
1261
1262
1.25M
      need_comma = true;
1263
1264
1.25M
      if (operand->flags & ARC_OPERAND_PCREL)
1265
207k
  {
1266
207k
    rpcl = true;
1267
207k
    vpcl = value;
1268
207k
    rset = true;
1269
1270
207k
    info->target = (bfd_vma) (memaddr & ~3) + value;
1271
207k
  }
1272
1.04M
      else if (!(operand->flags & ARC_OPERAND_IR))
1273
348k
  {
1274
348k
    vpcl = value;
1275
348k
    rset = true;
1276
348k
  }
1277
1278
      /* Print the operand as directed by the flags.  */
1279
1.25M
      if (operand->flags & ARC_OPERAND_IR)
1280
694k
  {
1281
694k
    const char *rname;
1282
1283
694k
    assert (value >=0 && value < 64);
1284
694k
    rname = arcExtMap_coreRegName (value);
1285
694k
    if (!rname)
1286
694k
      rname = regnames[value];
1287
694k
    (*info->fprintf_styled_func) (info->stream, dis_style_register,
1288
694k
          "%s", rname);
1289
1290
    /* Check if we have a double register to print.  */
1291
694k
    if (operand->flags & ARC_OPERAND_TRUNCATE)
1292
1.03k
      {
1293
1.03k
        if ((value & 0x01) == 0)
1294
478
    {
1295
478
      rname = arcExtMap_coreRegName (value + 1);
1296
478
      if (!rname)
1297
478
        rname = regnames[value + 1];
1298
478
    }
1299
557
        else
1300
557
    rname = _("\nWarning: illegal use of double register "
1301
1.03k
        "pair.\n");
1302
1.03k
        (*info->fprintf_styled_func) (info->stream, dis_style_register,
1303
1.03k
              "%s", rname);
1304
1.03k
      }
1305
694k
    if (value == 63)
1306
19.8k
      rpcl = true;
1307
674k
    else
1308
674k
      rpcl = false;
1309
694k
  }
1310
555k
      else if (operand->flags & ARC_OPERAND_LIMM)
1311
6.98k
  {
1312
6.98k
    const char *rname = get_auxreg (opcode, value, arc_infop->isa_mask);
1313
1314
6.98k
    if (rname && open_braket)
1315
1.04k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1316
1.04k
            "%s", rname);
1317
5.94k
    else
1318
5.94k
      {
1319
5.94k
        (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1320
5.94k
              "%#x", value);
1321
5.94k
        if (info->insn_type == dis_branch
1322
5.94k
      || info->insn_type == dis_jsr)
1323
1.01k
    info->target = (bfd_vma) value;
1324
5.94k
      }
1325
6.98k
  }
1326
548k
      else if (operand->flags & ARC_OPERAND_SIGNED)
1327
242k
  {
1328
242k
    const char *rname = get_auxreg (opcode, value, arc_infop->isa_mask);
1329
242k
    if (rname && open_braket)
1330
482
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1331
482
            "%s", rname);
1332
242k
    else
1333
242k
      {
1334
242k
        if (arc_infop->print_hex)
1335
6.81k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1336
6.81k
                "%#x", value);
1337
235k
        else
1338
235k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1339
235k
                "%d", value);
1340
242k
      }
1341
242k
  }
1342
305k
      else if (operand->flags & ARC_OPERAND_ADDRTYPE)
1343
3.32k
  {
1344
3.32k
    const char *addrtype = get_addrtype (value);
1345
3.32k
    (*info->fprintf_styled_func) (info->stream, dis_style_address,
1346
3.32k
          "%s", addrtype);
1347
    /* A colon follow an address type.  */
1348
3.32k
    need_comma = false;
1349
3.32k
  }
1350
302k
      else
1351
302k
  {
1352
302k
    if (operand->flags & ARC_OPERAND_TRUNCATE
1353
302k
        && !(operand->flags & ARC_OPERAND_ALIGNED32)
1354
302k
        && !(operand->flags & ARC_OPERAND_ALIGNED16)
1355
302k
        && value >= 0 && value <= 14)
1356
4.27k
      {
1357
        /* Leave/Enter mnemonics.  */
1358
4.27k
        switch (value)
1359
4.27k
    {
1360
676
    case 0:
1361
676
      need_comma = false;
1362
676
      break;
1363
2.13k
    case 1:
1364
2.13k
      (*info->fprintf_styled_func) (info->stream,
1365
2.13k
            dis_style_register, "r13");
1366
2.13k
      break;
1367
1.46k
    default:
1368
1.46k
      (*info->fprintf_styled_func) (info->stream,
1369
1.46k
            dis_style_register, "r13");
1370
1.46k
      (*info->fprintf_styled_func) (info->stream,
1371
1.46k
            dis_style_text, "-");
1372
1.46k
      (*info->fprintf_styled_func) (info->stream,
1373
1.46k
            dis_style_register, "%s",
1374
1.46k
            regnames[13 + value - 1]);
1375
1.46k
      break;
1376
4.27k
    }
1377
4.27k
        rpcl = false;
1378
4.27k
        rset = false;
1379
4.27k
      }
1380
298k
    else
1381
298k
      {
1382
298k
        const char *rname = get_auxreg (opcode, value,
1383
298k
                arc_infop->isa_mask);
1384
298k
        if (rname && open_braket)
1385
362
    (*info->fprintf_styled_func) (info->stream, dis_style_register,
1386
362
                "%s", rname);
1387
297k
        else
1388
297k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1389
297k
                "%#x", value);
1390
298k
      }
1391
302k
  }
1392
1393
1.25M
      if (operand->flags & ARC_OPERAND_LIMM)
1394
6.98k
  {
1395
6.98k
    arc_infop->operands[arc_infop->operands_count].kind
1396
6.98k
      = ARC_OPERAND_KIND_LIMM;
1397
    /* It is not important to have exactly the LIMM indicator
1398
       here.  */
1399
6.98k
    arc_infop->operands[arc_infop->operands_count].value = 63;
1400
6.98k
  }
1401
1.24M
      else
1402
1.24M
  {
1403
1.24M
    arc_infop->operands[arc_infop->operands_count].value = value;
1404
1.24M
    arc_infop->operands[arc_infop->operands_count].kind
1405
1.24M
      = (operand->flags & ARC_OPERAND_IR
1406
1.24M
         ? ARC_OPERAND_KIND_REG
1407
1.24M
         : ARC_OPERAND_KIND_SHIMM);
1408
1.24M
  }
1409
1.25M
      arc_infop->operands_count ++;
1410
1.25M
    }
1411
1412
  /* Pretty print extra info for pc-relative operands.  */
1413
531k
  if (rpcl && rset)
1414
207k
    {
1415
207k
      if (info->flags & INSN_HAS_RELOC)
1416
  /* If the instruction has a reloc associated with it, then the
1417
     offset field in the instruction will actually be the addend
1418
     for the reloc.  (We are using REL type relocs).  In such
1419
     cases, we can ignore the pc when computing addresses, since
1420
     the addend is not currently pc-relative.  */
1421
0
  memaddr = 0;
1422
1423
207k
      (*info->fprintf_styled_func) (info->stream,
1424
207k
            dis_style_comment_start, "\t;");
1425
207k
      (*info->print_address_func) ((memaddr & ~3) + vpcl, info);
1426
207k
    }
1427
1428
531k
  return insn_len;
1429
531k
}
1430
1431
1432
disassembler_ftype
1433
arc_get_disassembler (bfd *abfd)
1434
3.15k
{
1435
  /* BFD my be absent, if opcodes is invoked from the debugger that
1436
     has connected to remote target and doesn't have an ELF file.  */
1437
3.15k
  if (abfd != NULL)
1438
60
    {
1439
      /* Read the extension insns and registers, if any.  */
1440
60
      build_ARC_extmap (abfd);
1441
#ifdef DEBUG
1442
      dump_ARC_extmap ();
1443
#endif
1444
60
    }
1445
1446
3.15k
  return print_insn_arc;
1447
3.15k
}
1448
1449
/* Indices into option argument vector for options that do require
1450
   an argument.  Use ARC_OPTION_ARG_NONE for options that don't
1451
   expect an argument.  */
1452
typedef enum
1453
{
1454
  ARC_OPTION_ARG_NONE = -1,
1455
  ARC_OPTION_ARG_ARCH,
1456
  ARC_OPTION_ARG_SIZE
1457
} arc_option_arg_t;
1458
1459
/* Valid ARC disassembler options.  */
1460
static struct
1461
{
1462
  const char *name;
1463
  const char *description;
1464
  arc_option_arg_t arg;
1465
} arc_options[] =
1466
{
1467
  { "cpu=",       N_("Enforce the designated architecture while decoding."),
1468
      ARC_OPTION_ARG_ARCH },
1469
  { "dsp",    N_("Recognize DSP instructions."),
1470
      ARC_OPTION_ARG_NONE },
1471
  { "spfp",   N_("Recognize FPX SP instructions."),
1472
      ARC_OPTION_ARG_NONE },
1473
  { "dpfp",   N_("Recognize FPX DP instructions."),
1474
      ARC_OPTION_ARG_NONE },
1475
  { "quarkse_em", N_("Recognize FPU QuarkSE-EM instructions."),
1476
      ARC_OPTION_ARG_NONE },
1477
  { "fpuda",    N_("Recognize double assist FPU instructions."),
1478
      ARC_OPTION_ARG_NONE },
1479
  { "fpus",   N_("Recognize single precision FPU instructions."),
1480
      ARC_OPTION_ARG_NONE },
1481
  { "fpud",   N_("Recognize double precision FPU instructions."),
1482
      ARC_OPTION_ARG_NONE },
1483
  { "nps400",   N_("Recognize NPS400 instructions."),
1484
      ARC_OPTION_ARG_NONE },
1485
  { "hex",    N_("Use only hexadecimal number to print immediates."),
1486
      ARC_OPTION_ARG_NONE }
1487
};
1488
1489
/* Populate the structure for representing ARC's disassembly options.
1490
   Such a dynamic initialization is desired, because it makes the maintenance
1491
   easier and also gdb uses this to enable the "disassembler-option".  */
1492
1493
const disasm_options_and_args_t *
1494
disassembler_options_arc (void)
1495
0
{
1496
0
  static disasm_options_and_args_t *opts_and_args;
1497
1498
0
  if (opts_and_args == NULL)
1499
0
    {
1500
0
      disasm_option_arg_t *args;
1501
0
      disasm_options_t *opts;
1502
0
      size_t i;
1503
0
      const size_t nr_of_options = ARRAY_SIZE (arc_options);
1504
      /* There is a null element at the end of CPU_TYPES, therefore
1505
   NR_OF_CPUS is actually 1 more and that is desired here too.  */
1506
0
      const size_t nr_of_cpus = ARRAY_SIZE (cpu_types);
1507
1508
0
      opts_and_args = XNEW (disasm_options_and_args_t);
1509
0
      opts_and_args->args
1510
0
  = XNEWVEC (disasm_option_arg_t, ARC_OPTION_ARG_SIZE + 1);
1511
0
      opts_and_args->options.name
1512
0
  = XNEWVEC (const char *, nr_of_options + 1);
1513
0
      opts_and_args->options.description
1514
0
  = XNEWVEC (const char *, nr_of_options + 1);
1515
0
      opts_and_args->options.arg
1516
0
  = XNEWVEC (const disasm_option_arg_t *, nr_of_options + 1);
1517
1518
      /* Populate the arguments for "cpu=" option.  */
1519
0
      args = opts_and_args->args;
1520
0
      args[ARC_OPTION_ARG_ARCH].name = "ARCH";
1521
0
      args[ARC_OPTION_ARG_ARCH].values = XNEWVEC (const char *, nr_of_cpus);
1522
0
      for (i = 0; i < nr_of_cpus; ++i)
1523
0
  args[ARC_OPTION_ARG_ARCH].values[i] = cpu_types[i].name;
1524
0
      args[ARC_OPTION_ARG_SIZE].name = NULL;
1525
0
      args[ARC_OPTION_ARG_SIZE].values = NULL;
1526
1527
      /* Populate the options.  */
1528
0
      opts = &opts_and_args->options;
1529
0
      for (i = 0; i < nr_of_options; ++i)
1530
0
  {
1531
0
    opts->name[i] = arc_options[i].name;
1532
0
    opts->description[i] = arc_options[i].description;
1533
0
    if (arc_options[i].arg != ARC_OPTION_ARG_NONE)
1534
0
      opts->arg[i] = &args[arc_options[i].arg];
1535
0
    else
1536
0
      opts->arg[i] = NULL;
1537
0
  }
1538
0
      opts->name[nr_of_options] = NULL;
1539
0
      opts->description[nr_of_options] = NULL;
1540
0
      opts->arg[nr_of_options] = NULL;
1541
0
    }
1542
1543
0
  return opts_and_args;
1544
0
}
1545
1546
1547
void
1548
print_arc_disassembler_options (FILE *stream)
1549
0
{
1550
0
  const disasm_options_and_args_t *opts_and_args;
1551
0
  const disasm_option_arg_t *args;
1552
0
  const disasm_options_t *opts;
1553
0
  size_t i, j;
1554
0
  size_t max_len = 0;
1555
1556
0
  opts_and_args = disassembler_options_arc ();
1557
0
  opts = &opts_and_args->options;
1558
0
  args = opts_and_args->args;
1559
1560
0
  fprintf (stream, _("\nThe following ARC specific disassembler options are"
1561
0
         " supported for use \nwith the -M switch (multiple"
1562
0
         " options should be separated by commas):\n"));
1563
1564
  /* Find the maximum length for printing options (and their arg name).  */
1565
0
  for (i = 0; opts->name[i] != NULL; ++i)
1566
0
    {
1567
0
      size_t len = strlen (opts->name[i]);
1568
0
      len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0;
1569
0
      max_len = (len > max_len) ? len : max_len;
1570
0
    }
1571
1572
  /* Print the options, their arg and description, if any.  */
1573
0
  for (i = 0, ++max_len; opts->name[i] != NULL; ++i)
1574
0
    {
1575
0
      fprintf (stream, "  %s", opts->name[i]);
1576
0
      if (opts->arg[i] != NULL)
1577
0
  fprintf (stream, "%s", opts->arg[i]->name);
1578
0
      if (opts->description[i] != NULL)
1579
0
  {
1580
0
    size_t len = strlen (opts->name[i]);
1581
0
    len += (opts->arg[i]) ? strlen (opts->arg[i]->name) : 0;
1582
0
    fprintf (stream,
1583
0
       "%*c %s", (int) (max_len - len), ' ', opts->description[i]);
1584
0
  }
1585
0
      fprintf (stream, _("\n"));
1586
0
    }
1587
1588
  /* Print the possible values of an argument.  */
1589
0
  for (i = 0; args[i].name != NULL; ++i)
1590
0
    {
1591
0
      size_t len = 3;
1592
0
      if (args[i].values == NULL)
1593
0
  continue;
1594
0
      fprintf (stream, _("\n\
1595
0
  For the options above, the following values are supported for \"%s\":\n   "),
1596
0
         args[i].name);
1597
0
      for (j = 0; args[i].values[j] != NULL; ++j)
1598
0
  {
1599
0
    fprintf (stream, " %s", args[i].values[j]);
1600
0
    len += strlen (args[i].values[j]) + 1;
1601
    /* reset line if printed too long.  */
1602
0
    if (len >= 78)
1603
0
      {
1604
0
        fprintf (stream, _("\n   "));
1605
0
        len = 3;
1606
0
      }
1607
0
  }
1608
0
      fprintf (stream, _("\n"));
1609
0
    }
1610
1611
0
  fprintf (stream, _("\n"));
1612
0
}
1613
1614
void arc_insn_decode (bfd_vma addr,
1615
          struct disassemble_info *info,
1616
          disassembler_ftype disasm_func,
1617
          struct arc_instruction *insn)
1618
0
{
1619
0
  const struct arc_opcode *opcode;
1620
0
  struct arc_disassemble_info *arc_infop;
1621
1622
  /* Ensure that insn would be in the reset state.  */
1623
0
  memset (insn, 0, sizeof (struct arc_instruction));
1624
1625
  /* There was an error when disassembling, for example memory read error.  */
1626
0
  if (disasm_func (addr, info) < 0)
1627
0
    {
1628
0
      insn->valid = false;
1629
0
      return;
1630
0
    }
1631
1632
0
  assert (info->private_data != NULL);
1633
0
  arc_infop = info->private_data;
1634
1635
0
  insn->length  = arc_infop->insn_len;;
1636
0
  insn->address = addr;
1637
1638
  /* Quick exit if memory at this address is not an instruction.  */
1639
0
  if (info->insn_type == dis_noninsn)
1640
0
    {
1641
0
      insn->valid = false;
1642
0
      return;
1643
0
    }
1644
1645
0
  insn->valid = true;
1646
1647
0
  opcode = (const struct arc_opcode *) arc_infop->opcode;
1648
0
  insn->insn_class = opcode->insn_class;
1649
0
  insn->limm_value = arc_infop->limm;
1650
0
  insn->limm_p     = arc_infop->limm_p;
1651
1652
0
  insn->is_control_flow = (info->insn_type == dis_branch
1653
0
         || info->insn_type == dis_condbranch
1654
0
         || info->insn_type == dis_jsr
1655
0
         || info->insn_type == dis_condjsr);
1656
1657
0
  insn->has_delay_slot = info->branch_delay_insns;
1658
0
  insn->writeback_mode
1659
0
    = (enum arc_ldst_writeback_mode) arc_infop->writeback_mode;
1660
0
  insn->data_size_mode = info->data_size;
1661
0
  insn->condition_code = arc_infop->condition_code;
1662
0
  memcpy (insn->operands, arc_infop->operands,
1663
0
    sizeof (struct arc_insn_operand) * MAX_INSN_ARGS);
1664
0
  insn->operands_count = arc_infop->operands_count;
1665
0
}
1666
1667
/* Local variables:
1668
   eval: (c-set-style "gnu")
1669
   indent-tabs-mode: t
1670
   End:  */