Home | History | Annotate | Line # | Download | only in opcodes
or1k-asm.c revision 1.1.1.9
      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-2026 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_OR1K_GOT_AHI16 },
    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     else if (strncasecmp (str, "got", 3) == 0)
    285       {
    286 	str += 3;
    287 	cls = RCLASS_GOT;
    288       }
    289 
    290     if (strncasecmp (str, "hi(", 3) == 0)
    291       {
    292 	str += 3;
    293 	typ = RTYPE_HI;
    294       }
    295     else if (strncasecmp (str, "lo(", 3) == 0)
    296       {
    297 	str += 3;
    298 	typ = RTYPE_LO;
    299       }
    300     else if (strncasecmp (str, "ha(", 3) == 0)
    301       {
    302 	str += 3;
    303 	typ = RTYPE_AHI;
    304       }
    305     else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
    306       {
    307 	str += 3;
    308 	typ = RTYPE_PO;
    309       }
    310     else
    311       return -1;
    312 
    313     *strp = str;
    314     return (cls << RCLASS_SHIFT) | typ;
    315 }
    316 
    317 static const char *
    318 parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
    319 	     long *valuep, int splitp)
    320 {
    321   const char *errmsg;
    322   enum cgen_parse_operand_result result_type;
    323   bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
    324   enum or1k_rtype reloc_type;
    325   int reloc_code;
    326   bfd_vma ret;
    327 
    328   if (**strp == '#')
    329     ++*strp;
    330 
    331   reloc_code = parse_reloc (strp);
    332   reloc_type = reloc_code & RTYPE_MASK;
    333   if (reloc_code >= 0)
    334     {
    335       enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
    336       if (splitp)
    337 	{
    338 	  if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
    339 	      && reloc_class != RCLASS_GOT)
    340 	    /* If split we or up the type to RTYPE_SLO or RTYPE_SPO.  */
    341 	    reloc_type |= 1;
    342 	  else
    343 	    return INVALID_STORE_RELOC;
    344 	}
    345       reloc = or1k_imm16_relocs[reloc_class][reloc_type];
    346     }
    347 
    348   if (reloc != BFD_RELOC_UNUSED)
    349     {
    350       bfd_vma value;
    351 
    352       errmsg = cgen_parse_address (cd, strp, opindex, reloc,
    353 				   &result_type, &value);
    354       if (**strp != ')')
    355 	errmsg = MISSING_CLOSING_PARENTHESIS;
    356       ++*strp;
    357 
    358       ret = value;
    359 
    360       if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
    361 	switch (reloc_type)
    362 	  {
    363 	  case RTYPE_AHI:
    364 	    ret += 0x8000;
    365 	    /* FALLTHRU */
    366 	  case RTYPE_HI:
    367 	    ret >>= 16;
    368 	    /* FALLTHRU */
    369 	  case RTYPE_LO:
    370 	  case RTYPE_SLO:
    371 	    ret &= 0xffff;
    372 	    ret = (ret ^ 0x8000) - 0x8000;
    373 	    break;
    374 	  case RTYPE_PO:
    375 	  case RTYPE_SPO:
    376 	    ret &= 0x1fff;
    377 	    break;
    378 	  default:
    379 	    errmsg = INVALID_RELOC_TYPE;
    380 	  }
    381     }
    382   else
    383     {
    384       long value;
    385       errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
    386       ret = value;
    387     }
    388 
    389   if (errmsg == NULL)
    390     *valuep = ret;
    391 
    392   return errmsg;
    393 }
    394 
    395 static const char *
    396 parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
    397 {
    398   return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
    399 }
    400 
    401 static const char *
    402 parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
    403 		    long *valuep)
    404 {
    405   return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
    406 }
    407 
    408 static const char *
    409 parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
    410 	      unsigned long *valuep)
    411 {
    412   const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
    413   if (errmsg == NULL)
    414     *valuep &= 0xffff;
    415   return errmsg;
    416 }
    417 
    418 static const char *
    419 parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
    420 		    unsigned long *valuep)
    421 {
    422   const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
    423   if (errmsg == NULL)
    424     *valuep &= 0xffff;
    425   return errmsg;
    426 }
    427 
    428 /* Parse register pairs with syntax rA,rB to a flag + rA value.  */
    429 
    430 static const char *
    431 parse_regpair (CGEN_CPU_DESC cd, const char **strp,
    432 	       int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
    433 {
    434   long reg1_index;
    435   long reg2_index;
    436   const char *errmsg;
    437 
    438   /* The first part should just be a register.  */
    439   errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
    440 			       &reg1_index);
    441 
    442   /* If that worked skip the comma separator.  */
    443   if (errmsg == NULL)
    444     {
    445       if (**strp == ',')
    446 	++*strp;
    447       else
    448 	errmsg = "Unexpected character, expected ','";
    449     }
    450 
    451   /* If that worked the next part is just another register.  */
    452   if (errmsg == NULL)
    453     errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
    454 				 &reg2_index);
    455 
    456   /* Validate the register pair is valid and create the output value.  */
    457   if (errmsg == NULL)
    458     {
    459       int regoffset = reg2_index - reg1_index;
    460 
    461       if (regoffset == 1 || regoffset == 2)
    462 	{
    463 	  unsigned short offsetmask;
    464 	  unsigned short value;
    465 
    466 	  offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
    467 	  value = offsetmask | reg1_index;
    468 
    469 	  *valuep = value;
    470 	}
    471       else
    472 	errmsg = "Invalid register pair, offset not 1 or 2.";
    473     }
    474 
    475   return errmsg;
    476 }
    477 
    478 /* -- */
    479 
    480 const char * or1k_cgen_parse_operand
    481   (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
    482 
    483 /* Main entry point for operand parsing.
    484 
    485    This function is basically just a big switch statement.  Earlier versions
    486    used tables to look up the function to use, but
    487    - if the table contains both assembler and disassembler functions then
    488      the disassembler contains much of the assembler and vice-versa,
    489    - there's a lot of inlining possibilities as things grow,
    490    - using a switch statement avoids the function call overhead.
    491 
    492    This function could be moved into `parse_insn_normal', but keeping it
    493    separate makes clear the interface between `parse_insn_normal' and each of
    494    the handlers.  */
    495 
    496 const char *
    497 or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
    498 			   int opindex,
    499 			   const char ** strp,
    500 			   CGEN_FIELDS * fields)
    501 {
    502   const char * errmsg = NULL;
    503   /* Used by scalar operands that still need to be parsed.  */
    504   long junk ATTRIBUTE_UNUSED;
    505 
    506   switch (opindex)
    507     {
    508     case OR1K_OPERAND_DISP21 :
    509       {
    510         bfd_vma value = 0;
    511         errmsg = parse_disp21 (cd, strp, OR1K_OPERAND_DISP21, 0, NULL,  & value);
    512         fields->f_disp21 = value;
    513       }
    514       break;
    515     case OR1K_OPERAND_DISP26 :
    516       {
    517         bfd_vma value = 0;
    518         errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL,  & value);
    519         fields->f_disp26 = value;
    520       }
    521       break;
    522     case OR1K_OPERAND_RA :
    523       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
    524       break;
    525     case OR1K_OPERAND_RAD32F :
    526       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RAD32F, (unsigned long *) (& fields->f_rad32));
    527       break;
    528     case OR1K_OPERAND_RADI :
    529       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RADI, (unsigned long *) (& fields->f_rad32));
    530       break;
    531     case OR1K_OPERAND_RASF :
    532       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
    533       break;
    534     case OR1K_OPERAND_RB :
    535       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
    536       break;
    537     case OR1K_OPERAND_RBD32F :
    538       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBD32F, (unsigned long *) (& fields->f_rbd32));
    539       break;
    540     case OR1K_OPERAND_RBDI :
    541       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBDI, (unsigned long *) (& fields->f_rbd32));
    542       break;
    543     case OR1K_OPERAND_RBSF :
    544       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
    545       break;
    546     case OR1K_OPERAND_RD :
    547       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
    548       break;
    549     case OR1K_OPERAND_RDD32F :
    550       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDD32F, (unsigned long *) (& fields->f_rdd32));
    551       break;
    552     case OR1K_OPERAND_RDDI :
    553       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDDI, (unsigned long *) (& fields->f_rdd32));
    554       break;
    555     case OR1K_OPERAND_RDSF :
    556       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
    557       break;
    558     case OR1K_OPERAND_SIMM16 :
    559       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
    560       break;
    561     case OR1K_OPERAND_SIMM16_SPLIT :
    562       errmsg = parse_simm16_split (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
    563       break;
    564     case OR1K_OPERAND_UIMM16 :
    565       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
    566       break;
    567     case OR1K_OPERAND_UIMM16_SPLIT :
    568       errmsg = parse_uimm16_split (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
    569       break;
    570     case OR1K_OPERAND_UIMM6 :
    571       errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
    572       break;
    573 
    574     default :
    575       /* xgettext:c-format */
    576       opcodes_error_handler
    577 	(_("internal error: unrecognized field %d while parsing"),
    578 	 opindex);
    579       abort ();
    580   }
    581 
    582   return errmsg;
    583 }
    584 
    585 cgen_parse_fn * const or1k_cgen_parse_handlers[] =
    586 {
    587   parse_insn_normal,
    588 };
    589 
    590 void
    591 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
    592 {
    593   or1k_cgen_init_opcode_table (cd);
    594   or1k_cgen_init_ibld_table (cd);
    595   cd->parse_handlers = & or1k_cgen_parse_handlers[0];
    596   cd->parse_operand = or1k_cgen_parse_operand;
    597 #ifdef CGEN_ASM_INIT_HOOK
    598 CGEN_ASM_INIT_HOOK
    599 #endif
    600 }
    601 
    602 
    603 
    605 /* Regex construction routine.
    606 
    607    This translates an opcode syntax string into a regex string,
    608    by replacing any non-character syntax element (such as an
    609    opcode) with the pattern '.*'
    610 
    611    It then compiles the regex and stores it in the opcode, for
    612    later use by or1k_cgen_assemble_insn
    613 
    614    Returns NULL for success, an error message for failure.  */
    615 
    616 char *
    617 or1k_cgen_build_insn_regex (CGEN_INSN *insn)
    618 {
    619   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
    620   const char *mnem = CGEN_INSN_MNEMONIC (insn);
    621   char rxbuf[CGEN_MAX_RX_ELEMENTS];
    622   char *rx = rxbuf;
    623   const CGEN_SYNTAX_CHAR_TYPE *syn;
    624   int reg_err;
    625 
    626   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
    627 
    628   /* Mnemonics come first in the syntax string.  */
    629   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
    630     return _("missing mnemonic in syntax string");
    631   ++syn;
    632 
    633   /* Generate a case sensitive regular expression that emulates case
    634      insensitive matching in the "C" locale.  We cannot generate a case
    635      insensitive regular expression because in Turkish locales, 'i' and 'I'
    636      are not equal modulo case conversion.  */
    637 
    638   /* Copy the literal mnemonic out of the insn.  */
    639   for (; *mnem; mnem++)
    640     {
    641       char c = *mnem;
    642 
    643       if (ISALPHA (c))
    644 	{
    645 	  *rx++ = '[';
    646 	  *rx++ = TOLOWER (c);
    647 	  *rx++ = TOUPPER (c);
    648 	  *rx++ = ']';
    649 	}
    650       else
    651 	*rx++ = c;
    652     }
    653 
    654   /* Copy any remaining literals from the syntax string into the rx.  */
    655   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
    656     {
    657       if (CGEN_SYNTAX_CHAR_P (* syn))
    658 	{
    659 	  char c = CGEN_SYNTAX_CHAR (* syn);
    660 
    661 	  switch (c)
    662 	    {
    663 	      /* Escape any regex metacharacters in the syntax.  */
    664 	    case '.': case '[': case '\\':
    665 	    case '*': case '^': case '$':
    666 
    667 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
    668 	    case '?': case '{': case '}':
    669 	    case '(': case ')': case '*':
    670 	    case '|': case '+': case ']':
    671 #endif
    672 	      *rx++ = '\\';
    673 	      *rx++ = c;
    674 	      break;
    675 
    676 	    default:
    677 	      if (ISALPHA (c))
    678 		{
    679 		  *rx++ = '[';
    680 		  *rx++ = TOLOWER (c);
    681 		  *rx++ = TOUPPER (c);
    682 		  *rx++ = ']';
    683 		}
    684 	      else
    685 		*rx++ = c;
    686 	      break;
    687 	    }
    688 	}
    689       else
    690 	{
    691 	  /* Replace non-syntax fields with globs.  */
    692 	  *rx++ = '.';
    693 	  *rx++ = '*';
    694 	}
    695     }
    696 
    697   /* Trailing whitespace ok.  */
    698   * rx++ = '[';
    699   * rx++ = ' ';
    700   * rx++ = '\t';
    701   * rx++ = ']';
    702   * rx++ = '*';
    703 
    704   /* But anchor it after that.  */
    705   * rx++ = '$';
    706   * rx = '\0';
    707 
    708   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
    709   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
    710 
    711   if (reg_err == 0)
    712     return NULL;
    713   else
    714     {
    715       static char msg[80];
    716 
    717       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
    718       regfree ((regex_t *) CGEN_INSN_RX (insn));
    719       free (CGEN_INSN_RX (insn));
    720       (CGEN_INSN_RX (insn)) = NULL;
    721       return msg;
    722     }
    723 }
    724 
    725 
    726 /* Default insn parser.
    728 
    729    The syntax string is scanned and operands are parsed and stored in FIELDS.
    730    Relocs are queued as we go via other callbacks.
    731 
    732    ??? Note that this is currently an all-or-nothing parser.  If we fail to
    733    parse the instruction, we return 0 and the caller will start over from
    734    the beginning.  Backtracking will be necessary in parsing subexpressions,
    735    but that can be handled there.  Not handling backtracking here may get
    736    expensive in the case of the m68k.  Deal with later.
    737 
    738    Returns NULL for success, an error message for failure.  */
    739 
    740 static const char *
    741 parse_insn_normal (CGEN_CPU_DESC cd,
    742 		   const CGEN_INSN *insn,
    743 		   const char **strp,
    744 		   CGEN_FIELDS *fields)
    745 {
    746   /* ??? Runtime added insns not handled yet.  */
    747   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
    748   const char *str = *strp;
    749   const char *errmsg;
    750   const char *p;
    751   const CGEN_SYNTAX_CHAR_TYPE * syn;
    752 #ifdef CGEN_MNEMONIC_OPERANDS
    753   /* FIXME: wip */
    754   int past_opcode_p;
    755 #endif
    756 
    757   /* For now we assume the mnemonic is first (there are no leading operands).
    758      We can parse it without needing to set up operand parsing.
    759      GAS's input scrubber will ensure mnemonics are lowercase, but we may
    760      not be called from GAS.  */
    761   p = CGEN_INSN_MNEMONIC (insn);
    762   while (*p && TOLOWER (*p) == TOLOWER (*str))
    763     ++p, ++str;
    764 
    765   if (* p)
    766     return _("unrecognized instruction");
    767 
    768 #ifndef CGEN_MNEMONIC_OPERANDS
    769   if (* str && ! ISSPACE (* str))
    770     return _("unrecognized instruction");
    771 #endif
    772 
    773   CGEN_INIT_PARSE (cd);
    774   cgen_init_parse_operand (cd);
    775 #ifdef CGEN_MNEMONIC_OPERANDS
    776   past_opcode_p = 0;
    777 #endif
    778 
    779   /* We don't check for (*str != '\0') here because we want to parse
    780      any trailing fake arguments in the syntax string.  */
    781   syn = CGEN_SYNTAX_STRING (syntax);
    782 
    783   /* Mnemonics come first for now, ensure valid string.  */
    784   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
    785     abort ();
    786 
    787   ++syn;
    788 
    789   while (* syn != 0)
    790     {
    791       /* Non operand chars must match exactly.  */
    792       if (CGEN_SYNTAX_CHAR_P (* syn))
    793 	{
    794 	  /* FIXME: While we allow for non-GAS callers above, we assume the
    795 	     first char after the mnemonic part is a space.  */
    796 	  /* FIXME: We also take inappropriate advantage of the fact that
    797 	     GAS's input scrubber will remove extraneous blanks.  */
    798 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
    799 	    {
    800 #ifdef CGEN_MNEMONIC_OPERANDS
    801 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
    802 		past_opcode_p = 1;
    803 #endif
    804 	      ++ syn;
    805 	      ++ str;
    806 	    }
    807 	  else if (*str)
    808 	    {
    809 	      /* Syntax char didn't match.  Can't be this insn.  */
    810 	      static char msg [80];
    811 
    812 	      /* xgettext:c-format */
    813 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
    814 		       CGEN_SYNTAX_CHAR(*syn), *str);
    815 	      return msg;
    816 	    }
    817 	  else
    818 	    {
    819 	      /* Ran out of input.  */
    820 	      static char msg [80];
    821 
    822 	      /* xgettext:c-format */
    823 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
    824 		       CGEN_SYNTAX_CHAR(*syn));
    825 	      return msg;
    826 	    }
    827 	  continue;
    828 	}
    829 
    830 #ifdef CGEN_MNEMONIC_OPERANDS
    831       (void) past_opcode_p;
    832 #endif
    833       /* We have an operand of some sort.  */
    834       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
    835       if (errmsg)
    836 	return errmsg;
    837 
    838       /* Done with this operand, continue with next one.  */
    839       ++ syn;
    840     }
    841 
    842   /* If we're at the end of the syntax string, we're done.  */
    843   if (* syn == 0)
    844     {
    845       /* FIXME: For the moment we assume a valid `str' can only contain
    846 	 blanks now.  IE: We needn't try again with a longer version of
    847 	 the insn and it is assumed that longer versions of insns appear
    848 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
    849       while (ISSPACE (* str))
    850 	++ str;
    851 
    852       if (* str != '\0')
    853 	return _("junk at end of line"); /* FIXME: would like to include `str' */
    854 
    855       return NULL;
    856     }
    857 
    858   /* We couldn't parse it.  */
    859   return _("unrecognized instruction");
    860 }
    861 
    862 /* Main entry point.
    864    This routine is called for each instruction to be assembled.
    865    STR points to the insn to be assembled.
    866    We assume all necessary tables have been initialized.
    867    The assembled instruction, less any fixups, is stored in BUF.
    868    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
    869    still needs to be converted to target byte order, otherwise BUF is an array
    870    of bytes in target byte order.
    871    The result is a pointer to the insn's entry in the opcode table,
    872    or NULL if an error occured (an error message will have already been
    873    printed).
    874 
    875    Note that when processing (non-alias) macro-insns,
    876    this function recurses.
    877 
    878    ??? It's possible to make this cpu-independent.
    879    One would have to deal with a few minor things.
    880    At this point in time doing so would be more of a curiosity than useful
    881    [for example this file isn't _that_ big], but keeping the possibility in
    882    mind helps keep the design clean.  */
    883 
    884 const CGEN_INSN *
    885 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
    886 			   const char *str,
    887 			   CGEN_FIELDS *fields,
    888 			   CGEN_INSN_BYTES_PTR buf,
    889 			   char **errmsg)
    890 {
    891   const char *start;
    892   CGEN_INSN_LIST *ilist;
    893   const char *parse_errmsg = NULL;
    894   const char *insert_errmsg = NULL;
    895   int recognized_mnemonic = 0;
    896 
    897   /* Skip leading white space.  */
    898   while (ISSPACE (* str))
    899     ++ str;
    900 
    901   /* The instructions are stored in hashed lists.
    902      Get the first in the list.  */
    903   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
    904 
    905   /* Keep looking until we find a match.  */
    906   start = str;
    907   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
    908     {
    909       const CGEN_INSN *insn = ilist->insn;
    910       recognized_mnemonic = 1;
    911 
    912 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
    913       /* Not usually needed as unsupported opcodes
    914 	 shouldn't be in the hash lists.  */
    915       /* Is this insn supported by the selected cpu?  */
    916       if (! or1k_cgen_insn_supported (cd, insn))
    917 	continue;
    918 #endif
    919       /* If the RELAXED attribute is set, this is an insn that shouldn't be
    920 	 chosen immediately.  Instead, it is used during assembler/linker
    921 	 relaxation if possible.  */
    922       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
    923 	continue;
    924 
    925       str = start;
    926 
    927       /* Skip this insn if str doesn't look right lexically.  */
    928       if (CGEN_INSN_RX (insn) != NULL &&
    929 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
    930 	continue;
    931 
    932       /* Allow parse/insert handlers to obtain length of insn.  */
    933       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
    934 
    935       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
    936       if (parse_errmsg != NULL)
    937 	continue;
    938 
    939       /* ??? 0 is passed for `pc'.  */
    940       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
    941 						 (bfd_vma) 0);
    942       if (insert_errmsg != NULL)
    943         continue;
    944 
    945       /* It is up to the caller to actually output the insn and any
    946          queued relocs.  */
    947       return insn;
    948     }
    949 
    950   {
    951     static char errbuf[150];
    952     const char *tmp_errmsg;
    953 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
    954 #define be_verbose 1
    955 #else
    956 #define be_verbose 0
    957 #endif
    958 
    959     if (be_verbose)
    960       {
    961 	/* If requesting verbose error messages, use insert_errmsg.
    962 	   Failing that, use parse_errmsg.  */
    963 	tmp_errmsg = (insert_errmsg ? insert_errmsg :
    964 		      parse_errmsg ? parse_errmsg :
    965 		      recognized_mnemonic ?
    966 		      _("unrecognized form of instruction") :
    967 		      _("unrecognized instruction"));
    968 
    969 	if (strlen (start) > 50)
    970 	  /* xgettext:c-format */
    971 	  sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
    972 	else
    973 	  /* xgettext:c-format */
    974 	  sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
    975       }
    976     else
    977       {
    978 	if (strlen (start) > 50)
    979 	  /* xgettext:c-format */
    980 	  sprintf (errbuf, _("bad instruction `%.50s...'"), start);
    981 	else
    982 	  /* xgettext:c-format */
    983 	  sprintf (errbuf, _("bad instruction `%.50s'"), start);
    984       }
    985 
    986     *errmsg = errbuf;
    987     return NULL;
    988   }
    989 }
    990