Home | History | Annotate | Download | only in cpu
      1 /* OpenRISC 1000 opcode support.  -*- C -*-
      2    Copyright 2000-2014 Free Software Foundation, Inc.
      3 
      4    Originally ontributed for OR32 by Red Hat Inc;
      5 
      6    This file is part of the GNU Binutils.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, see <http://www.gnu.org/licenses/>. */
     20 
     21 /* This file is an addendum to or1k.cpu.  Heavy use of C code isn't
     22    appropriate in .cpu files, so it resides here.  This especially applies
     23    to assembly/disassembly where parsing/printing can be quite involved.
     24    Such things aren't really part of the specification of the cpu, per se,
     25    so .cpu files provide the general framework and .opc files handle the
     26    nitty-gritty details as necessary.
     27 
     28    Each section is delimited with start and end markers.
     29 
     30    <arch>-opc.h additions use: "-- opc.h"
     31    <arch>-opc.c additions use: "-- opc.c"
     32    <arch>-asm.c additions use: "-- asm.c"
     33    <arch>-dis.c additions use: "-- dis.c"
     34    <arch>-ibd.h additions use: "-- ibd.h"  */
     35 
     36 /* -- opc.h */
     37 
     38 #undef  CGEN_DIS_HASH_SIZE
     39 #define CGEN_DIS_HASH_SIZE 256
     40 #undef  CGEN_DIS_HASH
     41 #define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 2)
     42 
     43 /* -- */
     44 
     45 /* -- opc.c */
     46 /* -- */
     47 
     48 /* -- asm.c */
     49 
     50 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
     51 
     52 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
     53 
     54 static const char *
     55 parse_disp26 (CGEN_CPU_DESC cd,
     56 	      const char ** strp,
     57 	      int opindex,
     58 	      int opinfo,
     59 	      enum cgen_parse_operand_result * resultp,
     60 	      bfd_vma * valuep)
     61 {
     62   const char *errmsg = NULL;
     63   enum cgen_parse_operand_result result_type;
     64 
     65   if (strncasecmp (*strp, "plt(", 4) == 0)
     66     {
     67       bfd_vma value;
     68 
     69       *strp += 4;
     70       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26,
     71 				   & result_type, & value);
     72       if (**strp != ')')
     73 	return MISSING_CLOSING_PARENTHESIS;
     74       ++*strp;
     75       if (errmsg == NULL
     76 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
     77 	value = (value >> 2) & 0xffff;
     78       *valuep = value;
     79       return errmsg;
     80     }
     81   return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
     82 }
     83 
     84 static const char *
     85 parse_simm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, long * valuep)
     86 {
     87   const char *errmsg;
     88   enum cgen_parse_operand_result result_type;
     89   long ret;
     90 
     91   if (**strp == '#')
     92     ++*strp;
     93 
     94   if (strncasecmp (*strp, "hi(", 3) == 0)
     95     {
     96       bfd_vma value;
     97 
     98       *strp += 3;
     99       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
    100 				   & result_type, & value);
    101       if (**strp != ')')
    102 	errmsg = MISSING_CLOSING_PARENTHESIS;
    103       ++*strp;
    104 
    105       ret = value;
    106 
    107       if (errmsg == NULL
    108 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    109 	{
    110 	  ret >>= 16;
    111 	  ret &= 0xffff;
    112 	  ret = (ret ^ 0x8000) - 0x8000;
    113 	}
    114     }
    115   else if (strncasecmp (*strp, "lo(", 3) == 0)
    116     {
    117       bfd_vma value;
    118 
    119       *strp += 3;
    120       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
    121 				   & result_type, & value);
    122       if (**strp != ')')
    123 	return MISSING_CLOSING_PARENTHESIS;
    124       ++*strp;
    125 
    126       ret = value;
    127 
    128       if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    129 	{
    130 	  ret &= 0xffff;
    131 	  ret = (ret ^ 0x8000) - 0x8000;
    132 	}
    133     }
    134   else if (strncasecmp (*strp, "got(", 4) == 0)
    135     {
    136       bfd_vma value;
    137 
    138       *strp += 4;
    139       errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_GOT16,
    140 				   & result_type, & value);
    141       if (**strp != ')')
    142 	return MISSING_CLOSING_PARENTHESIS;
    143       ++*strp;
    144       if (errmsg == NULL
    145 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    146 	value &= 0xffff;
    147       *valuep = value;
    148       return errmsg;
    149     }
    150   else if (strncasecmp (*strp, "gotpchi(", 8) == 0)
    151     {
    152       bfd_vma value;
    153 
    154       *strp += 8;
    155       errmsg = cgen_parse_address (cd, strp, opindex,
    156 				   BFD_RELOC_OR1K_GOTPC_HI16,
    157 				   & result_type, & value);
    158       if (**strp != ')')
    159 	return MISSING_CLOSING_PARENTHESIS;
    160       ++*strp;
    161       if (errmsg == NULL
    162 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    163 	value = (value >> 16) & 0xffff;
    164       *valuep = value;
    165       return errmsg;
    166     }
    167   else if (strncasecmp (*strp, "gotpclo(", 8) == 0)
    168     {
    169       bfd_vma value;
    170 
    171       *strp += 8;
    172       errmsg = cgen_parse_address (cd, strp, opindex,
    173 				   BFD_RELOC_OR1K_GOTPC_LO16,
    174 				   &result_type, &value);
    175       if (**strp != ')')
    176 	return MISSING_CLOSING_PARENTHESIS;
    177       ++*strp;
    178       if (errmsg == NULL
    179 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    180 	value &= 0xffff;
    181       *valuep = value;
    182       return errmsg;
    183     }
    184   else if (strncasecmp (*strp, "gotoffhi(", 9) == 0)
    185     {
    186       bfd_vma value;
    187 
    188       *strp += 9;
    189       errmsg = cgen_parse_address (cd, strp, opindex,
    190 				   BFD_RELOC_OR1K_GOTOFF_HI16,
    191 				   & result_type, & value);
    192 
    193       if (**strp != ')')
    194 	return MISSING_CLOSING_PARENTHESIS;
    195       ++*strp;
    196       if (errmsg == NULL
    197 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    198 	value = (value >> 16) & 0xffff;
    199       *valuep = value;
    200       return errmsg;
    201     }
    202   else if (strncasecmp (*strp, "gotofflo(", 9) == 0)
    203     {
    204       bfd_vma value;
    205 
    206       *strp += 9;
    207       errmsg = cgen_parse_address (cd, strp, opindex,
    208 				   BFD_RELOC_OR1K_GOTOFF_LO16,
    209 				   &result_type, &value);
    210       if (**strp != ')')
    211 	return MISSING_CLOSING_PARENTHESIS;
    212       ++*strp;
    213       if (errmsg == NULL
    214 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    215 	value &= 0xffff;
    216       *valuep = value;
    217       return errmsg;
    218     }
    219   else if (strncasecmp (*strp, "tlsgdhi(", 8) == 0)
    220     {
    221       bfd_vma value;
    222 
    223       *strp += 8;
    224       errmsg = cgen_parse_address (cd, strp, opindex,
    225 				   BFD_RELOC_OR1K_TLS_GD_HI16,
    226 				   & result_type, & value);
    227 
    228       if (**strp != ')')
    229 	return MISSING_CLOSING_PARENTHESIS;
    230       ++*strp;
    231       if (errmsg == NULL
    232 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    233 	value = (value >> 16) & 0xffff;
    234       *valuep = value;
    235       return errmsg;
    236     }
    237   else if (strncasecmp (*strp, "tlsgdlo(", 8) == 0)
    238     {
    239       bfd_vma value;
    240 
    241       *strp += 8;
    242       errmsg = cgen_parse_address (cd, strp, opindex,
    243 				   BFD_RELOC_OR1K_TLS_GD_LO16,
    244 				   &result_type, &value);
    245       if (**strp != ')')
    246 	return MISSING_CLOSING_PARENTHESIS;
    247       ++*strp;
    248       if (errmsg == NULL
    249 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    250 	value &= 0xffff;
    251       *valuep = value;
    252       return errmsg;
    253     }
    254   else if (strncasecmp (*strp, "tlsldmhi(", 9) == 0)
    255     {
    256       bfd_vma value;
    257 
    258       *strp += 9;
    259       errmsg = cgen_parse_address (cd, strp, opindex,
    260 				   BFD_RELOC_OR1K_TLS_LDM_HI16,
    261 				   & result_type, & value);
    262 
    263       if (**strp != ')')
    264 	return MISSING_CLOSING_PARENTHESIS;
    265       ++*strp;
    266       if (errmsg == NULL
    267 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    268 	value = (value >> 16) & 0xffff;
    269       *valuep = value;
    270       return errmsg;
    271     }
    272   else if (strncasecmp (*strp, "tlsldmlo(", 9) == 0)
    273     {
    274       bfd_vma value;
    275 
    276       *strp += 9;
    277       errmsg = cgen_parse_address (cd, strp, opindex,
    278 				   BFD_RELOC_OR1K_TLS_LDM_LO16,
    279 				   &result_type, &value);
    280       if (**strp != ')')
    281 	return MISSING_CLOSING_PARENTHESIS;
    282       ++*strp;
    283       if (errmsg == NULL
    284 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    285 	value &= 0xffff;
    286       *valuep = value;
    287       return errmsg;
    288     }
    289   else if (strncasecmp (*strp, "dtpoffhi(", 9) == 0)
    290     {
    291       bfd_vma value;
    292 
    293       *strp += 9;
    294       errmsg = cgen_parse_address (cd, strp, opindex,
    295 				   BFD_RELOC_OR1K_TLS_LDO_HI16,
    296 				   & result_type, & value);
    297 
    298       if (**strp != ')')
    299 	return MISSING_CLOSING_PARENTHESIS;
    300       ++*strp;
    301       if (errmsg == NULL
    302 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    303 	value = (value >> 16) & 0xffff;
    304       *valuep = value;
    305       return errmsg;
    306     }
    307   else if (strncasecmp (*strp, "dtpofflo(", 9) == 0)
    308     {
    309       bfd_vma value;
    310 
    311       *strp += 9;
    312       errmsg = cgen_parse_address (cd, strp, opindex,
    313 				   BFD_RELOC_OR1K_TLS_LDO_LO16,
    314 				   &result_type, &value);
    315       if (**strp != ')')
    316 	return MISSING_CLOSING_PARENTHESIS;
    317       ++*strp;
    318       if (errmsg == NULL
    319 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    320 	value &= 0xffff;
    321       *valuep = value;
    322       return errmsg;
    323     }
    324   else if (strncasecmp (*strp, "gottpoffhi(", 11) == 0)
    325     {
    326       bfd_vma value;
    327 
    328       *strp += 11;
    329       errmsg = cgen_parse_address (cd, strp, opindex,
    330 				   BFD_RELOC_OR1K_TLS_IE_HI16,
    331 				   & result_type, & value);
    332 
    333       if (**strp != ')')
    334 	return MISSING_CLOSING_PARENTHESIS;
    335       ++*strp;
    336       if (errmsg == NULL
    337 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    338 	value = (value >> 16) & 0xffff;
    339       *valuep = value;
    340       return errmsg;
    341     }
    342   else if (strncasecmp (*strp, "gottpofflo(", 11) == 0)
    343     {
    344       bfd_vma value;
    345 
    346       *strp += 11;
    347       errmsg = cgen_parse_address (cd, strp, opindex,
    348 				   BFD_RELOC_OR1K_TLS_IE_LO16,
    349 				   &result_type, &value);
    350       if (**strp != ')')
    351 	return MISSING_CLOSING_PARENTHESIS;
    352       ++*strp;
    353       if (errmsg == NULL
    354 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    355 	value &= 0xffff;
    356       *valuep = value;
    357       return errmsg;
    358     }
    359   else if (strncasecmp (*strp, "tpoffhi(", 8) == 0)
    360     {
    361       bfd_vma value;
    362 
    363       *strp += 8;
    364       errmsg = cgen_parse_address (cd, strp, opindex,
    365 				   BFD_RELOC_OR1K_TLS_LE_HI16,
    366 				   & result_type, & value);
    367 
    368       if (**strp != ')')
    369 	return MISSING_CLOSING_PARENTHESIS;
    370       ++*strp;
    371       if (errmsg == NULL
    372 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    373 	value = (value >> 16) & 0xffff;
    374       *valuep = value;
    375       return errmsg;
    376     }
    377   else if (strncasecmp (*strp, "tpofflo(", 8) == 0)
    378     {
    379       bfd_vma value;
    380 
    381       *strp += 8;
    382       errmsg = cgen_parse_address (cd, strp, opindex,
    383 				   BFD_RELOC_OR1K_TLS_LE_LO16,
    384 				   &result_type, &value);
    385       if (**strp != ')')
    386 	return MISSING_CLOSING_PARENTHESIS;
    387       ++*strp;
    388       if (errmsg == NULL
    389 	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    390 	value &= 0xffff;
    391       *valuep = value;
    392       return errmsg;
    393     }
    394   else
    395     {
    396       long value;
    397       errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
    398       ret = value;
    399     }
    400 
    401   if (errmsg == NULL)
    402     *valuep = ret;
    403 
    404   return errmsg;
    405 }
    406 
    407 static const char *
    408 parse_uimm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, unsigned long * valuep)
    409 {
    410   const char *errmsg = parse_simm16(cd, strp, opindex, (long *) valuep);
    411 
    412   if (errmsg == NULL)
    413     *valuep &= 0xffff;
    414   return errmsg;
    415 }
    416 
    417 /* -- */
    418 
    419 /* -- ibd.h */
    420 
    421 /* -- */
    422