Coverage Report

Created: 2026-07-25 10:20

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
405k
  (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf))  \
129
405k
   : bfd_getb32 (buf))
130
131
979k
#define BITS(word,s,e)  (((word) >> (s)) & ((1ull << ((e) - (s)) << 1) - 1))
132
979k
#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.76k
{
140
3.76k
  struct arc_disassemble_info *arc_infop = calloc (1, sizeof (*arc_infop));
141
142
3.76k
  info->private_data = arc_infop;
143
3.76k
  return arc_infop != NULL;
144
3.76k
}
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.2k
{
153
14.2k
  unsigned int i;
154
121k
  for (i = 0; i < arc_infop->decode_count; i++)
155
115k
    if (arc_infop->decode[i].insn_class == insn_class
156
16.6k
  && arc_infop->decode[i].subclass == subclass)
157
8.53k
      return;
158
159
14.2k
  assert (i < MAX_DECODES);
160
5.76k
  arc_infop->decode[i].insn_class = insn_class;
161
5.76k
  arc_infop->decode[i].subclass = subclass;
162
5.76k
  arc_infop->decode_count = i + 1;
163
5.76k
}
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
309k
{
171
  /* Check opcode for major 0x06, return if it is not in.  */
172
309k
  if (arc_opcode_len (opcode) == 4
173
309k
      && (OPCODE_32BIT_INSN (opcode->opcode) != 0x06
174
    /* Can be an APEX extensions.  */
175
292k
    && OPCODE_32BIT_INSN (opcode->opcode) != 0x07))
176
287k
    return false;
177
178
  /* or not a known truble class.  */
179
22.6k
  switch (opcode->insn_class)
180
22.6k
    {
181
12.0k
    case FLOAT:
182
16.0k
    case DSP:
183
18.4k
    case ARITH:
184
19.0k
    case MPY:
185
19.0k
      break;
186
3.67k
    default:
187
3.67k
      return false;
188
22.6k
    }
189
190
19.0k
  struct arc_disassemble_info *arc_infop = info->private_data;
191
25.2k
  for (unsigned int i = 0; i < arc_infop->decode_count; i++)
192
7.51k
    if (arc_infop->decode[i].insn_class == opcode->insn_class
193
3.03k
  && arc_infop->decode[i].subclass == opcode->subclass)
194
1.28k
      return false;
195
196
17.7k
  return true;
197
19.0k
}
198
199
static bfd_vma
200
bfd_getm32 (unsigned int data)
201
264k
{
202
264k
  bfd_vma value = 0;
203
204
264k
  value = ((data & 0xff00) | (data & 0xff)) << 16;
205
264k
  value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
206
264k
  return value;
207
264k
}
208
209
static bool
210
special_flag_p (const char *opname,
211
    const char *flgname)
