Home | History | Annotate | Line # | Download | only in opcodes
or1k-asm.c revision 1.4.2.2
      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_RADF :
    524       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r2);
    525       break;
    526     case OR1K_OPERAND_RADI :
    527       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RADI, (unsigned long *) (& fields->f_rad32));
    528       break;
    529     case OR1K_OPERAND_RASF :
    530       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
    531       break;
    532     case OR1K_OPERAND_RB :
    533       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
    534       break;
    535     case OR1K_OPERAND_RBD32F :
    536       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBD32F, (unsigned long *) (& fields->f_rbd32));
    537       break;
    538     case OR1K_OPERAND_RBDF :
    539       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r3);
    540       break;
    541     case OR1K_OPERAND_RBDI :
    542       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBDI, (unsigned long *) (& fields->f_rbd32));
    543       break;
    544     case OR1K_OPERAND_RBSF :
    545       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
    546       break;
    547     case OR1K_OPERAND_RD :
    548       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
    549       break;
    550     case OR1K_OPERAND_RDD32F :
    551       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDD32F, (unsigned long *) (& fields->f_rdd32));
    552       break;
    553     case OR1K_OPERAND_RDDF :
    554       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
    555       break;
    556     case OR1K_OPERAND_RDDI :
    557       errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDDI, (unsigned long *) (& fields->f_rdd32));
    558       break;
    559     case OR1K_OPERAND_RDSF :
    560       errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
    561       break;
    562     case OR1K_OPERAND_SIMM16 :
    563       errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
    564       break;
    565     case OR1K_OPERAND_SIMM16_SPLIT :
    566       errmsg = parse_simm16_split (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
    567       break;
    568     case OR1K_OPERAND_UIMM16 :
    569       errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
    570       break;
    571     case OR1K_OPERAND_UIMM16_SPLIT :
    572       errmsg = parse_uimm16_split (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
    573       break;
    574     case OR1K_OPERAND_UIMM6 :
    575       errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
    576       break;
    577 
    578     default :
    579       /* xgettext:c-format */
    580       opcodes_error_handler
    581 	(_("internal error: unrecognized field %d while parsing"),
    582 	 opindex);
    583       abort ();
    584   }
    585 
    586   return errmsg;
    587 }
    588 
    589 cgen_parse_fn * const or1k_cgen_parse_handlers[] =
    590 {
    591   parse_insn_normal,
    592 };
    593 
    594 void
    595 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
    596 {
    597   or1k_cgen_init_opcode_table (cd);
    598   or1k_cgen_init_ibld_table (cd);
    599   cd->parse_handlers = & or1k_cgen_parse_handlers[0];
    600   cd->parse_operand = or1k_cgen_parse_operand;
    601 #ifdef CGEN_ASM_INIT_HOOK
    602 CGEN_ASM_INIT_HOOK
    603 #endif
    604 }
    605 
    606 
    607 
    609 /* Regex construction routine.
    610 
    611    This translates an opcode syntax string into a regex string,
    612    by replacing any non-character syntax element (such as an
    613    opcode) with the pattern '.*'
    614 
    615    It then compiles the regex and stores it in the opcode, for
    616    later use by or1k_cgen_assemble_insn
    617 
    618    Returns NULL for success, an error message for failure.  */
    619 
    620 char *
    621 or1k_cgen_build_insn_regex (CGEN_INSN *insn)
    622 {
    623   CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
    624   const char *mnem = CGEN_INSN_MNEMONIC (insn);
    625   char rxbuf[CGEN_MAX_RX_ELEMENTS];
    626   char *rx = rxbuf;
    627   const CGEN_SYNTAX_CHAR_TYPE *syn;
    628   int reg_err;
    629 
    630   syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
    631 
    632   /* Mnemonics come first in the syntax string.  */
    633   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
    634     return _("missing mnemonic in syntax string");
    635   ++syn;
    636 
    637   /* Generate a case sensitive regular expression that emulates case
    638      insensitive matching in the "C" locale.  We cannot generate a case
    639      insensitive regular expression because in Turkish locales, 'i' and 'I'
    640      are not equal modulo case conversion.  */
    641 
    642   /* Copy the literal mnemonic out of the insn.  */
    643   for (; *mnem; mnem++)
    644     {
    645       char c = *mnem;
    646 
    647       if (ISALPHA (c))
    648 	{
    649 	  *rx++ = '[';
    650 	  *rx++ = TOLOWER (c);
    651 	  *rx++ = TOUPPER (c);
    652 	  *rx++ = ']';
    653 	}
    654       else
    655 	*rx++ = c;
    656     }
    657 
    658   /* Copy any remaining literals from the syntax string into the rx.  */
    659   for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
    660     {
    661       if (CGEN_SYNTAX_CHAR_P (* syn))
    662 	{
    663 	  char c = CGEN_SYNTAX_CHAR (* syn);
    664 
    665 	  switch (c)
    666 	    {
    667 	      /* Escape any regex metacharacters in the syntax.  */
    668 	    case '.': case '[': case '\\':
    669 	    case '*': case '^': case '$':
    670 
    671 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
    672 	    case '?': case '{': case '}':
    673 	    case '(': case ')': case '*':
    674 	    case '|': case '+': case ']':
    675 #endif
    676 	      *rx++ = '\\';
    677 	      *rx++ = c;
    678 	      break;
    679 
    680 	    default:
    681 	      if (ISALPHA (c))
    682 		{
    683 		  *rx++ = '[';
    684 		  *rx++ = TOLOWER (c);
    685 		  *rx++ = TOUPPER (c);
    686 		  *rx++ = ']';
    687 		}
    688 	      else
    689 		*rx++ = c;
    690 	      break;
    691 	    }
    692 	}
    693       else
    694 	{
    695 	  /* Replace non-syntax fields with globs.  */
    696 	  *rx++ = '.';
    697 	  *rx++ = '*';
    698 	}
    699     }
    700 
    701   /* Trailing whitespace ok.  */
    702   * rx++ = '[';
    703   * rx++ = ' ';
    704   * rx++ = '\t';
    705   * rx++ = ']';
    706   * rx++ = '*';
    707 
    708   /* But anchor it after that.  */
    709   * rx++ = '$';
    710   * rx = '\0';
    711 
    712   CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
    713   reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
    714 
    715   if (reg_err == 0)
    716     return NULL;
    717   else
    718     {
    719       static char msg[80];
    720 
    721       regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
    722       regfree ((regex_t *) CGEN_INSN_RX (insn));
    723       free (CGEN_INSN_RX (insn));
    724       (CGEN_INSN_RX (insn)) = NULL;
    725       return msg;
    726     }
    727 }
    728 
    729 
    730 /* Default insn parser.
    732 
    733    The syntax string is scanned and operands are parsed and stored in FIELDS.
    734    Relocs are queued as we go via other callbacks.
    735 
    736    ??? Note that this is currently an all-or-nothing parser.  If we fail to
    737    parse the instruction, we return 0 and the caller will start over from
    738    the beginning.  Backtracking will be necessary in parsing subexpressions,
    739    but that can be handled there.  Not handling backtracking here may get
    740    expensive in the case of the m68k.  Deal with later.
    741 
    742    Returns NULL for success, an error message for failure.  */
    743 
    744 static const char *
    745 parse_insn_normal (CGEN_CPU_DESC cd,
    746 		   const CGEN_INSN *insn,
    747 		   const char **strp,
    748 		   CGEN_FIELDS *fields)
    749 {
    750   /* ??? Runtime added insns not handled yet.  */
    751   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
    752   const char *str = *strp;
    753   const char *errmsg;
    754   const char *p;
    755   const CGEN_SYNTAX_CHAR_TYPE * syn;
    756 #ifdef CGEN_MNEMONIC_OPERANDS
    757   /* FIXME: wip */
    758   int past_opcode_p;
    759 #endif
    760 
    761   /* For now we assume the mnemonic is first (there are no leading operands).
    762      We can parse it without needing to set up operand parsing.
    763      GAS's input scrubber will ensure mnemonics are lowercase, but we may
    764      not be called from GAS.  */
    765   p = CGEN_INSN_MNEMONIC (insn);
    766   while (*p && TOLOWER (*p) == TOLOWER (*str))
    767     ++p, ++str;
    768 
    769   if (* p)
    770     return _("unrecognized instruction");
    771 
    772 #ifndef CGEN_MNEMONIC_OPERANDS
    773   if (* str && ! ISSPACE (* str))
    774     return _("unrecognized instruction");
    775 #endif
    776 
    777   CGEN_INIT_PARSE (cd);
    778   cgen_init_parse_operand (cd);
    779 #ifdef CGEN_MNEMONIC_OPERANDS
    780   past_opcode_p = 0;
    781 #endif
    782 
    783   /* We don't check for (*str != '\0') here because we want to parse
    784      any trailing fake arguments in the syntax string.  */
    785   syn = CGEN_SYNTAX_STRING (syntax);
    786 
    787   /* Mnemonics come first for now, ensure valid string.  */
    788   if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
    789     abort ();
    790 
    791   ++syn;
    792 
    793   while (* syn != 0)
    794     {
    795       /* Non operand chars must match exactly.  */
    796       if (CGEN_SYNTAX_CHAR_P (* syn))
    797 	{
    798 	  /* FIXME: While we allow for non-GAS callers above, we assume the
    799 	     first char after the mnemonic part is a space.  */
    800 	  /* FIXME: We also take inappropriate advantage of the fact that
    801 	     GAS's input scrubber will remove extraneous blanks.  */
    802 	  if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
    803 	    {
    804 #ifdef CGEN_MNEMONIC_OPERANDS
    805 	      if (CGEN_SYNTAX_CHAR(* syn) == ' ')
    806 		past_opcode_p = 1;
    807 #endif
    808 	      ++ syn;
    809 	      ++ str;
    810 	    }
    811 	  else if (*str)
    812 	    {
    813 	      /* Syntax char didn't match.  Can't be this insn.  */
    814 	      static char msg [80];
    815 
    816 	      /* xgettext:c-format */
    817 	      sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
    818 		       CGEN_SYNTAX_CHAR(*syn), *str);
    819 	      return msg;
    820 	    }
    821 	  else
    822 	    {
    823 	      /* Ran out of input.  */
    824 	      static char msg [80];
    825 
    826 	      /* xgettext:c-format */
    827 	      sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
    828 		       CGEN_SYNTAX_CHAR(*syn));
    829 	      return msg;
    830 	    }
    831 	  continue;
    832 	}
    833 
    834 #ifdef CGEN_MNEMONIC_OPERANDS
    835       (void) past_opcode_p;
    836 #endif
    837       /* We have an operand of some sort.  */
    838       errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
    839       if (errmsg)
    840 	return errmsg;
    841 
    842       /* Done with this operand, continue with next one.  */
    843       ++ syn;
    844     }
    845 
    846   /* If we're at the end of the syntax string, we're done.  */
    847   if (* syn == 0)
    848     {
    849       /* FIXME: For the moment we assume a valid `str' can only contain
    850 	 blanks now.  IE: We needn't try again with a longer version of
    851 	 the insn and it is assumed that longer versions of insns appear
    852 	 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
    853       while (ISSPACE (* str))
    854 	++ str;
    855 
    856       if (* str != '\0')
    857 	return _("junk at end of line"); /* FIXME: would like to include `str' */
    858 
    859       return NULL;
    860     }
    861 
    862   /* We couldn't parse it.  */
    863   return _("unrecognized instruction");
    864 }
    865 
    866 /* Main entry point.
    868    This routine is called for each instruction to be assembled.
    869    STR points to the insn to be assembled.
    870    We assume all necessary tables have been initialized.
    871    The assembled instruction, less any fixups, is stored in BUF.
    872    Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
    873    still needs to be converted to target byte order, otherwise BUF is an array
    874    of bytes in target byte order.
    875    The result is a pointer to the insn's entry in the opcode table,
    876    or NULL if an error occured (an error message will have already been
    877    printed).
    878 
    879    Note that when processing (non-alias) macro-insns,
    880    this function recurses.
    881 
    882    ??? It's possible to make this cpu-independent.
    883    One would have to deal with a few minor things.
    884    At this point in time doing so would be more of a curiosity than useful
    885    [for example this file isn't _that_ big], but keeping the possibility in
    886    mind helps keep the design clean.  */
    887 
    888 const CGEN_INSN *
    889 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
    890 			   const char *str,
    891 			   CGEN_FIELDS *fields,
    892 			   CGEN_INSN_BYTES_PTR buf,
    893 			   char **errmsg)
    894 {
    895   const char *start;
    896   CGEN_INSN_LIST *ilist;
    897   const char *parse_errmsg = NULL;
    898   const char *insert_errmsg = NULL;
    899   int recognized_mnemonic = 0;
    900 
    901   /* Skip leading white space.  */
    902   while (ISSPACE (* str))
    903     ++ str;
    904 
    905   /* The instructions are stored in hashed lists.
    906      Get the first in the list.  */
    907   ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
    908 
    909   /* Keep looking until we find a match.  */
    910   start = str;
    911   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
    912     {
    913       const CGEN_INSN *insn = ilist->insn;
    914       recognized_mnemonic = 1;
    915 
    916 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
    917       /* Not usually needed as unsupported opcodes
    918 	 shouldn't be in the hash lists.  */
    919       /* Is this insn supported by the selected cpu?  */
    920       if (! or1k_cgen_insn_supported (cd, insn))
    921 	continue;
    922 #endif
    923       /* If the RELAXED attribute is set, this is an insn that shouldn't be
    924 	 chosen immediately.  Instead, it is used during assembler/linker
    925 	 relaxation if possible.  */
    926       if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
    927 	continue;
    928 
    929       str = start;
    930 
    931       /* Skip this insn if str doesn't look right lexically.  */
    932       if (CGEN_INSN_RX (insn) != NULL &&
    933 	  regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
    934 	continue;
    935 
    936       /* Allow parse/insert handlers to obtain length of insn.  */
    937       CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
    938 
    939       parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
    940       if (parse_errmsg != NULL)
    941 	continue;
    942 
    943       /* ??? 0 is passed for `pc'.  */
    944       insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
    945 						 (bfd_vma) 0);
    946       if (insert_errmsg != NULL)
    947         continue;
    948 
    949       /* It is up to the caller to actually output the insn and any
    950          queued relocs.  */
    951       return insn;
    952     }
    953 
    954   {
    955     static char errbuf[150];
    956     const char *tmp_errmsg;
    957 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
    958 #define be_verbose 1
    959 #else
    960 #define be_verbose 0
    961 #endif
    962 
    963     if (be_verbose)
    964       {
    965 	/* If requesting verbose error messages, use insert_errmsg.
    966 	   Failing that, use parse_errmsg.  */
    967 	tmp_errmsg = (insert_errmsg ? insert_errmsg :
    968 		      parse_errmsg ? parse_errmsg :
    969 		      recognized_mnemonic ?
    970 		      _("unrecognized form of instruction") :
    971 		      _("unrecognized instruction"));
    972 
    973 	if (strlen (start) > 50)
    974 	  /* xgettext:c-format */
    975 	  sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
    976 	else
    977 	  /* xgettext:c-format */
    978 	  sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
    979       }
    980     else
    981       {
    982 	if (strlen (start) > 50)
    983 	  /* xgettext:c-format */
    984 	  sprintf (errbuf, _("bad instruction `%.50s...'"), start);
    985 	else
    986 	  /* xgettext:c-format */
    987 	  sprintf (errbuf, _("bad instruction `%.50s'"), start);
    988       }
    989 
    990     *errmsg = errbuf;
    991     return NULL;
    992   }
    993 }
    994