Home | History | Annotate | Line # | Download | only in cpu
      1      1.1     skrll /* IQ2000 opcode support.  -*- C -*-
      2      1.1     skrll 
      3  1.1.1.2  christos    Copyright 2000, 2001, 2002, 2005, 2007, 2009 Free Software Foundation, Inc.
      4      1.1     skrll 
      5      1.1     skrll    Contributed by Red Hat Inc; developed under contract from Fujitsu.
      6      1.1     skrll 
      7      1.1     skrll    This file is part of the GNU Binutils.
      8      1.1     skrll 
      9      1.1     skrll    This program is free software; you can redistribute it and/or modify
     10      1.1     skrll    it under the terms of the GNU General Public License as published by
     11      1.1     skrll    the Free Software Foundation; either version 3 of the License, or
     12      1.1     skrll    (at your option) any later version.
     13      1.1     skrll 
     14      1.1     skrll    This program is distributed in the hope that it will be useful,
     15      1.1     skrll    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16      1.1     skrll    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17      1.1     skrll    GNU General Public License for more details.
     18      1.1     skrll 
     19      1.1     skrll    You should have received a copy of the GNU General Public License
     20      1.1     skrll    along with this program; if not, write to the Free Software
     21      1.1     skrll    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     22      1.1     skrll    MA 02110-1301, USA.  */
     23      1.1     skrll 
     24      1.1     skrll /* This file is an addendum to iq2000.cpu.  Heavy use of C code isn't
     25      1.1     skrll    appropriate in .cpu files, so it resides here.  This especially applies
     26      1.1     skrll    to assembly/disassembly where parsing/printing can be quite involved.
     27      1.1     skrll    Such things aren't really part of the specification of the cpu, per se,
     28      1.1     skrll    so .cpu files provide the general framework and .opc files handle the
     29      1.1     skrll    nitty-gritty details as necessary.
     30      1.1     skrll 
     31      1.1     skrll    Each section is delimited with start and end markers.
     32      1.1     skrll 
     33      1.1     skrll    <arch>-opc.h additions use: "-- opc.h"
     34      1.1     skrll    <arch>-opc.c additions use: "-- opc.c"
     35      1.1     skrll    <arch>-asm.c additions use: "-- asm.c"
     36      1.1     skrll    <arch>-dis.c additions use: "-- dis.c"
     37      1.1     skrll    <arch>-ibd.h additions use: "-- ibd.h".  */
     38      1.1     skrll 
     39      1.1     skrll /* -- opc.h */
     41      1.1     skrll 
     42      1.1     skrll /* Allows reason codes to be output when assembler errors occur.  */
     43      1.1     skrll #define CGEN_VERBOSE_ASSEMBLER_ERRORS
     44      1.1     skrll 
     45      1.1     skrll /* Override disassembly hashing - there are variable bits in the top
     46      1.1     skrll    byte of these instructions.  */
     47      1.1     skrll #define CGEN_DIS_HASH_SIZE 8
     48      1.1     skrll #define CGEN_DIS_HASH(buf,value) (((* (unsigned char*) (buf)) >> 6) % CGEN_DIS_HASH_SIZE)
     49      1.1     skrll 
     50      1.1     skrll /* following activates check beyond hashing since some iq2000 and iq10
     51      1.1     skrll    instructions have same mnemonics but different functionality. */
     52      1.1     skrll #define CGEN_VALIDATE_INSN_SUPPORTED
     53      1.1     skrll 
     54      1.1     skrll extern int iq2000_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
     55      1.1     skrll 
     56      1.1     skrll /* -- asm.c */
     57      1.1     skrll 
     58      1.1     skrll #include "safe-ctype.h"
     59      1.1     skrll 
     60      1.1     skrll static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
     61      1.1     skrll 
     62      1.1     skrll /* Special check to ensure that instruction exists for given machine.  */
     63      1.1     skrll 
     64      1.1     skrll int
     65      1.1     skrll iq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
     66      1.1     skrll {
     67      1.1     skrll   int machs = cd->machs;
     68      1.1     skrll 
     69      1.1     skrll   return (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0;
     70      1.1     skrll }
     71      1.1     skrll 
     72      1.1     skrll static int
     73      1.1     skrll iq2000_cgen_isa_register (const char **strp)
     74      1.1     skrll {
     75      1.1     skrll   int len;
     76      1.1     skrll   int ch1, ch2;
     77      1.1     skrll 
     78      1.1     skrll   if (**strp == 'r' || **strp == 'R')
     79      1.1     skrll     {
     80      1.1     skrll       len = strlen (*strp);
     81      1.1     skrll       if (len == 2)
     82      1.1     skrll         {
     83      1.1     skrll           ch1 = (*strp)[1];
     84      1.1     skrll           if ('0' <= ch1 && ch1 <= '9')
     85      1.1     skrll             return 1;
     86      1.1     skrll         }
     87      1.1     skrll       else if (len == 3)
     88      1.1     skrll         {
     89      1.1     skrll 	  ch1 = (*strp)[1];
     90      1.1     skrll           ch2 = (*strp)[2];
     91      1.1     skrll           if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
     92      1.1     skrll             return 1;
     93      1.1     skrll           if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
     94      1.1     skrll             return 1;
     95      1.1     skrll         }
     96      1.1     skrll     }
     97      1.1     skrll   if (**strp == '%'
     98      1.1     skrll       && TOLOWER ((*strp)[1]) != 'l'
     99      1.1     skrll       && TOLOWER ((*strp)[1]) != 'h')
    100      1.1     skrll     return 1;
    101      1.1     skrll   return 0;
    102      1.1     skrll }
    103      1.1     skrll 
    104      1.1     skrll /* Handle negated literal.  */
    105      1.1     skrll 
    106      1.1     skrll static const char *
    107      1.1     skrll parse_mimm (CGEN_CPU_DESC cd,
    108      1.1     skrll 	    const char **strp,
    109      1.1     skrll 	    int opindex,
    110      1.1     skrll 	    unsigned long *valuep)
    111      1.1     skrll {
    112      1.1     skrll   const char *errmsg;
    113      1.1     skrll 
    114      1.1     skrll   /* Verify this isn't a register.  */
    115      1.1     skrll   if (iq2000_cgen_isa_register (strp))
    116      1.1     skrll     errmsg = _("immediate value cannot be register");
    117      1.1     skrll   else
    118      1.1     skrll     {
    119      1.1     skrll       long value;
    120      1.1     skrll 
    121      1.1     skrll       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
    122      1.1     skrll       if (errmsg == NULL)
    123      1.1     skrll 	{
    124      1.1     skrll 	  long x = (-value) & 0xFFFF0000;
    125      1.1     skrll 
    126      1.1     skrll 	  if (x != 0 && x != (long) 0xFFFF0000)
    127      1.1     skrll 	    errmsg = _("immediate value out of range");
    128      1.1     skrll 	  else
    129      1.1     skrll 	    *valuep = (-value & 0xFFFF);
    130      1.1     skrll 	}
    131      1.1     skrll     }
    132      1.1     skrll   return errmsg;
    133      1.1     skrll }
    134      1.1     skrll 
    135      1.1     skrll /* Handle signed/unsigned literal.  */
    136      1.1     skrll 
    137      1.1     skrll static const char *
    138      1.1     skrll parse_imm (CGEN_CPU_DESC cd,
    139      1.1     skrll 	   const char **strp,
    140      1.1     skrll 	   int opindex,
    141      1.1     skrll 	   unsigned long *valuep)
    142      1.1     skrll {
    143      1.1     skrll   const char *errmsg;
    144      1.1     skrll 
    145      1.1     skrll   if (iq2000_cgen_isa_register (strp))
    146      1.1     skrll     errmsg = _("immediate value cannot be register");
    147      1.1     skrll   else
    148      1.1     skrll     {
    149      1.1     skrll       long value;
    150      1.1     skrll 
    151      1.1     skrll       errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
    152      1.1     skrll       if (errmsg == NULL)
    153      1.1     skrll 	{
    154      1.1     skrll 	  long x = value & 0xFFFF0000;
    155      1.1     skrll 
    156      1.1     skrll 	  if (x != 0 && x != (long) 0xFFFF0000)
    157      1.1     skrll 	    errmsg = _("immediate value out of range");
    158      1.1     skrll 	  else
    159      1.1     skrll 	    *valuep = (value & 0xFFFF);
    160      1.1     skrll 	}
    161      1.1     skrll     }
    162      1.1     skrll   return errmsg;
    163      1.1     skrll }
    164      1.1     skrll 
    165      1.1     skrll /* Handle iq10 21-bit jmp offset.  */
    166      1.1     skrll 
    167      1.1     skrll static const char *
    168      1.1     skrll parse_jtargq10 (CGEN_CPU_DESC cd,
    169      1.1     skrll 		const char **strp,
    170      1.1     skrll 		int opindex,
    171      1.1     skrll 		int reloc ATTRIBUTE_UNUSED,
    172      1.1     skrll 		enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED,
    173      1.1     skrll 		bfd_vma *valuep)
    174      1.1     skrll {
    175      1.1     skrll   const char *errmsg;
    176      1.1     skrll   bfd_vma value;
    177      1.1     skrll   enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
    178      1.1     skrll 
    179      1.1     skrll   errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
    180      1.1     skrll 			       & result_type, & value);
    181      1.1     skrll   if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    182      1.1     skrll     {
    183      1.1     skrll       /* Check value is within 23-bits
    184      1.1     skrll 	 (remembering that 2-bit shift right will occur).  */
    185      1.1     skrll       if (value > 0x7fffff)
    186      1.1     skrll         return _("21-bit offset out of range");
    187      1.1     skrll     }
    188      1.1     skrll   *valuep = (value & 0x7FFFFF);
    189      1.1     skrll   return errmsg;
    190      1.1     skrll }
    191      1.1     skrll 
    192      1.1     skrll /* Handle high().  */
    193      1.1     skrll 
    194      1.1     skrll static const char *
    195      1.1     skrll parse_hi16 (CGEN_CPU_DESC cd,
    196      1.1     skrll 	    const char **strp,
    197      1.1     skrll 	    int opindex,
    198      1.1     skrll 	    unsigned long *valuep)
    199      1.1     skrll {
    200      1.1     skrll   if (strncasecmp (*strp, "%hi(", 4) == 0)
    201      1.1     skrll     {
    202      1.1     skrll       enum cgen_parse_operand_result result_type;
    203      1.1     skrll       bfd_vma value;
    204      1.1     skrll       const char *errmsg;
    205      1.1     skrll 
    206      1.1     skrll       *strp += 4;
    207      1.1     skrll       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
    208      1.1     skrll 				   & result_type, & value);
    209      1.1     skrll       if (**strp != ')')
    210      1.1     skrll 	return MISSING_CLOSING_PARENTHESIS;
    211      1.1     skrll 
    212      1.1     skrll       ++*strp;
    213      1.1     skrll       if (errmsg == NULL
    214      1.1     skrll   	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    215      1.1     skrll 	{
    216      1.1     skrll 	  /* If value has top-bit of %lo on, then it will
    217      1.1     skrll 	     sign-propagate and so we compensate by adding
    218      1.1     skrll 	     1 to the resultant %hi value.  */
    219      1.1     skrll 	  if (value & 0x8000)
    220      1.1     skrll 	    value += 0x10000;
    221      1.1     skrll 	  value >>= 16;
    222      1.1     skrll 	  value &= 0xffff;
    223      1.1     skrll 	}
    224      1.1     skrll       *valuep = value;
    225      1.1     skrll 
    226      1.1     skrll       return errmsg;
    227      1.1     skrll     }
    228      1.1     skrll 
    229      1.1     skrll   /* We add %uhi in case a user just wants the high 16-bits or is using
    230      1.1     skrll      an insn like ori for %lo which does not sign-propagate.  */
    231      1.1     skrll   if (strncasecmp (*strp, "%uhi(", 5) == 0)
    232      1.1     skrll     {
    233      1.1     skrll       enum cgen_parse_operand_result result_type;
    234      1.1     skrll       bfd_vma value;
    235      1.1     skrll       const char *errmsg;
    236      1.1     skrll 
    237      1.1     skrll       *strp += 5;
    238      1.1     skrll       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
    239      1.1     skrll 				   & result_type, & value);
    240      1.1     skrll       if (**strp != ')')
    241      1.1     skrll 	return MISSING_CLOSING_PARENTHESIS;
    242      1.1     skrll 
    243      1.1     skrll       ++*strp;
    244      1.1     skrll       if (errmsg == NULL
    245      1.1     skrll   	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    246      1.1     skrll 	value >>= 16;
    247      1.1     skrll 
    248      1.1     skrll       value &= 0xffff;
    249      1.1     skrll       *valuep = value;
    250      1.1     skrll 
    251      1.1     skrll       return errmsg;
    252      1.1     skrll     }
    253      1.1     skrll 
    254      1.1     skrll   return parse_imm (cd, strp, opindex, valuep);
    255      1.1     skrll }
    256      1.1     skrll 
    257      1.1     skrll /* Handle %lo in a signed context.
    258      1.1     skrll    The signedness of the value doesn't matter to %lo(), but this also
    259      1.1     skrll    handles the case where %lo() isn't present.  */
    260      1.1     skrll 
    261      1.1     skrll static const char *
    262      1.1     skrll parse_lo16 (CGEN_CPU_DESC cd,
    263      1.1     skrll 	    const char **strp,
    264      1.1     skrll 	    int opindex,
    265      1.1     skrll 	    unsigned long *valuep)
    266      1.1     skrll {
    267      1.1     skrll   if (strncasecmp (*strp, "%lo(", 4) == 0)
    268      1.1     skrll     {
    269      1.1     skrll       const char *errmsg;
    270      1.1     skrll       enum cgen_parse_operand_result result_type;
    271      1.1     skrll       bfd_vma value;
    272      1.1     skrll 
    273      1.1     skrll       *strp += 4;
    274      1.1     skrll       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
    275      1.1     skrll 				   & result_type, & value);
    276      1.1     skrll       if (**strp != ')')
    277      1.1     skrll 	return MISSING_CLOSING_PARENTHESIS;
    278      1.1     skrll       ++*strp;
    279      1.1     skrll       if (errmsg == NULL
    280      1.1     skrll 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    281      1.1     skrll 	value &= 0xffff;
    282      1.1     skrll       *valuep = value;
    283      1.1     skrll       return errmsg;
    284      1.1     skrll     }
    285      1.1     skrll 
    286      1.1     skrll   return parse_imm (cd, strp, opindex, valuep);
    287      1.1     skrll }
    288      1.1     skrll 
    289      1.1     skrll /* Handle %lo in a negated signed context.
    290      1.1     skrll    The signedness of the value doesn't matter to %lo(), but this also
    291      1.1     skrll    handles the case where %lo() isn't present.  */
    292      1.1     skrll 
    293      1.1     skrll static const char *
    294      1.1     skrll parse_mlo16 (CGEN_CPU_DESC cd,
    295      1.1     skrll 	     const char **strp,
    296      1.1     skrll 	     int opindex,
    297      1.1     skrll 	     unsigned long *valuep)
    298      1.1     skrll {
    299      1.1     skrll   if (strncasecmp (*strp, "%lo(", 4) == 0)
    300      1.1     skrll     {
    301      1.1     skrll       const char *errmsg;
    302      1.1     skrll       enum cgen_parse_operand_result result_type;
    303      1.1     skrll       bfd_vma value;
    304      1.1     skrll 
    305      1.1     skrll       *strp += 4;
    306      1.1     skrll       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
    307      1.1     skrll 				   & result_type, & value);
    308      1.1     skrll       if (**strp != ')')
    309      1.1     skrll 	return MISSING_CLOSING_PARENTHESIS;
    310      1.1     skrll       ++*strp;
    311      1.1     skrll       if (errmsg == NULL
    312      1.1     skrll 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    313      1.1     skrll 	value = (-value) & 0xffff;
    314      1.1     skrll       *valuep = value;
    315      1.1     skrll       return errmsg;
    316      1.1     skrll     }
    317      1.1     skrll 
    318      1.1     skrll   return parse_mimm (cd, strp, opindex, valuep);
    319      1.1     skrll }
    320      1.1     skrll 
    321                    /* -- */
    322