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