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