212
202k
{
213
202k
  const struct arc_flag_special *flg_spec;
214
202k
  unsigned i, j, flgidx;
215
216
1.64M
  for (i = 0; i < arc_num_flag_special; i++)
217
1.50M
    {
218
1.50M
      flg_spec = &arc_flag_special_cases[i];
219
220
1.50M
      if (strcmp (opname, flg_spec->name))
221
1.36M
  continue;
222
223
      /* Found potential special case instruction.  */
224
2.09M
      for (j=0;; ++j)
225
2.23M
  {
226
2.23M
    flgidx = flg_spec->flags[j];
227
2.23M
    if (flgidx == 0)
228
82.7k
      break; /* End of the array.  */
229
230
2.15M
    if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
231
56.6k
      return true;
232
2.15M
  }
233
139k
    }
234
146k
  return false;
235
202k
}
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
918k
{
249
918k
  unsigned int i = 0;
250
918k
  const struct arc_opcode *opcode = NULL;
251
918k
  const struct arc_opcode *t_op = NULL;
252
918k
  const unsigned char *opidx;
253
918k
  const unsigned char *flgidx;
254
918k
  bool warn_p = false;
255
256
918k
  do
257
2.50G
    {
258
2.50G
      bool invalid = false;
259
260
2.50G
      opcode = &arc_table[i++];
261
262
2.50G
      if (!(opcode->cpu & isa_mask))
263
1.21G
  continue;
264
265
1.28G
      if (arc_opcode_len (opcode) != (int) insn_len)
266
749M
  continue;
267
268
536M
      if ((insn & opcode->mask) != opcode->opcode)
269
535M
  continue;
270
271
862k
      *has_limm = false;
272
273
      /* Possible candidate, check the operands.  */
274
3.37M
      for (opidx = opcode->operands; *opidx; opidx++)
275
2.52M
  {
276
2.52M
    int value, limmind;
277
2.52M
    const struct arc_operand *operand = &arc_operands[*opidx];
278
279
2.52M
    if (operand->flags & ARC_OPERAND_FAKE)
280
560k
      continue;
281
282
1.96M
    if (operand->extract)
283
1.71M
      value = (*operand->extract) (insn, &invalid);
284
257k
    else
285
257k
      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.96M
    limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E;
290
1.96M
    if (operand->flags & ARC_OPERAND_IR
291
1.08M
        && !(operand->flags & ARC_OPERAND_LIMM))
292
1.08M
      {
293
1.08M
        if ((value == 0x3E && insn_len == 4)
294
1.07M
      || (value == limmind && insn_len == 2))
295
15.3k
    {
296
15.3k
      invalid = true;
297
15.3k
      break;
298
15.3k
    }
299
1.08M
      }
300
301
1.95M
    if (operand->flags & ARC_OPERAND_LIMM
302
12.3k
        && !(operand->flags & ARC_OPERAND_DUPLICATE))
303
9.60k
      *has_limm = true;
304
1.95M
  }
305
306
      /* Check the flags.  */
307
1.57M
      for (flgidx = opcode->flags; *flgidx; flgidx++)
308
724k
  {
309
    /* Get a valid flag class.  */
310
724k
    const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
311
724k
    const unsigned *flgopridx;
312
724k
    int foundA = 0, foundB = 0;
313
724k
    unsigned int value;
314
315
    /* Check first the extensions.  */
316
724k
    if (cl_flags->flag_class & F_CLASS_EXTEND)
317
144k
      {
318
144k
        value = (insn & 0x1F);
319
144k
        if (arcExtMap_condCodeName (value))
320
0
    continue;
321
144k
      }
322
323
    /* Check for the implicit flags.  */
324
724k
    if (cl_flags->flag_class & F_CLASS_IMPLICIT)
325
149k
      continue;
326
327
5.74M
    for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
328
5.16M
      {
329
5.16M
        const struct arc_flag_operand *flg_operand =
330
5.16M
    &arc_flag_operands[*flgopridx];
331
332
5.16M
        value = (insn >> flg_operand->shift)
333
5.16M
    & ((1 << flg_operand->bits) - 1);
334
5.16M
        if (value == flg_operand->code)
335
698k
    foundA = 1;
336
5.16M
        if (value)
337
2.40M
    foundB = 1;
338
5.16M
      }
339
340
574k
    if (!foundA && foundB)
341
9.63k
      {
342
9.63k
        invalid = true;
343
9.63k
        break;
344
9.63k
      }
345
574k
  }
346
347
862k
      if (invalid)
348
30.7k
  continue;
349
350
831k
      if (insn_len == 4
351
309k
    && overlaps)
352
309k
  {
353
309k
    warn_p = true;
354
309k
    t_op = opcode;
355
309k
    if (skip_this_opcode (info, opcode))
356
17.7k
      continue;
357
309k
  }
358
359
      /* The instruction is valid.  */
360
813k
      return opcode;
361
831k
    }
362
2.50G
  while (opcode->mask);
363
364
105k
  if (warn_p)
365
14.8k
    {
366
14.8k
      info->fprintf_styled_func
367
14.8k
  (info->stream, dis_style_text,
368
14.8k
   _("\nWarning: disassembly may be wrong due to "
369
14.8k
     "guessed opcode class choice.\n"
370
14.8k
     "Use -M<class[,class]> to select the correct "
371
14.8k
     "opcode class(es).\n\t\t\t\t"));
372
14.8k
      return t_op;
373
14.8k
    }
374
375
90.1k
  return NULL;
376
105k
}
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
918k
{
411
918k
  const struct arc_opcode *opcode = NULL;
412
918k
  bool needs_limm = false;
413
918k
  const extInstruction_t *einsn, *i;
414
918k
  unsigned limm = 0;
415
918k
  struct arc_disassemble_info *arc_infop = info->private_data;
416
417
  /* First, try the extension instructions.  */
418
918k
  if (*insn_len == 4)
419
377k
    {
420
377k
      einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn);
421
377k
      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
377k
    }
440
441
  /* Then, try finding the first match in the opcode table.  */
442
918k
  if (opcode == NULL)
443
918k
    opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
444
918k
             isa_mask, &needs_limm, true);
445
446
918k
  if (opcode != NULL && needs_limm)
447
6.21k
    {
448
6.21k
      bfd_byte buffer[4];
449
6.21k
      int status;
450
451
6.21k
      status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
452
6.21k
                                          4, info);
453
6.21k
      if (status != 0)
454
167
        {
455
167
          opcode = NULL;
456
167
        }
457
6.04k
      else
458
6.04k
        {
459
6.04k
          limm = ARRANGE_ENDIAN (info, buffer);
460
6.04k
          *insn_len += 4;
461
6.04k
        }
462
6.21k
    }
463
464
918k
  if (opcode != NULL)
465
828k
    {
466
828k
      iter->insn = insn;
467
828k
      iter->limm = limm;
468
828k
      iter->opcode = opcode;
469
828k
      iter->opidx = opcode->operands;
470
828k
    }
471
472
918k
  *opcode_result = opcode;
473
474
  /* Update private data.  */
475
918k
  arc_infop->opcode = opcode;
476
918k
  arc_infop->limm = limm;
477
918k
  arc_infop->limm_p = needs_limm;
478
479
918k
  return true;
480
918k
}
481
482
static void
483
print_flags (const struct arc_opcode *opcode,
484
       unsigned long long *insn,
485
       struct disassemble_info *info)
