Coverage Report

Created: 2025-06-24 06:45

/src/binutils-gdb/opcodes/arc-ext.c
Line
Count
Source (jump to first uncovered line)
1
/* ARC target-dependent stuff.  Extension structure access functions
2
   Copyright (C) 1995-2025 Free Software Foundation, Inc.
3
4
   This file is part of libopcodes.
5
6
   This library is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3, or (at your option)
9
   any later version.
10
11
   It is distributed in the hope that it will be useful, but WITHOUT
12
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14
   License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19
   MA 02110-1301, USA.  */
20
21
#include "sysdep.h"
22
#include <stdlib.h>
23
#include <stdio.h>
24
25
#include "bfd.h"
26
#include "arc-ext.h"
27
#include "elf/arc.h"
28
#include "libiberty.h"
29
30
/* This module provides support for extensions to the ARC processor
31
   architecture.  */
32
33
34
/* Local constants.  */
35
36
1.45M
#define FIRST_EXTENSION_CORE_REGISTER   32
37
90.0k
#define LAST_EXTENSION_CORE_REGISTER    59
38
321k
#define FIRST_EXTENSION_CONDITION_CODE  0x10
39
34.9k
#define LAST_EXTENSION_CONDITION_CODE   0x1f
40
41
#define NUM_EXT_CORE      \
42
1.74k
  (LAST_EXTENSION_CORE_REGISTER  - FIRST_EXTENSION_CORE_REGISTER  + 1)
43
#define NUM_EXT_COND      \
44
1.02k
  (LAST_EXTENSION_CONDITION_CODE - FIRST_EXTENSION_CONDITION_CODE + 1)
45
246k
#define INST_HASH_BITS    6
46
246k
#define INST_HASH_SIZE    (1 << INST_HASH_BITS)
47
243k
#define INST_HASH_MASK    (INST_HASH_SIZE - 1)
48
49
50
/* Local types.  */
51
52
/* These types define the information stored in the table.  */
53
54
struct ExtAuxRegister
55
{
56
  unsigned      address;
57
  char *      name;
58
  struct ExtAuxRegister * next;
59
};
60
61
struct ExtCoreRegister
62
{
63
  short       number;
64
  enum ExtReadWrite rw;
65
  char *      name;
66
};
67
68
struct arcExtMap
69
{
70
  struct ExtAuxRegister* auxRegisters;
71
  struct ExtInstruction* instructions[INST_HASH_SIZE];
72
  struct ExtCoreRegister coreRegisters[NUM_EXT_CORE];
73
  char *     condCodes[NUM_EXT_COND];
74
};
75
76
77
/* Local data.  */
78
79
/* Extension table.  */
80
static struct arcExtMap arc_extension_map;
81
82
83
/* Local macros.  */
84
85
/* A hash function used to map instructions into the table.  */
86
243k
#define INST_HASH(MAJOR, MINOR)    ((((MAJOR) << 3) ^ (MINOR)) & INST_HASH_MASK)
87
88
89
/* Local functions.  */
90
91
static void
92
create_map (unsigned char *block,
93
      unsigned long length)
