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