486
828k
{
487
828k
  const unsigned char *flgidx;
488
828k
  unsigned int value;
489
828k
  struct arc_disassemble_info *arc_infop = info->private_data;
490
491
  /* Now extract and print the flags.  */
492
1.52M
  for (flgidx = opcode->flags; *flgidx; flgidx++)
493
694k
    {
494
      /* Get a valid flag class.  */
495
694k
      const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
496
694k
      const unsigned *flgopridx;
497
498
      /* Check first the extensions.  */
499
694k
      if (cl_flags->flag_class & F_CLASS_EXTEND)
500
141k
  {
501
141k
    const char *name;
502
141k
    value = (insn[0] & 0x1F);
503
504
141k
    name = arcExtMap_condCodeName (value);
505
141k
    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
141k
  }
512
513
5.85M
      for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
514
5.16M
  {
515
5.16M
    const struct arc_flag_operand *flg_operand =
516
5.16M
      &arc_flag_operands[*flgopridx];
517
518
    /* Implicit flags are only used for the insn decoder.  */
519
5.16M
    if (cl_flags->flag_class & F_CLASS_IMPLICIT)
520
149k
      {
521
149k
        if (cl_flags->flag_class & F_CLASS_COND)
522
37.0k
    arc_infop->condition_code = flg_operand->code;
523
112k
        else if (cl_flags->flag_class & F_CLASS_WB)
524
3.15k
    arc_infop->writeback_mode = flg_operand->code;
525
109k
        else if (cl_flags->flag_class & F_CLASS_ZZ)
526
109k
    info->data_size = flg_operand->code;
527
149k
        continue;
528
149k
      }
529
530
5.01M
    if (!flg_operand->favail)
531
1.95M
      continue;
532
533
3.05M
    value = (insn[0] >> flg_operand->shift)
534
3.05M
      & ((1 << flg_operand->bits) - 1);
535
3.05M
    if (value == flg_operand->code)
536
202k
      {
537
         /* FIXME!: print correctly nt/t flag.  */
538
202k
        if (!special_flag_p (opcode->name, flg_operand->name))
539
146k
    (*info->fprintf_styled_func) (info->stream,
540
146k
                dis_style_mnemonic, ".");
541
56.6k
        else if (info->insn_type == dis_dref)
542
16.7k
    {
543
16.7k
      switch (flg_operand->name[0])
544
16.7k
        {
545
6.02k
        case 'b':
546
6.02k
          info->data_size = 1;
547
6.02k
          break;
548
10.6k
        case 'h':
549
10.6k
        case 'w':
550
10.6k
          info->data_size = 2;
551
10.6k
          break;
552
0
        default:
553
0
          info->data_size = 4;
554
0
          break;
555
16.7k
        }
556
16.7k
    }
557
202k
        if (flg_operand->name[0] == 'd'
558
59.5k
      && flg_operand->name[1] == 0)
559
48.1k
    info->branch_delay_insns = 1;
560
561
        /* Check if it is a conditional flag.  */
562
202k
        if (cl_flags->flag_class & F_CLASS_COND)
563
44.4k
    {
564
44.4k
      if (info->insn_type == dis_jsr)
565
6.05k
        info->insn_type = dis_condjsr;
566
38.3k
      else if (info->insn_type == dis_branch)
567
34.0k
        info->insn_type = dis_condbranch;
568
44.4k
      arc_infop->condition_code = flg_operand->code;
569
44.4k
    }
570
571
        /* Check for the write back modes.  */
572
202k
        if (cl_flags->flag_class & F_CLASS_WB)
573
19.5k
    arc_infop->writeback_mode = flg_operand->code;
574
575
202k
        (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
576
202k
              "%s", flg_operand->name);
577
202k
      }
578
3.05M
  }
579
694k
    }
580
828k
}
581
582
static const char *
583
get_auxreg (const struct arc_opcode *opcode,
584
      int value,
585
      unsigned isa_mask)