94
0
{
95
0
  unsigned char *p = block;
96
97
0
  while (p && p < (block + length))
98
0
    {
99
      /* p[0] == length of record
100
   p[1] == type of record
101
   For instructions:
102
     p[2]  = opcode
103
     p[3]  = minor opcode (if opcode == 3)
104
     p[4]  = flags
105
     p[5]+ = name
106
   For core regs and condition codes:
107
     p[2]  = value
108
     p[3]+ = name
109
   For auxiliary regs:
110
     p[2..5] = value
111
     p[6]+   = name
112
       (value is p[2]<<24|p[3]<<16|p[4]<<8|p[5]).  */
113
114
      /* The sequence of records is temrinated by an "empty"
115
   record.  */
116
0
      if (p[0] == 0)
117
0
  break;
118
119
0
      switch (p[1])
120
0
  {
121
0
  case EXT_INSTRUCTION:
122
0
    {
123
0
      struct ExtInstruction  *insn = XNEW (struct ExtInstruction);
124
0
      int         major = p[2];
125
0
      int         minor = p[3];
126
0
      struct ExtInstruction **bucket =
127
0
       &arc_extension_map.instructions[INST_HASH (major, minor)];
128
129
0
      insn->name  = xstrdup ((char *) (p + 5));
130
0
      insn->major = major;
131
0
      insn->minor = minor;
132
0
      insn->flags = p[4];
133
0
      insn->next  = *bucket;
134
0
      insn->suffix = 0;
135
0
      insn->syntax = 0;
136
0
      insn->modsyn = 0;
137
0
      *bucket = insn;
138
0
      break;
139
0
    }
140
141
0
  case EXT_CORE_REGISTER:
142
0
    {
143
0
      unsigned char number = p[2];
144
0
      char*   name   = (char *) (p + 3);
145
146
0
      arc_extension_map.
147
0
        coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
148
0
        = number;
149
0
      arc_extension_map.
150
0
        coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
151
0
        = REG_READWRITE;
152
0
      arc_extension_map.
153
0
        coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
154
0
        = xstrdup (name);
155
0
      break;
156
0
    }
157
158
0
  case EXT_LONG_CORE_REGISTER:
159
0
    {
160
0
      unsigned char     number = p[2];
161
0
      char*       name   = (char *) (p + 7);
162
0
      enum ExtReadWrite rw     = p[6];
163
164
0
      arc_extension_map.
165
0
        coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
166
0
        = number;
167
0
      arc_extension_map.
168
0
        coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
169
0
        = rw;
170
0
      arc_extension_map.
171
0
        coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
172
0
        = xstrdup (name);
173
0
      break;
174
0
    }
175
176
0
  case EXT_COND_CODE:
177
0
    {
178
0
      char *cc_name = xstrdup ((char *) (p + 3));
179
180
0
      arc_extension_map.
181
0
        condCodes[p[2] - FIRST_EXTENSION_CONDITION_CODE]
182
0
        = cc_name;
183
0
      break;
184
0
    }
185
186
0
  case EXT_AUX_REGISTER:
187
0
    {
188
      /* Trickier -- need to store linked list of these.  */
189
0
      struct ExtAuxRegister *newAuxRegister
190
0
        = XNEW (struct ExtAuxRegister);
191
0
      char *aux_name = xstrdup ((char *) (p + 6));
192
193
0
      newAuxRegister->name = aux_name;
194
0
      newAuxRegister->address = (((unsigned) p[2] << 24) | (p[3] << 16)
195
0
               | (p[4] << 8) | p[5]);
196
0
      newAuxRegister->next = arc_extension_map.auxRegisters;
197
0
      arc_extension_map.auxRegisters = newAuxRegister;
198
0
      break;
199
0
    }
200
201
0
  default:
202
0
    break;
203
0
  }
204
205
0
      p += p[0]; /* Move on to next record.  */
206
0
    }
207
0
}
208
209
210
/* Free memory that has been allocated for the extensions.  */
211
212
static void
213
destroy_map (void)
214
60
{
215
60
  struct ExtAuxRegister *r;
216
60
  unsigned int     i;
217
218
  /* Free auxiliary registers.  */
219
60
  r = arc_extension_map.auxRegisters;
220
60
  while (r)
221
0
    {
222
      /* N.B. after r has been freed, r->next is invalid!  */
223
0
      struct ExtAuxRegister* next = r->next;
224
225
0
      free (r->name);
226
0
      free (r);
227
0
      r = next;
228
0
    }
229
230
  /* Free instructions.  */
231
3.90k
  for (i = 0; i < INST_HASH_SIZE; i++)
232
3.84k
    {
233
3.84k
      struct ExtInstruction *insn = arc_extension_map.instructions[i];
234
235
3.84k
      while (insn)
236
0
  {
237
    /* N.B. after insn has been freed, insn->next is invalid!  */
238
0
    struct ExtInstruction *next = insn->next;
239
240
0
    free (insn->name);
241
0
    free (insn);
242
0
    insn = next;
243
0
  }
244
3.84k
    }
245
246
  /* Free core registers.  */
247
1.74k
  for (i = 0; i < NUM_EXT_CORE; i++)
248
1.68k
    free (arc_extension_map.coreRegisters[i].name);
249
250
  /* Free condition codes.  */
251
1.02k
  for (i = 0; i < NUM_EXT_COND; i++)
252
960
    free (arc_extension_map.condCodes[i]);
253
254
60
  memset (&arc_extension_map, 0, sizeof (arc_extension_map));
255
60
}
256
257
258
static const char *
259
ExtReadWrite_image (enum ExtReadWrite val)
260
0
{
261
0
    switch (val)
262
0
    {
263
0
  case REG_INVALID  : return "INVALID";
264
0
  case REG_READ   : return "RO";
265
0
  case REG_WRITE    : return "WO";
266
0
  case REG_READWRITE: return "R/W";
267
0
  default     : return "???";
268
0
    }
269
0
}
270
271
272
/* Externally visible functions.  */
273
274
/* Get the name of an extension instruction.  */
275
276
const extInstruction_t *
277
arcExtMap_insn (int opcode, unsigned long long insn)
278
243k
{
279
  /* Here the following tasks need to be done.  First of all, the
280
     opcode stored in the Extension Map is the real opcode.  However,
281
     the subopcode stored in the instruction to be disassembled is
282
     mangled.  We pass (in minor opcode), the instruction word.  Here
283
     we will un-mangle it and get the real subopcode which we can look
284
     for in the Extension Map.  This function is used both for the
285
     ARCTangent and the ARCompact, so we would also need some sort of
286
     a way to distinguish between the two architectures.  This is
287
     because the ARCTangent does not do any of this mangling so we
288
     have no issues there.  */
289
290
  /* If P[22:23] is 0 or 2 then un-mangle using iiiiiI.  If it is 1
291
     then use iiiiIi.  Now, if P is 3 then check M[5:5] and if it is 0
292
     then un-mangle using iiiiiI else iiiiii.  */
293
294
243k
  unsigned char minor;
295
243k
  extInstruction_t *temp;
296
297
  /* 16-bit instructions.  */
298
243k
  if (0x08 <= opcode && opcode <= 0x0b)
299
33.6k
    {
300
33.6k
      unsigned char b, c, i;
301
302
33.6k
      b = (insn & 0x0700) >> 8;
303
33.6k
      c = (insn & 0x00e0) >> 5;
304
33.6k
      i = (insn & 0x001f);
305
306
33.6k
      if (i)
307
30.2k
  minor = i;
308
3.45k
      else
309
3.45k
  minor = (c == 0x07) ? b : c;
310
33.6k
    }
311
  /* 32-bit instructions.  */
312
209k
  else
313
209k
    {
314
209k
      unsigned char I, A, B;
315
316
209k
      I = (insn & 0x003f0000) >> 16;
317
209k
      A = (insn & 0x0000003f);
318
209k
      B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9);
319
320
209k
      if (I != 0x2f)
321
203k
  {
322
#ifndef UNMANGLED
323
    switch (P)
324
      {
325
      case 3:
326
        if (M)
327
    {
328
      minor = I;
329
      break;
330
    }
331
      case 0:
332
      case 2:
333
        minor = (I >> 1) | ((I & 0x1) << 5);
334
        break;
335
      case 1:
336
        minor = (I >> 1) | (I & 0x1) | ((I & 0x2) << 4);
337
      }
338
#else
339
203k
    minor = I;
340
203k
#endif
341
203k
  }
342
6.08k
      else
343
6.08k
  {
344
6.08k
    if (A != 0x3f)
345
3.84k
      minor = A;
346
2.23k
    else
347
2.23k
      minor = B;
348
6.08k
  }
349
209k
    }
