Home | History | Annotate | Line # | Download | only in cpu
      1  1.1  christos /* Morpho Technologies mRISC opcode support, for GNU Binutils.  -*- C -*-
      2  1.1  christos    Copyright 2001, 2007, 2008, 2009, 2012 Free Software Foundation, Inc.
      3  1.1  christos 
      4  1.1  christos    Contributed by Red Hat Inc; developed under contract from
      5  1.1  christos    Morpho Technologies.
      6  1.1  christos 
      7  1.1  christos    This file is part of the GNU Binutils.
      8  1.1  christos 
      9  1.1  christos    This program is free software; you can redistribute it and/or modify
     10  1.1  christos    it under the terms of the GNU General Public License as published by
     11  1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12  1.1  christos    (at your option) any later version.
     13  1.1  christos 
     14  1.1  christos    This program is distributed in the hope that it will be useful,
     15  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  1.1  christos    GNU General Public License for more details.
     18  1.1  christos 
     19  1.1  christos    You should have received a copy of the GNU General Public License
     20  1.1  christos    along with this program; if not, write to the Free Software
     21  1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     22  1.1  christos    MA 02110-1301, USA.  */
     23  1.1  christos 
     24  1.1  christos 
     25  1.1  christos /* Each section is delimited with start and end markers.
     26  1.1  christos 
     27  1.1  christos    <arch>-opc.h additions use: "-- opc.h"
     28  1.1  christos    <arch>-opc.c additions use: "-- opc.c"
     29  1.1  christos    <arch>-asm.c additions use: "-- asm.c"
     30  1.1  christos    <arch>-dis.c additions use: "-- dis.c"
     31  1.1  christos    <arch>-ibd.h additions use: "-- ibd.h"  */
     32  1.1  christos 
     33  1.1  christos /* -- opc.h */
     35  1.1  christos 
     36  1.1  christos /* Check applicability of instructions against machines.  */
     37  1.1  christos #define CGEN_VALIDATE_INSN_SUPPORTED
     38  1.1  christos 
     39  1.1  christos /* Allows reason codes to be output when assembler errors occur.  */
     40  1.1  christos #define CGEN_VERBOSE_ASSEMBLER_ERRORS
     41  1.1  christos 
     42  1.1  christos /* Override disassembly hashing - there are variable bits in the top
     43  1.1  christos    byte of these instructions.  */
     44  1.1  christos #define CGEN_DIS_HASH_SIZE 8
     45  1.1  christos #define CGEN_DIS_HASH(buf, value) (((* (unsigned char *) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)
     46  1.1  christos 
     47  1.1  christos #define CGEN_ASM_HASH_SIZE 127
     48  1.1  christos #define CGEN_ASM_HASH(insn) mt_asm_hash (insn)
     49  1.1  christos 
     50  1.1  christos extern unsigned int mt_asm_hash (const char *);
     51  1.1  christos 
     52  1.1  christos extern int mt_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
     53  1.1  christos 
     54  1.1  christos 
     55  1.1  christos /* -- opc.c */
     57  1.1  christos #include "safe-ctype.h"
     58  1.1  christos 
     59  1.1  christos /* Special check to ensure that instruction exists for given machine.  */
     60  1.1  christos 
     61  1.1  christos int
     62  1.1  christos mt_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
     63  1.1  christos {
     64  1.1  christos   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
     65  1.1  christos 
     66  1.1  christos   /* No mach attribute?  Assume it's supported for all machs.  */
     67  1.1  christos   if (machs == 0)
     68  1.1  christos     return 1;
     69  1.1  christos 
     70  1.1  christos   return ((machs & cd->machs) != 0);
     71  1.1  christos }
     72  1.1  christos 
     73  1.1  christos /* A better hash function for instruction mnemonics.  */
     74  1.1  christos 
     75  1.1  christos unsigned int
     76  1.1  christos mt_asm_hash (const char* insn)
     77  1.1  christos {
     78  1.1  christos   unsigned int hash;
     79  1.1  christos   const char* m = insn;
     80  1.1  christos 
     81  1.1  christos   for (hash = 0; *m && ! ISSPACE (*m); m++)
     82  1.1  christos     hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
     83  1.1  christos 
     84  1.1  christos   /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
     85  1.1  christos 
     86  1.1  christos   return hash % CGEN_ASM_HASH_SIZE;
     87  1.1  christos }
     88  1.1  christos 
     89  1.1  christos 
     90  1.1  christos /* -- asm.c */
     92  1.1  christos /* Range checking for signed numbers.  Returns 0 if acceptable
     93  1.1  christos    and 1 if the value is out of bounds for a signed quantity.  */
     94  1.1  christos 
     95  1.1  christos static int
     96  1.1  christos signed_out_of_bounds (long val)
     97  1.1  christos {
     98  1.1  christos   if ((val < -32768) || (val > 32767))
     99  1.1  christos     return 1;
    100  1.1  christos   return 0;
    101  1.1  christos }
    102  1.1  christos 
    103  1.1  christos static const char *
    104  1.1  christos parse_loopsize (CGEN_CPU_DESC cd,
    105  1.1  christos 		const char **strp,
    106  1.1  christos 		int opindex,
    107  1.1  christos 		void *arg)
    108  1.1  christos {
    109  1.1  christos   signed long * valuep = (signed long *) arg;
    110  1.1  christos   const char *errmsg;
    111  1.1  christos   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
    112  1.1  christos   enum cgen_parse_operand_result result_type;
    113  1.1  christos   bfd_vma value;
    114  1.1  christos 
    115  1.1  christos   /* Is it a control transfer instructions?  */
    116  1.1  christos   if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_LOOPSIZE)
    117  1.1  christos     {
    118  1.1  christos       code = BFD_RELOC_MT_PCINSN8;
    119  1.1  christos       errmsg = cgen_parse_address (cd, strp, opindex, code,
    120  1.1  christos                                    & result_type, & value);
    121  1.1  christos       *valuep = value;
    122  1.1  christos       return errmsg;
    123  1.1  christos     }
    124  1.1  christos 
    125  1.1  christos   abort ();
    126  1.1  christos }
    127  1.1  christos 
    128  1.1  christos static const char *
    129  1.1  christos parse_imm16 (CGEN_CPU_DESC cd,
    130  1.1  christos 	     const char **strp,
    131  1.1  christos 	     int opindex,
    132  1.1  christos 	     void *arg)
    133  1.1  christos {
    134  1.1  christos   signed long * valuep = (signed long *) arg;
    135  1.1  christos   const char *errmsg;
    136  1.1  christos   enum cgen_parse_operand_result result_type;
    137  1.1  christos   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
    138  1.1  christos   bfd_vma value;
    139  1.1  christos 
    140  1.1  christos   /* Is it a control transfer instructions?  */
    141  1.1  christos   if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16O)
    142  1.1  christos     {
    143  1.1  christos       code = BFD_RELOC_16_PCREL;
    144  1.1  christos       errmsg = cgen_parse_address (cd, strp, opindex, code,
    145  1.1  christos                                    & result_type, & value);
    146  1.1  christos       if (errmsg == NULL)
    147  1.1  christos 	{
    148  1.1  christos 	  if (signed_out_of_bounds (value))
    149  1.1  christos 	    errmsg = _("Operand out of range. Must be between -32768 and 32767.");
    150  1.1  christos 	}
    151  1.1  christos       *valuep = value;
    152  1.1  christos       return errmsg;
    153  1.1  christos     }
    154  1.1  christos 
    155  1.1  christos   /* If it's not a control transfer instruction, then
    156  1.1  christos      we have to check for %OP relocating operators.  */
    157  1.1  christos   if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16L)
    158  1.1  christos     ;
    159  1.1  christos   else if (strncmp (*strp, "%hi16", 5) == 0)
    160  1.1  christos     {
    161  1.1  christos       *strp += 5;
    162  1.1  christos       code = BFD_RELOC_HI16;
    163  1.1  christos     }
    164  1.1  christos   else if (strncmp (*strp, "%lo16", 5) == 0)
    165  1.1  christos     {
    166  1.1  christos       *strp += 5;
    167  1.1  christos       code = BFD_RELOC_LO16;
    168  1.1  christos     }
    169  1.1  christos 
    170  1.1  christos   /* If we found a %OP relocating operator, then parse it as an address.
    171  1.1  christos      If not, we need to parse it as an integer, either signed or unsigned
    172  1.1  christos      depending on which operand type we have.  */
    173  1.1  christos   if (code != BFD_RELOC_NONE)
    174  1.1  christos     {
    175  1.1  christos        /* %OP relocating operator found.  */
    176  1.1  christos        errmsg = cgen_parse_address (cd, strp, opindex, code,
    177  1.1  christos                                    & result_type, & value);
    178  1.1  christos        if (errmsg == NULL)
    179  1.1  christos 	 {
    180  1.1  christos            switch (result_type)
    181  1.1  christos 	     {
    182  1.1  christos 	     case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
    183  1.1  christos 	       if (code == BFD_RELOC_HI16)
    184  1.1  christos 		 value = (value >> 16) & 0xFFFF;
    185  1.1  christos 	       else if (code == BFD_RELOC_LO16)
    186  1.1  christos 		 value = value  & 0xFFFF;
    187  1.1  christos 	       else
    188  1.1  christos 		 errmsg = _("Biiiig Trouble in parse_imm16!");
    189  1.1  christos 	       break;
    190  1.1  christos 
    191  1.1  christos 	     case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
    192  1.1  christos 	       /* No special processing for this case.  */
    193  1.1  christos 	       break;
    194  1.1  christos 
    195  1.1  christos 	     default:
    196  1.1  christos 	       errmsg = _("The percent-operator's operand is not a symbol");
    197  1.1  christos 	       break;
    198  1.1  christos              }
    199  1.1  christos 	 }
    200  1.1  christos        *valuep = value;
    201  1.1  christos     }
    202  1.1  christos   else
    203  1.1  christos     {
    204  1.1  christos       /* Parse hex values like 0xffff as unsigned, and sign extend
    205  1.1  christos 	 them manually.  */
    206  1.1  christos       int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MT_OPERAND_IMM16);
    207  1.1  christos 
    208  1.1  christos       if ((*strp)[0] == '0'
    209  1.1  christos 	  && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
    210  1.1  christos 	parse_signed = 0;
    211  1.1  christos 
    212  1.1  christos       /* No relocating operator.  Parse as an number.  */
    213  1.1  christos       if (parse_signed)
    214  1.1  christos 	{
    215  1.1  christos           /* Parse as as signed integer.  */
    216  1.1  christos 
    217  1.1  christos           errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
    218  1.1  christos 
    219  1.1  christos           if (errmsg == NULL)
    220  1.1  christos 	    {
    221  1.1  christos #if 0
    222  1.1  christos 	      /* Manual range checking is needed for the signed case.  */
    223  1.1  christos 	      if (*valuep & 0x8000)
    224  1.1  christos                 value = 0xffff0000 | *valuep;
    225  1.1  christos 	      else
    226  1.1  christos                 value = *valuep;
    227  1.1  christos 
    228  1.1  christos 	      if (signed_out_of_bounds (value))
    229  1.1  christos 	        errmsg = _("Operand out of range. Must be between -32768 and 32767.");
    230  1.1  christos 	      /* Truncate to 16 bits. This is necessary
    231  1.1  christos 		 because cgen will have sign extended *valuep.  */
    232  1.1  christos 	      *valuep &= 0xFFFF;
    233  1.1  christos #endif
    234  1.1  christos 	    }
    235  1.1  christos 	}
    236  1.1  christos       else
    237  1.1  christos 	{
    238  1.1  christos           /* MT_OPERAND_IMM16Z.  Parse as an unsigned integer.  */
    239  1.1  christos           errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
    240  1.1  christos 
    241  1.1  christos 	  if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16
    242  1.1  christos 	      && *valuep >= 0x8000
    243  1.1  christos 	      && *valuep <= 0xffff)
    244  1.1  christos 	    *valuep -= 0x10000;
    245  1.1  christos 	}
    246  1.1  christos     }
    247  1.1  christos 
    248  1.1  christos   return errmsg;
    249  1.1  christos }
    250  1.1  christos 
    251  1.1  christos 
    252  1.1  christos static const char *
    253  1.1  christos parse_dup (CGEN_CPU_DESC cd,
    254  1.1  christos 	   const char **strp,
    255  1.1  christos 	   int opindex,
    256  1.1  christos 	   unsigned long *valuep)
    257  1.1  christos {
    258  1.1  christos   const char *errmsg = NULL;
    259  1.1  christos 
    260  1.1  christos   if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
    261  1.1  christos     {
    262  1.1  christos       *strp += 3;
    263  1.1  christos       *valuep = 1;
    264  1.1  christos     }
    265  1.1  christos   else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
    266  1.1  christos     {
    267  1.1  christos       *strp += 2;
    268  1.1  christos       *valuep = 0;
    269  1.1  christos     }
    270  1.1  christos   else
    271  1.1  christos     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
    272  1.1  christos 
    273  1.1  christos   return errmsg;
    274  1.1  christos }
    275  1.1  christos 
    276  1.1  christos 
    277  1.1  christos static const char *
    278  1.1  christos parse_ball (CGEN_CPU_DESC cd,
    279  1.1  christos 	    const char **strp,
    280  1.1  christos 	    int opindex,
    281  1.1  christos 	    unsigned long *valuep)
    282  1.1  christos {
    283  1.1  christos   const char *errmsg = NULL;
    284  1.1  christos 
    285  1.1  christos   if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
    286  1.1  christos     {
    287  1.1  christos       *strp += 3;
    288  1.1  christos       *valuep = 1;
    289  1.1  christos     }
    290  1.1  christos   else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
    291  1.1  christos     {
    292  1.1  christos       *strp += 3;
    293  1.1  christos       *valuep = 0;
    294  1.1  christos     }
    295  1.1  christos   else
    296  1.1  christos     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
    297  1.1  christos 
    298  1.1  christos   return errmsg;
    299  1.1  christos }
    300  1.1  christos 
    301  1.1  christos static const char *
    302  1.1  christos parse_xmode (CGEN_CPU_DESC cd,
    303  1.1  christos 	     const char **strp,
    304  1.1  christos 	     int opindex,
    305  1.1  christos 	     unsigned long *valuep)
    306  1.1  christos {
    307  1.1  christos   const char *errmsg = NULL;
    308  1.1  christos 
    309  1.1  christos   if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
    310  1.1  christos     {
    311  1.1  christos       *strp += 2;
    312  1.1  christos       *valuep = 1;
    313  1.1  christos     }
    314  1.1  christos   else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
    315  1.1  christos     {
    316  1.1  christos       *strp += 2;
    317  1.1  christos       *valuep = 0;
    318  1.1  christos     }
    319  1.1  christos   else
    320  1.1  christos     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
    321  1.1  christos 
    322  1.1  christos   return errmsg;
    323  1.1  christos }
    324  1.1  christos 
    325  1.1  christos static const char *
    326  1.1  christos parse_rc (CGEN_CPU_DESC cd,
    327  1.1  christos 	  const char **strp,
    328  1.1  christos 	  int opindex,
    329  1.1  christos 	  unsigned long *valuep)
    330  1.1  christos {
    331  1.1  christos   const char *errmsg = NULL;
    332  1.1  christos 
    333  1.1  christos   if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
    334  1.1  christos     {
    335  1.1  christos       *strp += 1;
    336  1.1  christos       *valuep = 1;
    337  1.1  christos     }
    338  1.1  christos   else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
    339  1.1  christos     {
    340  1.1  christos       *strp += 1;
    341  1.1  christos       *valuep = 0;
    342  1.1  christos     }
    343  1.1  christos   else
    344  1.1  christos     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
    345  1.1  christos 
    346  1.1  christos   return errmsg;
    347  1.1  christos }
    348  1.1  christos 
    349  1.1  christos static const char *
    350  1.1  christos parse_cbrb (CGEN_CPU_DESC cd,
    351  1.1  christos 	    const char **strp,
    352  1.1  christos 	    int opindex,
    353  1.1  christos 	    unsigned long *valuep)
    354  1.1  christos {
    355  1.1  christos   const char *errmsg = NULL;
    356  1.1  christos 
    357  1.1  christos   if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
    358  1.1  christos     {
    359  1.1  christos       *strp += 2;
    360  1.1  christos       *valuep = 1;
    361  1.1  christos     }
    362  1.1  christos   else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
    363  1.1  christos     {
    364  1.1  christos       *strp += 2;
    365  1.1  christos       *valuep = 0;
    366  1.1  christos     }
    367  1.1  christos   else
    368  1.1  christos     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
    369  1.1  christos 
    370  1.1  christos   return errmsg;
    371  1.1  christos }
    372  1.1  christos 
    373  1.1  christos static const char *
    374  1.1  christos parse_rbbc (CGEN_CPU_DESC cd,
    375  1.1  christos 	    const char **strp,
    376  1.1  christos 	    int opindex,
    377  1.1  christos 	    unsigned long *valuep)
    378  1.1  christos {
    379  1.1  christos   const char *errmsg = NULL;
    380  1.1  christos 
    381  1.1  christos   if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
    382  1.1  christos     {
    383  1.1  christos       *strp += 2;
    384  1.1  christos       *valuep = 0;
    385  1.1  christos     }
    386  1.1  christos   else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
    387  1.1  christos     {
    388  1.1  christos       *strp += 3;
    389  1.1  christos       *valuep = 1;
    390  1.1  christos     }
    391  1.1  christos   else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
    392  1.1  christos     {
    393  1.1  christos       *strp += 3;
    394  1.1  christos       *valuep = 2;
    395  1.1  christos     }
    396  1.1  christos   else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
    397  1.1  christos     {
    398  1.1  christos       *strp += 2;
    399  1.1  christos       *valuep = 3;
    400  1.1  christos     }
    401  1.1  christos   else
    402  1.1  christos     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
    403  1.1  christos 
    404  1.1  christos   return errmsg;
    405  1.1  christos }
    406  1.1  christos 
    407  1.1  christos static const char *
    408  1.1  christos parse_type (CGEN_CPU_DESC cd,
    409  1.1  christos 	    const char **strp,
    410  1.1  christos 	    int opindex,
    411  1.1  christos 	    unsigned long *valuep)
    412  1.1  christos {
    413  1.1  christos   const char *errmsg = NULL;
    414  1.1  christos 
    415  1.1  christos   if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
    416  1.1  christos     {
    417  1.1  christos       *strp += 3;
    418  1.1  christos       *valuep = 0;
    419  1.1  christos     }
    420  1.1  christos   else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
    421  1.1  christos     {
    422  1.1  christos       *strp += 4;
    423  1.1  christos       *valuep = 1;
    424  1.1  christos     }
    425  1.1  christos   else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
    426  1.1  christos     {
    427  1.1  christos       *strp += 2;
    428  1.1  christos       *valuep = 2;
    429  1.1  christos     }
    430  1.1  christos   else
    431  1.1  christos     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
    432  1.1  christos 
    433  1.1  christos  if ((errmsg == NULL) && (*valuep == 3))
    434  1.1  christos     errmsg = _("invalid operand.  type may have values 0,1,2 only.");
    435  1.1  christos 
    436  1.1  christos   return errmsg;
    437  1.1  christos }
    438  1.1  christos 
    439  1.1  christos /* -- dis.c */
    440  1.1  christos static void
    441  1.1  christos print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    442  1.1  christos 		 void * dis_info,
    443  1.1  christos 		 long value,
    444  1.1  christos 		 unsigned int attrs ATTRIBUTE_UNUSED,
    445  1.1  christos 		 bfd_vma pc ATTRIBUTE_UNUSED,
    446  1.1  christos 		 int length ATTRIBUTE_UNUSED)
    447  1.1  christos {
    448  1.1  christos   disassemble_info *info = (disassemble_info *) dis_info;
    449  1.1  christos 
    450  1.1  christos   info->fprintf_func (info->stream, "$%lx", value & 0xffffffff);
    451  1.1  christos 
    452  1.1  christos   if (0)
    453  1.1  christos     print_normal (cd, dis_info, value, attrs, pc, length);
    454  1.1  christos }
    455  1.1  christos 
    456  1.1  christos static void
    457  1.1  christos print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    458  1.1  christos 	     void * dis_info,
    459  1.1  christos 	     long value,
    460  1.1  christos 	     unsigned int attrs ATTRIBUTE_UNUSED,
    461  1.1  christos 	     bfd_vma pc ATTRIBUTE_UNUSED,
    462  1.1  christos 	     int length ATTRIBUTE_UNUSED)
    463  1.1  christos {
    464  1.1  christos   print_address (cd, dis_info, value + pc, attrs, pc, length);
    465  1.1  christos }
    466  1.1  christos 
    467  1.1  christos /* -- */
    468  1.1  christos 
    469  1.1  christos 
    470                
    471                
    472                
    473