(root)/
binutils-2.41/
opcodes/
arc-ext.c
       1  /* ARC target-dependent stuff.  Extension structure access functions
       2     Copyright (C) 1995-2023 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  }