350
351
243k
  temp = arc_extension_map.instructions[INST_HASH (opcode, minor)];
352
243k
  while (temp)
353
0
    {
354
0
      if ((temp->major == opcode) && (temp->minor == minor))
355
0
  {
356
0
    return temp;
357
0
  }
358
0
      temp = temp->next;
359
0
    }
360
361
243k
  return NULL;
362
243k
}
363
364
/* Get the name of an extension core register.  */
365
366
const char *
367
arcExtMap_coreRegName (int regnum)
368
695k
{
369
695k
  if (regnum < FIRST_EXTENSION_CORE_REGISTER
370
695k
      || regnum > LAST_EXTENSION_CORE_REGISTER)
371
633k
    return NULL;
372
61.8k
  return arc_extension_map.
373
61.8k
    coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name;
374
695k
}
375
376
/* Get the access mode of an extension core register.  */
377
378
enum ExtReadWrite
379
arcExtMap_coreReadWrite (int regnum)
380
0
{
381
0
  if (regnum < FIRST_EXTENSION_CORE_REGISTER
382
0
      || regnum > LAST_EXTENSION_CORE_REGISTER)
383
0
    return REG_INVALID;
384
0
  return arc_extension_map.
385
0
    coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw;
386
0
}
387
388
/* Get the name of an extension condition code.  */
389
390
const char *
391
arcExtMap_condCodeName (int code)
392
143k
{
393
143k
  if (code < FIRST_EXTENSION_CONDITION_CODE
394
143k
      || code > LAST_EXTENSION_CONDITION_CODE)
395
109k
    return NULL;
396
33.9k
  return arc_extension_map.
397
33.9k
    condCodes[code - FIRST_EXTENSION_CONDITION_CODE];
398
143k
}
399
400
/* Get the name of an extension auxiliary register.  */
401
402
const char *
403
arcExtMap_auxRegName (unsigned address)
404
5.75k
{
405
  /* Walk the list of auxiliary register names and find the name.  */
406
5.75k
  struct ExtAuxRegister *r;
407
408
5.75k
  for (r = arc_extension_map.auxRegisters; r; r = r->next)
409
0
    {
410
0
      if (r->address == address)
411
0
  return (const char *)r->name;
412
0
    }
413
5.75k
  return NULL;
414
5.75k
}
415
416
/* Load extensions described in .arcextmap and
417
   .gnu.linkonce.arcextmap.* ELF section.  */
