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