Home | History | Annotate | Line # | Download | only in cpu
or1k.opc revision 1.3
      1  1.1      matt /* OpenRISC 1000 opcode support.  -*- C -*-
      2  1.1      matt    Copyright 2000-2014 Free Software Foundation, Inc.
      3  1.1      matt 
      4  1.1      matt    Originally ontributed for OR32 by Red Hat Inc;
      5  1.1      matt 
      6  1.1      matt    This file is part of the GNU Binutils.
      7  1.1      matt 
      8  1.1      matt    This program is free software; you can redistribute it and/or modify
      9  1.1      matt    it under the terms of the GNU General Public License as published by
     10  1.1      matt    the Free Software Foundation; either version 3 of the License, or
     11  1.1      matt    (at your option) any later version.
     12  1.1      matt 
     13  1.1      matt    This program is distributed in the hope that it will be useful,
     14  1.1      matt    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  1.1      matt    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  1.1      matt    GNU General Public License for more details.
     17  1.1      matt 
     18  1.1      matt    You should have received a copy of the GNU General Public License
     19  1.1      matt    along with this program; if not, see <http://www.gnu.org/licenses/>. */
     20  1.1      matt 
     21  1.1      matt /* This file is an addendum to or1k.cpu.  Heavy use of C code isn't
     22  1.1      matt    appropriate in .cpu files, so it resides here.  This especially applies
     23  1.1      matt    to assembly/disassembly where parsing/printing can be quite involved.
     24  1.1      matt    Such things aren't really part of the specification of the cpu, per se,
     25  1.1      matt    so .cpu files provide the general framework and .opc files handle the
     26  1.1      matt    nitty-gritty details as necessary.
     27  1.1      matt 
     28  1.1      matt    Each section is delimited with start and end markers.
     29  1.1      matt 
     30  1.1      matt    <arch>-opc.h additions use: "-- opc.h"
     31  1.1      matt    <arch>-opc.c additions use: "-- opc.c"
     32  1.1      matt    <arch>-asm.c additions use: "-- asm.c"
     33  1.1      matt    <arch>-dis.c additions use: "-- dis.c"
     34  1.1      matt    <arch>-ibd.h additions use: "-- ibd.h"  */
     35  1.1      matt 
     36  1.1      matt /* -- opc.h */
     37  1.1      matt 
     38  1.1      matt #undef  CGEN_DIS_HASH_SIZE
     39  1.1      matt #define CGEN_DIS_HASH_SIZE 256
     40  1.1      matt #undef  CGEN_DIS_HASH
     41  1.1      matt #define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 2)
     42  1.1      matt 
     43  1.2  christos /* Check applicability of instructions against machines.  */
     44  1.2  christos #define CGEN_VALIDATE_INSN_SUPPORTED
     45  1.2  christos 
     46  1.2  christos extern int or1k_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
     47  1.2  christos 
     48  1.1      matt /* -- */
     49  1.1      matt 
     50  1.1      matt /* -- opc.c */
     51  1.2  christos 
     52  1.2  christos /* Special check to ensure that instruction exists for given machine.  */
     53  1.2  christos 
     54  1.2  christos int
     55  1.2  christos or1k_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
     56  1.2  christos {
     57  1.2  christos   int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
     58  1.2  christos 
     59  1.2  christos   /* No mach attribute?  Assume it's supported for all machs.  */
     60  1.2  christos   if (machs == 0)
     61  1.2  christos     return 1;
     62  1.2  christos 
     63  1.2  christos   return ((machs & cd->machs) != 0);
     64  1.2  christos }
     65  1.2  christos 
     66  1.1      matt /* -- */
     67  1.1      matt 
     68  1.1      matt /* -- asm.c */
     69  1.1      matt 
     70  1.1      matt static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
     71  1.2  christos static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
     72  1.2  christos static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
     73  1.1      matt 
     74  1.1      matt #define CGEN_VERBOSE_ASSEMBLER_ERRORS
     75  1.1      matt 
     76  1.1      matt static const char *
     77  1.1      matt parse_disp26 (CGEN_CPU_DESC cd,
     78  1.1      matt 	      const char ** strp,
     79  1.1      matt 	      int opindex,
     80  1.2  christos 	      int opinfo ATTRIBUTE_UNUSED,
     81  1.1      matt 	      enum cgen_parse_operand_result * resultp,
     82  1.1      matt 	      bfd_vma * valuep)
     83  1.1      matt {
     84  1.2  christos   const char *str = *strp;
     85  1.1      matt   const char *errmsg = NULL;
     86  1.2  christos   bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
     87  1.1      matt 
     88  1.2  christos   if (strncasecmp (str, "plta(", 5) == 0)
     89  1.2  christos     {
     90  1.2  christos       *strp = str + 5;
     91  1.2  christos       reloc = BFD_RELOC_OR1K_PLTA26;
     92  1.2  christos     }
     93  1.2  christos   else if (strncasecmp (str, "plt(", 4) == 0)
     94  1.1      matt     {
     95  1.2  christos       *strp = str + 4;
     96  1.2  christos       reloc = BFD_RELOC_OR1K_PLT26;
     97  1.1      matt     }
     98  1.1      matt 
     99  1.2  christos   errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
    100  1.1      matt 
    101  1.2  christos   if (reloc != BFD_RELOC_OR1K_REL_26)
    102  1.1      matt     {
    103  1.1      matt       if (**strp != ')')
    104  1.1      matt 	errmsg = MISSING_CLOSING_PARENTHESIS;
    105  1.2  christos       else
    106  1.2  christos 	++*strp;
    107  1.1      matt     }
    108  1.1      matt 
    109  1.2  christos   return errmsg;
    110  1.2  christos }
    111  1.1      matt 
    112  1.2  christos static const char *
    113  1.2  christos parse_disp21 (CGEN_CPU_DESC cd,
    114  1.2  christos 	      const char ** strp,
    115  1.2  christos 	      int opindex,
    116  1.2  christos 	      int opinfo ATTRIBUTE_UNUSED,
    117  1.2  christos 	      enum cgen_parse_operand_result * resultp,
    118  1.2  christos 	      bfd_vma * valuep)
    119  1.2  christos {
    120  1.2  christos   const char *str = *strp;
    121  1.2  christos   const char *errmsg = NULL;
    122  1.2  christos   bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
    123  1.1      matt 
    124  1.2  christos   if (strncasecmp (str, "got(", 4) == 0)
    125  1.2  christos     {
    126  1.2  christos       *strp = str + 4;
    127  1.2  christos       reloc = BFD_RELOC_OR1K_GOT_PG21;
    128  1.1      matt     }
    129  1.2  christos   else if (strncasecmp (str, "tlsgd(", 6) == 0)
    130  1.1      matt     {
    131  1.2  christos       *strp = str + 6;
    132  1.2  christos       reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
    133  1.1      matt     }
    134  1.2  christos   else if (strncasecmp (str, "tlsldm(", 7) == 0)
    135  1.1      matt     {
    136  1.2  christos       *strp = str + 7;
    137  1.2  christos       reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
    138  1.1      matt     }
    139  1.2  christos   else if (strncasecmp (str, "gottp(", 6) == 0)
    140  1.1      matt     {
    141  1.2  christos       *strp = str + 6;
    142  1.2  christos       reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
    143  1.1      matt     }
    144  1.1      matt 
    145  1.2  christos   errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
    146  1.1      matt 
    147  1.2  christos   if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
    148  1.1      matt     {
    149  1.1      matt       if (**strp != ')')
    150  1.2  christos 	errmsg = MISSING_CLOSING_PARENTHESIS;
    151  1.2  christos       else
    152  1.2  christos 	++*strp;
    153  1.1      matt     }
    154  1.1      matt 
    155  1.2  christos   return errmsg;
    156  1.2  christos }
    157  1.1      matt 
    158  1.2  christos enum or1k_rclass
    159  1.2  christos {
    160  1.2  christos   RCLASS_DIRECT   = 0,
    161  1.2  christos   RCLASS_GOT      = 1,
    162  1.2  christos   RCLASS_GOTPC    = 2,
    163  1.2  christos   RCLASS_GOTOFF   = 3,
    164  1.2  christos   RCLASS_TLSGD    = 4,
    165  1.2  christos   RCLASS_TLSLDM   = 5,
    166  1.2  christos   RCLASS_DTPOFF   = 6,
    167  1.2  christos   RCLASS_GOTTPOFF = 7,
    168  1.2  christos   RCLASS_TPOFF    = 8,
    169  1.2  christos };
    170  1.1      matt 
    171  1.2  christos enum or1k_rtype
    172  1.2  christos {
    173  1.2  christos   RTYPE_LO = 0,
    174  1.2  christos   RTYPE_SLO = 1,
    175  1.2  christos   RTYPE_PO = 2,
    176  1.2  christos   RTYPE_SPO = 3,
    177  1.2  christos   RTYPE_HI = 4,
    178  1.2  christos   RTYPE_AHI = 5,
    179  1.2  christos };
    180  1.2  christos 
    181  1.2  christos #define RCLASS_SHIFT 3
    182  1.2  christos #define RTYPE_MASK   7
    183  1.2  christos 
    184  1.2  christos static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
    185  1.2  christos   { BFD_RELOC_LO16,
    186  1.2  christos     BFD_RELOC_OR1K_SLO16,
    187  1.2  christos     BFD_RELOC_OR1K_LO13,
    188  1.2  christos     BFD_RELOC_OR1K_SLO13,
    189  1.2  christos     BFD_RELOC_HI16,
    190  1.2  christos     BFD_RELOC_HI16_S, },
    191  1.2  christos   { BFD_RELOC_OR1K_GOT16,
    192  1.2  christos     BFD_RELOC_UNUSED,
    193  1.2  christos     BFD_RELOC_OR1K_GOT_LO13,
    194  1.2  christos     BFD_RELOC_UNUSED,
    195  1.2  christos     BFD_RELOC_UNUSED,
    196  1.3  christos     BFD_RELOC_OR1K_GOT_AHI16 },
    197  1.2  christos   { BFD_RELOC_OR1K_GOTPC_LO16,
    198  1.2  christos     BFD_RELOC_UNUSED,
    199  1.2  christos     BFD_RELOC_UNUSED,
    200  1.2  christos     BFD_RELOC_UNUSED,
    201  1.2  christos     BFD_RELOC_OR1K_GOTPC_HI16,
    202  1.2  christos     BFD_RELOC_UNUSED },
    203  1.2  christos   { BFD_RELOC_LO16_GOTOFF,
    204  1.2  christos     BFD_RELOC_OR1K_GOTOFF_SLO16,
    205  1.2  christos     BFD_RELOC_UNUSED,
    206  1.2  christos     BFD_RELOC_UNUSED,
    207  1.2  christos     BFD_RELOC_HI16_GOTOFF,
    208  1.2  christos     BFD_RELOC_HI16_S_GOTOFF },
    209  1.2  christos   { BFD_RELOC_OR1K_TLS_GD_LO16,
    210  1.2  christos     BFD_RELOC_UNUSED,
    211  1.2  christos     BFD_RELOC_OR1K_TLS_GD_LO13,
    212  1.2  christos     BFD_RELOC_UNUSED,
    213  1.2  christos     BFD_RELOC_OR1K_TLS_GD_HI16,
    214  1.2  christos     BFD_RELOC_UNUSED },
    215  1.2  christos   { BFD_RELOC_OR1K_TLS_LDM_LO16,
    216  1.2  christos     BFD_RELOC_UNUSED,
    217  1.2  christos     BFD_RELOC_OR1K_TLS_LDM_LO13,
    218  1.2  christos     BFD_RELOC_UNUSED,
    219  1.2  christos     BFD_RELOC_OR1K_TLS_LDM_HI16,
    220  1.2  christos     BFD_RELOC_UNUSED },
    221  1.2  christos   { BFD_RELOC_OR1K_TLS_LDO_LO16,
    222  1.2  christos     BFD_RELOC_UNUSED,
    223  1.2  christos     BFD_RELOC_UNUSED,
    224  1.2  christos     BFD_RELOC_UNUSED,
    225  1.2  christos     BFD_RELOC_OR1K_TLS_LDO_HI16,
    226  1.2  christos     BFD_RELOC_UNUSED },
    227  1.2  christos   { BFD_RELOC_OR1K_TLS_IE_LO16,
    228  1.2  christos     BFD_RELOC_UNUSED,
    229  1.2  christos     BFD_RELOC_OR1K_TLS_IE_LO13,
    230  1.2  christos     BFD_RELOC_UNUSED,
    231  1.2  christos     BFD_RELOC_OR1K_TLS_IE_HI16,
    232  1.2  christos     BFD_RELOC_OR1K_TLS_IE_AHI16 },
    233  1.2  christos   { BFD_RELOC_OR1K_TLS_LE_LO16,
    234  1.2  christos     BFD_RELOC_OR1K_TLS_LE_SLO16,
    235  1.2  christos     BFD_RELOC_UNUSED,
    236  1.2  christos     BFD_RELOC_UNUSED,
    237  1.2  christos     BFD_RELOC_OR1K_TLS_LE_HI16,
    238  1.2  christos     BFD_RELOC_OR1K_TLS_LE_AHI16 },
    239  1.2  christos };
    240  1.1      matt 
    241  1.2  christos static int
    242  1.2  christos parse_reloc (const char **strp)
    243  1.2  christos {
    244  1.2  christos     const char *str = *strp;
    245  1.2  christos     enum or1k_rclass cls = RCLASS_DIRECT;
    246  1.2  christos     enum or1k_rtype typ;
    247  1.2  christos 
    248  1.2  christos     if (strncasecmp (str, "got(", 4) == 0)
    249  1.2  christos       {
    250  1.2  christos 	*strp = str + 4;
    251  1.2  christos 	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
    252  1.2  christos       }
    253  1.2  christos     if (strncasecmp (str, "gotpo(", 6) == 0)
    254  1.2  christos       {
    255  1.2  christos 	*strp = str + 6;
    256  1.2  christos 	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
    257  1.2  christos       }
    258  1.2  christos     if (strncasecmp (str, "gottppo(", 8) == 0)
    259  1.2  christos       {
    260  1.2  christos 	*strp = str + 8;
    261  1.2  christos 	return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
    262  1.2  christos       }
    263  1.2  christos 
    264  1.2  christos     if (strncasecmp (str, "gotpc", 5) == 0)
    265  1.2  christos       {
    266  1.2  christos 	str += 5;
    267  1.2  christos 	cls = RCLASS_GOTPC;
    268  1.2  christos       }
    269  1.2  christos     else if (strncasecmp (str, "gotoff", 6) == 0)
    270  1.2  christos       {
    271  1.2  christos 	str += 6;
    272  1.2  christos 	cls = RCLASS_GOTOFF;
    273  1.2  christos       }
    274  1.2  christos     else if (strncasecmp (str, "tlsgd", 5) == 0)
    275  1.2  christos       {
    276  1.2  christos 	str += 5;
    277  1.2  christos 	cls = RCLASS_TLSGD;
    278  1.2  christos       }
    279  1.2  christos     else if (strncasecmp (str, "tlsldm", 6) == 0)
    280  1.2  christos       {
    281  1.2  christos 	str += 6;
    282  1.2  christos 	cls = RCLASS_TLSLDM;
    283  1.2  christos       }
    284  1.2  christos     else if (strncasecmp (str, "dtpoff", 6) == 0)
    285  1.2  christos       {
    286  1.2  christos 	str += 6;
    287  1.2  christos 	cls = RCLASS_DTPOFF;
    288  1.2  christos       }
    289  1.2  christos     else if (strncasecmp (str, "gottpoff", 8) == 0)
    290  1.2  christos       {
    291  1.2  christos 	str += 8;
    292  1.2  christos 	cls = RCLASS_GOTTPOFF;
    293  1.2  christos       }
    294  1.2  christos     else if (strncasecmp (str, "tpoff", 5) == 0)
    295  1.2  christos       {
    296  1.2  christos 	str += 5;
    297  1.2  christos 	cls = RCLASS_TPOFF;
    298  1.2  christos       }
    299  1.3  christos     else if (strncasecmp (str, "got", 3) == 0)
    300  1.3  christos       {
    301  1.3  christos 	str += 3;
    302  1.3  christos 	cls = RCLASS_GOT;
    303  1.3  christos       }
    304  1.2  christos 
    305  1.2  christos     if (strncasecmp (str, "hi(", 3) == 0)
    306  1.2  christos       {
    307  1.2  christos 	str += 3;
    308  1.2  christos 	typ = RTYPE_HI;
    309  1.2  christos       }
    310  1.2  christos     else if (strncasecmp (str, "lo(", 3) == 0)
    311  1.2  christos       {
    312  1.2  christos 	str += 3;
    313  1.2  christos 	typ = RTYPE_LO;
    314  1.2  christos       }
    315  1.2  christos     else if (strncasecmp (str, "ha(", 3) == 0)
    316  1.2  christos       {
    317  1.2  christos 	str += 3;
    318  1.2  christos 	typ = RTYPE_AHI;
    319  1.2  christos       }
    320  1.2  christos     else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
    321  1.2  christos       {
    322  1.2  christos 	str += 3;
    323  1.2  christos 	typ = RTYPE_PO;
    324  1.2  christos       }
    325  1.2  christos     else
    326  1.2  christos       return -1;
    327  1.1      matt 
    328  1.2  christos     *strp = str;
    329  1.2  christos     return (cls << RCLASS_SHIFT) | typ;
    330  1.2  christos }
    331  1.1      matt 
    332  1.2  christos static const char *
    333  1.2  christos parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
    334  1.2  christos 	     long *valuep, int splitp)
    335  1.2  christos {
    336  1.2  christos   const char *errmsg;
    337  1.2  christos   enum cgen_parse_operand_result result_type;
    338  1.2  christos   bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
    339  1.2  christos   enum or1k_rtype reloc_type;
    340  1.2  christos   int reloc_code;
    341  1.2  christos   bfd_vma ret;
    342  1.1      matt 
    343  1.2  christos   if (**strp == '#')
    344  1.2  christos     ++*strp;
    345  1.1      matt 
    346  1.2  christos   reloc_code = parse_reloc (strp);
    347  1.2  christos   reloc_type = reloc_code & RTYPE_MASK;
    348  1.2  christos   if (reloc_code >= 0)
    349  1.1      matt     {
    350  1.2  christos       enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
    351  1.2  christos       if (splitp)
    352  1.2  christos 	{
    353  1.2  christos 	  if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
    354  1.2  christos 	      && reloc_class != RCLASS_GOT)
    355  1.2  christos 	    /* If split we or up the type to RTYPE_SLO or RTYPE_SPO.  */
    356  1.2  christos 	    reloc_type |= 1;
    357  1.2  christos 	  else
    358  1.2  christos 	    return INVALID_STORE_RELOC;
    359  1.2  christos 	}
    360  1.2  christos       reloc = or1k_imm16_relocs[reloc_class][reloc_type];
    361  1.1      matt     }
    362  1.1      matt 
    363  1.2  christos   if (reloc != BFD_RELOC_UNUSED)
    364  1.1      matt     {
    365  1.1      matt       bfd_vma value;
    366  1.1      matt 
    367  1.2  christos       errmsg = cgen_parse_address (cd, strp, opindex, reloc,
    368  1.1      matt 				   &result_type, &value);
    369  1.1      matt       if (**strp != ')')
    370  1.2  christos 	errmsg = MISSING_CLOSING_PARENTHESIS;
    371  1.1      matt       ++*strp;
    372  1.1      matt 
    373  1.2  christos       ret = value;
    374  1.1      matt 
    375  1.2  christos       if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    376  1.2  christos 	switch (reloc_type)
    377  1.2  christos 	  {
    378  1.2  christos 	  case RTYPE_AHI:
    379  1.2  christos 	    ret += 0x8000;
    380  1.2  christos 	    /* FALLTHRU */
    381  1.2  christos 	  case RTYPE_HI:
    382  1.2  christos 	    ret >>= 16;
    383  1.2  christos 	    /* FALLTHRU */
    384  1.2  christos 	  case RTYPE_LO:
    385  1.2  christos 	  case RTYPE_SLO:
    386  1.2  christos 	    ret &= 0xffff;
    387  1.2  christos 	    ret = (ret ^ 0x8000) - 0x8000;
    388  1.2  christos 	    break;
    389  1.2  christos 	  case RTYPE_PO:
    390  1.2  christos 	  case RTYPE_SPO:
    391  1.2  christos 	    ret &= 0x1fff;
    392  1.2  christos 	    break;
    393  1.2  christos 	  default:
    394  1.2  christos 	    errmsg = INVALID_RELOC_TYPE;
    395  1.2  christos 	  }
    396  1.1      matt     }
    397  1.1      matt   else
    398  1.1      matt     {
    399  1.1      matt       long value;
    400  1.1      matt       errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
    401  1.1      matt       ret = value;
    402  1.1      matt     }
    403  1.1      matt 
    404  1.1      matt   if (errmsg == NULL)
    405  1.1      matt     *valuep = ret;
    406  1.1      matt 
    407  1.1      matt   return errmsg;
    408  1.1      matt }
    409  1.1      matt 
    410  1.1      matt static const char *
    411  1.2  christos parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
    412  1.1      matt {
    413  1.2  christos   return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
    414  1.2  christos }
    415  1.2  christos 
    416  1.2  christos static const char *
    417  1.2  christos parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
    418  1.2  christos 		    long *valuep)
    419  1.2  christos {
    420  1.2  christos   return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
    421  1.2  christos }
    422  1.1      matt 
    423  1.2  christos static const char *
    424  1.2  christos parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
    425  1.2  christos 	      unsigned long *valuep)
    426  1.2  christos {
    427  1.2  christos   const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
    428  1.1      matt   if (errmsg == NULL)
    429  1.1      matt     *valuep &= 0xffff;
    430  1.1      matt   return errmsg;
    431  1.1      matt }
    432  1.1      matt 
    433  1.2  christos static const char *
    434  1.2  christos parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
    435  1.2  christos 		    unsigned long *valuep)
    436  1.2  christos {
    437  1.2  christos   const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
    438  1.2  christos   if (errmsg == NULL)
    439  1.2  christos     *valuep &= 0xffff;
    440  1.2  christos   return errmsg;
    441  1.2  christos }
    442  1.2  christos 
    443  1.2  christos /* Parse register pairs with syntax rA,rB to a flag + rA value.  */
    444  1.2  christos 
    445  1.2  christos static const char *
    446  1.2  christos parse_regpair (CGEN_CPU_DESC cd, const char **strp,
    447  1.2  christos 	       int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
    448  1.2  christos {
    449  1.2  christos   long reg1_index;
    450  1.2  christos   long reg2_index;
    451  1.2  christos   const char *errmsg;
    452  1.2  christos 
    453  1.2  christos   /* The first part should just be a register.  */
    454  1.2  christos   errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
    455  1.2  christos 			       &reg1_index);
    456  1.2  christos 
    457  1.2  christos   /* If that worked skip the comma separator.  */
    458  1.2  christos   if (errmsg == NULL)
    459  1.2  christos     {
    460  1.2  christos       if (**strp == ',')
    461  1.2  christos 	++*strp;
    462  1.2  christos       else
    463  1.2  christos 	errmsg = "Unexpected character, expected ','";
    464  1.2  christos     }
    465  1.2  christos 
    466  1.2  christos   /* If that worked the next part is just another register.  */
    467  1.2  christos   if (errmsg == NULL)
    468  1.2  christos     errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
    469  1.2  christos 				 &reg2_index);
    470  1.2  christos 
    471  1.2  christos   /* Validate the register pair is valid and create the output value.  */
    472  1.2  christos   if (errmsg == NULL)
    473  1.2  christos     {
    474  1.2  christos       int regoffset = reg2_index - reg1_index;
    475  1.2  christos 
    476  1.2  christos       if (regoffset == 1 || regoffset == 2)
    477  1.2  christos 	{
    478  1.2  christos 	  unsigned short offsetmask;
    479  1.2  christos 	  unsigned short value;
    480  1.2  christos 
    481  1.2  christos 	  offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
    482  1.2  christos 	  value = offsetmask | reg1_index;
    483  1.2  christos 
    484  1.2  christos 	  *valuep = value;
    485  1.2  christos 	}
    486  1.2  christos       else
    487  1.2  christos 	errmsg = "Invalid register pair, offset not 1 or 2.";
    488  1.2  christos     }
    489  1.2  christos 
    490  1.2  christos   return errmsg;
    491  1.2  christos }
    492  1.2  christos 
    493  1.2  christos /* -- */
    494  1.2  christos 
    495  1.2  christos /* -- dis.c */
    496  1.2  christos 
    497  1.2  christos static void
    498  1.2  christos print_regpair (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    499  1.2  christos 	       void * dis_info,
    500  1.2  christos 	       long value,
    501  1.2  christos 	       unsigned int attrs ATTRIBUTE_UNUSED,
    502  1.2  christos 	       bfd_vma pc ATTRIBUTE_UNUSED,
    503  1.2  christos 	       int length ATTRIBUTE_UNUSED)
    504  1.2  christos {
    505  1.2  christos   disassemble_info *info = dis_info;
    506  1.2  christos   char reg1_index;
    507  1.2  christos   char reg2_index;
    508  1.2  christos 
    509  1.2  christos   reg1_index = value & 0x1f;
    510  1.2  christos   reg2_index = reg1_index + ((value & (1 << 5)) ? 2 : 1);
    511  1.2  christos 
    512  1.2  christos   (*info->fprintf_func) (info->stream, "r%d,r%d", reg1_index, reg2_index);
    513  1.2  christos }
    514  1.2  christos 
    515  1.1      matt /* -- */
    516  1.1      matt 
    517  1.1      matt /* -- ibd.h */
    518  1.1      matt 
    519  1.1      matt /* -- */
    520