418
419
void
420
build_ARC_extmap (bfd *text_bfd)
421
60
{
422
60
  asection *sect;
423
424
  /* The map is built each time gdb loads an executable file - so free
425
     any existing map, as the map defined by the new file may differ
426
     from the old.  */
427
60
  destroy_map ();
428
429
633
  for (sect = text_bfd->sections; sect != NULL; sect = sect->next)
430
573
    if (!strncmp (sect->name,
431
573
      ".gnu.linkonce.arcextmap.",
432
573
    sizeof (".gnu.linkonce.arcextmap.") - 1)
433
573
  || !strcmp (sect->name,".arcextmap"))
434
0
      {
435
0
  bfd_size_type  count  = bfd_section_size (sect);
436
0
  unsigned char* buffer = xmalloc (count);
437
438
0
  if (buffer)
439
0
    {
440
0
      if (bfd_get_section_contents (text_bfd, sect, buffer, 0, count))
441
0
        create_map (buffer, count);
442
0
      free (buffer);
443
0
    }
444
0
      }
445
60
}
446
447
/* Debug function used to dump the ARC information fount in arcextmap
448
   sections.  */
449
450
void
451
dump_ARC_extmap (void)
452
0
{
453
0
    struct ExtAuxRegister *r;
454
0
    int        i;
455
456
0
    r = arc_extension_map.auxRegisters;
457
458
0
    while (r)
459
0
    {
460
0
  printf ("AUX : %s %u\n", r->name, r->address);
461
0
  r = r->next;
462
0
    }
463
464
0
    for (i = 0; i < INST_HASH_SIZE; i++)
465
0
    {
466
0
  struct ExtInstruction *insn;
467
468
0
  for (insn = arc_extension_map.instructions[i];
469
0
       insn != NULL; insn = insn->next)
470
0
    {
471
0
      printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor);
472
0
      switch (insn->flags & ARC_SYNTAX_MASK)
473
0
        {
474
0
        case ARC_SYNTAX_2OP:
475
0
    printf ("SYNTAX_2OP");
476
0
    break;
477
0
        case ARC_SYNTAX_3OP:
478
0
    printf ("SYNTAX_3OP");
479
0
    break;
480
0
        case ARC_SYNTAX_1OP:
481
0
    printf ("SYNTAX_1OP");
482
0
    break;
483
0
        case ARC_SYNTAX_NOP:
484
0
    printf ("SYNTAX_NOP");
485
0
    break;
486
0
        default:
487
0
    printf ("SYNTAX_UNK");
488
0
    break;
489
0
        }
490
491
0
      if (insn->flags & 0x10)
492
0
        printf ("|MODIFIER");
493
494
0
      printf (" %s\n", insn->name);
495
0
    }
496
0
    }
497
498
0
    for (i = 0; i < NUM_EXT_CORE; i++)
499
0
    {
500
0
  struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i];
501
502
0
  if (reg.name)
503
0
    printf ("CORE: 0x%04x %s %s\n", reg.number,
504
0
      ExtReadWrite_image (reg.rw),
505
0
      reg.name);