586
817k
{
587
817k
  const char *name;
588
817k
  unsigned int i;
589
817k
  const struct arc_aux_reg *auxr = &arc_aux_regs[0];
590
591
817k
  if (opcode->insn_class != AUXREG)
592
810k
    return NULL;
593
594
6.57k
  name = arcExtMap_auxRegName (value);
595
6.57k
  if (name)
596
0
    return name;
597
598
871k
  for (i = 0; i < arc_num_aux_regs; i++, auxr++)
599
871k
    {
600
871k
      if (!(auxr->cpu & isa_mask))
601
322k
  continue;
602
603
548k
      if (auxr->subclass != NONE)
604
1.71k
  return NULL;
605
606
547k
      if (auxr->address == value)
607
4.13k
  return auxr->name;
608
547k
    }
609
734
  return NULL;
610
6.57k
}
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.81k
{
618
4.81k
  if (value >= ARC_NUM_ADDRTYPES)
619
0
    return "unknown";
620
621
4.81k
  return addrtypenames[value];
622
4.81k
}
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
919k
{
635
919k
  bfd_byte major_opcode = msb >> 3;
636
637
919k
  switch (info->mach)
638
919k
    {
639
444k
    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
444k
      if (major_opcode == 0xb)
646
19.3k
        {
647
19.3k
          bfd_byte minor_opcode = lsb & 0x1f;
648
649
19.3k
    if (minor_opcode < 4)
650
3.95k
      return 6;
651
15.4k
    else if (minor_opcode == 0x10 || minor_opcode == 0x11)
652
2.93k
      return 8;
653
19.3k
        }
654
437k
      if (major_opcode == 0xa)
655
6.30k
        {
656
6.30k
          return 8;
657
6.30k
        }
658
      /* Fall through.  */
659
481k
    case bfd_mach_arc_arc600:
660
481k
      return (major_opcode > 0xb) ? 2 : 4;
661
0
      break;
662
663
424k
    case bfd_mach_arc_arcv2:
664
424k
      return (major_opcode > 0x7) ? 2 : 4;
665
0
      break;
666
667
9
    default:
668
9
      return 0;
669
919k
    }
670
919k
}
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.39M
{
680
2.39M
  int value;
681
682
  /* Read the limm operand, if required.  */
683
2.39M
  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
8.41k
    value = limm;
687
2.38M
  else
688
2.38M
    {
689
2.38M
      if (operand->extract)
690
1.63M
  value = (*operand->extract) (insn, (bool *) NULL);
691
747k
      else
692
747k
        {
693
747k
          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
747k
          else
700
747k
            {
701
747k
              value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
702
747k
            }
703
747k
          if (operand->flags & ARC_OPERAND_SIGNED)
704
2.75k
            {
705
2.75k
              int signbit = 1 << (operand->bits - 1);
706
2.75k
              value = (value ^ signbit) - signbit;
707
2.75k
            }
708
747k
        }
709
2.38M
    }
710
711
2.39M
  return value;
712
2.39M
}
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
3.22M
{
725
3.22M
  if (*iter->opidx == 0)
726
828k
    {
727
828k
      *operand = NULL;
728
828k
      return false;
729
828k
    }
730
731
2.39M
  *operand = &arc_operands[*iter->opidx];
732
2.39M
  *value = extract_operand_value (*operand, iter->insn, iter->limm);
733
2.39M
  iter->opidx++;
734
735
2.39M
  return true;
736
3.22M
}
737
738
/* Helper for parsing the options.  */
739
740
static void
741
parse_option (struct arc_disassemble_info *arc_infop, const char *option)
742
13.8k
{
743
13.8k
  if (strcmp (option, "dsp") == 0)
744
490
    add_to_decode (arc_infop, DSP, NONE);
745
746
13.3k
  else if (strcmp (option, "spfp") == 0)
747
320
    add_to_decode (arc_infop, FLOAT, SPX);
748
749
13.0k
  else if (strcmp (option, "dpfp") == 0)
750
340
    add_to_decode (arc_infop, FLOAT, DPX);
751
752
12.7k
  else if (strcmp (option, "quarkse_em") == 0)
753
258
    {
754
258
      add_to_decode (arc_infop, FLOAT, DPX);
755
258
      add_to_decode (arc_infop, FLOAT, SPX);
756
258
      add_to_decode (arc_infop, FLOAT, QUARKSE1);
757
258
      add_to_decode (arc_infop, FLOAT, QUARKSE2);
758
258
    }
759
760
12.4k
  else if (strcmp (option, "fpuda") == 0)
761
292
    add_to_decode (arc_infop, FLOAT, DPA);
762
763
12.1k
  else if (strcmp (option, "nps400") == 0)
764
708
    {
765
708
      add_to_decode (arc_infop, ACL, NPS400);
766
708
      add_to_decode (arc_infop, ARITH, NPS400);
767
708
      add_to_decode (arc_infop, BITOP, NPS400);
768
708
      add_to_decode (arc_infop, BMU, NPS400);
769
708
      add_to_decode (arc_infop, CONTROL, NPS400);
770
708
      add_to_decode (arc_infop, DMA, NPS400);
771
708
      add_to_decode (arc_infop, DPI, NPS400);
772
708
      add_to_decode (arc_infop, MEMORY, NPS400);
773
708
      add_to_decode (arc_infop, MISC, NPS400);
774
708
      add_to_decode (arc_infop, NET, NPS400);
775
708
      add_to_decode (arc_infop, PMU, NPS400);
776
708
      add_to_decode (arc_infop, PROTOCOL_DECODE, NPS400);
777
708
      add_to_decode (arc_infop, ULTRAIP, NPS400);
778
708
    }
779
780
11.4k
  else if (strcmp (option, "fpus") == 0)
781
502
    {
782
502
      add_to_decode (arc_infop, FLOAT, SP);
783
502
      add_to_decode (arc_infop, FLOAT, CVT);
784
502
    }
785
786
10.9k
  else if (strcmp (option, "fpud") == 0)
787
426
    {
788
426
      add_to_decode (arc_infop, FLOAT, DP);
789
426
      add_to_decode (arc_infop, FLOAT, CVT);
790
426
    }
791
10.5k
  else if (startswith (option, "hex"))
792
206
    arc_infop->print_hex = true;
793
10.3k
  else
794
    /* xgettext:c-format */
795
10.3k
    opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
796
13.8k
}
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.12k
{
827
1.12k
  int i;
828
829
25.3k
  for (i = 0; cpu_types[i].name; ++i)
830
24.5k
    if (strcmp (cpu_types[i].name, option) == 0)
831
294
      return cpu_types[i].flags;
832
833
  /* xgettext:c-format */
834
826
  opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option);
835
826
  return ARC_OPCODE_NONE;
