xref: /netbsd-src/external/gpl3/binutils.old/dist/cpu/fr30.opc (revision 16dce51364ebe8aeafbae46bc5aa167b8115bc45)
1*16dce513Schristos/* FR30 opcode support.  -*- C -*-
2*16dce513Schristos   Copyright 2011 Free Software Foundation, Inc.
3*16dce513Schristos
4*16dce513Schristos   Contributed by Red Hat Inc;
5*16dce513Schristos
6*16dce513Schristos   This file is part of the GNU Binutils.
7*16dce513Schristos
8*16dce513Schristos   This program is free software; you can redistribute it and/or modify
9*16dce513Schristos   it under the terms of the GNU General Public License as published by
10*16dce513Schristos   the Free Software Foundation; either version 3 of the License, or
11*16dce513Schristos   (at your option) any later version.
12*16dce513Schristos
13*16dce513Schristos   This program is distributed in the hope that it will be useful,
14*16dce513Schristos   but WITHOUT ANY WARRANTY; without even the implied warranty of
15*16dce513Schristos   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*16dce513Schristos   GNU General Public License for more details.
17*16dce513Schristos
18*16dce513Schristos   You should have received a copy of the GNU General Public License
19*16dce513Schristos   along with this program; if not, write to the Free Software
20*16dce513Schristos   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*16dce513Schristos   MA 02110-1301, USA.  */
22*16dce513Schristos
23*16dce513Schristos/* This file is an addendum to fr30.cpu.  Heavy use of C code isn't
24*16dce513Schristos   appropriate in .cpu files, so it resides here.  This especially applies
25*16dce513Schristos   to assembly/disassembly where parsing/printing can be quite involved.
26*16dce513Schristos   Such things aren't really part of the specification of the cpu, per se,
27*16dce513Schristos   so .cpu files provide the general framework and .opc files handle the
28*16dce513Schristos   nitty-gritty details as necessary.
29*16dce513Schristos
30*16dce513Schristos   Each section is delimited with start and end markers.
31*16dce513Schristos
32*16dce513Schristos   <arch>-opc.h additions use: "-- opc.h"
33*16dce513Schristos   <arch>-opc.c additions use: "-- opc.c"
34*16dce513Schristos   <arch>-asm.c additions use: "-- asm.c"
35*16dce513Schristos   <arch>-dis.c additions use: "-- dis.c"
36*16dce513Schristos   <arch>-ibd.h additions use: "-- ibd.h".  */
37*16dce513Schristos
38*16dce513Schristos/* -- opc.h */
39*16dce513Schristos
40*16dce513Schristos/* ??? This can be improved upon.  */
41*16dce513Schristos#undef  CGEN_DIS_HASH_SIZE
42*16dce513Schristos#define CGEN_DIS_HASH_SIZE 16
43*16dce513Schristos#undef  CGEN_DIS_HASH
44*16dce513Schristos#define CGEN_DIS_HASH(buffer, value) (((unsigned char *) (buffer))[0] >> 4)
45*16dce513Schristos
46*16dce513Schristos/* -- */
47*16dce513Schristos
48*16dce513Schristos/* -- asm.c */
49*16dce513Schristos/* Handle register lists for LDMx and STMx.  */
50*16dce513Schristos
51*16dce513Schristosstatic int
52*16dce513Schristosparse_register_number (const char **strp)
53*16dce513Schristos{
54*16dce513Schristos  int regno;
55*16dce513Schristos
56*16dce513Schristos  if (**strp < '0' || **strp > '9')
57*16dce513Schristos    return -1; /* Error.  */
58*16dce513Schristos  regno = **strp - '0';
59*16dce513Schristos  ++*strp;
60*16dce513Schristos
61*16dce513Schristos  if (**strp >= '0' && **strp <= '9')
62*16dce513Schristos    {
63*16dce513Schristos      regno = regno * 10 + (**strp - '0');
64*16dce513Schristos      ++*strp;
65*16dce513Schristos    }
66*16dce513Schristos
67*16dce513Schristos  return regno;
68*16dce513Schristos}
69*16dce513Schristos
70*16dce513Schristosstatic const char *
71*16dce513Schristosparse_register_list (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
72*16dce513Schristos		     const char **strp,
73*16dce513Schristos		     int opindex ATTRIBUTE_UNUSED,
74*16dce513Schristos		     unsigned long *valuep,
75*16dce513Schristos		     int high_low,   /* 0 == high, 1 == low.  */
76*16dce513Schristos		     int load_store) /* 0 == load, 1 == store.  */
77*16dce513Schristos{
78*16dce513Schristos  *valuep = 0;
79*16dce513Schristos  while (**strp && **strp != ')')
80*16dce513Schristos    {
81*16dce513Schristos      int regno;
82*16dce513Schristos
83*16dce513Schristos      if (**strp != 'R' && **strp != 'r')
84*16dce513Schristos	break;
85*16dce513Schristos      ++*strp;
86*16dce513Schristos
87*16dce513Schristos      regno = parse_register_number (strp);
88*16dce513Schristos      if (regno == -1)
89*16dce513Schristos	return _("Register number is not valid");
90*16dce513Schristos      if (regno > 7 && !high_low)
91*16dce513Schristos	return _("Register must be between r0 and r7");
92*16dce513Schristos      if (regno < 8 && high_low)
93*16dce513Schristos	return _("Register must be between r8 and r15");
94*16dce513Schristos
95*16dce513Schristos      if (high_low)
96*16dce513Schristos	regno -= 8;
97*16dce513Schristos
98*16dce513Schristos      if (load_store) /* Mask is reversed for store.  */
99*16dce513Schristos	*valuep |= 0x80 >> regno;
100*16dce513Schristos      else
101*16dce513Schristos	*valuep |= 1 << regno;
102*16dce513Schristos
103*16dce513Schristos      if (**strp == ',')
104*16dce513Schristos	{
105*16dce513Schristos	  if (*(*strp + 1) == ')')
106*16dce513Schristos	    break;
107*16dce513Schristos	  ++*strp;
108*16dce513Schristos	}
109*16dce513Schristos    }
110*16dce513Schristos
111*16dce513Schristos  if (!*strp || **strp != ')')
112*16dce513Schristos    return _("Register list is not valid");
113*16dce513Schristos
114*16dce513Schristos  return NULL;
115*16dce513Schristos}
116*16dce513Schristos
117*16dce513Schristosstatic const char *
118*16dce513Schristosparse_low_register_list_ld (CGEN_CPU_DESC cd,
119*16dce513Schristos			    const char **strp,
120*16dce513Schristos			    int opindex,
121*16dce513Schristos			    unsigned long *valuep)
122*16dce513Schristos{
123*16dce513Schristos  return parse_register_list (cd, strp, opindex, valuep,
124*16dce513Schristos			      0 /* Low.  */, 0 /* Load.  */);
125*16dce513Schristos}
126*16dce513Schristos
127*16dce513Schristosstatic const char *
128*16dce513Schristosparse_hi_register_list_ld (CGEN_CPU_DESC cd,
129*16dce513Schristos			   const char **strp,
130*16dce513Schristos			   int opindex,
131*16dce513Schristos			   unsigned long *valuep)
132*16dce513Schristos{
133*16dce513Schristos  return parse_register_list (cd, strp, opindex, valuep,
134*16dce513Schristos			      1 /* High.  */, 0 /* Load.  */);
135*16dce513Schristos}
136*16dce513Schristos
137*16dce513Schristosstatic const char *
138*16dce513Schristosparse_low_register_list_st (CGEN_CPU_DESC cd,
139*16dce513Schristos			    const char **strp,
140*16dce513Schristos			    int opindex,
141*16dce513Schristos			    unsigned long *valuep)
142*16dce513Schristos{
143*16dce513Schristos  return parse_register_list (cd, strp, opindex, valuep,
144*16dce513Schristos			      0 /* Low.  */, 1 /* Store.  */);
145*16dce513Schristos}
146*16dce513Schristos
147*16dce513Schristosstatic const char *
148*16dce513Schristosparse_hi_register_list_st (CGEN_CPU_DESC cd,
149*16dce513Schristos			   const char **strp,
150*16dce513Schristos			   int opindex,
151*16dce513Schristos			   unsigned long *valuep)
152*16dce513Schristos{
153*16dce513Schristos  return parse_register_list (cd, strp, opindex, valuep,
154*16dce513Schristos			      1 /* High.  */, 1 /* Store.  */);
155*16dce513Schristos}
156*16dce513Schristos
157*16dce513Schristos/* -- */
158*16dce513Schristos
159*16dce513Schristos/* -- dis.c */
160*16dce513Schristosstatic void
161*16dce513Schristosprint_register_list (void * dis_info,
162*16dce513Schristos		     long value,
163*16dce513Schristos		     long offset,
164*16dce513Schristos		     int load_store) /* 0 == load, 1 == store.  */
165*16dce513Schristos{
166*16dce513Schristos  disassemble_info *info = dis_info;
167*16dce513Schristos  int mask;
168*16dce513Schristos  int reg_index = 0;
169*16dce513Schristos  char * comma = "";
170*16dce513Schristos
171*16dce513Schristos  if (load_store)
172*16dce513Schristos    mask = 0x80;
173*16dce513Schristos  else
174*16dce513Schristos    mask = 1;
175*16dce513Schristos
176*16dce513Schristos  if (value & mask)
177*16dce513Schristos    {
178*16dce513Schristos      (*info->fprintf_func) (info->stream, "r%li", reg_index + offset);
179*16dce513Schristos      comma = ",";
180*16dce513Schristos    }
181*16dce513Schristos
182*16dce513Schristos  for (reg_index = 1; reg_index <= 7; ++reg_index)
183*16dce513Schristos    {
184*16dce513Schristos      if (load_store)
185*16dce513Schristos	mask >>= 1;
186*16dce513Schristos      else
187*16dce513Schristos	mask <<= 1;
188*16dce513Schristos
189*16dce513Schristos      if (value & mask)
190*16dce513Schristos	{
191*16dce513Schristos	  (*info->fprintf_func) (info->stream, "%sr%li", comma, reg_index + offset);
192*16dce513Schristos	  comma = ",";
193*16dce513Schristos	}
194*16dce513Schristos    }
195*16dce513Schristos}
196*16dce513Schristos
197*16dce513Schristosstatic void
198*16dce513Schristosprint_hi_register_list_ld (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
199*16dce513Schristos			   void * dis_info,
200*16dce513Schristos			   long value,
201*16dce513Schristos			   unsigned int attrs ATTRIBUTE_UNUSED,
202*16dce513Schristos			   bfd_vma pc ATTRIBUTE_UNUSED,
203*16dce513Schristos			   int length ATTRIBUTE_UNUSED)
204*16dce513Schristos{
205*16dce513Schristos  print_register_list (dis_info, value, 8, 0 /* Load.  */);
206*16dce513Schristos}
207*16dce513Schristos
208*16dce513Schristosstatic void
209*16dce513Schristosprint_low_register_list_ld (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
210*16dce513Schristos			    void * dis_info,
211*16dce513Schristos			    long value,
212*16dce513Schristos			    unsigned int attrs ATTRIBUTE_UNUSED,
213*16dce513Schristos			    bfd_vma pc ATTRIBUTE_UNUSED,
214*16dce513Schristos			    int length ATTRIBUTE_UNUSED)
215*16dce513Schristos{
216*16dce513Schristos  print_register_list (dis_info, value, 0, 0 /* Load.  */);
217*16dce513Schristos}
218*16dce513Schristos
219*16dce513Schristosstatic void
220*16dce513Schristosprint_hi_register_list_st (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
221*16dce513Schristos			   void * dis_info,
222*16dce513Schristos			   long value,
223*16dce513Schristos			   unsigned int attrs ATTRIBUTE_UNUSED,
224*16dce513Schristos			   bfd_vma pc ATTRIBUTE_UNUSED,
225*16dce513Schristos			   int length ATTRIBUTE_UNUSED)
226*16dce513Schristos{
227*16dce513Schristos  print_register_list (dis_info, value, 8, 1 /* Store.  */);
228*16dce513Schristos}
229*16dce513Schristos
230*16dce513Schristosstatic void
231*16dce513Schristosprint_low_register_list_st (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
232*16dce513Schristos			    void * dis_info,
233*16dce513Schristos			    long value,
234*16dce513Schristos			    unsigned int attrs ATTRIBUTE_UNUSED,
235*16dce513Schristos			    bfd_vma pc ATTRIBUTE_UNUSED,
236*16dce513Schristos			    int length ATTRIBUTE_UNUSED)
237*16dce513Schristos{
238*16dce513Schristos  print_register_list (dis_info, value, 0, 1 /* Store.  */);
239*16dce513Schristos}
240*16dce513Schristos
241*16dce513Schristosstatic void
242*16dce513Schristosprint_m4 (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
243*16dce513Schristos	  void * dis_info,
244*16dce513Schristos	  long value,
245*16dce513Schristos	  unsigned int attrs ATTRIBUTE_UNUSED,
246*16dce513Schristos	  bfd_vma pc ATTRIBUTE_UNUSED,
247*16dce513Schristos	  int length ATTRIBUTE_UNUSED)
248*16dce513Schristos{
249*16dce513Schristos  disassemble_info *info = (disassemble_info *) dis_info;
250*16dce513Schristos
251*16dce513Schristos  (*info->fprintf_func) (info->stream, "%ld", value);
252*16dce513Schristos}
253*16dce513Schristos/* -- */
254