xref: /netbsd-src/external/gpl3/binutils.old/dist/cpu/epiphany.opc (revision 16dce51364ebe8aeafbae46bc5aa167b8115bc45)
1*16dce513Schristos/* Adapteva epiphany opcode support.  -*- C -*-
2*16dce513Schristos
3*16dce513Schristos   Copyright 2009, 2011 Free Software Foundation, Inc.
4*16dce513Schristos
5*16dce513Schristos   Contributed by Embecosm on behalf of Adapteva, Inc.
6*16dce513Schristos
7*16dce513Schristos   This file is part of the GNU Binutils and of GDB.
8*16dce513Schristos
9*16dce513Schristos   This program is free software; you can redistribute it and/or modify
10*16dce513Schristos   it under the terms of the GNU General Public License as published by
11*16dce513Schristos   the Free Software Foundation; either version 3 of the License, or
12*16dce513Schristos   (at your option) any later version.
13*16dce513Schristos
14*16dce513Schristos   This program is distributed in the hope that it will be useful,
15*16dce513Schristos   but WITHOUT ANY WARRANTY; without even the implied warranty of
16*16dce513Schristos   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*16dce513Schristos   GNU General Public License for more details.
18*16dce513Schristos
19*16dce513Schristos   You should have received a copy of the GNU General Public License
20*16dce513Schristos   along with this program; if not, write to the Free Software
21*16dce513Schristos   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22*16dce513Schristos   MA 02110-1301, USA.  */
23*16dce513Schristos
24*16dce513Schristos/*
25*16dce513Schristos   Each section is delimited with start and end markers.
26*16dce513Schristos
27*16dce513Schristos   <arch>-opc.h additions use: "-- opc.h"
28*16dce513Schristos   <arch>-opc.c additions use: "-- opc.c"
29*16dce513Schristos   <arch>-asm.c additions use: "-- asm.c"
30*16dce513Schristos   <arch>-dis.c additions use: "-- dis.c"
31*16dce513Schristos   <arch>-ibd.h additions use: "-- ibd.h".  */
32*16dce513Schristos
33*16dce513Schristos/* -- opc.h */
34*16dce513Schristos
35*16dce513Schristos/* enumerate relaxation types for gas. */
36*16dce513Schristostypedef enum epiphany_relax_types
37*16dce513Schristos{
38*16dce513Schristos  EPIPHANY_RELAX_NONE=0,
39*16dce513Schristos  EPIPHANY_RELAX_NEED_RELAXING,
40*16dce513Schristos
41*16dce513Schristos  EPIPHANY_RELAX_BRANCH_SHORT,	/* Fits into +127..-128 */
42*16dce513Schristos  EPIPHANY_RELAX_BRANCH_LONG,	/* b/bl/b<cond> +-2*16 */
43*16dce513Schristos
44*16dce513Schristos  EPIPHANY_RELAX_ARITH_SIMM3,	/* add/sub -7..3 */
45*16dce513Schristos  EPIPHANY_RELAX_ARITH_SIMM11,	/* add/sub -2**11-1 .. 2**10-1 */
46*16dce513Schristos
47*16dce513Schristos  EPIPHANY_RELAX_MOV_IMM8,		/* mov r,imm8 */
48*16dce513Schristos  EPIPHANY_RELAX_MOV_IMM16,	/* mov r,imm16 */
49*16dce513Schristos
50*16dce513Schristos  EPIPHANY_RELAX_LDST_IMM3,	/* (ldr|str)* r,[r,disp3] */
51*16dce513Schristos  EPIPHANY_RELAX_LDST_IMM11	/* (ldr|str)* r,[r,disp11] */
52*16dce513Schristos
53*16dce513Schristos} EPIPHANY_RELAX_TYPES;
54*16dce513Schristos
55*16dce513Schristos/* Override disassembly hashing... */
56*16dce513Schristos
57*16dce513Schristos/* Can only depend on instruction having 4 decode bits which gets us to the
58*16dce513Schristos   major groups of 16/32 instructions. */
59*16dce513Schristos#undef CGEN_DIS_HASH_SIZE
60*16dce513Schristos#if 1
61*16dce513Schristos
62*16dce513Schristos/* hash code on the 4 LSBs */
63*16dce513Schristos#define CGEN_DIS_HASH_SIZE 16
64*16dce513Schristos
65*16dce513Schristos#define CGEN_DIS_HASH(buf, value) ((*buf) & 0xf)
66*16dce513Schristos#else
67*16dce513Schristos#define CGEN_DIS_HASH_SIZE 1
68*16dce513Schristos#define CGEN_DIS_HASH(buf, value) 0
69*16dce513Schristos#endif
70*16dce513Schristos
71*16dce513Schristosextern const char * parse_shortregs (CGEN_CPU_DESC cd,
72*16dce513Schristos				     const char ** strp,
73*16dce513Schristos				     CGEN_KEYWORD * keywords,
74*16dce513Schristos				     long * valuep);
75*16dce513Schristos
76*16dce513Schristosextern const char * parse_branch_addr (CGEN_CPU_DESC cd,
77*16dce513Schristos				       const char ** strp,
78*16dce513Schristos				       int opindex,
79*16dce513Schristos				       int opinfo,
80*16dce513Schristos				       enum cgen_parse_operand_result * resultp,
81*16dce513Schristos				       bfd_vma *valuep);
82*16dce513Schristos
83*16dce513Schristos/* Allows reason codes to be output when assembler errors occur.  */
84*16dce513Schristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS
85*16dce513Schristos
86*16dce513Schristos
87*16dce513Schristos/* -- opc.c */
88*16dce513Schristos
89*16dce513Schristos
90*16dce513Schristos
91*16dce513Schristos/* -- asm.c */
92*16dce513Schristosconst char *
93*16dce513Schristosparse_shortregs (CGEN_CPU_DESC cd,
94*16dce513Schristos		 const char ** strp,
95*16dce513Schristos		 CGEN_KEYWORD * keywords,
96*16dce513Schristos		 long * regno)
97*16dce513Schristos{
98*16dce513Schristos  const char * errmsg;
99*16dce513Schristos
100*16dce513Schristos  /* Parse register.  */
101*16dce513Schristos  errmsg = cgen_parse_keyword (cd, strp, keywords, regno);
102*16dce513Schristos
103*16dce513Schristos  if (errmsg)
104*16dce513Schristos    return errmsg;
105*16dce513Schristos
106*16dce513Schristos  if (*regno > 7)
107*16dce513Schristos    errmsg = _("register unavailable for short instructions");
108*16dce513Schristos
109*16dce513Schristos  return errmsg;
110*16dce513Schristos}
111*16dce513Schristos
112*16dce513Schristosstatic const char * parse_simm_not_reg (CGEN_CPU_DESC, const char **, int,
113*16dce513Schristos					long *);
114*16dce513Schristos
115*16dce513Schristosstatic const char *
116*16dce513Schristosparse_uimm_not_reg (CGEN_CPU_DESC cd,
117*16dce513Schristos		    const char ** strp,
118*16dce513Schristos		    int opindex,
119*16dce513Schristos		    unsigned long * valuep)
120*16dce513Schristos{
121*16dce513Schristos  long * svalp = (void *) valuep;
122*16dce513Schristos  return parse_simm_not_reg (cd, strp, opindex, svalp);
123*16dce513Schristos}
124*16dce513Schristos
125*16dce513Schristos/* Handle simm3/simm11/imm3/imm12.  */
126*16dce513Schristos
127*16dce513Schristosstatic const char *
128*16dce513Schristosparse_simm_not_reg (CGEN_CPU_DESC cd,
129*16dce513Schristos		   const char ** strp,
130*16dce513Schristos		   int opindex,
131*16dce513Schristos		   long * valuep)
132*16dce513Schristos{
133*16dce513Schristos  const char * errmsg;
134*16dce513Schristos
135*16dce513Schristos  int   sign = 0;
136*16dce513Schristos  int   bits = 0;
137*16dce513Schristos
138*16dce513Schristos  switch (opindex)
139*16dce513Schristos    {
140*16dce513Schristos    case EPIPHANY_OPERAND_SIMM3:
141*16dce513Schristos      sign = 1; bits = 3; break;
142*16dce513Schristos    case EPIPHANY_OPERAND_SIMM11:
143*16dce513Schristos      sign = 1; bits = 11; break;
144*16dce513Schristos    case EPIPHANY_OPERAND_DISP3:
145*16dce513Schristos      sign = 0; bits = 3; break;
146*16dce513Schristos    case EPIPHANY_OPERAND_DISP11:
147*16dce513Schristos      /* Load/store displacement is a sign-magnitude 12 bit value.  */
148*16dce513Schristos      sign = 0; bits = 11; break;
149*16dce513Schristos    }
150*16dce513Schristos
151*16dce513Schristos  /* First try to parse as a register name and reject the operand.  */
152*16dce513Schristos  errmsg = cgen_parse_keyword (cd, strp, & epiphany_cgen_opval_gr_names,valuep);
153*16dce513Schristos  if (!errmsg)
154*16dce513Schristos    return _("register name used as immediate value");
155*16dce513Schristos
156*16dce513Schristos  errmsg = (sign ? cgen_parse_signed_integer (cd, strp, opindex, valuep)
157*16dce513Schristos	    : cgen_parse_unsigned_integer (cd, strp, opindex,
158*16dce513Schristos					  (unsigned long *) valuep));
159*16dce513Schristos  if (errmsg)
160*16dce513Schristos    return errmsg;
161*16dce513Schristos
162*16dce513Schristos  if (sign)
163*16dce513Schristos    errmsg = cgen_validate_signed_integer (*valuep,
164*16dce513Schristos					  -((1L << bits) - 1), (1 << (bits - 1)) - 1);
165*16dce513Schristos  else
166*16dce513Schristos    errmsg = cgen_validate_unsigned_integer (*valuep, 0, (1L << bits) - 1);
167*16dce513Schristos
168*16dce513Schristos  return errmsg;
169*16dce513Schristos}
170*16dce513Schristos
171*16dce513Schristosstatic const char *
172*16dce513Schristosparse_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
173*16dce513Schristos		 const char ** strp,
174*16dce513Schristos		 int opindex ATTRIBUTE_UNUSED,
175*16dce513Schristos		 unsigned long *valuep)
176*16dce513Schristos{
177*16dce513Schristos  if (**strp == '#')
178*16dce513Schristos    ++*strp;			/* Skip leading hashes.  */
179*16dce513Schristos
180*16dce513Schristos  if (**strp == '-')
181*16dce513Schristos    {
182*16dce513Schristos      *valuep = 1;
183*16dce513Schristos      ++*strp;
184*16dce513Schristos    }
185*16dce513Schristos  else if (**strp == '+')
186*16dce513Schristos    {
187*16dce513Schristos      *valuep = 0;
188*16dce513Schristos      ++*strp;
189*16dce513Schristos    }
190*16dce513Schristos  else
191*16dce513Schristos    *valuep = 0;
192*16dce513Schristos
193*16dce513Schristos  return NULL;
194*16dce513Schristos}
195*16dce513Schristos
196*16dce513Schristosstatic const char *
197*16dce513Schristosparse_imm8 (CGEN_CPU_DESC cd,
198*16dce513Schristos	    const char ** strp,
199*16dce513Schristos	    int opindex,
200*16dce513Schristos	    bfd_reloc_code_real_type code,
201*16dce513Schristos	    enum cgen_parse_operand_result * result_type,
202*16dce513Schristos	    bfd_vma * valuep)
203*16dce513Schristos{
204*16dce513Schristos  const char * errmsg;
205*16dce513Schristos  enum cgen_parse_operand_result rt;
206*16dce513Schristos  long dummyval;
207*16dce513Schristos
208*16dce513Schristos  if (!result_type)
209*16dce513Schristos    result_type = &rt;
210*16dce513Schristos
211*16dce513Schristos  code = BFD_RELOC_NONE;
212*16dce513Schristos
213*16dce513Schristos  if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names, &dummyval)
214*16dce513Schristos      || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
215*16dce513Schristos			      &dummyval))
216*16dce513Schristos    /* Don't treat "mov ip,ip" as a move-immediate.  */
217*16dce513Schristos    return _("register source in immediate move");
218*16dce513Schristos
219*16dce513Schristos  errmsg = cgen_parse_address (cd, strp, opindex, code, result_type, valuep);
220*16dce513Schristos  if (errmsg)
221*16dce513Schristos    return errmsg;
222*16dce513Schristos
223*16dce513Schristos  if (*result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
224*16dce513Schristos    errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xff);
225*16dce513Schristos  else
226*16dce513Schristos    errmsg = _("byte relocation unsupported");
227*16dce513Schristos
228*16dce513Schristos  *valuep &= 0xff;
229*16dce513Schristos  return errmsg;
230*16dce513Schristos}
231*16dce513Schristos
232*16dce513Schristosstatic const char * MISSING_CLOSE_PARENTHESIS = N_("missing `)'");
233*16dce513Schristos
234*16dce513Schristosstatic const char *
235*16dce513Schristosparse_imm16 (CGEN_CPU_DESC cd,
236*16dce513Schristos	     const char ** strp,
237*16dce513Schristos	     int opindex,
238*16dce513Schristos	     bfd_reloc_code_real_type code ATTRIBUTE_UNUSED,
239*16dce513Schristos	     enum cgen_parse_operand_result * result_type,
240*16dce513Schristos	     bfd_vma * valuep)
241*16dce513Schristos{
242*16dce513Schristos  const char * errmsg;
243*16dce513Schristos  enum cgen_parse_operand_result rt;
244*16dce513Schristos  long dummyval;
245*16dce513Schristos
246*16dce513Schristos  if (!result_type)
247*16dce513Schristos    result_type = &rt;
248*16dce513Schristos
249*16dce513Schristos  if (strncasecmp (*strp, "%high(", 6) == 0)
250*16dce513Schristos    {
251*16dce513Schristos      *strp += 6;
252*16dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_HIGH,
253*16dce513Schristos				   result_type, valuep);
254*16dce513Schristos      if (**strp != ')')
255*16dce513Schristos	return MISSING_CLOSE_PARENTHESIS;
256*16dce513Schristos      ++*strp;
257*16dce513Schristos      *valuep >>= 16;
258*16dce513Schristos    }
259*16dce513Schristos  else if (strncasecmp (*strp, "%low(", 5) == 0)
260*16dce513Schristos    {
261*16dce513Schristos      *strp += 5;
262*16dce513Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_LOW,
263*16dce513Schristos				   result_type, valuep);
264*16dce513Schristos      if (**strp != ')')
265*16dce513Schristos	return MISSING_CLOSE_PARENTHESIS;
266*16dce513Schristos      ++*strp;
267*16dce513Schristos    }
268*16dce513Schristos  else if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names,
269*16dce513Schristos				&dummyval)
270*16dce513Schristos	   || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names,
271*16dce513Schristos				   &dummyval))
272*16dce513Schristos    /* Don't treat "mov ip,ip" as a move-immediate.  */
273*16dce513Schristos    return _("register source in immediate move");
274*16dce513Schristos  else
275*16dce513Schristos    errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_16,
276*16dce513Schristos				 result_type, valuep);
277*16dce513Schristos
278*16dce513Schristos  if (!errmsg && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
279*16dce513Schristos    errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xffff);
280*16dce513Schristos
281*16dce513Schristos  *valuep &= 0xffff;
282*16dce513Schristos  return errmsg;
283*16dce513Schristos}
284*16dce513Schristos
285*16dce513Schristosconst char *
286*16dce513Schristosparse_branch_addr (CGEN_CPU_DESC cd,
287*16dce513Schristos		   const char ** strp,
288*16dce513Schristos		   int opindex,
289*16dce513Schristos		   int opinfo ATTRIBUTE_UNUSED,
290*16dce513Schristos		   enum cgen_parse_operand_result * resultp ATTRIBUTE_UNUSED,
291*16dce513Schristos		   bfd_vma *valuep ATTRIBUTE_UNUSED)
292*16dce513Schristos{
293*16dce513Schristos  const char * errmsg;
294*16dce513Schristos  enum cgen_parse_operand_result result_type;
295*16dce513Schristos  bfd_reloc_code_real_type code = BFD_RELOC_NONE;
296*16dce513Schristos  bfd_vma value;
297*16dce513Schristos
298*16dce513Schristos  switch (opindex)
299*16dce513Schristos    {
300*16dce513Schristos    case EPIPHANY_OPERAND_SIMM24:
301*16dce513Schristos      code = BFD_RELOC_EPIPHANY_SIMM24;
302*16dce513Schristos      break;
303*16dce513Schristos
304*16dce513Schristos    case EPIPHANY_OPERAND_SIMM8:
305*16dce513Schristos      code = BFD_RELOC_EPIPHANY_SIMM8;
306*16dce513Schristos      break;
307*16dce513Schristos
308*16dce513Schristos    default:
309*16dce513Schristos      errmsg = _("ABORT: unknown operand");
310*16dce513Schristos      return errmsg;
311*16dce513Schristos    }
312*16dce513Schristos
313*16dce513Schristos  errmsg = cgen_parse_address (cd, strp, opindex, code,
314*16dce513Schristos			       &result_type, &value);
315*16dce513Schristos  if (errmsg == NULL)
316*16dce513Schristos    {
317*16dce513Schristos      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
318*16dce513Schristos	{
319*16dce513Schristos	  /* Act as if we had done a PC-relative branch, ala .+num.  */
320*16dce513Schristos	  char buf[20];
321*16dce513Schristos	  const char * bufp = (const char *) buf;
322*16dce513Schristos
323*16dce513Schristos	  sprintf (buf, ".+%ld", (long) value);
324*16dce513Schristos	  errmsg = cgen_parse_address (cd, &bufp, opindex, code, &result_type,
325*16dce513Schristos				       &value);
326*16dce513Schristos	}
327*16dce513Schristos
328*16dce513Schristos      if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED)
329*16dce513Schristos	{
330*16dce513Schristos	  /* This will happen for things like (s2-s1) where s2 and s1
331*16dce513Schristos	     are labels.  */
332*16dce513Schristos	  /* Nothing further to be done.  */
333*16dce513Schristos	}
334*16dce513Schristos      else
335*16dce513Schristos	errmsg = _("Not a pc-relative address.");
336*16dce513Schristos    }
337*16dce513Schristos  return errmsg;
338*16dce513Schristos}
339*16dce513Schristos
340*16dce513Schristos/* -- dis.c */
341*16dce513Schristos
342*16dce513Schristos#define CGEN_PRINT_INSN epiphany_print_insn
343*16dce513Schristos
344*16dce513Schristosstatic int
345*16dce513Schristosepiphany_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
346*16dce513Schristos{
347*16dce513Schristos  bfd_byte buf[CGEN_MAX_INSN_SIZE];
348*16dce513Schristos  int buflen;
349*16dce513Schristos  int status;
350*16dce513Schristos
351*16dce513Schristos  info->bytes_per_chunk = 2;
352*16dce513Schristos  info->bytes_per_line = 4;
353*16dce513Schristos
354*16dce513Schristos  /* Attempt to read the base part of the insn.  */
355*16dce513Schristos  buflen = cd->base_insn_bitsize / 8;
356*16dce513Schristos  status = (*info->read_memory_func) (pc, buf, buflen, info);
357*16dce513Schristos
358*16dce513Schristos  /* Try again with the minimum part, if min < base.  */
359*16dce513Schristos  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
360*16dce513Schristos    {
361*16dce513Schristos      buflen = cd->min_insn_bitsize / 8;
362*16dce513Schristos      status = (*info->read_memory_func) (pc, buf, buflen, info);
363*16dce513Schristos    }
364*16dce513Schristos
365*16dce513Schristos  if (status != 0)
366*16dce513Schristos    {
367*16dce513Schristos      (*info->memory_error_func) (status, pc, info);
368*16dce513Schristos      return -1;
369*16dce513Schristos    }
370*16dce513Schristos
371*16dce513Schristos  return print_insn (cd, pc, info, buf, buflen);
372*16dce513Schristos}
373*16dce513Schristos
374*16dce513Schristos
375*16dce513Schristosstatic void
376*16dce513Schristosprint_postindex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
377*16dce513Schristos		 void * dis_info,
378*16dce513Schristos		 long value,
379*16dce513Schristos		 unsigned int attrs ATTRIBUTE_UNUSED,
380*16dce513Schristos		 bfd_vma pc ATTRIBUTE_UNUSED,
381*16dce513Schristos		 int length ATTRIBUTE_UNUSED)
382*16dce513Schristos{
383*16dce513Schristos  disassemble_info *info = (disassemble_info *) dis_info;
384*16dce513Schristos  (*info->fprintf_func) (info->stream, value ? "-" : "+");
385*16dce513Schristos}
386*16dce513Schristos
387*16dce513Schristosstatic void
388*16dce513Schristosprint_simm_not_reg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
389*16dce513Schristos		    void * dis_info,
390*16dce513Schristos		    long value,
391*16dce513Schristos		    unsigned int attrs ATTRIBUTE_UNUSED,
392*16dce513Schristos		    bfd_vma pc ATTRIBUTE_UNUSED,
393*16dce513Schristos		    int length ATTRIBUTE_UNUSED)
394*16dce513Schristos{
395*16dce513Schristos  print_address (cd, dis_info, value, attrs, pc, length);
396*16dce513Schristos}
397*16dce513Schristos
398*16dce513Schristosstatic void
399*16dce513Schristosprint_uimm_not_reg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
400*16dce513Schristos		    void * dis_info,
401*16dce513Schristos		    unsigned long value,
402*16dce513Schristos		    unsigned int attrs ATTRIBUTE_UNUSED,
403*16dce513Schristos		    bfd_vma pc ATTRIBUTE_UNUSED,
404*16dce513Schristos		    int length ATTRIBUTE_UNUSED)
405*16dce513Schristos{
406*16dce513Schristos  disassemble_info *info = (disassemble_info *)dis_info;
407*16dce513Schristos
408*16dce513Schristos  if (value & 0x800)
409*16dce513Schristos    (*info->fprintf_func) (info->stream, "-");
410*16dce513Schristos
411*16dce513Schristos  value &= 0x7ff;
412*16dce513Schristos  print_address (cd, dis_info, value, attrs, pc, length);
413*16dce513Schristos}
414*16dce513Schristos
415*16dce513Schristos
416*16dce513Schristos/* -- */
417*16dce513Schristos
418