836
1.12k
}
837
838
static bool
839
arc_parse_option (const char *option, void *data)
840
14.9k
{
841
14.9k
  struct arc_disassemble_info *arc_infop = data;
842
843
14.9k
  if (strncmp (option, "cpu=", 4) == 0)
844
    /* Strip leading `cpu=`.  */
845
1.12k
    arc_infop->isa_mask = parse_cpu_option (option + 4);
846
13.8k
  else
847
13.8k
    parse_option (arc_infop, option);
848
14.9k
  return true;
849
14.9k
}
850
851
/* Go over the options list and parse it.  */
852
853
static void
854
parse_disassembler_options (struct disassemble_info *info)
855
3.76k
{
856
3.76k
  struct arc_disassemble_info *arc_infop = info->private_data;
857
858
3.76k
  arc_infop->isa_mask = ARC_OPCODE_NONE;
859
860
3.76k
  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.76k
  if (arc_infop->isa_mask == ARC_OPCODE_NONE)
864
3.54k
    {
865
3.54k
      switch (info->mach)
866
3.54k
  {
867
1.74k
  case bfd_mach_arc_arc700:
868
1.74k
    arc_infop->isa_mask = ARC_OPCODE_ARC700;
869
1.74k
    break;
870
871
245
  case bfd_mach_arc_arc600:
872
245
    arc_infop->isa_mask = ARC_OPCODE_ARC600;
873
245
    break;
874
875
1.24k
  case bfd_mach_arc_arcv2:
876
1.55k
  default:
877
1.55k
    {
878
1.55k
      Elf_Internal_Ehdr *header = NULL;
879
880
1.55k
      if (info->section && info->section->owner)
881
166
        header = elf_elfheader (info->section->owner);
882
1.55k
      arc_infop->isa_mask = ARC_OPCODE_ARCv2EM;
883
1.55k
      if (header != NULL
884
166
    && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
885
43
        arc_infop->isa_mask = ARC_OPCODE_ARCv2HS;
886
1.55k
    }
887
1.55k
    break;
888
3.54k
  }
889
3.54k
    }
890
891
3.76k
  if (arc_infop->isa_mask == ARC_OPCODE_ARCv2HS)
892
253
    {
893
      /* FPU instructions are not extensions for HS.  */
894
253
      add_to_decode (arc_infop, FLOAT, SP);
895
253
      add_to_decode (arc_infop, FLOAT, DP);
896
253
      add_to_decode (arc_infop, FLOAT, CVT);
897
253
    }
898
3.76k
}
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
828k
{
905
828k
  enum dis_insn_type insn_type;
906
907
828k
  switch (opcode->insn_class)
908
828k
    {
909
290k
    case BRANCH:
910
292k
    case BBIT0:
911
296k
    case BBIT1:
912
298k
    case BI:
913
299k
    case BIH:
914
323k
    case BRCC:
915
324k
    case DBNZ:
916
336k
    case EI:
917
343k
    case JLI:
918
348k
    case JUMP:
919
349k
    case LOOP:
920
349k
      if (!strncmp (opcode->name, "bl", 2)
921
242k
    || !strncmp (opcode->name, "jl", 2))
922
115k
  {
923
115k
    if (opcode->subclass == COND)
924
2.68k
      insn_type = dis_condjsr;
925
112k
    else
926
112k
      insn_type = dis_jsr;
927
115k
  }
928
234k
      else
929
234k
  {
930
234k
    if (opcode->subclass == COND)
931
40.4k
      insn_type = dis_condbranch;
932
193k
    else
933
193k
      insn_type = dis_branch;
934
234k
  }
935
349k
      break;
936
166k
    case LOAD:
937
237k
    case STORE:
938
239k
    case MEMORY:
939
239k
    case ENTER:
940
240k
    case PUSH:
941
243k
    case POP:
942
243k
      insn_type = dis_dref;
943
243k
      break;
944
6.97k
    case LEAVE:
945
6.97k
      insn_type = dis_branch;
946
6.97k
      break;
947
228k
    default:
948
228k
      insn_type = dis_nonbranch;
949
228k
      break;
950
828k
    }
951
952
828k
  return insn_type;
953
828k
}
954
955
/* Disassemble ARC instructions.  */
956
957
static int
958
print_insn_arc (bfd_vma memaddr,
959
    struct disassemble_info *info)
960
923k
{
961
923k
  bfd_byte buffer[8];
962
923k
  unsigned int highbyte, lowbyte;
963
923k
  int status;
964
923k
  unsigned int insn_len;
965
923k
  unsigned long long insn = 0;
966
923k
  const struct arc_opcode *opcode;
967
923k
  bool need_comma;
968
923k
  bool open_braket;
969
923k
  int size;
970
923k
  const struct arc_operand *operand;
971
923k
  int value, vpcl;
972
923k
  struct arc_operand_iterator iter;
973
923k
  struct arc_disassemble_info *arc_infop;
974
923k
  bool rpcl = false, rset = false;
975
976
923k
  if (info->private_data == NULL)
977
3.76k
    {
978
3.76k
      if (!init_arc_disasm_info (info))
979
0
  return -1;
980
981
3.76k
      parse_disassembler_options (info);
982
3.76k
    }
983
984
923k
  memset (&iter, 0, sizeof (iter));
985
923k
  highbyte = info->endian == BFD_ENDIAN_LITTLE ? 1 : 0;
986
923k
  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
923k
  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
923k
  if (info->section
1000
299k
      && !(info->section->flags & SEC_CODE))
1001
3.67k
    {
1002
      /* This is not a CODE section.  */
1003
3.67k
      switch (info->section->size)
1004
3.67k
  {
1005
0
  case 1:
1006
1
  case 2:
1007
1
  case 4:
1008
1
    size = info->section->size;
1009
1
    break;
1010
3.67k
  default:
1011
3.67k
    size = (info->section->size & 0x01) ? 1 : 4;
1012
3.67k
    break;
1013
3.67k
  }
1014
3.67k
      info->bytes_per_chunk = 1;
1015
3.67k
      info->display_endian = info->endian;
1016
3.67k
    }
1017
920k
  else
1018
920k
    {
1019
920k
      size = 2;
1020
920k
      info->bytes_per_chunk = 2;
1021
920k
      info->display_endian = info->endian;
1022
920k
    }
1023
1024
  /* Read the insn into a host word.  */
1025
923k
  status = (*info->read_memory_func) (memaddr, buffer, size, info);
1026
1027
923k
  if (status != 0)
1028
982
    {
1029
982
      (*info->memory_error_func) (status, memaddr, info);
1030
982
      return -1;
1031
982
    }
1032
1033
922k
  if (info->section
1034
299k
      && !(info->section->flags & SEC_CODE))
1035
3.67k
    {
1036
      /* Data section.  */
1037
3.67k
      unsigned long data;
1038
1039
3.67k
      data = bfd_get_bits (buffer, size * 8,
1040
3.67k
         info->display_endian == BFD_ENDIAN_BIG);
1041
3.67k
      switch (size)
1042
3.67k
  {
1043
3.10k
  case 1:
1044
3.10k
    (*info->fprintf_styled_func) (info->stream,
1045
3.10k
          dis_style_assembler_directive,
1046
3.10k
          ".byte");
1047
3.10k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1048
3.10k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1049
3.10k
          "0x%02lx", data);
1050
3.10k
    break;
1051
1
  case 2:
1052
1
    (*info->fprintf_styled_func) (info->stream,
1053
1
          dis_style_assembler_directive,
1054
1
          ".short");
1055
1
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1056
1
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1057
1
          "0x%04lx", data);
1058
1
    break;
1059
576
  case 4:
1060
576
    (*info->fprintf_styled_func) (info->stream,
1061
576
          dis_style_assembler_directive,
1062
576
          ".word");
1063
576
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1064
576
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1065
576
          "0x%08lx", data);
1066
576
    break;
1067
0
  default:
1068
0
    return -1;
1069
3.67k
  }
