Home | History | Annotate | Download | only in opcodes
      1 /* ARC target-dependent stuff.  Extension structure access functions
      2    Copyright (C) 1995-2016 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   long			 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 	  }
    174 
    175 	case EXT_COND_CODE:
    176 	  {
    177 	    char *cc_name = xstrdup ((char *) (p + 3));
    178 
    179 	    arc_extension_map.
    180 	      condCodes[p[2] - FIRST_EXTENSION_CONDITION_CODE]
    181 	      = cc_name;
    182 	    break;
    183 	  }
    184 
    185 	case EXT_AUX_REGISTER:
    186 	  {
    187 	    /* Trickier -- need to store linked list of these.  */
    188 	    struct ExtAuxRegister *newAuxRegister
    189 	      = XNEW (struct ExtAuxRegister);
    190 	    char *aux_name = xstrdup ((char *) (p + 6));
    191 
    192 	    newAuxRegister->name = aux_name;
    193 	    newAuxRegister->address = (p[2] << 24) | (p[3] << 16)
    194 	      | (p[4] << 8) | p[5];
    195 	    newAuxRegister->next = arc_extension_map.auxRegisters;
    196 	    arc_extension_map.auxRegisters = newAuxRegister;
    197 	    break;
    198 	  }
    199 
    200 	default:
    201 	  break;
    202 	}
    203 
    204       p += p[0]; /* Move on to next record.  */
    205     }
    206 }
    207 
    208 
    209 /* Free memory that has been allocated for the extensions.  */
    210 
    211 static void
    212 destroy_map (void)
    213 {
    214   struct ExtAuxRegister *r;
    215   unsigned int		 i;
    216 
    217   /* Free auxiliary registers.  */
    218   r = arc_extension_map.auxRegisters;
    219   while (r)
    220     {
    221       /* N.B. after r has been freed, r->next is invalid!  */
    222       struct ExtAuxRegister* next = r->next;
    223 
    224       free (r->name);
    225       free (r);
    226       r = next;
    227     }
    228 
    229   /* Free instructions.  */
    230   for (i = 0; i < INST_HASH_SIZE; i++)
    231     {
    232       struct ExtInstruction *insn = arc_extension_map.instructions[i];
    233 
    234       while (insn)
    235 	{
    236 	  /* N.B. after insn has been freed, insn->next is invalid!  */
    237 	  struct ExtInstruction *next = insn->next;
    238 
    239 	  free (insn->name);
    240 	  free (insn);
    241 	  insn = next;
    242 	}
    243     }
    244 
    245   /* Free core registers.  */
    246   for (i = 0; i < NUM_EXT_CORE; i++)
    247     {
    248       if (arc_extension_map.coreRegisters[i].name)
    249 	free (arc_extension_map.coreRegisters[i].name);
    250     }
    251 
    252   /* Free condition codes.  */
    253   for (i = 0; i < NUM_EXT_COND; i++)
    254     {
    255       if (arc_extension_map.condCodes[i])
    256 	free (arc_extension_map.condCodes[i]);
    257     }
    258 
    259   memset (&arc_extension_map, 0, sizeof (arc_extension_map));
    260 }
    261 
    262 
    263 static const char *
    264 ExtReadWrite_image (enum ExtReadWrite val)
    265 {
    266     switch (val)
    267     {
    268 	case REG_INVALID  : return "INVALID";
    269 	case REG_READ	  : return "RO";
    270 	case REG_WRITE	  : return "WO";
    271 	case REG_READWRITE: return "R/W";
    272 	default		  : return "???";
    273     }
    274 }
    275 
    276 
    277 /* Externally visible functions.  */
    278 
    279 /* Get the name of an extension instruction.  */
    280 
    281 const extInstruction_t *
    282 arcExtMap_insn (int opcode, int insn)
    283 {
    284   /* Here the following tasks need to be done.  First of all, the
    285      opcode stored in the Extension Map is the real opcode.  However,
    286      the subopcode stored in the instruction to be disassembled is
    287      mangled.  We pass (in minor opcode), the instruction word.  Here
    288      we will un-mangle it and get the real subopcode which we can look
    289      for in the Extension Map.  This function is used both for the
    290      ARCTangent and the ARCompact, so we would also need some sort of
    291      a way to distinguish between the two architectures.  This is
    292      because the ARCTangent does not do any of this mangling so we
    293      have no issues there.  */
    294 
    295   /* If P[22:23] is 0 or 2 then un-mangle using iiiiiI.  If it is 1
    296      then use iiiiIi.  Now, if P is 3 then check M[5:5] and if it is 0
    297      then un-mangle using iiiiiI else iiiiii.  */
    298 
    299   unsigned char minor;
    300   extInstruction_t *temp;
    301 
    302   /* 16-bit instructions.  */
    303   if (0x08 <= opcode && opcode <= 0x0b)
    304     {
    305       unsigned char b, c, i;
    306 
    307       b = (insn & 0x0700) >> 8;
    308       c = (insn & 0x00e0) >> 5;
    309       i = (insn & 0x001f);
    310 
    311       if (i)
    312 	minor = i;
    313       else
    314 	minor = (c == 0x07) ? b : c;
    315     }
    316   /* 32-bit instructions.  */
    317   else
    318     {
    319       unsigned char I, A, B;
    320 
    321       I = (insn & 0x003f0000) >> 16;
    322       A = (insn & 0x0000003f);
    323       B = ((insn & 0x07000000) >> 24) | ((insn & 0x00007000) >> 9);
    324 
    325       if (I != 0x2f)
    326 	{
    327 #ifndef UNMANGLED
    328 	  switch (P)
    329 	    {
    330 	    case 3:
    331 	      if (M)
    332 		{
    333 		  minor = I;
    334 		  break;
    335 		}
    336 	    case 0:
    337 	    case 2:
    338 	      minor = (I >> 1) | ((I & 0x1) << 5);
    339 	      break;
    340 	    case 1:
    341 	      minor = (I >> 1) | (I & 0x1) | ((I & 0x2) << 4);
    342 	    }
    343 #else
    344 	  minor = I;
    345 #endif
    346 	}
    347       else
    348 	{
    349 	  if (A != 0x3f)
    350 	    minor = A;
    351 	  else
    352 	    minor = B;
    353 	}
    354     }
    355 
    356   temp = arc_extension_map.instructions[INST_HASH (opcode, minor)];
    357   while (temp)
    358     {
    359       if ((temp->major == opcode) && (temp->minor == minor))
    360 	{
    361 	  return temp;
    362 	}
    363       temp = temp->next;
    364     }
    365 
    366   return NULL;
    367 }
    368 
    369 /* Get the name of an extension core register.  */
    370 
    371 const char *
    372 arcExtMap_coreRegName (int regnum)
    373 {
    374   if (regnum < FIRST_EXTENSION_CORE_REGISTER
    375       || regnum > LAST_EXTENSION_CORE_REGISTER)
    376     return NULL;
    377   return arc_extension_map.
    378     coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].name;
    379 }
    380 
    381 /* Get the access mode of an extension core register.  */
    382 
    383 enum ExtReadWrite
    384 arcExtMap_coreReadWrite (int regnum)
    385 {
    386   if (regnum < FIRST_EXTENSION_CORE_REGISTER
    387       || regnum > LAST_EXTENSION_CORE_REGISTER)
    388     return REG_INVALID;
    389   return arc_extension_map.
    390     coreRegisters[regnum - FIRST_EXTENSION_CORE_REGISTER].rw;
    391 }
    392 
    393 /* Get the name of an extension condition code.  */
    394 
    395 const char *
    396 arcExtMap_condCodeName (int code)
    397 {
    398   if (code < FIRST_EXTENSION_CONDITION_CODE
    399       || code > LAST_EXTENSION_CONDITION_CODE)
    400     return NULL;
    401   return arc_extension_map.
    402     condCodes[code - FIRST_EXTENSION_CONDITION_CODE];
    403 }
    404 
    405 /* Get the name of an extension auxiliary register.  */
    406 
    407 const char *
    408 arcExtMap_auxRegName (long address)
    409 {
    410   /* Walk the list of auxiliary register names and find the name.  */
    411   struct ExtAuxRegister *r;
    412 
    413   for (r = arc_extension_map.auxRegisters; r; r = r->next)
    414     {
    415       if (r->address == address)
    416 	return (const char *)r->name;
    417     }
    418   return NULL;
    419 }
    420 
    421 /* Load extensions described in .arcextmap and
    422    .gnu.linkonce.arcextmap.* ELF section.  */
    423 
    424 void
    425 build_ARC_extmap (bfd *text_bfd)
    426 {
    427   asection *sect;
    428 
    429   /* The map is built each time gdb loads an executable file - so free
    430      any existing map, as the map defined by the new file may differ
    431      from the old.  */
    432   destroy_map ();
    433 
    434   for (sect = text_bfd->sections; sect != NULL; sect = sect->next)
    435     if (!strncmp (sect->name,
    436 		  ".gnu.linkonce.arcextmap.",
    437 	  sizeof (".gnu.linkonce.arcextmap.") - 1)
    438 	|| !strcmp (sect->name,".arcextmap"))
    439       {
    440 	bfd_size_type  count  = bfd_get_section_size (sect);
    441 	unsigned char* buffer = xmalloc (count);
    442 
    443 	if (buffer)
    444 	  {
    445 	    if (bfd_get_section_contents (text_bfd, sect, buffer, 0, count))
    446 	      create_map (buffer, count);
    447 	    free (buffer);
    448 	  }
    449       }
    450 }
    451 
    452 /* Debug function used to dump the ARC information fount in arcextmap
    453    sections.  */
    454 
    455 void
    456 dump_ARC_extmap (void)
    457 {
    458     struct ExtAuxRegister *r;
    459     int			   i;
    460 
    461     r = arc_extension_map.auxRegisters;
    462 
    463     while (r)
    464     {
    465 	printf ("AUX : %s %ld\n", r->name, r->address);
    466 	r = r->next;
    467     }
    468 
    469     for (i = 0; i < INST_HASH_SIZE; i++)
    470     {
    471 	struct ExtInstruction *insn;
    472 
    473 	for (insn = arc_extension_map.instructions[i];
    474 	     insn != NULL; insn = insn->next)
    475 	  {
    476 	    printf ("INST: 0x%02x 0x%02x ", insn->major, insn->minor);
    477 	    switch (insn->flags & ARC_SYNTAX_MASK)
    478 	      {
    479 	      case ARC_SYNTAX_2OP:
    480 		printf ("SYNTAX_2OP");
    481 		break;
    482 	      case ARC_SYNTAX_3OP:
    483 		printf ("SYNTAX_3OP");
    484 		break;
    485 	      case ARC_SYNTAX_1OP:
    486 		printf ("SYNTAX_1OP");
    487 		break;
    488 	      case ARC_SYNTAX_NOP:
    489 		printf ("SYNTAX_NOP");
    490 		break;
    491 	      default:
    492 		printf ("SYNTAX_UNK");
    493 		break;
    494 	      }
    495 
    496 	    if (insn->flags & 0x10)
    497 	      printf ("|MODIFIER");
    498 
    499 	    printf (" %s\n", insn->name);
    500 	  }
    501     }
    502 
    503     for (i = 0; i < NUM_EXT_CORE; i++)
    504     {
    505 	struct ExtCoreRegister reg = arc_extension_map.coreRegisters[i];
    506 
    507 	if (reg.name)
    508 	  printf ("CORE: 0x%04x %s %s\n", reg.number,
    509 		  ExtReadWrite_image (reg.rw),
    510 		  reg.name);
    511     }
    512 
    513     for (i = 0; i < NUM_EXT_COND; i++)
    514 	if (arc_extension_map.condCodes[i])
    515 	    printf ("COND: %s\n", arc_extension_map.condCodes[i]);
    516 }
    517 
    518 /* For a given extension instruction generate the equivalent arc
    519    opcode structure.  */
    520 
    521 struct arc_opcode *
    522 arcExtMap_genOpcode (const extInstruction_t *einsn,
    523 		     unsigned arc_target,
    524 		     const char **errmsg)
    525 {
    526   struct arc_opcode *q, *arc_ext_opcodes = NULL;
    527   const unsigned char *lflags_f;
    528   const unsigned char *lflags_ccf;
    529   int count;
    530 
    531   /* Check for the class to see how many instructions we generate.  */
    532   switch (einsn->flags & ARC_SYNTAX_MASK)
    533     {
    534     case ARC_SYNTAX_3OP:
    535       count = (einsn->modsyn & ARC_OP1_MUST_BE_IMM) ? 10 : 20;
    536       break;
    537     case ARC_SYNTAX_2OP:
    538       count = (einsn->flags & 0x10) ? 7 : 6;
    539       break;
    540     case ARC_SYNTAX_1OP:
    541       count = 3;
    542       break;
    543     case ARC_SYNTAX_NOP:
    544       count = 1;
    545       break;
    546     default:
    547       count = 0;
    548       break;
    549     }
    550 
    551   /* Allocate memory.  */
    552   arc_ext_opcodes = (struct arc_opcode *)
    553     xmalloc ((count + 1) * sizeof (*arc_ext_opcodes));
    554 
    555   if (arc_ext_opcodes == NULL)
    556     {
    557       *errmsg = "Virtual memory exhausted";
    558       return NULL;
    559     }
    560 
    561   /* Generate the patterns.  */
    562   q = arc_ext_opcodes;
    563 
    564   if (einsn->suffix)
    565     {
    566       lflags_f   = flags_none;
    567       lflags_ccf = flags_none;
    568     }
    569   else
    570     {
    571       lflags_f   = flags_f;
    572       lflags_ccf = flags_ccf;
    573     }
    574 
    575   if (einsn->suffix & ARC_SUFFIX_COND)
    576     lflags_ccf = flags_cc;
    577   if (einsn->suffix & ARC_SUFFIX_FLAG)
    578     {
    579       lflags_f   = flags_f;
    580       lflags_ccf = flags_f;
    581     }
    582   if (einsn->suffix & (ARC_SUFFIX_FLAG | ARC_SUFFIX_COND))
    583     lflags_ccf = flags_ccf;
    584 
    585   if (einsn->flags & ARC_SYNTAX_2OP
    586       && !(einsn->flags & 0x10))
    587     {
    588       /* Regular 2OP instruction.  */
    589       if (einsn->suffix & ARC_SUFFIX_COND)
    590 	*errmsg = "Suffix SUFFIX_COND ignored";
    591 
    592       INSERT_XOP (q, einsn->name,
    593 		  INSN2OP_BC (einsn->major, einsn->minor), MINSN2OP_BC,
    594 		  arc_target, arg_32bit_rbrc, lflags_f);
    595 
    596       INSERT_XOP (q, einsn->name,
    597 		  INSN2OP_0C (einsn->major, einsn->minor), MINSN2OP_0C,
    598 		  arc_target, arg_32bit_zarc, lflags_f);
    599 
    600       INSERT_XOP (q, einsn->name,
    601 		  INSN2OP_BU (einsn->major, einsn->minor), MINSN2OP_BU,
    602 		  arc_target, arg_32bit_rbu6, lflags_f);
    603 
    604       INSERT_XOP (q, einsn->name,
    605 		  INSN2OP_0U (einsn->major, einsn->minor), MINSN2OP_0U,
    606 		  arc_target, arg_32bit_zau6, lflags_f);
    607 
    608       INSERT_XOP (q, einsn->name,
    609 		  INSN2OP_BL (einsn->major, einsn->minor), MINSN2OP_BL,
    610 		  arc_target, arg_32bit_rblimm, lflags_f);
    611 
    612       INSERT_XOP (q, einsn->name,
    613 		  INSN2OP_0L (einsn->major, einsn->minor), MINSN2OP_0L,
    614 		  arc_target, arg_32bit_zalimm, lflags_f);
    615     }
    616   else if (einsn->flags & (0x10 | ARC_SYNTAX_2OP))
    617     {
    618       /* This is actually a 3OP pattern.  The first operand is
    619 	 immplied and is set to zero.  */
    620       INSERT_XOP (q, einsn->name,
    621 		  INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
    622 		  arc_target, arg_32bit_rbrc, lflags_f);
    623 
    624       INSERT_XOP (q, einsn->name,
    625 		  INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
    626 		  arc_target, arg_32bit_rbu6, lflags_f);
    627 
    628       INSERT_XOP (q, einsn->name,
    629 		  INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
    630 		  arc_target, arg_32bit_rblimm, lflags_f);
    631 
    632       INSERT_XOP (q, einsn->name,
    633 		  INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
    634 		  arc_target, arg_32bit_limmrc, lflags_ccf);
    635 
    636       INSERT_XOP (q, einsn->name,
    637 		  INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
    638 		  arc_target, arg_32bit_limmu6, lflags_ccf);
    639 
    640       INSERT_XOP (q, einsn->name,
    641 		  INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
    642 		  arc_target, arg_32bit_limms12, lflags_f);
    643 
    644       INSERT_XOP (q, einsn->name,
    645 		  INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
    646 		  arc_target, arg_32bit_limmlimm, lflags_ccf);
    647     }
    648   else if (einsn->flags & ARC_SYNTAX_3OP
    649 	   && !(einsn->modsyn & ARC_OP1_MUST_BE_IMM))
    650     {
    651       /* Regular 3OP instruction.  */
    652       INSERT_XOP (q, einsn->name,
    653 		  INSN3OP_ABC (einsn->major, einsn->minor),  MINSN3OP_ABC,
    654 		  arc_target, arg_32bit_rarbrc, lflags_f);
    655 
    656       INSERT_XOP (q, einsn->name,
    657 		  INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
    658 		  arc_target, arg_32bit_zarbrc, lflags_f);
    659 
    660       INSERT_XOP (q, einsn->name,
    661 		  INSN3OP_CBBC (einsn->major, einsn->minor), MINSN3OP_CBBC,
    662 		  arc_target, arg_32bit_rbrbrc, lflags_ccf);
    663 
    664       INSERT_XOP (q, einsn->name,
    665 		  INSN3OP_ABU (einsn->major, einsn->minor),  MINSN3OP_ABU,
    666 		  arc_target, arg_32bit_rarbu6, lflags_f);
    667 
    668       INSERT_XOP (q, einsn->name,
    669 		  INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
    670 		  arc_target, arg_32bit_zarbu6, lflags_f);
    671 
    672       INSERT_XOP (q, einsn->name,
    673 		  INSN3OP_CBBU (einsn->major, einsn->minor), MINSN3OP_CBBU,
    674 		  arc_target, arg_32bit_rbrbu6, lflags_ccf);
    675 
    676       INSERT_XOP (q, einsn->name,
    677 		  INSN3OP_BBS (einsn->major, einsn->minor),  MINSN3OP_BBS,
    678 		  arc_target, arg_32bit_rbrbs12, lflags_f);
    679 
    680       INSERT_XOP (q, einsn->name,
    681 		  INSN3OP_ALC (einsn->major, einsn->minor),  MINSN3OP_ALC,
    682 		  arc_target, arg_32bit_ralimmrc, lflags_f);
    683 
    684       INSERT_XOP (q, einsn->name,
    685 		  INSN3OP_ABL (einsn->major, einsn->minor),  MINSN3OP_ABL,
    686 		  arc_target, arg_32bit_rarblimm, lflags_f);
    687 
    688       INSERT_XOP (q, einsn->name,
    689 		  INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
    690 		  arc_target, arg_32bit_zalimmrc, lflags_f);
    691 
    692       INSERT_XOP (q, einsn->name,
    693 		  INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
    694 		  arc_target, arg_32bit_zarblimm, lflags_f);
    695 
    696       INSERT_XOP (q, einsn->name,
    697 		  INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
    698 		  arc_target, arg_32bit_zalimmrc, lflags_ccf);
    699 
    700       INSERT_XOP (q, einsn->name,
    701 		  INSN3OP_CBBL (einsn->major, einsn->minor), MINSN3OP_CBBL,
    702 		  arc_target, arg_32bit_rbrblimm, lflags_ccf);
    703 
    704       INSERT_XOP (q, einsn->name,
    705 		  INSN3OP_ALU (einsn->major, einsn->minor),  MINSN3OP_ALU,
    706 		  arc_target, arg_32bit_ralimmu6, lflags_f);
    707 
    708       INSERT_XOP (q, einsn->name,
    709 		  INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
    710 		  arc_target, arg_32bit_zalimmu6, lflags_f);
    711 
    712       INSERT_XOP (q, einsn->name,
    713 		  INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
    714 		  arc_target, arg_32bit_zalimmu6, lflags_ccf);
    715 
    716       INSERT_XOP (q, einsn->name,
    717 		  INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
    718 		  arc_target, arg_32bit_zalimms12, lflags_f);
    719 
    720       INSERT_XOP (q, einsn->name,
    721 		  INSN3OP_ALL (einsn->major, einsn->minor),  MINSN3OP_ALL,
    722 		  arc_target, arg_32bit_ralimmlimm, lflags_f);
    723 
    724       INSERT_XOP (q, einsn->name,
    725 		  INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
    726 		  arc_target, arg_32bit_zalimmlimm, lflags_f);
    727 
    728       INSERT_XOP (q, einsn->name,
    729 		  INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
    730 		  arc_target, arg_32bit_zalimmlimm, lflags_ccf);
    731     }
    732   else if (einsn->flags & ARC_SYNTAX_3OP)
    733     {
    734       /* 3OP instruction which accepts only zero as first
    735 	 argument.  */
    736       INSERT_XOP (q, einsn->name,
    737 		  INSN3OP_0BC (einsn->major, einsn->minor),  MINSN3OP_0BC,
    738 		  arc_target, arg_32bit_zarbrc, lflags_f);
    739 
    740       INSERT_XOP (q, einsn->name,
    741 		  INSN3OP_0BU (einsn->major, einsn->minor),  MINSN3OP_0BU,
    742 		  arc_target, arg_32bit_zarbu6, lflags_f);
    743 
    744       INSERT_XOP (q, einsn->name,
    745 		  INSN3OP_0LC (einsn->major, einsn->minor),  MINSN3OP_0LC,
    746 		  arc_target, arg_32bit_zalimmrc, lflags_f);
    747 
    748       INSERT_XOP (q, einsn->name,
    749 		  INSN3OP_0BL (einsn->major, einsn->minor),  MINSN3OP_0BL,
    750 		  arc_target, arg_32bit_zarblimm, lflags_f);
    751 
    752       INSERT_XOP (q, einsn->name,
    753 		  INSN3OP_C0LC (einsn->major, einsn->minor), MINSN3OP_C0LC,
    754 		  arc_target, arg_32bit_zalimmrc, lflags_ccf);
    755 
    756       INSERT_XOP (q, einsn->name,
    757 		  INSN3OP_0LU (einsn->major, einsn->minor),  MINSN3OP_0LU,
    758 		  arc_target, arg_32bit_zalimmu6, lflags_f);
    759 
    760       INSERT_XOP (q, einsn->name,
    761 		  INSN3OP_C0LU (einsn->major, einsn->minor), MINSN3OP_C0LU,
    762 		  arc_target, arg_32bit_zalimmu6, lflags_ccf);
    763 
    764       INSERT_XOP (q, einsn->name,
    765 		  INSN3OP_0LS (einsn->major, einsn->minor),  MINSN3OP_0LS,
    766 		  arc_target, arg_32bit_zalimms12, lflags_f);
    767 
    768       INSERT_XOP (q, einsn->name,
    769 		  INSN3OP_0LL (einsn->major, einsn->minor),  MINSN3OP_0LL,
    770 		  arc_target, arg_32bit_zalimmlimm, lflags_f);
    771 
    772       INSERT_XOP (q, einsn->name,
    773 		  INSN3OP_C0LL (einsn->major, einsn->minor), MINSN3OP_C0LL,
    774 		  arc_target, arg_32bit_zalimmlimm, lflags_ccf);
    775     }
    776   else if (einsn->flags & ARC_SYNTAX_1OP)
    777     {
    778       if (einsn->suffix & ARC_SUFFIX_COND)
    779 	*errmsg = "Suffix SUFFIX_COND ignored";
    780 
    781       INSERT_XOP (q, einsn->name,
    782 		  INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor),
    783 		  MINSN2OP_0C, arc_target, arg_32bit_rc, lflags_f);
    784 
    785       INSERT_XOP (q, einsn->name,
    786 		  INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
    787 		  | (0x01 << 22), MINSN2OP_0U, arc_target, arg_32bit_u6,
    788 		  lflags_f);
    789 
    790       INSERT_XOP (q, einsn->name,
    791 		  INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
    792 		  | FIELDC (62), MINSN2OP_0L, arc_target, arg_32bit_limm,
    793 		  lflags_f);
    794 
    795     }
    796   else if (einsn->flags & ARC_SYNTAX_NOP)
    797     {
    798       if (einsn->suffix & ARC_SUFFIX_COND)
    799 	*errmsg = "Suffix SUFFIX_COND ignored";
    800 
    801       INSERT_XOP (q, einsn->name,
    802 		  INSN2OP (einsn->major, 0x3F) | FIELDB (einsn->minor)
    803 		  | (0x01 << 22), MINSN2OP_0L, arc_target, arg_none, lflags_f);
    804     }
    805   else
    806     {
    807       *errmsg = "Unknown syntax";
    808       return NULL;
    809     }
    810 
    811   /* End marker.  */
    812   memset (q, 0, sizeof (*arc_ext_opcodes));
    813 
    814   return arc_ext_opcodes;
    815 }
    816