506
0
    }
507
508
0
    for (i = 0; i < NUM_EXT_COND; i++)
509
0
  if (arc_extension_map.condCodes[i])
510
0
      printf ("COND: %s\n", arc_extension_map.condCodes[i]);
511
0
}
512
513
/* For a given extension instruction generate the equivalent arc
514
   opcode structure.  */
515
516
struct arc_opcode *
517
arcExtMap_genOpcode (const extInstruction_t *einsn,
518
         unsigned arc_target,
519
         const char **errmsg)
520
0
{
521
0
  struct arc_opcode *q, *arc_ext_opcodes = NULL;
522
0
  const unsigned char *lflags_f;
523
0
  const unsigned char *lflags_ccf;
524
0
  int count;
525
526
  /* Check for the class to see how many instructions we generate.  */
527
0
  switch (einsn->flags & ARC_SYNTAX_MASK)
528
0
    {
529
0
    case ARC_SYNTAX_3OP:
530
0
      count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20;
531
0
      break;
532
0
    case ARC_SYNTAX_2OP:
533
0
      count = (einsn->flags & 0x10) ? 7 : 6;
534
0
      break;
535
0
    case ARC_SYNTAX_1OP:
536
0
      count = 3;
537
0
      break;
538
0
    case ARC_SYNTAX_NOP:
539
0
      count = 1;
540
0
      break;
541
0
    default:
542
0
      count = 0;
543
0
      break;
544
0
    }
545
546
  /* Allocate memory.  */
547
0
  arc_ext_opcodes = (struct arc_opcode *)
548
0
    xmalloc ((count + 1) * sizeof (*arc_ext_opcodes));
549
550
0
  if (arc_ext_opcodes == NULL)
551
0
    {
552
0
      *errmsg = "Virtual memory exhausted";
553
0
      return NULL;
554
0
    }
555
556
  /* Generate the patterns.  */
557
0
  q = arc_ext_opcodes;
558
559
0
  if (einsn->suffix)
560
0
    {
561
0
      lflags_f   = flags_none;
562
0
      lflags_ccf = flags_none;
563
0
    }
564
0
  else
565
0
    {
566
0
      lflags_f   = flags_f;
567
0
      lflags_ccf = flags_ccf;
568
0
    }
569
570
0
  if (einsn->suffix & ARC_SUFFIX_COND)
571
0
    lflags_ccf = flags_cc;
572
0
  if (einsn->suffix & ARC_SUFFIX_FLAG)
573
0
    {
574
0
      lflags_f   = flags_f;
575
0
      lflags_ccf = flags_f;
576
0
    }
577
0
  if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND))
578
0
    lflags_ccf = flags_ccf;
579
580
0
  if (einsn->flags & ARC_SYNTAX_2OP
581
0
      && !(einsn->flags & 0x10))
582
0
    {
583
      /* Regular 2OP instruction.  */
584
0
      if (einsn->suffix & ARC_SUFFIX_COND)
585
0
  *errmsg = "Suffix SUFFIX_COND ignored";
586
587
0
      INSERT_XOP (q, einsn->name,
588
0
      INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC,
589
0
      arc_target, arg_32bit_rbrc, lflags_f);
590
591
0
      INSERT_XOP (q, einsn->name,
592
0
      INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C,
593
0
      arc_target, arg_32bit_zarc, lflags_f);
594
595
0
      INSERT_XOP (q, einsn->name,
596
0
      INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU,
597
0
      arc_target, arg_32bit_rbu6, lflags_f);
598
599
0
      INSERT_XOP (q, einsn->name,
600
0
      INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U,
601
0
      arc_target, arg_32bit_zau6, lflags_f);
602
603
0
      INSERT_XOP (q, einsn->name,
604
0
      INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL,
605
0
      arc_target, arg_32bit_rblimm, lflags_f);
606
607
0
      INSERT_XOP (q, einsn->name,
608
0
      INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L,
609
0
      arc_target, arg_32bit_zalimm, lflags_f);
610
0
    }
611
0
  else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP))
