Home | History | Annotate | Download | only in cpu
      1 /* XSTORMY16 opcode support.  -*- C -*-
      2    Copyright 2011 Free Software Foundation, Inc.
      3 
      4    Contributed by Red Hat Inc;
      5 
      6    This file is part of the GNU Binutils.
      7 
      8    This program is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 3 of the License, or
     11    (at your option) any later version.
     12 
     13    This program is distributed in the hope that it will be useful,
     14    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16    GNU General Public License for more details.
     17 
     18    You should have received a copy of the GNU General Public License
     19    along with this program; if not, write to the Free Software
     20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21    MA 02110-1301, USA.  */
     22 
     23 /* This file is an addendum to xstormy16.cpu.  Heavy use of C code isn't
     24    appropriate in .cpu files, so it resides here.  This especially applies
     25    to assembly/disassembly where parsing/printing can be quite involved.
     26    Such things aren't really part of the specification of the cpu, per se,
     27    so .cpu files provide the general framework and .opc files handle the
     28    nitty-gritty details as necessary.
     29 
     30    Each section is delimited with start and end markers.
     31 
     32    <arch>-opc.h additions use: "-- opc.h"
     33    <arch>-opc.c additions use: "-- opc.c"
     34    <arch>-asm.c additions use: "-- asm.c"
     35    <arch>-dis.c additions use: "-- dis.c"
     36    <arch>-ibd.h additions use: "-- ibd.h".  */
     37 
     38 /* -- opc.h */
     40 
     41 /* Allows reason codes to be output when assembler errors occur.  */
     42 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
     43 
     44 /* We can't use the default hash size because many bits are used by
     45    operands.  */
     46 #define CGEN_DIS_HASH_SIZE 1
     47 #define CGEN_DIS_HASH(buf, value) 0
     48 /* -- */
     49 
     50 /* -- asm.c */
     52 
     53 /* The machine-independent code doesn't know how to disambiguate
     54      mov (foo),r3
     55    and
     56      mov (r2),r3
     57    where 'foo' is a label.  This helps it out. */
     58 
     59 static const char *
     60 parse_mem8 (CGEN_CPU_DESC cd,
     61 	    const char **strp,
     62 	    int opindex,
     63 	    unsigned long *valuep)
     64 {
     65   if (**strp == '(')
     66     {
     67       const char *s = *strp;
     68 
     69       if (s[1] == '-' && s[2] == '-')
     70 	return _("Bad register in preincrement");
     71 
     72       while (ISALNUM (*++s))
     73 	;
     74       if (s[0] == '+' && s[1] == '+' && (s[2] == ')' || s[2] == ','))
     75 	return _("Bad register in postincrement");
     76       if (s[0] == ',' || s[0] == ')')
     77 	return _("Bad register name");
     78     }
     79   else if (cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names,
     80 			       (long *) valuep) == NULL)
     81     return _("Label conflicts with register name");
     82   else if (strncasecmp (*strp, "rx,", 3) == 0
     83 	   || strncasecmp (*strp, "rxl,", 3) == 0
     84 	   || strncasecmp (*strp, "rxh,", 3) == 0)
     85     return _("Label conflicts with `Rx'");
     86   else if (**strp == '#')
     87     return _("Bad immediate expression");
     88 
     89   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
     90 }
     91 
     92 /* For the add and subtract instructions, there are two immediate forms,
     93    one for small operands and one for large ones.  We want to use
     94    the small one when possible, but we do not want to generate relocs
     95    of the small size.  This is somewhat tricky.  */
     96 
     97 static const char *
     98 parse_small_immediate (CGEN_CPU_DESC cd,
     99 		       const char **strp,
    100 		       int opindex,
    101 		       unsigned long *valuep)
    102 {
    103   bfd_vma value;
    104   enum cgen_parse_operand_result result;
    105   const char *errmsg;
    106 
    107   if (**strp == '@')
    108     return _("No relocation for small immediate");
    109 
    110   errmsg = (* cd->parse_operand_fn)
    111     (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE,
    112      & result, & value);
    113 
    114   if (errmsg)
    115     return errmsg;
    116 
    117   if (result != CGEN_PARSE_OPERAND_RESULT_NUMBER)
    118     return _("Small operand was not an immediate number");
    119 
    120   *valuep = value;
    121   return NULL;
    122 }
    123 
    124 /* Literal scan be either a normal literal, a @hi() or @lo relocation.  */
    125 
    126 static const char *
    127 parse_immediate16 (CGEN_CPU_DESC cd,
    128 		   const char **strp,
    129 		   int opindex,
    130 		   unsigned long *valuep)
    131 {
    132   const char *errmsg;
    133   enum cgen_parse_operand_result result;
    134   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
    135   bfd_vma value;
    136 
    137   if (strncmp (*strp, "@hi(", 4) == 0)
    138     {
    139       *strp += 4;
    140       code = BFD_RELOC_HI16;
    141     }
    142   else
    143   if (strncmp (*strp, "@lo(", 4) == 0)
    144     {
    145       *strp += 4;
    146       code = BFD_RELOC_LO16;
    147     }
    148 
    149   if (code == BFD_RELOC_NONE)
    150     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
    151   else
    152     {
    153       errmsg = cgen_parse_address (cd, strp, opindex, code, &result, &value);
    154       if ((errmsg == NULL) &&
    155 	  (result != CGEN_PARSE_OPERAND_RESULT_QUEUED))
    156 	errmsg = _("Operand is not a symbol");
    157 
    158       *valuep = value;
    159       if ((code == BFD_RELOC_HI16 || code == BFD_RELOC_LO16)
    160 	  && **strp == ')')
    161 	*strp += 1;
    162       else
    163         {
    164 	  errmsg = _("Syntax error: No trailing ')'");
    165 	  return errmsg;
    166 	}
    167     }
    168   return errmsg;
    169 }
    170 /* -- */
    171