Home | History | Annotate | Line # | Download | only in opcodes
      1 /* ARC target-dependent stuff.  Extension structure access functions
      2    Copyright (C) 1995-2026 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 #define FIRST_EXTENSION_CORE_REGISTER   32
     37 #define LAST_EXTENSION_CORE_REGISTER    59
     38 #define FIRST_EXTENSION_CONDITION_CODE  0x10
     39 #define LAST_EXTENSION_CONDITION_CODE   0x1f
     40 
     41 #define NUM_EXT_CORE      \
     42   (LAST_EXTENSION_CORE_REGISTER  - FIRST_EXTENSION_CORE_REGISTER  + 1)
     43 #define NUM_EXT_COND      \
     44   (LAST_EXTENSION_CONDITION_CODE - FIRST_EXTENSION_CONDITION_CODE + 1)
     45 #define INST_HASH_BITS    6
     46 #define INST_HASH_SIZE    (1 << INST_HASH_BITS)
     47 #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 #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 {
     95   unsigned char *p = block;
     96 
     97   while (p && p < (block + length))
     98     {
     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       if (p[0] == 0)
    117 	break;
    118 
    119       switch (p[1])
    120 	{
    121 	case EXT_INSTRUCTION:
    122 	  {
    123 	    struct ExtInstruction  *insn = XNEW (struct ExtInstruction);
    124 	    int			    major = p[2];
    125 	    int			    minor = p[3];
    126 	    struct ExtInstruction **bucket =
    127 		   &arc_extension_map.instructions[INST_HASH (major, minor)];
    128 
    129 	    insn->name  = xstrdup ((char *) (p + 5));
    130 	    insn->major = major;
    131 	    insn->minor = minor;
    132 	    insn->flags = p[4];
    133 	    insn->next  = *bucket;
    134 	    insn->suffix = 0;
    135 	    insn->syntax = 0;
    136 	    insn->modsyn = 0;
    137 	    *bucket = insn;
    138 	    break;
    139 	  }
    140 
    141 	case EXT_CORE_REGISTER:
    142 	  {
    143 	    unsigned char number = p[2];
    144 	    char*	  name	 = (char *) (p + 3);
    145 
    146 	    arc_extension_map.
    147 	      coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
    148 	      = number;
    149 	    arc_extension_map.
    150 	      coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
    151 	      = REG_READWRITE;
    152 	    arc_extension_map.
    153 	      coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
    154 	      = xstrdup (name);
    155 	    break;
    156 	  }
    157 
    158 	case EXT_LONG_CORE_REGISTER:
    159 	  {
    160 	    unsigned char     number = p[2];
    161 	    char*	      name   = (char *) (p + 7);
    162 	    enum ExtReadWrite rw     = p[6];
    163 
    164 	    arc_extension_map.
    165 	      coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].number
    166 	      = number;
    167 	    arc_extension_map.
    168 	      coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].rw
    169 	      = rw;
    170 	    arc_extension_map.
    171 	      coreRegisters[number - FIRST_EXTENSION_CORE_REGISTER].name
    172 	      = xstrdup (name);
    173 	    break;
    174 	  }
    175 
    176 	case EXT_COND_CODE:
    177 	  {
    178 	    char *cc_name = xstrdup ((char *) (p + 3));
    179 
    180 	    arc_extension_map.
    181 	      condCodes[p[2] - FIRST_EXTENSION_CONDITION_CODE]
    182 	      = cc_name;
    183 	    break;
    184 	  }
    185 
    186 	case EXT_AUX_REGISTER:
    187 	  {
    188 	    /* Trickier -- need to store linked list of these.  */
    189 	    struct ExtAuxRegister *newAuxRegister
    190 	      = XNEW (struct ExtAuxRegister);
    191 	    char *aux_name = xstrdup ((char *) (p + 6));
    192 
    193 	    newAuxRegister->name = aux_name;
    194 	    newAuxRegister->address = (((unsigned) p[2] << 24) | (p[3] << 16)
    195 				       | (p[4] << 8) | p[5]);
    196 	    newAuxRegister->next = arc_extension_map.auxRegisters;
    197 	    arc_extension_map.auxRegisters = newAuxRegister;
    198 	    break;
    199 	  }
    200 
    201 	default:
    202 	  break;
    203 	}
    204 
    205       p += p[0]; /* Move on to next record.  */
    206     }
    207 }
    208 
    209 
    210 /* Free memory that has been allocated for the extensions.  */
    211 
    212 static void
    213 destroy_map (void)
    214 {
    215   struct ExtAuxRegister *r;
    216   unsigned int		 i;
    217 
    218   /* Free auxiliary registers.  */
    219   r = arc_extension_map.auxRegisters;
    220   while (r)
    221     {
    222       /* N.B. after r has been freed, r->next is invalid!  */
    223       struct ExtAuxRegister* next = r->next;
    224 
    225       free (r->name);
    226       free (r);
    227       r = next;
    228     }
    229 
    230   /* Free instructions.  */
    231   for (i = 0; i < INST_HASH_SIZE; i++)
    232     {
    233       struct ExtInstruction *insn = arc_extension_map.instructions[i];
    234 
    235       while (insn)
    236 	{
    237 	  /* N.B. after insn has been freed, insn->next is invalid!  */
    238 	  struct ExtInstruction *next = insn->next;
    239 
    240 	  free (insn->name);
    241 	  free (insn);
    242 	  insn = next;
    243 	}
    244     }
    245 
    246   /* Free core registers.  */
    247   for (i = 0; i < NUM_EXT_CORE; i++)
    248     free (arc_extension_map.coreRegisters[i].name);
    249 
    250   /* Free condition codes.  */
    251   for (i = 0; i < NUM_EXT_COND; i++)
    252     free (arc_extension_map.condCodes[i]);
    253 
    254   memset (&arc_extension_map, 0, sizeof (arc_extension_map));
    255 }
    256 
    257 
    258 static const char *
    259 ExtReadWrite_image (enum ExtReadWrite val)
    260 {
    261     switch (val)
    262     {
    263 	case REG_INVALID  : return "INVALID";
    264 	case REG_READ	  : return "RO";
    265 	case REG_WRITE	  : return "WO";
    266 	case REG_READWRITE: return "R/W";
    267 	default		  : return "???";
    268     }
    269 }
    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 {
    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   unsigned char minor;
    295   extInstruction_t *temp;
    296 
    297   /* 16-bit instructions.  */
    298   if (0x08 <= opcode && opcode <= 0x0b)
    299     {
    300       unsigned char b, c, i;
    301 
    302       b = (insn & 0x0700) >> 8;
    303       c = (insn & 0x00e0) >> 5;
    304       i = (insn & 0x001f);
    305 
    306       if (i)
    307 	minor = i;
    308       else
    309 	minor = (c == 0x07) ? b : c;
    310     }
    311   /* 32-bit instructions.  */
    312   else
    313     {
    314       unsigned char I, A, B;
    315 
    316       I = (insn & 0x003f0000) >> 16;
    317       A = (insn & 0x0000003f);
    318       B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9);
    319 
    320       if (I != 0x2f)
    321 	{
    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 	  minor = I;
    340 #endif
    341 	}
    342       else
    343 	{
    344 	  if (A != 0x3f)
    345 	    minor = A;
    346 	  else
    347 	    minor = B;
    348 	}
    349     }
    350 
    351   temp = arc_extension_map.instructions[INST_HASH (opcode, minor)];
    352   while (temp)
    353     {
    354       if ((temp->major == opcode) && (temp->minor == minor))
    355 	{
    356 	  return temp;
    357 	}
    358       temp = temp->next;
    359     }
    360 
    361   return NULL;
    362 }
    363 
    364 /* Get the name of an extension core register.  */
    365 
    366 const char *
    367 arcExtMap_coreRegName (int regnum)
    368 {
    369   if (regnum < FIRST_EXTENSION_CORE_REGISTER
    370       || regnum > LAST_EXTENSION_CORE_REGISTER)
    371     return NULL;
    372   return arc_extension_map.
    373     coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name;
    374 }
    375 
    376 /* Get the access mode of an extension core register.  */
    377 
    378 enum ExtReadWrite
    379 arcExtMap_coreReadWrite (int regnum)
    380 {
    381   if (regnum < FIRST_EXTENSION_CORE_REGISTER
    382       || regnum > LAST_EXTENSION_CORE_REGISTER)
    383     return REG_INVALID;
    384   return arc_extension_map.
    385     coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw;
    386 }
    387 
    388 /* Get the name of an extension condition code.  */
    389 
    390 const char *
    391 arcExtMap_condCodeName (int code)
    392 {
    393   if (code < FIRST_EXTENSION_CONDITION_CODE
    394       || code > LAST_EXTENSION_CONDITION_CODE)
    395     return NULL;
    396   return arc_extension_map.
    397     condCodes[code - FIRST_EXTENSION_CONDITION_CODE];
    398 }
    399 
    400 /* Get the name of an extension auxiliary register.  */
    401 
    402 const char *
    403 arcExtMap_auxRegName (unsigned address)
    404 {
    405   /* Walk the list of auxiliary register names and find the name.  */
    406   struct ExtAuxRegister *r;
    407 
    408   for (r = arc_extension_map.auxRegisters; r; r = r->next)
    409     {
    410       if (r->address == address)
    411 	return (const char *)r->name;
    412     }
    413   return NULL;
    414 }
    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 {
    422   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   destroy_map ();
    428 
    429   for (sect = text_bfd->sections; sect != NULL; sect = sect->next)
    430     if (!strncmp (sect->name,
    431 		  ".gnu.linkonce.arcextmap.",
    432 	  sizeof (".gnu.linkonce.arcextmap.") - 1)
    433 	|| !strcmp (sect->name,".arcextmap"))
    434       {
    435 	bfd_size_type  count  = bfd_section_size (sect);
    436 	unsigned char* buffer = xmalloc (count);
    437 
    438 	if (buffer)
    439 	  {
    440 	    if (bfd_get_section_contents (text_bfd, sect, buffer, 0, count))
    441 	      create_map (buffer, count);
    442 	    free (buffer);
    443 	  }
    444       }
    445 }
    446 
    447 /* Debug function used to dump the ARC information fount in arcextmap
    448    sections.  */
    449 
    450 void
    451 dump_ARC_extmap (void)
    452 {
    453     struct ExtAuxRegister *r;
    454     int			   i;
    455 
    456     r = arc_extension_map.auxRegisters;
    457 
    458     while (r)
    459     {
    460 	printf ("AUX : %s %u\n", r->name, r->address);
    461 	r = r->next;
    462     }
    463 
    464     for (i = 0; i < INST_HASH_SIZE; i++)
    465     {
    466 	struct ExtInstruction *insn;
    467 
    468 	for (insn = arc_extension_map.instructions[i];
    469 	     insn != NULL; insn = insn->next)
    470 	  {
    471 	    printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor);
    472 	    switch (insn->flags & ARC_SYNTAX_MASK)
    473 	      {
    474 	      case ARC_SYNTAX_2OP:
    475 		printf ("SYNTAX_2OP");
    476 		break;
    477 	      case ARC_SYNTAX_3OP:
    478 		printf ("SYNTAX_3OP");
    479 		break;
    480 	      case ARC_SYNTAX_1OP:
    481 		printf ("SYNTAX_1OP");
    482 		break;
    483 	      case ARC_SYNTAX_NOP:
    484 		printf ("SYNTAX_NOP");
    485 		break;
    486 	      default:
    487 		printf ("SYNTAX_UNK");
    488 		break;
    489 	      }
    490 
    491 	    if (insn->flags & 0x10)
    492 	      printf ("|MODIFIER");
    493 
    494 	    printf (" %s\n", insn->name);
    495 	  }
    496     }
    497 
    498     for (i = 0; i < NUM_EXT_CORE; i++)
    499     {
    500 	struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i];
    501 
    502 	if (reg.name)
    503 	  printf ("CORE: 0x%04x %s %s\n", reg.number,
    504 		  ExtReadWrite_image (reg.rw),
    505 		  reg.name);
    506     }
    507 
    508     for (i = 0; i < NUM_EXT_COND; i++)
    509 	if (arc_extension_map.condCodes[i])
    510 	    printf ("COND: %s\n", arc_extension_map.condCodes[i]);
    511 }
    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 {
    521   struct arc_opcode *q, *arc_ext_opcodes = NULL;
    522   const unsigned char *lflags_f;
    523   const unsigned char *lflags_ccf;
    524   int count;
    525 
    526   /* Check for the class to see how many instructions we generate.  */
    527   switch (einsn->flags & ARC_SYNTAX_MASK)
    528     {
    529     case ARC_SYNTAX_3OP:
    530       count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20;
    531       break;
    532     case ARC_SYNTAX_2OP:
    533       count = (einsn->flags & 0x10) ? 7 : 6;
    534       break;
    535     case ARC_SYNTAX_1OP:
    536       count = 3;
    537       break;
    538     case ARC_SYNTAX_NOP:
    539       count = 1;
    540       break;
    541     default:
    542       count = 0;
    543       break;
    544     }
    545 
    546   /* Allocate memory.  */
    547   arc_ext_opcodes = (struct arc_opcode *)
    548     xmalloc ((count + 1) * sizeof (*arc_ext_opcodes));
    549 
    550   if (arc_ext_opcodes == NULL)
    551     {
    552       *errmsg = "Virtual memory exhausted";
    553       return NULL;
    554     }
    555 
    556   /* Generate the patterns.  */
    557   q = arc_ext_opcodes;
    558 
    559   if (einsn->suffix)
    560     {
    561       lflags_f   = flags_none;
    562       lflags_ccf = flags_none;
    563     }
    564   else
    565     {
    566       lflags_f   = flags_f;
    567       lflags_ccf = flags_ccf;
    568     }
    569 
    570   if (einsn->suffix & ARC_SUFFIX_COND)
    571     lflags_ccf = flags_cc;
    572   if (einsn->suffix & ARC_SUFFIX_FLAG)
    573     {
    574       lflags_f   = flags_f;
    575       lflags_ccf = flags_f;
    576     }
    577   if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND))
    578     lflags_ccf = flags_ccf;
    579 
    580   if (einsn->flags & ARC_SYNTAX_2OP
    581       && !(einsn->flags & 0x10))
    582     {
    583       /* Regular 2OP instruction.  */
    584       if (einsn->suffix & ARC_SUFFIX_COND)
    585 	*errmsg = "Suffix SUFFIX_COND ignored";
    586 
    587       INSERT_XOP (q, einsn->name,
    588 		  INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC,
    589 		  arc_target, arg_32bit_rbrc, lflags_f);
    590 
    591       INSERT_XOP (q, einsn->name,
    592 		  INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C,
    593 		  arc_target, arg_32bit_zarc, lflags_f);
    594 
    595       INSERT_XOP (q, einsn->name,
    596 		  INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU,
    597 		  arc_target, arg_32bit_rbu6, lflags_f);
    598 
    599       INSERT_XOP (q, einsn->name,
    600 		  INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U,
    601 		  arc_target, arg_32bit_zau6, lflags_f);
    602 
    603       INSERT_XOP (q, einsn->name,
    604 		  INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL,
    605 		  arc_target, arg_32bit_rblimm, lflags_f);
    606 
    607       INSERT_XOP (q, einsn->name,
    608 		  INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L,
    609 		  arc_target, arg_32bit_zalimm, lflags_f);
    610     }
    611   else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP))
    612     {
    613       /* This is actually a 3OP pattern.  The first operand is
    614 	 immplied and is set to zero.  */
    615       INSERT_XOP (q, einsn->name,
    616 		  INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
    617 		  arc_target, arg_32bit_rbrc, lflags_f);
    618 
    619       INSERT_XOP (q, einsn->name,
    620 		  INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
    621 		  arc_target, arg_32bit_rbu6, lflags_f);
    622 
    623       INSERT_XOP (q, einsn->name,
    624 		  INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
    625 		  arc_target, arg_32bit_rblimm, lflags_f);
    626 
    627       INSERT_XOP (q, einsn->name,
    628 		  INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
    629 		  arc_target, arg_32bit_limmrc, lflags_ccf);
    630 
    631       INSERT_XOP (q, einsn->name,
    632 		  INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
    633 		  arc_target, arg_32bit_limmu6, lflags_ccf);
    634 
    635       INSERT_XOP (q, einsn->name,
    636 		  INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
    637 		  arc_target, arg_32bit_limms12, lflags_f);
    638 
    639       INSERT_XOP (q, einsn->name,
    640 		  INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
    641 		  arc_target, arg_32bit_limmlimm, lflags_ccf);
    642     }
    643   else if (einsn->flags & ARC_SYNTAX_3OP
    644 	   && !(einsn->modsyn & ARC_OP1_MUST_BE_IMM))
    645     {
    646       /* Regular 3OP instruction.  */
    647       INSERT_XOP (q, einsn->name,
    648 		  INSN3OP_ABC (einsn->major, einsn->minor),  MINSN3OP_ABC,
    649 		  arc_target, arg_32bit_rarbrc, lflags_f);
    650 
    651       INSERT_XOP (q, einsn->name,
    652 		  INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
    653 		  arc_target, arg_32bit_zarbrc, lflags_f);
    654 
    655       INSERT_XOP (q, einsn->name,
    656 		  INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC,
    657 		  arc_target, arg_32bit_rbrbrc, lflags_ccf);
    658 
    659       INSERT_XOP (q, einsn->name,
    660 		  INSN3OP_ABU (einsn->major, einsn->minor),  MINSN3OP_ABU,
    661 		  arc_target, arg_32bit_rarbu6, lflags_f);
    662 
    663       INSERT_XOP (q, einsn->name,
    664 		  INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
    665 		  arc_target, arg_32bit_zarbu6, lflags_f);
    666 
    667       INSERT_XOP (q, einsn->name,
    668 		  INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU,
    669 		  arc_target, arg_32bit_rbrbu6, lflags_ccf);
    670 
    671       INSERT_XOP (q, einsn->name,
    672 		  INSN3OP_BBS (einsn->major, einsn->minor),  MINSN3OP_BBS,
    673 		  arc_target, arg_32bit_rbrbs12, lflags_f);
    674 
    675       INSERT_XOP (q, einsn->name,
    676 		  INSN3OP_ALC (einsn->major, einsn->minor),  MINSN3OP_ALC,
    677 		  arc_target, arg_32bit_ralimmrc, lflags_f);
    678 
    679       INSERT_XOP (q, einsn->name,
    680 		  INSN3OP_ABL (einsn->major, einsn->minor),  MINSN3OP_ABL,
    681 		  arc_target, arg_32bit_rarblimm, lflags_f);
    682 
    683       INSERT_XOP (q, einsn->name,
    684 		  INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
    685 		  arc_target, arg_32bit_zalimmrc, lflags_f);
    686 
    687       INSERT_XOP (q, einsn->name,
    688 		  INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
    689 		  arc_target, arg_32bit_zarblimm, lflags_f);
    690 
    691       INSERT_XOP (q, einsn->name,
    692 		  INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
    693 		  arc_target, arg_32bit_zalimmrc, lflags_ccf);
    694 
    695       INSERT_XOP (q, einsn->name,
    696 		  INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL,
    697 		  arc_target, arg_32bit_rbrblimm, lflags_ccf);
    698 
    699       INSERT_XOP (q, einsn->name,
    700 		  INSN3OP_ALU (einsn->major, einsn->minor),  MINSN3OP_ALU,
    701 		  arc_target, arg_32bit_ralimmu6, lflags_f);
    702 
    703       INSERT_XOP (q, einsn->name,
    704 		  INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
    705 		  arc_target, arg_32bit_zalimmu6, lflags_f);
    706 
    707       INSERT_XOP (q, einsn->name,
    708 		  INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
    709 		  arc_target, arg_32bit_zalimmu6, lflags_ccf);
    710 
    711       INSERT_XOP (q, einsn->name,
    712 		  INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
    713 		  arc_target, arg_32bit_zalimms12, lflags_f);
    714 
    715       INSERT_XOP (q, einsn->name,
    716 		  INSN3OP_ALL (einsn->major, einsn->minor),  MINSN3OP_ALL,
    717 		  arc_target, arg_32bit_ralimmlimm, lflags_f);
    718 
    719       INSERT_XOP (q, einsn->name,
    720 		  INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
    721 		  arc_target, arg_32bit_zalimmlimm, lflags_f);
    722 
    723       INSERT_XOP (q, einsn->name,
    724 		  INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
    725 		  arc_target, arg_32bit_zalimmlimm, lflags_ccf);
    726     }
    727   else if (einsn->flags & ARC_SYNTAX_3OP)
    728     {
    729       /* 3OP instruction which accepts only zero as first
    730 	 argument.  */
    731       INSERT_XOP (q, einsn->name,
    732 		  INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
    733 		  arc_target, arg_32bit_zarbrc, lflags_f);
    734 
    735       INSERT_XOP (q, einsn->name,
    736 		  INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
    737 		  arc_target, arg_32bit_zarbu6, lflags_f);
    738 
    739       INSERT_XOP (q, einsn->name,
    740 		  INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
    741 		  arc_target, arg_32bit_zalimmrc, lflags_f);
    742 
    743       INSERT_XOP (q, einsn->name,
    744 		  INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
    745 		  arc_target, arg_32bit_zarblimm, lflags_f);
    746 
    747       INSERT_XOP (q, einsn->name,
    748 		  INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
    749 		  arc_target, arg_32bit_zalimmrc, lflags_ccf);
    750 
    751       INSERT_XOP (q, einsn->name,
    752 		  INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
    753 		  arc_target, arg_32bit_zalimmu6, lflags_f);
    754 
    755       INSERT_XOP (q, einsn->name,
    756 		  INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
    757 		  arc_target, arg_32bit_zalimmu6, lflags_ccf);
    758 
    759       INSERT_XOP (q, einsn->name,
    760 		  INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
    761 		  arc_target, arg_32bit_zalimms12, lflags_f);
    762 
    763       INSERT_XOP (q, einsn->name,
    764 		  INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
    765 		  arc_target, arg_32bit_zalimmlimm, lflags_f);
    766 
    767       INSERT_XOP (q, einsn->name,
    768 		  INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
    769 		  arc_target, arg_32bit_zalimmlimm, lflags_ccf);
    770     }
    771   else if (einsn->flags & ARC_SYNTAX_1OP)
    772     {
    773       if (einsn->suffix & ARC_SUFFIX_COND)
    774 	*errmsg = "Suffix SUFFIX_COND ignored";
    775 
    776       INSERT_XOP (q, einsn->name,
    777 		  INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor),
    778 		  MINSN2OP_0C, arc_target, arg_32bit_rc, lflags_f);
    779 
    780       INSERT_XOP (q, einsn->name,
    781 		  INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
    782 		  | (0x01 << 22), MINSN2OP_0U, arc_target, arg_32bit_u6,
    783 		  lflags_f);
    784 
    785       INSERT_XOP (q, einsn->name,
    786 		  INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
    787 		  | FIELDC (62), MINSN2OP_0L, arc_target, arg_32bit_limm,
    788 		  lflags_f);
    789 
    790     }
    791   else if (einsn->flags & ARC_SYNTAX_NOP)
    792     {
    793       if (einsn->suffix & ARC_SUFFIX_COND)
    794 	*errmsg = "Suffix SUFFIX_COND ignored";
    795 
    796       INSERT_XOP (q, einsn->name,
    797 		  INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
    798 		  | (0x01 << 22), MINSN2OP_0L, arc_target, arg_none, lflags_f);
    799     }
    800   else
    801     {
    802       *errmsg = "Unknown syntax";
    803       return NULL;
    804     }
    805 
    806   /* End marker.  */
    807   memset (q, 0, sizeof (*arc_ext_opcodes));
    808 
    809   return arc_ext_opcodes;
    810 }
    811