1070
3.67k
      return size;
1071
3.67k
    }
1072
1073
919k
  insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
1074
919k
  pr_debug ("instruction length = %d bytes\n", insn_len);
1075
919k
  if (insn_len == 0)
1076
9
    return -1;
1077
1078
919k
  arc_infop = info->private_data;
1079
919k
  arc_infop->insn_len = insn_len;
1080
1081
919k
  switch (insn_len)
1082
919k
    {
1083
527k
    case 2:
1084
527k
      insn = (buffer[highbyte] << 8) | buffer[lowbyte];
1085
527k
      break;
1086
1087
377k
    case 4:
1088
377k
      {
1089
  /* This is a long instruction: Read the remaning 2 bytes.  */
1090
377k
  status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
1091
377k
  if (status != 0)
1092
403
    {
1093
403
      (*info->memory_error_func) (status, memaddr + 2, info);
1094
403
      return -1;
1095
403
    }
1096
377k
  insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
1097
377k
      }
1098
0
      break;
1099
1100
3.95k
    case 6:
1101
3.95k
      {
1102
3.95k
  status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
1103
3.95k
  if (status != 0)
1104
32
    {
1105
32
      (*info->memory_error_func) (status, memaddr + 2, info);
1106
32
      return -1;
1107
32
    }
1108
3.92k
  insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
1109
3.92k
  insn |= ((unsigned long long) buffer[highbyte] << 40)
1110
3.92k
    | ((unsigned long long) buffer[lowbyte] << 32);
1111
3.92k
      }
1112
0
      break;
1113
1114
9.24k
    case 8:
1115
9.24k
      {
1116
9.24k
  status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
1117
9.24k
  if (status != 0)
1118
61
    {
1119
61
      (*info->memory_error_func) (status, memaddr + 2, info);
1120
61
      return -1;
1121
61
    }
1122
9.18k
  insn =
1123
9.18k
    ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
1124
9.18k
     | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
1125
9.18k
      }
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
919k
    }
1132
1133
918k
  pr_debug ("instruction value = %llx\n", insn);
1134
1135
  /* Set some defaults for the insn info.  */
1136
918k
  info->insn_info_valid    = 1;
1137
918k
  info->branch_delay_insns = 0;
1138
918k
  info->data_size    = 4;
1139
918k
  info->insn_type    = dis_nonbranch;
1140
918k
  info->target       = 0;
1141
918k
  info->target2      = 0;
1142
1143
  /* FIXME to be moved in dissasemble_init_for_target.  */
1144
918k
  info->disassembler_needs_relocs = true;
1145
1146
  /* Find the first match in the opcode table.  */
1147
918k
  if (!find_format (memaddr, insn, &insn_len, arc_infop->isa_mask, info,
1148
918k
        &opcode, &iter))
1149
0
    return -1;
1150
1151
918k
  if (!opcode)
1152
90.3k
    {
1153
90.3k
      switch (insn_len)
1154
90.3k
  {
1155
13.0k
  case 2:
1156
13.0k
    (*info->fprintf_styled_func) (info->stream,
1157
13.0k
          dis_style_assembler_directive,
1158
13.0k
          ".short");
1159
13.0k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1160
13.0k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1161
13.0k
          "0x%04llx", insn & 0xffff);
1162
13.0k
    break;
1163
1164
70.5k
  case 4:
1165
70.5k
    (*info->fprintf_styled_func) (info->stream,
1166
70.5k
          dis_style_assembler_directive,
1167
70.5k
          ".word");
1168
70.5k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1169
70.5k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1170
70.5k
          "0x%08llx", insn & 0xffffffff);
1171
70.5k
    break;
1172
1173
615
  case 6:
1174
615
    (*info->fprintf_styled_func) (info->stream,
1175
615
          dis_style_assembler_directive,
1176
615
          ".long");
