Home | History | Annotate | Line # | Download | only in opcodes
or1k-asm.c revision 1.1.1.5
      1 /* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
      2 /* Assembler interface for targets using CGEN. -*- C -*-
      3    CGEN: Cpu tools GENerator
      4 
      5    THIS FILE IS MACHINE GENERATED WITH CGEN.
      6    - the resultant file is machine generated, cgen-asm.in isn't
      7 
      8    Copyright (C) 1996-2020 Free Software Foundation, Inc.
      9 
     10    This file is part of libopcodes.
     11 
     12    This library is free software; you can redistribute it and/or modify
     13    it under the terms of the GNU General Public License as published by
     14    the Free Software Foundation; either version 3, or (at your option)
     15    any later version.
     16 
     17    It is distributed in the hope that it will be useful, but WITHOUT
     18    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     19    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     20    License for more details.
     21 
     22    You should have received a copy of the GNU General Public License
     23    along with this program; if not, write to the Free Software Foundation, Inc.,
     24    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
     25 
     26 
     27 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
     28    Keep that in mind.  */
     29 
     30 #include "sysdep.h"
     31 #include <stdio.h>
     32 #include "ansidecl.h"
     33 #include "bfd.h"
     34 #include "symcat.h"
     35 #include "or1k-desc.h"
     36 #include "or1k-opc.h"
     37 #include "opintl.h"
     38 #include "xregex.h"
     39 #include "libiberty.h"
     40 #include "safe-ctype.h"
     41 
     42 #undef  min
     43 #define min(a,b) ((a) < (b) ? (a) : (b))
     44 #undef  max
     45 #define max(a,b) ((a) > (b) ? (a) : (b))
     46 
     47 static const char * parse_insn_normal
     48   (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
     49 
     50 /* -- assembler routines inserted here.  */
     52 
     53 /* -- asm.c */
     54 
     55 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
     56 static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
     57 static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
     58 
     59 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
     60 
     61 static const char *
     62 parse_disp26 (CGEN_CPU_DESC cd,
     63 	      const char ** strp,
     64 	      int opindex,
     65 	      int opinfo ATTRIBUTE_UNUSED,
     66 	      enum cgen_parse_operand_result * resultp,
     67 	      bfd_vma * valuep)
     68 {
     69   const char *str = *strp;
     70   const char *errmsg = NULL;
     71   bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
     72 
     73   if (strncasecmp (str, "plta(", 5) == 0)
     74     {
     75       *strp = str + 5;
     76       reloc = BFD_RELOC_OR1K_PLTA26;
     77     }
     78   else if (strncasecmp (str, "plt(", 4) == 0)
     79     {
     80       *strp = str + 4;
     81       reloc = BFD_RELOC_OR1K_PLT26;
     82     }
     83 
     84   errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
     85 
     86   if (reloc != BFD_RELOC_OR1K_REL_26)
     87     {
     88       if (**strp != ')')
     89 	errmsg = MISSING_CLOSING_PARENTHESIS;
     90       else
     91 	++*strp;
     92     }
     93 
     94   return errmsg;
     95 }
     96 
     97 static const char *
     98 parse_disp21 (CGEN_CPU_DESC cd,
     99 	      const char ** strp,
    100 	      int opindex,
    101 	      int opinfo ATTRIBUTE_UNUSED,
    102 	      enum cgen_parse_operand_result * resultp,
    103 	      bfd_vma * valuep)
    104 {
    105   const char *str = *strp;
    106   const char *errmsg = NULL;
    107   bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
    108 
    109   if (strncasecmp (str, "got(", 4) == 0)
    110     {
    111       *strp = str + 4;
    112       reloc = BFD_RELOC_OR1K_GOT_PG21;
    113     }
    114   else if (strncasecmp (str, "tlsgd(", 6) == 0)
    115     {
    116       *strp = str + 6;
    117       reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
    118     }
    119   else if (strncasecmp (str, "tlsldm(", 7) == 0)
    120     {
    121       *strp = str + 7;
    122       reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
    123     }
    124   else if (strncasecmp (str, "gottp(", 6) == 0)
    125     {
    126       *strp = str + 6;
    127       reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
    128     }
    129 
    130   errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
    131 
    132   if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
    133     {
    134       if (**strp != ')')
    135 	errmsg = MISSING_CLOSING_PARENTHESIS;
    136       else
    137 	++*strp;
    138     }
    139 
    140   return errmsg;
    141 }
    142 
    143 enum or1k_rclass
    144 {
    145   RCLASS_DIRECT   = 0,
    146   RCLASS_GOT      = 1,
    147   RCLASS_GOTPC    = 2,
    148   RCLASS_GOTOFF   = 3,
    149   RCLASS_TLSGD    = 4,
    150   RCLASS_TLSLDM   = 5,
    151   RCLASS_DTPOFF   = 6,
    152   RCLASS_GOTTPOFF = 7,
    153   RCLASS_TPOFF    = 8,
    154 };
    155 
    156 enum or1k_rtype
    157 {
    158   RTYPE_LO = 0,
    159   RTYPE_SLO = 1,
    160   RTYPE_PO = 2,
    161   RTYPE_SPO = 3,
    162   RTYPE_HI = 4,
    163   RTYPE_AHI = 5,
    164 };
    165 
    166 #define RCLASS_SHIFT 3
    167 #define RTYPE_MASK   7
    168 
    169 static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
    170   { BFD_RELOC_LO16,
    171     BFD_RELOC_OR1K_SLO16,
    172     BFD_RELOC_OR1K_LO13,
    173     BFD_RELOC_OR1K_SLO13,
    174     BFD_RELOC_HI16,
    175     BFD_RELOC_HI16_S, },
    176   { BFD_RELOC_OR1K_GOT16,
    177     BFD_RELOC_UNUSED,
    178     BFD_RELOC_OR1K_GOT_LO13,
    179     BFD_RELOC_UNUSED,
    180     BFD_RELOC_UNUSED,
    181     BFD_RELOC_UNUSED },
    182   { BFD_RELOC_OR1K_GOTPC_LO16,
    183     BFD_RELOC_UNUSED,
    184     BFD_RELOC_UNUSED,
    185     BFD_RELOC_UNUSED,
    186     BFD_RELOC_OR1K_GOTPC_HI16,
    187     BFD_RELOC_UNUSED },
    188   { BFD_RELOC_LO16_GOTOFF,
    189     BFD_RELOC_OR1K_GOTOFF_SLO16,
    190     BFD_RELOC_UNUSED,
    191     BFD_RELOC_UNUSED,
    192     BFD_RELOC_HI16_GOTOFF,
    193     BFD_RELOC_HI16_S_GOTOFF },
    194   { BFD_RELOC_OR1K_TLS_GD_LO16,
    195     BFD_RELOC_UNUSED,
    196     BFD_RELOC_OR1K_TLS_GD_LO13,
    197     BFD_RELOC_UNUSED,
    198     BFD_RELOC_OR1K_TLS_GD_HI16,
    199     BFD_RELOC_UNUSED },
    200   { BFD_RELOC_OR1K_TLS_LDM_LO16,
    201     BFD_RELOC_UNUSED,
    202     BFD_RELOC_OR1K_TLS_LDM_LO13,
    203     BFD_RELOC_UNUSED,
    204     BFD_RELOC_OR1K_TLS_LDM_HI16,
    205     BFD_RELOC_UNUSED },
    206   { BFD_RELOC_OR1K_TLS_LDO_LO16,
    207     BFD_RELOC_UNUSED,
    208     BFD_RELOC_UNUSED,
    209     BFD_RELOC_UNUSED,
    210     BFD_RELOC_OR1K_TLS_LDO_HI16,
    211     BFD_RELOC_UNUSED },
    212   { BFD_RELOC_OR1K_TLS_IE_LO16,
    213     BFD_RELOC_UNUSED,
    214     BFD_RELOC_OR1K_TLS_IE_LO13,
    215     BFD_RELOC_UNUSED,
    216     BFD_RELOC_OR1K_TLS_IE_HI16,
    217     BFD_RELOC_OR1K_TLS_IE_AHI16 },
    218   { BFD_RELOC_OR1K_TLS_LE_LO16,
    219     BFD_RELOC_OR1K_TLS_LE_SLO16,
    220     BFD_RELOC_UNUSED,
    221     BFD_RELOC_UNUSED,
    222     BFD_RELOC_OR1K_TLS_LE_HI16,
    223     BFD_RELOC_OR1K_TLS_LE_AHI16 },
    224 };
    225 
    226 static int
    227 parse_reloc (const char **strp)
    228 {
    229     const char *str = *strp;
    230     enum or1k_rclass cls = RCLASS_DIRECT;
    231     enum or1k_rtype typ;
    232 
    233     if (strncasecmp (str, "got(", 4) == 0)
    234       {
    235 	*strp = str + 4;
    236 	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
    237       }
    238     if (strncasecmp (str, "gotpo(", 6) == 0)
    239       {
    240 	*strp = str + 6;
    241 	return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
    242       }
    243     if (strncasecmp (str, "gottppo(", 8) == 0)
    244       {
    245 	*strp = str + 8;
    246 	return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
    247       }
    248 
    249     if (strncasecmp (str, "gotpc", 5) == 0)
    250       {
    251 	str += 5;
    252 	cls = RCLASS_GOTPC;
    253       }
    254     else if (strncasecmp (str, "gotoff", 6) == 0)
    255       {
    256 	str += 6;
    257 	cls = RCLASS_GOTOFF;
    258       }
    259     else if (strncasecmp (str, "tlsgd", 5) == 0)
    260       {
    261 	str += 5;
    262 	cls = RCLASS_TLSGD;
    263       }
    264     else if (strncasecmp (str, "tlsldm", 6) == 0)
    265       {
    266 	str += 6;
    267 	cls = RCLASS_TLSLDM;
    268       }
    269     else if (strncasecmp (str, "dtpoff", 6) == 0)
    270       {
    271 	str += 6;
    272 	cls = RCLASS_DTPOFF;
    273       }
    274     else if (strncasecmp (str, "gottpoff", 8) == 0)
    275       {
    276 	str += 8;
    277 	cls = RCLASS_GOTTPOFF;
    278       }
    279     else if (strncasecmp (str, "tpoff", 5) == 0)
    280       {
    281 	str += 5;
    282 	cls = RCLASS_TPOFF;
    283       }
    284 
    285     if (strncasecmp (str, "hi(", 3) == 0)
    286       {
    287 	str += 3;
    288 	typ = RTYPE_HI;
    289       }
    290     else if (strncasecmp (str, "lo(", 3) == 0)
    291       {
    292 	str += 3;
    293 	typ = RTYPE_LO;
    294       }
    295     else if (strncasecmp (str, "ha(", 3) == 0)
    296       {
    297 	str += 3;
    298 	typ = RTYPE_AHI;
    299       }
    300     else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
    301       {
    302 	str += 3;
    303 	typ = RTYPE_PO;
    304       }
    305     else
    306       return -1;
    307 
    308     *strp = str;
    309     return (cls << RCLASS_SHIFT) | typ;
    310 }
    311 
    312 static const char *
    313 parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
    314 	     long *valuep, int splitp)
    315 {
    316   const char *errmsg;
    317   enum cgen_parse_operand_result result_type;
    318   bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
    319   enum or1k_rtype reloc_type;
    320   int reloc_code;
    321   bfd_vma ret;
    322 
    323   if (**strp == '#')
    324     ++*strp;
    325 
    326   reloc_code = parse_reloc (strp);
    327   reloc_type = reloc_code & RTYPE_MASK;
    328   if (reloc_code >= 0)
    329     {
    330       enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
    331       if (splitp)
    332 	{
    333 	  if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
    334 	      && reloc_class != RCLASS_GOT)
    335 	    /* If split we or up the type to RTYPE_SLO or RTYPE_SPO.  */
    336 	    reloc_type |= 1;
    337 	  else
    338 	    return INVALID_STORE_RELOC;
    339 	}
    340       reloc = or1k_imm16_relocs[reloc_class][reloc_type];
    341     }
    342 
    343   if (reloc != BFD_RELOC_UNUSED)
    344     {
    345       bfd_vma value;
    346 
    347       errmsg = cgen_parse_address (cd, strp, opindex, reloc,
    348 				   &result_type, &value);
    349       if (**strp != ')')
    350 	errmsg = MISSING_CLOSING_PARENTHESIS;
    351       ++*strp;
    352 
    353       ret = value;
    354 
    355       if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    356 	switch (reloc_type)
    357 	  {
    358 	  case RTYPE_AHI:
    359 	    ret += 0x8000;
    360 	    /* FALLTHRU */
    361 	  case RTYPE_HI:
    362 	    ret >>= 16;
    363 	    /* FALLTHRU */
    364 	  case RTYPE_LO:
    365 	  case RTYPE_SLO:
    366 	    ret &= 0xffff;
    367 	    ret = (ret ^ 0x8000) - 0x8000;
    368 	    break;
    369 	  case RTYPE_PO:
    370 	  case RTYPE_SPO:
    371 	    ret &= 0x1fff;
    372 	    break;
    373 	  default:
    374 	    errmsg = INVALID_RELOC_TYPE;
    375 	  }
    376     }
    377   else
    378     {
    379       long value;
    380       errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
    381       ret = value;
    382     }
    383 
    384   if (errmsg == NULL)
    385     *valuep = ret;
    386 
    387   return errmsg;
    388 }
    389 
    390 static const char *
    391 parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
    392 {
    393   return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
    394 }
    395 
    396 static const char *
    397 parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
    398 		    long *valuep)
    399 {
    400   return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
    401 }
    402 
    403 static const char *
    404 parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
    405 	      unsigned long *valuep)
    406 {
    407   const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
    408   if (errmsg == NULL)
    409     *valuep &= 0xffff;
    410   return errmsg;
    411 }
    412 
    413 static const char *
    414 parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
    415 		    unsigned long *valuep)
    416 {
    417   const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
    418   if (errmsg == NULL)
    419     *valuep &= 0xffff;
    420   return errmsg;
    421 }
    422 
    423 /* Parse register pairs with syntax rA,rB to a flag + rA value.  */
    424 
    425 static const char *
    426 parse_regpair (CGEN_CPU_DESC cd, const char **strp,
    427 	       int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
    428 {
    429   long reg1_index;
    430   long reg2_index;
    431   const char *errmsg;
    432 
    433   /* The first part should just be a register.  */
    434   errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
    435 			       &reg1_index);
    436 
    437   /* If that worked skip the comma separator.  */
    438   if (errmsg == NULL)
    439     {
    440       if (**strp == ',')
    441 	++*strp;
    442       else
    443 	errmsg = "Unexpected character, expected ','";
    444     }
    445 
    446   /* If that worked the next part is just another register.  */
    447   if (errmsg == NULL)
    448     errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
    449 				 &reg2_index);
    450 
    451   /* Validate the register pair is valid and create the output value.  */
    452   if (errmsg == NULL)
    453     {
    454       int regoffset = reg2_index - reg1_index;
    455 
    456       if (regoffset == 1 || regoffset == 2)
    457 	{
    458 	  unsigned short offsetmask;
    459 	  unsigned short value;
    460 
    461 	  offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
    462 	  value = offsetmask | reg1_index;
    463 
    464 	  *valuep = value;
    465 	}
    466       else
    467 	errmsg = "Invalid register pair, offset not 1 or 2.";
    468     }
    469 
    470   return errmsg;
    471 }
    472 
    473 /* -- */
    474 
    475 const char * or1k_cgen_parse_operand
    476   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
    477 
    478 /* Main entry point for operand parsing.
    479 
    480    This function is basically just a big switch statement.  Earlier versions
    481    used tables to look up the function to use, but
    482    - if the table contains both assembler and disassembler functions then
    483      the disassembler contains much of the assembler and vice-versa,
    484    - there's a lot of inlining possibilities as things grow,
    485    - using a switch statement avoids the function call overhead.
    486 
    487    This function could be moved into `parse_insn_normal', but keeping it
    488    separate makes clear the interface between `parse_insn_normal' and each of
    489    the handlers.  */
    490 
    491 const char *
    492 or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
    493 			   int opindex,
    494 			   const char ** strp,
    495 			   CGEN_FIELDS * fields)
    496 {
    497   const char * errmsg = NULL;
    498   /* Used by scalar operands that still need to be parsed.  */
    499   long junk ATTRIBUTE_UNUSED;
    500 
    501   switch (opindex)
    502     {
    503     case OR1K_OPERAND_DISP21 :
    504       {
    505         bfd_vma value = 0;
    506         errmsg = parse_disp21 (cd, strp, OR1K_OPERAND_DISP21, 0, NULL,  & value);
    507         fields->f_disp21 = value;
    508       }
    509       break;
    510     case OR1K_OPERAND_DISP26 :
    511       {
    512         bfd_vma value = 0;
    513         errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL,  & value);
    514         fields->f_disp26 = value;
    515       }
    516       break;
    517     case OR1K_OPERAND_RA :
    518       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
    519       break;
    520     case OR1K_OPERAND_RAD32F :
    521       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RAD32F, (unsigned long *) (& fields->f_rad32));
    522       break;
    523     case OR1K_OPERAND_RADI :
    524       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RADI, (unsigned long *) (& fields->f_rad32));
    525       break;
    526     case OR1K_OPERAND_RASF :
    527       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
    528       break;
    529     case OR1K_OPERAND_RB :
    530       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
    531       break;
    532     case OR1K_OPERAND_RBD32F :
    533       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBD32F, (unsigned long *) (& fields->f_rbd32));
    534       break;
    535     case OR1K_OPERAND_RBDI :
    536       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBDI, (unsigned long *) (& fields->f_rbd32));
    537       break;
    538     case OR1K_OPERAND_RBSF :
    539       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
    540       break;
    541     case OR1K_OPERAND_RD :
    542       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
    543       break;
    544     case OR1K_OPERAND_RDD32F :
    545       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDD32F, (unsigned long *) (& fields->f_rdd32));
    546       break;
    547     case OR1K_OPERAND_RDDI :
    548       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDDI, (unsigned long *) (& fields->f_rdd32));
    549       break;
    550     case OR1K_OPERAND_RDSF :
    551       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
    552       break;
    553     case OR1K_OPERAND_SIMM16 :
    554       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
    555       break;
    556     case OR1K_OPERAND_SIMM16_SPLIT :
    557       errmsg = parse_simm16_split (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
    558       break;
    559     case OR1K_OPERAND_UIMM16 :
    560       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
    561       break;
    562     case OR1K_OPERAND_UIMM16_SPLIT :
    563       errmsg = parse_uimm16_split (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
    564       break;
    565     case OR1K_OPERAND_UIMM6 :
    566       errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
    567       break;
    568 
    569     default :
    570       /* xgettext:c-format */
    571       opcodes_error_handler
    572 	(_("internal error: unrecognized field %d while parsing"),
    573 	 opindex);
    574       abort ();
    575   }
    576 
    577   return errmsg;
    578 }
    579 
    580 cgen_parse_fn * const or1k_cgen_parse_handlers[] =
    581 {
    582   parse_insn_normal,
    583 };
    584 
    585 void
    586 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
    587 {
    588   or1k_cgen_init_opcode_table (cd);
    589   or1k_cgen_init_ibld_table (cd);
    590   cd->parse_handlers = & or1k_cgen_parse_handlers[0];
    591   cd->parse_operand = or1k_cgen_parse_operand;
    592 #ifdef CGEN_ASM_INIT_HOOK
    593 CGEN_ASM_INIT_HOOK
    594 #endif
    595 }
    596 
    597 
    598 
    600 /* Regex construction routine.
    601 
    602    This translates an opcode syntax string into a regex string,
    603    by replacing any non-character syntax element (such as an
    604    opcode) with the pattern '.*'
    605 
    606    It then compiles the regex and stores it in the opcode, for
    607    later use by or1k_cgen_assemble_insn
    608 
    609    Returns NULL for success, an error message for failure.  */
    610 
    611 char *
    612 or1k_cgen_build_insn_regex (CGEN_INSN *insn)
    613 {
    614   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
    615   const char *mnem = CGEN_INSN_MNEMONIC (insn);
    616   char rxbuf[CGEN_MAX_RX_ELEMENTS];
    617   char *rx = rxbuf;
    618   const CGEN_SYNTAX_CHAR_TYPE *syn;
    619   int reg_err;
    620 
    621   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
    622 
    623   /* Mnemonics come first in the syntax string.  */
    624   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
    625     return _("missing mnemonic in syntax string");
    626   ++syn;
    627 
    628   /* Generate a case sensitive regular expression that emulates case
    629      insensitive matching in the "C" locale.  We cannot generate a case
    630      insensitive regular expression because in Turkish locales, 'i' and 'I'
    631      are not equal modulo case conversion.  */
    632 
    633   /* Copy the literal mnemonic out of the insn.  */
    634   for (; *mnem; mnem++)
    635     {
    636       char c = *mnem;
    637 
    638       if (ISALPHA (c))
    639 	{
    640 	  *rx++ = '[';
    641 	  *rx++ = TOLOWER (c);
    642 	  *rx++ = TOUPPER (c);
    643 	  *rx++ = ']';
    644 	}
    645       else
    646 	*rx++ = c;
    647     }
    648 
    649   /* Copy any remaining literals from the syntax string into the rx.  */
    650   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
    651     {
    652       if (CGEN_SYNTAX_CHAR_P (* syn))
    653 	{
    654 	  char c = CGEN_SYNTAX_CHAR (* syn);
    655 
    656 	  switch (c)
    657 	    {
    658 	      /* Escape any regex metacharacters in the syntax.  */
    659 	    case '.': case '[': case '\\':
    660 	    case '*': case '^': case '$':
    661 
    662 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
    663 	    case '?': case '{': case '}':
    664 	    case '(': case ')': case '*':
    665 	    case '|': case '+': case ']':
    666 #endif
    667 	      *rx++ = '\\';
    668 	      *rx++ = c;
    669 	      break;
    670 
    671 	    default:
    672 	      if (ISALPHA (c))
    673 		{
    674 		  *rx++ = '[';
    675 		  *rx++ = TOLOWER (c);
    676 		  *rx++ = TOUPPER (c);
    677 		  *rx++ = ']';
    678 		}
    679 	      else
    680 		*rx++ = c;
    681 	      break;
    682 	    }
    683 	}
    684       else
    685 	{
    686 	  /* Replace non-syntax fields with globs.  */
    687 	  *rx++ = '.';
    688 	  *rx++ = '*';
    689 	}
    690     }
    691 
    692   /* Trailing whitespace ok.  */
    693   * rx++ = '[';
    694   * rx++ = ' ';
    695   * rx++ = '\t';
    696   * rx++ = ']';
    697   * rx++ = '*';
    698 
    699   /* But anchor it after that.  */
    700   * rx++ = '$';
    701   * rx = '\0';
    702 
    703   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
    704   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
    705 
    706   if (reg_err == 0)
    707     return NULL;
    708   else
    709     {
    710       static char msg[80];
    711 
    712       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
    713       regfree ((regex_t *) CGEN_INSN_RX (insn));
    714       free (CGEN_INSN_RX (insn));
    715       (CGEN_INSN_RX (insn)) = NULL;
    716       return msg;
    717     }
    718 }
    719 
    720 
    721 /* Default insn parser.
    723 
    724    The syntax string is scanned and operands are parsed and stored in FIELDS.
    725    Relocs are queued as we go via other callbacks.
    726 
    727    ??? Note that this is currently an all-or-nothing parser.  If we fail to
    728    parse the instruction, we return 0 and the caller will start over from
    729    the beginning.  Backtracking will be necessary in parsing subexpressions,
    730    but that can be handled there.  Not handling backtracking here may get
    731    expensive in the case of the m68k.  Deal with later.
    732 
    733    Returns NULL for success, an error message for failure.  */
    734 
    735 static const char *
    736 parse_insn_normal (CGEN_CPU_DESC cd,
    737 		   const CGEN_INSN *insn,
    738 		   const char **strp,
    739 		   CGEN_FIELDS *fields)
    740 {
    741   /* ??? Runtime added insns not handled yet.  */
    742   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
    743   const char *str = *strp;
    744   const char *errmsg;
    745   const char *p;
    746   const CGEN_SYNTAX_CHAR_TYPE * syn;
    747 #ifdef CGEN_MNEMONIC_OPERANDS
    748   /* FIXME: wip */
    749   int past_opcode_p;
    750 #endif
    751 
    752   /* For now we assume the mnemonic is first (there are no leading operands).
    753      We can parse it without needing to set up operand parsing.
    754      GAS's input scrubber will ensure mnemonics are lowercase, but we may
    755      not be called from GAS.  */
    756   p = CGEN_INSN_MNEMONIC (insn);
    757   while (*p && TOLOWER (*p) == TOLOWER (*str))
    758     ++p, ++str;
    759 
    760   if (* p)
    761     return _("unrecognized instruction");
    762 
    763 #ifndef CGEN_MNEMONIC_OPERANDS
    764   if (* str && ! ISSPACE (* str))
    765     return _("unrecognized instruction");
    766 #endif
    767 
    768   CGEN_INIT_PARSE (cd);
    769   cgen_init_parse_operand (cd);
    770 #ifdef CGEN_MNEMONIC_OPERANDS
    771   past_opcode_p = 0;
    772 #endif
    773 
    774   /* We don't check for (*str != '\0') here because we want to parse
    775      any trailing fake arguments in the syntax string.  */
    776   syn = CGEN_SYNTAX_STRING (syntax);
    777 
    778   /* Mnemonics come first for now, ensure valid string.  */
    779   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
    780     abort ();
    781 
    782   ++syn;
    783 
    784   while (* syn != 0)
    785     {
    786       /* Non operand chars must match exactly.  */
    787       if (CGEN_SYNTAX_CHAR_P (* syn))
    788 	{
    789 	  /* FIXME: While we allow for non-GAS callers above, we assume the
    790 	     first char after the mnemonic part is a space.  */
    791 	  /* FIXME: We also take inappropriate advantage of the fact that
    792 	     GAS's input scrubber will remove extraneous blanks.  */
    793 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
    794 	    {
    795 #ifdef CGEN_MNEMONIC_OPERANDS
    796 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
    797 		past_opcode_p = 1;
    798 #endif
    799 	      ++ syn;
    800 	      ++ str;
    801 	    }
    802 	  else if (*str)
    803 	    {
    804 	      /* Syntax char didn't match.  Can't be this insn.  */
    805 	      static char msg [80];
    806 
    807 	      /* xgettext:c-format */
    808 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
    809 		       CGEN_SYNTAX_CHAR(*syn), *str);
    810 	      return msg;
    811 	    }
    812 	  else
    813 	    {
    814 	      /* Ran out of input.  */
    815 	      static char msg [80];
    816 
    817 	      /* xgettext:c-format */
    818 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
    819 		       CGEN_SYNTAX_CHAR(*syn));
    820 	      return msg;
    821 	    }
    822 	  continue;
    823 	}
    824 
    825 #ifdef CGEN_MNEMONIC_OPERANDS
    826       (void) past_opcode_p;
    827 #endif
    828       /* We have an operand of some sort.  */
    829       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
    830       if (errmsg)
    831 	return errmsg;
    832 
    833       /* Done with this operand, continue with next one.  */
    834       ++ syn;
    835     }
    836 
    837   /* If we're at the end of the syntax string, we're done.  */
    838   if (* syn == 0)
    839     {
    840       /* FIXME: For the moment we assume a valid `str' can only contain
    841 	 blanks now.  IE: We needn't try again with a longer version of
    842 	 the insn and it is assumed that longer versions of insns appear
    843 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
    844       while (ISSPACE (* str))
    845 	++ str;
    846 
    847       if (* str != '\0')
    848 	return _("junk at end of line"); /* FIXME: would like to include `str' */
    849 
    850       return NULL;
    851     }
    852 
    853   /* We couldn't parse it.  */
    854   return _("unrecognized instruction");
    855 }
    856 
    857 /* Main entry point.
    859    This routine is called for each instruction to be assembled.
    860    STR points to the insn to be assembled.
    861    We assume all necessary tables have been initialized.
    862    The assembled instruction, less any fixups, is stored in BUF.
    863    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
    864    still needs to be converted to target byte order, otherwise BUF is an array
    865    of bytes in target byte order.
    866    The result is a pointer to the insn's entry in the opcode table,
    867    or NULL if an error occured (an error message will have already been
    868    printed).
    869 
    870    Note that when processing (non-alias) macro-insns,
    871    this function recurses.
    872 
    873    ??? It's possible to make this cpu-independent.
    874    One would have to deal with a few minor things.
    875    At this point in time doing so would be more of a curiosity than useful
    876    [for example this file isn't _that_ big], but keeping the possibility in
    877    mind helps keep the design clean.  */
    878 
    879 const CGEN_INSN *
    880 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
    881 			   const char *str,
    882 			   CGEN_FIELDS *fields,
    883 			   CGEN_INSN_BYTES_PTR buf,
    884 			   char **errmsg)
    885 {
    886   const char *start;
    887   CGEN_INSN_LIST *ilist;
    888   const char *parse_errmsg = NULL;
    889   const char *insert_errmsg = NULL;
    890   int recognized_mnemonic = 0;
    891 
    892   /* Skip leading white space.  */
    893   while (ISSPACE (* str))
    894     ++ str;
    895 
    896   /* The instructions are stored in hashed lists.
    897      Get the first in the list.  */
    898   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
    899 
    900   /* Keep looking until we find a match.  */
    901   start = str;
    902   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
    903     {
    904       const CGEN_INSN *insn = ilist->insn;
    905       recognized_mnemonic = 1;
    906 
    907 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
    908       /* Not usually needed as unsupported opcodes
    909 	 shouldn't be in the hash lists.  */
    910       /* Is this insn supported by the selected cpu?  */
    911       if (! or1k_cgen_insn_supported (cd, insn))
    912 	continue;
    913 #endif
    914       /* If the RELAXED attribute is set, this is an insn that shouldn't be
    915 	 chosen immediately.  Instead, it is used during assembler/linker
    916 	 relaxation if possible.  */
    917       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
    918 	continue;
    919 
    920       str = start;
    921 
    922       /* Skip this insn if str doesn't look right lexically.  */
    923       if (CGEN_INSN_RX (insn) != NULL &&
    924 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
    925 	continue;
    926 
    927       /* Allow parse/insert handlers to obtain length of insn.  */
    928       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
    929 
    930       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
    931       if (parse_errmsg != NULL)
    932 	continue;
    933 
    934       /* ??? 0 is passed for `pc'.  */
    935       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
    936 						 (bfd_vma) 0);
    937       if (insert_errmsg != NULL)
    938         continue;
    939 
    940       /* It is up to the caller to actually output the insn and any
    941          queued relocs.  */
    942       return insn;
    943     }
    944 
    945   {
    946     static char errbuf[150];
    947     const char *tmp_errmsg;
    948 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
    949 #define be_verbose 1
    950 #else
    951 #define be_verbose 0
    952 #endif
    953 
    954     if (be_verbose)
    955       {
    956 	/* If requesting verbose error messages, use insert_errmsg.
    957 	   Failing that, use parse_errmsg.  */
    958 	tmp_errmsg = (insert_errmsg ? insert_errmsg :
    959 		      parse_errmsg ? parse_errmsg :
    960 		      recognized_mnemonic ?
    961 		      _("unrecognized form of instruction") :
    962 		      _("unrecognized instruction"));
    963 
    964 	if (strlen (start) > 50)
    965 	  /* xgettext:c-format */
    966 	  sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
    967 	else
    968 	  /* xgettext:c-format */
    969 	  sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
    970       }
    971     else
    972       {
    973 	if (strlen (start) > 50)
    974 	  /* xgettext:c-format */
    975 	  sprintf (errbuf, _("bad instruction `%.50s...'"), start);
    976 	else
    977 	  /* xgettext:c-format */
    978 	  sprintf (errbuf, _("bad instruction `%.50s'"), start);
    979       }
    980 
    981     *errmsg = errbuf;
    982     return NULL;
    983   }
    984 }
    985