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