612
0
    {
613
      /* This is actually a 3OP pattern.  The first operand is
614
   immplied and is set to zero.  */
615
0
      INSERT_XOP (q, einsn->name,
616
0
      INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
617
0
      arc_target, arg_32bit_rbrc, lflags_f);
618
619
0
      INSERT_XOP (q, einsn->name,
620
0
      INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
621
0
      arc_target, arg_32bit_rbu6, lflags_f);
622
623
0
      INSERT_XOP (q, einsn->name,
624
0
      INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
625
0
      arc_target, arg_32bit_rblimm, lflags_f);
626
627
0
      INSERT_XOP (q, einsn->name,
628
0
      INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
629
0
      arc_target, arg_32bit_limmrc, lflags_ccf);
630
631
0
      INSERT_XOP (q, einsn->name,
632
0
      INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
633
0
      arc_target, arg_32bit_limmu6, lflags_ccf);
634
635
0
      INSERT_XOP (q, einsn->name,
636
0
      INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
637
0
      arc_target, arg_32bit_limms12, lflags_f);
638
639
0
      INSERT_XOP (q, einsn->name,
640
0
      INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
641
0
      arc_target, arg_32bit_limmlimm, lflags_ccf);
642
0
    }
643
0
  else if (einsn->flags & ARC_SYNTAX_3OP
644
0
     && !(einsn->modsyn & ARC_OP1_MUST_BE_IMM))
645
0
    {
646
      /* Regular 3OP instruction.  */
647
0
      INSERT_XOP (q, einsn->name,
648
0
      INSN3OP_ABC (einsn->major, einsn->minor),  MINSN3OP_ABC,
649
0
      arc_target, arg_32bit_rarbrc, lflags_f);
650
651
0
      INSERT_XOP (q, einsn->name,
652
0
      INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
653
0
      arc_target, arg_32bit_zarbrc, lflags_f);
654
655
0
      INSERT_XOP (q, einsn->name,
656
0
      INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC,
657
0
      arc_target, arg_32bit_rbrbrc, lflags_ccf);
658
659
0
      INSERT_XOP (q, einsn->name,
660
0
      INSN3OP_ABU (einsn->major, einsn->minor),  MINSN3OP_ABU,
661
0
      arc_target, arg_32bit_rarbu6, lflags_f);
662
663
0
      INSERT_XOP (q, einsn->name,
664
0
      INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
665
0
      arc_target, arg_32bit_zarbu6, lflags_f);
666
667
0
      INSERT_XOP (q, einsn->name,
668
0
      INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU,
669
0
      arc_target, arg_32bit_rbrbu6, lflags_ccf);
670
671
0
      INSERT_XOP (q, einsn->name,
672
0
      INSN3OP_BBS (einsn->major, einsn->minor),  MINSN3OP_BBS,
673
0
      arc_target, arg_32bit_rbrbs12, lflags_f);
674
675
0
      INSERT_XOP (q, einsn->name,
676
0
      INSN3OP_ALC (einsn->major, einsn->minor),  MINSN3OP_ALC,
677
0
      arc_target, arg_32bit_ralimmrc, lflags_f);
678
679
0
      INSERT_XOP (q, einsn->name,
680
0
      INSN3OP_ABL (einsn->major, einsn->minor),  MINSN3OP_ABL,
681
0
      arc_target, arg_32bit_rarblimm, lflags_f);
682
683
0
      INSERT_XOP (q, einsn->name,
684
0
      INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
685
0
      arc_target, arg_32bit_zalimmrc, lflags_f);
686
687
0
      INSERT_XOP (q, einsn->name,
688
0
      INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
689
0
      arc_target, arg_32bit_zarblimm, lflags_f);
690
691
0
      INSERT_XOP (q, einsn->name,
692
0
      INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
693
0
      arc_target, arg_32bit_zalimmrc, lflags_ccf);
694
695
0
      INSERT_XOP (q, einsn->name,
696
0
      INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL,
697
0
      arc_target, arg_32bit_rbrblimm, lflags_ccf);
698
699
0
      INSERT_XOP (q, einsn->name,
700
0
      INSN3OP_ALU (einsn->major, einsn->minor),  MINSN3OP_ALU,
701
0
      arc_target, arg_32bit_ralimmu6, lflags_f);
702
703
0
      INSERT_XOP (q, einsn->name,
704
0
      INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
705
0
      arc_target, arg_32bit_zalimmu6, lflags_f);
706
707
0
      INSERT_XOP (q, einsn->name,
708
0
      INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
709
0
      arc_target, arg_32bit_zalimmu6, lflags_ccf);
710
711
0
      INSERT_XOP (q, einsn->name,
712
0
      INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
713
0
      arc_target, arg_32bit_zalimms12, lflags_f);
714
715
0
      INSERT_XOP (q, einsn->name,
716
0
      INSN3OP_ALL (einsn->major, einsn->minor),  MINSN3OP_ALL,
717
0
      arc_target, arg_32bit_ralimmlimm, lflags_f);
718
719
0
      INSERT_XOP (q, einsn->name,
720
0
      INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
721
0
      arc_target, arg_32bit_zalimmlimm, lflags_f);
722
723
0
      INSERT_XOP (q, einsn->name,
724
0
      INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
725
0
      arc_target, arg_32bit_zalimmlimm, lflags_ccf);
726
0
    }
