2005-02-23 Andrew Cagney <cagney@gnu.org>
[deliverable/binutils-gdb.git] / cpu / m32r.opc
CommitLineData
e866a257
AC
1/* M32R opcode support. -*- C -*-
2
f4453dfa 3 Copyright 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
e866a257
AC
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
f4453dfa 26 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
e866a257 27
e866a257
AC
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"
f4453dfa 41 <arch>-ibd.h additions use: "-- ibd.h" */
e866a257
AC
42\f
43/* -- opc.h */
44
45#undef CGEN_DIS_HASH_SIZE
46#define CGEN_DIS_HASH_SIZE 256
47#undef CGEN_DIS_HASH
8ee9a8b2 48#if 0
e866a257
AC
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)))
8ee9a8b2
NC
56#else
57#define CGEN_DIS_HASH(buffer, value) m32r_cgen_dis_hash(buffer, value)
58extern unsigned int m32r_cgen_dis_hash(const char *, CGEN_INSN_INT);
59#endif
e866a257 60
8ee9a8b2
NC
61/* -- */
62\f
63/* -- opc.c */
64unsigned int
65m32r_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
e866a257
AC
87/* -- */
88\f
89/* -- asm.c */
90static const char * parse_hash
91 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
92static const char * parse_hi16
93 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
94static const char * parse_slo16
95 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
96static const char * parse_ulo16
97 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
98
99/* Handle '#' prefixes (i.e. skip over them). */
100
101static const char *
102parse_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
115static const char *
116parse_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)
f4453dfa
NC
153 {
154 value = value + (value & 0x8000 ? 0x10000 : 0);
155 value >>= 16;
156 }
e866a257
AC
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
168static const char *
169parse_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)
8ee9a8b2
NC
192 {
193 value &= 0xffff;
194 if (value & 0x8000)
195 value |= 0xffff0000;
196 }
e866a257
AC
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
220static const char *
221parse_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 */
255static void print_hash PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
256static 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
270static void
271print_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
286static int
287my_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;
8ee9a8b2
NC
296 int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
297 char *x;
e866a257
AC
298
299 /* Read the base part of the insn. */
300
8ee9a8b2
NC
301 status = (*info->read_memory_func) (pc - ((!big_p && (pc & 3) != 0) ? 2 : 0),
302 buf, buflen, info);
e866a257
AC
303 if (status != 0)
304 {
305 (*info->memory_error_func) (status, pc, info);
306 return -1;
307 }
308
309 /* 32 bit insn? */
8ee9a8b2
NC
310 x = (big_p ? &buf[0] : &buf[3]);
311 if ((pc & 3) == 0 && (*x & 0x80) != 0)
e866a257
AC
312 return print_insn (cd, pc, info, buf, buflen);
313
314 /* Print the first insn. */
315 if ((pc & 3) == 0)
316 {
8ee9a8b2 317 buf += (big_p ? 0 : 2);
e866a257
AC
318 if (print_insn (cd, pc, info, buf, 2) == 0)
319 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
8ee9a8b2 320 buf += (big_p ? 2 : -2);
e866a257
AC
321 }
322
8ee9a8b2
NC
323 x = (big_p ? &buf[0] : &buf[1]);
324 if (*x & 0x80)
e866a257
AC
325 {
326 /* Parallel. */
327 (*info->fprintf_func) (info->stream, " || ");
8ee9a8b2 328 *x &= 0x7f;
e866a257
AC
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.094169 seconds and 4 git commands to generate.