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