1177
615
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1178
615
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1179
615
               "0x%08llx", insn & 0xffffffff);
1180
615
    (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
1181
615
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1182
615
          "0x%04llx", (insn >> 32) & 0xffff);
1183
615
    break;
1184
1185
6.11k
  case 8:
1186
6.11k
    (*info->fprintf_styled_func) (info->stream,
1187
6.11k
          dis_style_assembler_directive,
1188
6.11k
          ".long");
1189
6.11k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1190
6.11k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1191
6.11k
          "0x%08llx", insn & 0xffffffff);
1192
6.11k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, " ");
1193
6.11k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1194
6.11k
          "0x%08llx", (insn >> 32));
1195
6.11k
    break;
1196
1197
0
  default:
1198
0
    return -1;
1199
90.3k
  }
1200
1201
90.3k
      info->insn_type = dis_noninsn;
1202
90.3k
      return insn_len;
1203
90.3k
    }
1204
1205
  /* Print the mnemonic.  */
1206
828k
  (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic,
1207
828k
        "%s", opcode->name);
1208
1209
  /* Preselect the insn class.  */
1210
828k
  info->insn_type = arc_opcode_to_insn_type (opcode);
1211
1212
828k
  pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
1213
1214
828k
  print_flags (opcode, &insn, info);
1215
1216
828k
  if (opcode->operands[0] != 0)
1217
827k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t");
1218
1219
828k
  need_comma = false;
1220
828k
  open_braket = false;
1221
828k
  arc_infop->operands_count = 0;
1222
1223
  /* Now extract and print the operands.  */
1224
828k
  operand = NULL;
1225
828k
  vpcl = 0;
1226
3.22M
  while (operand_iterator_next (&iter, &operand, &value))
1227
2.39M
    {
1228
2.39M
      if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1229
265k
  {
1230
265k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "]");
1231
265k
    open_braket = false;
1232
265k
    continue;
1233
265k
  }
1234
1235
      /* Only take input from real operands.  */
1236
2.12M
      if (ARC_OPERAND_IS_FAKE (operand))
1237
0
  continue;
1238
1239
2.12M
      if ((operand->flags & ARC_OPERAND_IGNORE)
1240
212k
    && (operand->flags & ARC_OPERAND_IR)
1241
22.2k
    && value == -1)
1242
13.6k
  continue;
1243
1244
2.11M
      if (operand->flags & ARC_OPERAND_COLON)
1245
4.81k
  {
1246
4.81k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, ":");
1247
4.81k
    continue;
1248
4.81k
  }
1249
1250
2.10M
      if (need_comma)
1251
1.01M
  (*info->fprintf_styled_func) (info->stream, dis_style_text,",");
1252
1253
2.10M
      if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1254
265k
  {
1255
265k
    (*info->fprintf_styled_func) (info->stream, dis_style_text, "[");
1256
265k
    open_braket = true;
1257
265k
    need_comma = false;
1258
265k
    continue;
1259
265k
  }
1260
1261
1.84M
      need_comma = true;
1262
1263
1.84M
      if (operand->flags & ARC_OPERAND_PCREL)
1264
336k
  {
1265
336k
    rpcl = true;
1266
336k
    vpcl = value;
1267
336k
    rset = true;
1268
1269
336k
    info->target = (bfd_vma) (memaddr & ~3) + value;
1270
336k
  }
1271
1.50M
      else if (!(operand->flags & ARC_OPERAND_IR))
1272
492k
  {
1273
492k
    vpcl = value;
1274
492k
    rset = true;
1275
492k
  }
1276
1277
      /* Print the operand as directed by the flags.  */
1278
1.84M
      if (operand->flags & ARC_OPERAND_IR)
1279
1.01M
  {
1280
1.01M
    const char *rname;
1281
1282
1.01M
    assert (value >=0 && value < 64);
1283
1.01M
    rname = arcExtMap_coreRegName (value);
1284
1.01M
    if (!rname)
1285
1.01M
      rname = regnames[value];
1286
1.01M
    (*info->fprintf_styled_func) (info->stream, dis_style_register,
1287
1.01M
          "%s", rname);
1288
1289
    /* Check if we have a double register to print.  */
1290
1.01M
    if (operand->flags & ARC_OPERAND_TRUNCATE)
1291
2.12k
      {
1292
2.12k
        if ((value & 0x01) == 0)
1293
1.11k
    {
1294
1.11k
      rname = arcExtMap_coreRegName (value + 1);
1295
1.11k
      if (!rname)
1296
1.11k
        rname = regnames[value + 1];
1297
1.11k
    }
1298
1.01k
        else
1299
1.01k
    rname = _("\nWarning: illegal use of double register "
1300
2.12k
        "pair.\n");
1301
2.12k
        (*info->fprintf_styled_func) (info->stream, dis_style_register,
1302
2.12k
              "%s", rname);
1303
2.12k
      }
1304
1.01M
    if (value == 63)
1305
21.5k
      rpcl = true;
1306
993k
    else
1307
993k
      rpcl = false;
1308
1.01M
  }
1309
829k
      else if (operand->flags & ARC_OPERAND_LIMM)
1310
8.41k
  {
1311
8.41k
    const char *rname = get_auxreg (opcode, value, arc_infop->isa_mask);
1312
1313
8.41k
    if (rname && open_braket)
1314
1.07k
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1315
1.07k
            "%s", rname);
