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