1*3d8817e4Smiod/* IQ2000 opcode support.  -*- C -*-
2*3d8817e4Smiod
3*3d8817e4Smiod   Copyright 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
4*3d8817e4Smiod
5*3d8817e4Smiod   Contributed by Red Hat Inc; developed under contract from Fujitsu.
6*3d8817e4Smiod
7*3d8817e4Smiod   This file is part of the GNU Binutils.
8*3d8817e4Smiod
9*3d8817e4Smiod   This program is free software; you can redistribute it and/or modify
10*3d8817e4Smiod   it under the terms of the GNU General Public License as published by
11*3d8817e4Smiod   the Free Software Foundation; either version 2 of the License, or
12*3d8817e4Smiod   (at your option) any later version.
13*3d8817e4Smiod
14*3d8817e4Smiod   This program is distributed in the hope that it will be useful,
15*3d8817e4Smiod   but WITHOUT ANY WARRANTY; without even the implied warranty of
16*3d8817e4Smiod   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*3d8817e4Smiod   GNU General Public License for more details.
18*3d8817e4Smiod
19*3d8817e4Smiod   You should have received a copy of the GNU General Public License
20*3d8817e4Smiod   along with this program; if not, write to the Free Software
21*3d8817e4Smiod   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22*3d8817e4Smiod   MA 02110-1301, USA.  */
23*3d8817e4Smiod
24*3d8817e4Smiod/* This file is an addendum to iq2000.cpu.  Heavy use of C code isn't
25*3d8817e4Smiod   appropriate in .cpu files, so it resides here.  This especially applies
26*3d8817e4Smiod   to assembly/disassembly where parsing/printing can be quite involved.
27*3d8817e4Smiod   Such things aren't really part of the specification of the cpu, per se,
28*3d8817e4Smiod   so .cpu files provide the general framework and .opc files handle the
29*3d8817e4Smiod   nitty-gritty details as necessary.
30*3d8817e4Smiod
31*3d8817e4Smiod   Each section is delimited with start and end markers.
32*3d8817e4Smiod
33*3d8817e4Smiod   <arch>-opc.h additions use: "-- opc.h"
34*3d8817e4Smiod   <arch>-opc.c additions use: "-- opc.c"
35*3d8817e4Smiod   <arch>-asm.c additions use: "-- asm.c"
36*3d8817e4Smiod   <arch>-dis.c additions use: "-- dis.c"
37*3d8817e4Smiod   <arch>-ibd.h additions use: "-- ibd.h".  */
38*3d8817e4Smiod
39*3d8817e4Smiod/* -- opc.h */
40*3d8817e4Smiod
41*3d8817e4Smiod/* Allows reason codes to be output when assembler errors occur.  */
42*3d8817e4Smiod#define CGEN_VERBOSE_ASSEMBLER_ERRORS
43*3d8817e4Smiod
44*3d8817e4Smiod/* Override disassembly hashing - there are variable bits in the top
45*3d8817e4Smiod   byte of these instructions.  */
46*3d8817e4Smiod#define CGEN_DIS_HASH_SIZE 8
47*3d8817e4Smiod#define CGEN_DIS_HASH(buf,value) (((* (unsigned char*) (buf)) >> 6) % CGEN_DIS_HASH_SIZE)
48*3d8817e4Smiod
49*3d8817e4Smiod/* following activates check beyond hashing since some iq2000 and iq10
50*3d8817e4Smiod   instructions have same mnemonics but different functionality. */
51*3d8817e4Smiod#define CGEN_VALIDATE_INSN_SUPPORTED
52*3d8817e4Smiod
53*3d8817e4Smiodextern int iq2000_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
54*3d8817e4Smiod
55*3d8817e4Smiod/* -- asm.c */
56*3d8817e4Smiod
57*3d8817e4Smiod#include "safe-ctype.h"
58*3d8817e4Smiod
59*3d8817e4Smiodstatic const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
60*3d8817e4Smiod
61*3d8817e4Smiod/* Special check to ensure that instruction exists for given machine.  */
62*3d8817e4Smiod
63*3d8817e4Smiodint
64*3d8817e4Smiodiq2000_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
65*3d8817e4Smiod{
66*3d8817e4Smiod  int machs = cd->machs;
67*3d8817e4Smiod
68*3d8817e4Smiod  return (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH) & machs) != 0;
69*3d8817e4Smiod}
70*3d8817e4Smiod
71*3d8817e4Smiodstatic int
72*3d8817e4Smiodiq2000_cgen_isa_register (const char **strp)
73*3d8817e4Smiod{
74*3d8817e4Smiod  int len;
75*3d8817e4Smiod  int ch1, ch2;
76*3d8817e4Smiod
77*3d8817e4Smiod  if (**strp == 'r' || **strp == 'R')
78*3d8817e4Smiod    {
79*3d8817e4Smiod      len = strlen (*strp);
80*3d8817e4Smiod      if (len == 2)
81*3d8817e4Smiod        {
82*3d8817e4Smiod          ch1 = (*strp)[1];
83*3d8817e4Smiod          if ('0' <= ch1 && ch1 <= '9')
84*3d8817e4Smiod            return 1;
85*3d8817e4Smiod        }
86*3d8817e4Smiod      else if (len == 3)
87*3d8817e4Smiod        {
88*3d8817e4Smiod	  ch1 = (*strp)[1];
89*3d8817e4Smiod          ch2 = (*strp)[2];
90*3d8817e4Smiod          if (('1' <= ch1 && ch1 <= '2') && ('0' <= ch2 && ch2 <= '9'))
91*3d8817e4Smiod            return 1;
92*3d8817e4Smiod          if ('3' == ch1 && (ch2 == '0' || ch2 == '1'))
93*3d8817e4Smiod            return 1;
94*3d8817e4Smiod        }
95*3d8817e4Smiod    }
96*3d8817e4Smiod  if (**strp == '%'
97*3d8817e4Smiod      && TOLOWER ((*strp)[1]) != 'l'
98*3d8817e4Smiod      && TOLOWER ((*strp)[1]) != 'h')
99*3d8817e4Smiod    return 1;
100*3d8817e4Smiod  return 0;
101*3d8817e4Smiod}
102*3d8817e4Smiod
103*3d8817e4Smiod/* Handle negated literal.  */
104*3d8817e4Smiod
105*3d8817e4Smiodstatic const char *
106*3d8817e4Smiodparse_mimm (CGEN_CPU_DESC cd,
107*3d8817e4Smiod	    const char **strp,
108*3d8817e4Smiod	    int opindex,
109*3d8817e4Smiod	    unsigned long *valuep)
110*3d8817e4Smiod{
111*3d8817e4Smiod  const char *errmsg;
112*3d8817e4Smiod
113*3d8817e4Smiod  /* Verify this isn't a register.  */
114*3d8817e4Smiod  if (iq2000_cgen_isa_register (strp))
115*3d8817e4Smiod    errmsg = _("immediate value cannot be register");
116*3d8817e4Smiod  else
117*3d8817e4Smiod    {
118*3d8817e4Smiod      long value;
119*3d8817e4Smiod
120*3d8817e4Smiod      errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
121*3d8817e4Smiod      if (errmsg == NULL)
122*3d8817e4Smiod	{
123*3d8817e4Smiod	  long x = (-value) & 0xFFFF0000;
124*3d8817e4Smiod
125*3d8817e4Smiod	  if (x != 0 && x != (long) 0xFFFF0000)
126*3d8817e4Smiod	    errmsg = _("immediate value out of range");
127*3d8817e4Smiod	  else
128*3d8817e4Smiod	    *valuep = (-value & 0xFFFF);
129*3d8817e4Smiod	}
130*3d8817e4Smiod    }
131*3d8817e4Smiod  return errmsg;
132*3d8817e4Smiod}
133*3d8817e4Smiod
134*3d8817e4Smiod/* Handle signed/unsigned literal.  */
135*3d8817e4Smiod
136*3d8817e4Smiodstatic const char *
137*3d8817e4Smiodparse_imm (CGEN_CPU_DESC cd,
138*3d8817e4Smiod	   const char **strp,
139*3d8817e4Smiod	   int opindex,
140*3d8817e4Smiod	   unsigned long *valuep)
141*3d8817e4Smiod{
142*3d8817e4Smiod  const char *errmsg;
143*3d8817e4Smiod
144*3d8817e4Smiod  if (iq2000_cgen_isa_register (strp))
145*3d8817e4Smiod    errmsg = _("immediate value cannot be register");
146*3d8817e4Smiod  else
147*3d8817e4Smiod    {
148*3d8817e4Smiod      long value;
149*3d8817e4Smiod
150*3d8817e4Smiod      errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
151*3d8817e4Smiod      if (errmsg == NULL)
152*3d8817e4Smiod	{
153*3d8817e4Smiod	  long x = value & 0xFFFF0000;
154*3d8817e4Smiod
155*3d8817e4Smiod	  if (x != 0 && x != (long) 0xFFFF0000)
156*3d8817e4Smiod	    errmsg = _("immediate value out of range");
157*3d8817e4Smiod	  else
158*3d8817e4Smiod	    *valuep = (value & 0xFFFF);
159*3d8817e4Smiod	}
160*3d8817e4Smiod    }
161*3d8817e4Smiod  return errmsg;
162*3d8817e4Smiod}
163*3d8817e4Smiod
164*3d8817e4Smiod/* Handle iq10 21-bit jmp offset.  */
165*3d8817e4Smiod
166*3d8817e4Smiodstatic const char *
167*3d8817e4Smiodparse_jtargq10 (CGEN_CPU_DESC cd,
168*3d8817e4Smiod		const char **strp,
169*3d8817e4Smiod		int opindex,
170*3d8817e4Smiod		int reloc ATTRIBUTE_UNUSED,
171*3d8817e4Smiod		enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED,
172*3d8817e4Smiod		bfd_vma *valuep)
173*3d8817e4Smiod{
174*3d8817e4Smiod  const char *errmsg;
175*3d8817e4Smiod  bfd_vma value;
176*3d8817e4Smiod  enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER;
177*3d8817e4Smiod
178*3d8817e4Smiod  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21,
179*3d8817e4Smiod			       & result_type, & value);
180*3d8817e4Smiod  if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
181*3d8817e4Smiod    {
182*3d8817e4Smiod      /* Check value is within 23-bits
183*3d8817e4Smiod	 (remembering that 2-bit shift right will occur).  */
184*3d8817e4Smiod      if (value > 0x7fffff)
185*3d8817e4Smiod        return _("21-bit offset out of range");
186*3d8817e4Smiod    }
187*3d8817e4Smiod  *valuep = (value & 0x7FFFFF);
188*3d8817e4Smiod  return errmsg;
189*3d8817e4Smiod}
190*3d8817e4Smiod
191*3d8817e4Smiod/* Handle high().  */
192*3d8817e4Smiod
193*3d8817e4Smiodstatic const char *
194*3d8817e4Smiodparse_hi16 (CGEN_CPU_DESC cd,
195*3d8817e4Smiod	    const char **strp,
196*3d8817e4Smiod	    int opindex,
197*3d8817e4Smiod	    unsigned long *valuep)
198*3d8817e4Smiod{
199*3d8817e4Smiod  if (strncasecmp (*strp, "%hi(", 4) == 0)
200*3d8817e4Smiod    {
201*3d8817e4Smiod      enum cgen_parse_operand_result result_type;
202*3d8817e4Smiod      bfd_vma value;
203*3d8817e4Smiod      const char *errmsg;
204*3d8817e4Smiod
205*3d8817e4Smiod      *strp += 4;
206*3d8817e4Smiod      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
207*3d8817e4Smiod				   & result_type, & value);
208*3d8817e4Smiod      if (**strp != ')')
209*3d8817e4Smiod	return MISSING_CLOSING_PARENTHESIS;
210*3d8817e4Smiod
211*3d8817e4Smiod      ++*strp;
212*3d8817e4Smiod      if (errmsg == NULL
213*3d8817e4Smiod  	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
214*3d8817e4Smiod	{
215*3d8817e4Smiod	  /* If value has top-bit of %lo on, then it will
216*3d8817e4Smiod	     sign-propagate and so we compensate by adding
217*3d8817e4Smiod	     1 to the resultant %hi value.  */
218*3d8817e4Smiod	  if (value & 0x8000)
219*3d8817e4Smiod	    value += 0x10000;
220*3d8817e4Smiod	  value >>= 16;
221*3d8817e4Smiod	  value &= 0xffff;
222*3d8817e4Smiod	}
223*3d8817e4Smiod      *valuep = value;
224*3d8817e4Smiod
225*3d8817e4Smiod      return errmsg;
226*3d8817e4Smiod    }
227*3d8817e4Smiod
228*3d8817e4Smiod  /* We add %uhi in case a user just wants the high 16-bits or is using
229*3d8817e4Smiod     an insn like ori for %lo which does not sign-propagate.  */
230*3d8817e4Smiod  if (strncasecmp (*strp, "%uhi(", 5) == 0)
231*3d8817e4Smiod    {
232*3d8817e4Smiod      enum cgen_parse_operand_result result_type;
233*3d8817e4Smiod      bfd_vma value;
234*3d8817e4Smiod      const char *errmsg;
235*3d8817e4Smiod
236*3d8817e4Smiod      *strp += 5;
237*3d8817e4Smiod      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_UHI16,
238*3d8817e4Smiod				   & result_type, & value);
239*3d8817e4Smiod      if (**strp != ')')
240*3d8817e4Smiod	return MISSING_CLOSING_PARENTHESIS;
241*3d8817e4Smiod
242*3d8817e4Smiod      ++*strp;
243*3d8817e4Smiod      if (errmsg == NULL
244*3d8817e4Smiod  	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
245*3d8817e4Smiod	value >>= 16;
246*3d8817e4Smiod
247*3d8817e4Smiod      value &= 0xffff;
248*3d8817e4Smiod      *valuep = value;
249*3d8817e4Smiod
250*3d8817e4Smiod      return errmsg;
251*3d8817e4Smiod    }
252*3d8817e4Smiod
253*3d8817e4Smiod  return parse_imm (cd, strp, opindex, valuep);
254*3d8817e4Smiod}
255*3d8817e4Smiod
256*3d8817e4Smiod/* Handle %lo in a signed context.
257*3d8817e4Smiod   The signedness of the value doesn't matter to %lo(), but this also
258*3d8817e4Smiod   handles the case where %lo() isn't present.  */
259*3d8817e4Smiod
260*3d8817e4Smiodstatic const char *
261*3d8817e4Smiodparse_lo16 (CGEN_CPU_DESC cd,
262*3d8817e4Smiod	    const char **strp,
263*3d8817e4Smiod	    int opindex,
264*3d8817e4Smiod	    unsigned long *valuep)
265*3d8817e4Smiod{
266*3d8817e4Smiod  if (strncasecmp (*strp, "%lo(", 4) == 0)
267*3d8817e4Smiod    {
268*3d8817e4Smiod      const char *errmsg;
269*3d8817e4Smiod      enum cgen_parse_operand_result result_type;
270*3d8817e4Smiod      bfd_vma value;
271*3d8817e4Smiod
272*3d8817e4Smiod      *strp += 4;
273*3d8817e4Smiod      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
274*3d8817e4Smiod				   & result_type, & value);
275*3d8817e4Smiod      if (**strp != ')')
276*3d8817e4Smiod	return MISSING_CLOSING_PARENTHESIS;
277*3d8817e4Smiod      ++*strp;
278*3d8817e4Smiod      if (errmsg == NULL
279*3d8817e4Smiod	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
280*3d8817e4Smiod	value &= 0xffff;
281*3d8817e4Smiod      *valuep = value;
282*3d8817e4Smiod      return errmsg;
283*3d8817e4Smiod    }
284*3d8817e4Smiod
285*3d8817e4Smiod  return parse_imm (cd, strp, opindex, valuep);
286*3d8817e4Smiod}
287*3d8817e4Smiod
288*3d8817e4Smiod/* Handle %lo in a negated signed context.
289*3d8817e4Smiod   The signedness of the value doesn't matter to %lo(), but this also
290*3d8817e4Smiod   handles the case where %lo() isn't present.  */
291*3d8817e4Smiod
292*3d8817e4Smiodstatic const char *
293*3d8817e4Smiodparse_mlo16 (CGEN_CPU_DESC cd,
294*3d8817e4Smiod	     const char **strp,
295*3d8817e4Smiod	     int opindex,
296*3d8817e4Smiod	     unsigned long *valuep)
297*3d8817e4Smiod{
298*3d8817e4Smiod  if (strncasecmp (*strp, "%lo(", 4) == 0)
299*3d8817e4Smiod    {
300*3d8817e4Smiod      const char *errmsg;
301*3d8817e4Smiod      enum cgen_parse_operand_result result_type;
302*3d8817e4Smiod      bfd_vma value;
303*3d8817e4Smiod
304*3d8817e4Smiod      *strp += 4;
305*3d8817e4Smiod      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
306*3d8817e4Smiod				   & result_type, & value);
307*3d8817e4Smiod      if (**strp != ')')
308*3d8817e4Smiod	return MISSING_CLOSING_PARENTHESIS;
309*3d8817e4Smiod      ++*strp;
310*3d8817e4Smiod      if (errmsg == NULL
311*3d8817e4Smiod	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
312*3d8817e4Smiod	value = (-value) & 0xffff;
313*3d8817e4Smiod      *valuep = value;
314*3d8817e4Smiod      return errmsg;
315*3d8817e4Smiod    }
316*3d8817e4Smiod
317*3d8817e4Smiod  return parse_mimm (cd, strp, opindex, valuep);
318*3d8817e4Smiod}
319*3d8817e4Smiod
320*3d8817e4Smiod/* -- */
321