Fix compile time warnings generated by gcc 4.0
[deliverable/binutils-gdb.git] / cpu / m32r.opc
1 /* M32R opcode support. -*- C -*-
2
3 Copyright 1998, 1999, 2000, 2001, 2004, 2005
4 Free Software Foundation, Inc.
5
6 Contributed by Red Hat Inc; developed under contract from
7 Mitsubishi Electric Corporation.
8
9 This file is part of the GNU Binutils.
10
11 Contributed by Red Hat Inc; developed under contract from Fujitsu.
12
13 This file is part of the GNU Binutils.
14
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
28
29 /* This file is an addendum to m32r.cpu. Heavy use of C code isn't
30 appropriate in .cpu files, so it resides here. This especially applies
31 to assembly/disassembly where parsing/printing can be quite involved.
32 Such things aren't really part of the specification of the cpu, per se,
33 so .cpu files provide the general framework and .opc files handle the
34 nitty-gritty details as necessary.
35
36 Each section is delimited with start and end markers.
37
38 <arch>-opc.h additions use: "-- opc.h"
39 <arch>-opc.c additions use: "-- opc.c"
40 <arch>-asm.c additions use: "-- asm.c"
41 <arch>-dis.c additions use: "-- dis.c"
42 <arch>-ibd.h additions use: "-- ibd.h" */
43 \f
44 /* -- opc.h */
45
46 #undef CGEN_DIS_HASH_SIZE
47 #define CGEN_DIS_HASH_SIZE 256
48 #undef CGEN_DIS_HASH
49 #if 0
50 #define X(b) (((unsigned char *) (b))[0] & 0xf0)
51 #define CGEN_DIS_HASH(buffer, value) \
52 (X (buffer) | \
53 (X (buffer) == 0x40 || X (buffer) == 0xe0 || X (buffer) == 0x60 || X (buffer) == 0x50 ? 0 \
54 : X (buffer) == 0x70 || X (buffer) == 0xf0 ? (((unsigned char *) (buffer))[0] & 0xf) \
55 : X (buffer) == 0x30 ? ((((unsigned char *) (buffer))[1] & 0x70) >> 4) \
56 : ((((unsigned char *) (buffer))[1] & 0xf0) >> 4)))
57 #else
58 #define CGEN_DIS_HASH(buffer, value) m32r_cgen_dis_hash(buffer, value)
59 extern unsigned int m32r_cgen_dis_hash(const char *, CGEN_INSN_INT);
60 #endif
61
62 /* -- */
63 \f
64 /* -- opc.c */
65 unsigned int
66 m32r_cgen_dis_hash (buf, value)
67 const char * buf ATTRIBUTE_UNUSED;
68 CGEN_INSN_INT value;
69 {
70 unsigned int x;
71
72 if (value & 0xffff0000) /* 32bit instructions */
73 value = (value >> 16) & 0xffff;
74
75 x = (value>>8) & 0xf0;
76 if (x == 0x40 || x == 0xe0 || x == 0x60 || x == 0x50)
77 return x;
78
79 if (x == 0x70 || x == 0xf0)
80 return x | ((value>>8) & 0x0f);
81
82 if (x == 0x30)
83 return x | ((value & 0x70) >> 4);
84 else
85 return x | ((value & 0xf0) >> 4);
86 }
87
88 /* -- */
89 \f
90 /* -- asm.c */
91 static const char * parse_hash
92 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
93 static const char * parse_hi16
94 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
95 static const char * parse_slo16
96 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
97 static const char * parse_ulo16
98 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
99
100 /* Handle '#' prefixes (i.e. skip over them). */
101
102 static const char *
103 parse_hash (cd, strp, opindex, valuep)
104 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
105 const char **strp;
106 int opindex ATTRIBUTE_UNUSED;
107 long *valuep ATTRIBUTE_UNUSED;
108 {
109 if (**strp == '#')
110 ++*strp;
111 return NULL;
112 }
113
114 /* Handle shigh(), high(). */
115
116 static const char *
117 parse_hi16 (cd, strp, opindex, valuep)
118 CGEN_CPU_DESC cd;
119 const char **strp;
120 int opindex;
121 unsigned long *valuep;
122 {
123 const char *errmsg;
124 enum cgen_parse_operand_result result_type;
125 bfd_vma value;
126
127 if (**strp == '#')
128 ++*strp;
129
130 if (strncasecmp (*strp, "high(", 5) == 0)
131 {
132 *strp += 5;
133 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
134 &result_type, &value);
135 if (**strp != ')')
136 return "missing `)'";
137 ++*strp;
138 if (errmsg == NULL
139 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
140 value >>= 16;
141 *valuep = value;
142 return errmsg;
143 }
144 else if (strncasecmp (*strp, "shigh(", 6) == 0)
145 {
146 *strp += 6;
147 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
148 &result_type, &value);
149 if (**strp != ')')
150 return "missing `)'";
151 ++*strp;
152 if (errmsg == NULL
153 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
154 {
155 value = value + (value & 0x8000 ? 0x10000 : 0);
156 value >>= 16;
157 }
158 *valuep = value;
159 return errmsg;
160 }
161
162 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
163 }
164
165 /* Handle low() in a signed context. Also handle sda().
166 The signedness of the value doesn't matter to low(), but this also
167 handles the case where low() isn't present. */
168
169 static const char *
170 parse_slo16 (cd, strp, opindex, valuep)
171 CGEN_CPU_DESC cd;
172 const char **strp;
173 int opindex;
174 long *valuep;
175 {
176 const char *errmsg;
177 enum cgen_parse_operand_result result_type;
178 bfd_vma value;
179
180 if (**strp == '#')
181 ++*strp;
182
183 if (strncasecmp (*strp, "low(", 4) == 0)
184 {
185 *strp += 4;
186 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
187 &result_type, &value);
188 if (**strp != ')')
189 return "missing `)'";
190 ++*strp;
191 if (errmsg == NULL
192 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
193 {
194 value &= 0xffff;
195 if (value & 0x8000)
196 value |= 0xffff0000;
197 }
198 *valuep = value;
199 return errmsg;
200 }
201
202 if (strncasecmp (*strp, "sda(", 4) == 0)
203 {
204 *strp += 4;
205 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_SDA16,
206 NULL, &value);
207 if (**strp != ')')
208 return "missing `)'";
209 ++*strp;
210 *valuep = value;
211 return errmsg;
212 }
213
214 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
215 }
216
217 /* Handle low() in an unsigned context.
218 The signedness of the value doesn't matter to low(), but this also
219 handles the case where low() isn't present. */
220
221 static const char *
222 parse_ulo16 (cd, strp, opindex, valuep)
223 CGEN_CPU_DESC cd;
224 const char **strp;
225 int opindex;
226 unsigned long *valuep;
227 {
228 const char *errmsg;
229 enum cgen_parse_operand_result result_type;
230 bfd_vma value;
231
232 if (**strp == '#')
233 ++*strp;
234
235 if (strncasecmp (*strp, "low(", 4) == 0)
236 {
237 *strp += 4;
238 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
239 &result_type, &value);
240 if (**strp != ')')
241 return "missing `)'";
242 ++*strp;
243 if (errmsg == NULL
244 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
245 value &= 0xffff;
246 *valuep = value;
247 return errmsg;
248 }
249
250 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
251 }
252
253 /* -- */
254 \f
255 /* -- dis.c */
256 static void print_hash PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
257 static int my_print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
258
259 /* Immediate values are prefixed with '#'. */
260
261 #define CGEN_PRINT_NORMAL(cd, info, value, attrs, pc, length) \
262 do \
263 { \
264 if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_HASH_PREFIX)) \
265 (*info->fprintf_func) (info->stream, "#"); \
266 } \
267 while (0)
268
269 /* Handle '#' prefixes as operands. */
270
271 static void
272 print_hash (cd, dis_info, value, attrs, pc, length)
273 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
274 PTR dis_info;
275 long value ATTRIBUTE_UNUSED;
276 unsigned int attrs ATTRIBUTE_UNUSED;
277 bfd_vma pc ATTRIBUTE_UNUSED;
278 int length ATTRIBUTE_UNUSED;
279 {
280 disassemble_info *info = (disassemble_info *) dis_info;
281 (*info->fprintf_func) (info->stream, "#");
282 }
283
284 #undef CGEN_PRINT_INSN
285 #define CGEN_PRINT_INSN my_print_insn
286
287 static int
288 my_print_insn (cd, pc, info)
289 CGEN_CPU_DESC cd;
290 bfd_vma pc;
291 disassemble_info *info;
292 {
293 char buffer[CGEN_MAX_INSN_SIZE];
294 char *buf = buffer;
295 int status;
296 int buflen = (pc & 3) == 0 ? 4 : 2;
297 int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
298 char *x;
299
300 /* Read the base part of the insn. */
301
302 status = (*info->read_memory_func) (pc - ((!big_p && (pc & 3) != 0) ? 2 : 0),
303 buf, buflen, info);
304 if (status != 0)
305 {
306 (*info->memory_error_func) (status, pc, info);
307 return -1;
308 }
309
310 /* 32 bit insn? */
311 x = (big_p ? &buf[0] : &buf[3]);
312 if ((pc & 3) == 0 && (*x & 0x80) != 0)
313 return print_insn (cd, pc, info, buf, buflen);
314
315 /* Print the first insn. */
316 if ((pc & 3) == 0)
317 {
318 buf += (big_p ? 0 : 2);
319 if (print_insn (cd, pc, info, buf, 2) == 0)
320 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
321 buf += (big_p ? 2 : -2);
322 }
323
324 x = (big_p ? &buf[0] : &buf[1]);
325 if (*x & 0x80)
326 {
327 /* Parallel. */
328 (*info->fprintf_func) (info->stream, " || ");
329 *x &= 0x7f;
330 }
331 else
332 (*info->fprintf_func) (info->stream, " -> ");
333
334 /* The "& 3" is to pass a consistent address.
335 Parallel insns arguably both begin on the word boundary.
336 Also, branch insns are calculated relative to the word boundary. */
337 if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
338 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
339
340 return (pc & 3) ? 2 : 4;
341 }
342
343 /* -- */
This page took 0.051274 seconds and 4 git commands to generate.