727
0
  else if (einsn->flags & ARC_SYNTAX_3OP)
728
0
    {
729
      /* 3OP instruction which accepts only zero as first
730
   argument.  */
731
0
      INSERT_XOP (q, einsn->name,
732
0
      INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
733
0
      arc_target, arg_32bit_zarbrc, lflags_f);
734
735
0
      INSERT_XOP (q, einsn->name,
736
0
      INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
737
0
      arc_target, arg_32bit_zarbu6, lflags_f);
738
739
0
      INSERT_XOP (q, einsn->name,
740
0
      INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
741
0
      arc_target, arg_32bit_zalimmrc, lflags_f);
742
743
0
      INSERT_XOP (q, einsn->name,
744
0
      INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
745
0
      arc_target, arg_32bit_zarblimm, lflags_f);
746
747
0
      INSERT_XOP (q, einsn->name,
748
0
      INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
749
0
      arc_target, arg_32bit_zalimmrc, lflags_ccf);
750
751
0
      INSERT_XOP (q, einsn->name,
752
0
      INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
753
0
      arc_target, arg_32bit_zalimmu6, lflags_f);
754
755
0
      INSERT_XOP (q, einsn->name,
756
0
      INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
757
0
      arc_target, arg_32bit_zalimmu6, lflags_ccf);
758
759
0
      INSERT_XOP (q, einsn->name,
760
0
      INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
761
0
      arc_target, arg_32bit_zalimms12, lflags_f);
762
763
0
      INSERT_XOP (q, einsn->name,
764
0
      INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
765
0
      arc_target, arg_32bit_zalimmlimm, lflags_f);
766
767
0
      INSERT_XOP (q, einsn->name,
768
0
      INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
769
0
      arc_target, arg_32bit_zalimmlimm, lflags_ccf);
770
0
    }
771
0
  else if (einsn->flags & ARC_SYNTAX_1OP)
772
0
    {
773
0
      if (einsn->suffix & ARC_SUFFIX_COND)
774
0
  *errmsg = "Suffix SUFFIX_COND ignored";
775
776
0
      INSERT_XOP (q, einsn->name,
777
0
      INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor),
778
0
      MINSN2OP_0C, arc_target, arg_32bit_rc, lflags_f);
779
780
0
      INSERT_XOP (q, einsn->name,
781
0
      INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
782
0
      | (0x01 << 22), MINSN2OP_0U, arc_target, arg_32bit_u6,
783
0
      lflags_f);
784
785
0
      INSERT_XOP (q, einsn->name,
786
0
      INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
787
0
      | FIELDC (62), MINSN2OP_0L, arc_target, arg_32bit_limm,
788
0
      lflags_f);
789
790
0
    }
791
0
  else if (einsn->flags & ARC_SYNTAX_NOP)
792
0
    {
793
0
      if (einsn->suffix & ARC_SUFFIX_COND)
794
0
  *errmsg = "Suffix SUFFIX_COND ignored";
795
796
0
      INSERT_XOP (q, einsn->name,
797
0
      INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
798
0
      | (0x01 << 22), MINSN2OP_0L, arc_target, arg_none, lflags_f);
799
0
    }
800
0
  else
801
0
    {
802
0
      *errmsg = "Unknown syntax";
803
0
      return NULL;
804
0
    }
805
806
  /* End marker.  */
807
0
  memset (q, 0, sizeof (*arc_ext_opcodes));
808
809
0
  return arc_ext_opcodes;
810
0
}