1316
7.34k
    else
1317
7.34k
      {
1318
7.34k
        (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1319
7.34k
              "%#x", value);
1320
7.34k
        if (info->insn_type == dis_branch
1321
6.93k
      || info->insn_type == dis_jsr)
1322
948
    info->target = (bfd_vma) value;
1323
7.34k
      }
1324
8.41k
  }
1325
820k
      else if (operand->flags & ARC_OPERAND_SIGNED)
1326
403k
  {
1327
403k
    const char *rname = get_auxreg (opcode, value, arc_infop->isa_mask);
1328
403k
    if (rname && open_braket)
1329
880
      (*info->fprintf_styled_func) (info->stream, dis_style_register,
1330
880
            "%s", rname);
1331
402k
    else
1332
402k
      {
1333
402k
        if (arc_infop->print_hex)
1334
8.21k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1335
8.21k
                "%#x", value);
1336
394k
        else
1337
394k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1338
394k
                "%d", value);
1339
402k
      }
1340
403k
  }
1341
417k
      else if (operand->flags & ARC_OPERAND_ADDRTYPE)
1342
4.81k
  {
1343
4.81k
    const char *addrtype = get_addrtype (value);
1344
4.81k
    (*info->fprintf_styled_func) (info->stream, dis_style_address,
1345
4.81k
          "%s", addrtype);
1346
    /* A colon follow an address type.  */
1347
4.81k
    need_comma = false;
1348
4.81k
  }
1349
412k
      else
1350
412k
  {
1351
412k
    if (operand->flags & ARC_OPERAND_TRUNCATE
1352
140k
        && !(operand->flags & ARC_OPERAND_ALIGNED32)
1353
69.2k
        && !(operand->flags & ARC_OPERAND_ALIGNED16)
1354
7.61k
        && value >= 0 && value <= 14)
1355
7.29k
      {
1356
        /* Leave/Enter mnemonics.  */
1357
7.29k
        switch (value)
1358
7.29k
    {
1359
2.13k
    case 0:
1360
2.13k
      need_comma = false;
1361
2.13k
      break;
1362
1.84k
    case 1:
1363
1.84k
      (*info->fprintf_styled_func) (info->stream,
1364
1.84k
            dis_style_register, "r13");
1365
1.84k
      break;
1366
3.31k
    default:
1367
3.31k
      (*info->fprintf_styled_func) (info->stream,
1368
3.31k
            dis_style_register, "r13");
1369
3.31k
      (*info->fprintf_styled_func) (info->stream,
1370
3.31k
            dis_style_text, "-");
1371
3.31k
      (*info->fprintf_styled_func) (info->stream,
1372
3.31k
            dis_style_register, "%s",
1373
3.31k
            regnames[13 + value - 1]);
1374
3.31k
      break;
1375
7.29k
    }
1376
7.29k
        rpcl = false;
1377
7.29k
        rset = false;
1378
7.29k
      }
1379
405k
    else
1380
405k
      {
1381
405k
        const char *rname = get_auxreg (opcode, value,
1382
405k
                arc_infop->isa_mask);
1383
405k
        if (rname && open_braket)
1384
654
    (*info->fprintf_styled_func) (info->stream, dis_style_register,
1385
654
                "%s", rname);
1386
404k
        else
1387
404k
    (*info->fprintf_styled_func) (info->stream, dis_style_immediate,
1388
404k
                "%#x", value);
1389
405k
      }
1390
412k
  }
1391
1392
1.84M
      if (operand->flags & ARC_OPERAND_LIMM)
1393
8.41k
  {
1394
8.41k
    arc_infop->operands[arc_infop->operands_count].kind
1395
8.41k
      = ARC_OPERAND_KIND_LIMM;
1396
    /* It is not important to have exactly the LIMM indicator
1397
       here.  */
1398
8.41k
    arc_infop->operands[arc_infop->operands_count].value = 63;
1399
8.41k
  }
1400
1.83M
      else
1401
1.83M
  {
1402
1.83M
    arc_infop->operands[arc_infop->operands_count].value = value;
1403
1.83M
    arc_infop->operands[arc_infop->operands_count].kind
1404
1.83M
      = (operand->flags & ARC_OPERAND_IR
1405
1.83M
         ? ARC_OPERAND_KIND_REG
1406
1.83M
         : ARC_OPERAND_KIND_SHIMM);
1407
1.83M
  }
1408
1.84M
      arc_infop->operands_count ++;
1409
1.84M
    }
1410
1411
  /* Pretty print extra info for pc-relative operands.  */
1412
828k
  if (rpcl && rset)
1413
337k
    {
1414
337k
      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
31
  memaddr = 0;
1421
1422
337k
      (*info->fprintf_styled_func) (info->stream,
1423
337k
            dis_style_comment_start, "\t;");
1424
337k
      (*info->print_address_func) ((memaddr & ~3) + vpcl, info);
1425
337k
    }
1426
1427
828k
  return insn_len;
1428
828k
}
1429
1430
1431
disassembler_ftype
1432
arc_get_disassembler (bfd *abfd)
1433
3.76k
{
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.76k
  if (abfd != NULL)
1437
366
    {
1438
      /* Read the extension insns and registers, if any.  */
1439
366
      build_ARC_extmap (abfd);
1440
#ifdef DEBUG
1441
      dump_ARC_extmap ();
1442
#endif
1443
366
    }
1444
1445
3.76k
  return print_insn_arc;
1446
3.76k
}
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:  */