gas/
[deliverable/binutils-gdb.git] / cpu / m32r.opc
CommitLineData
e866a257
AC
1/* M32R opcode support. -*- C -*-
2
33b71eeb
NC
3 Copyright 1998, 1999, 2000, 2001, 2004, 2005
4 Free Software Foundation, Inc.
e866a257
AC
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
e172dbf8 27 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
e866a257 28
e866a257
AC
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"
f4453dfa 42 <arch>-ibd.h additions use: "-- ibd.h" */
e866a257
AC
43\f
44/* -- opc.h */
45
46#undef CGEN_DIS_HASH_SIZE
47#define CGEN_DIS_HASH_SIZE 256
48#undef CGEN_DIS_HASH
8ee9a8b2 49#if 0
e866a257
AC
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)))
8ee9a8b2
NC
57#else
58#define CGEN_DIS_HASH(buffer, value) m32r_cgen_dis_hash(buffer, value)
59extern unsigned int m32r_cgen_dis_hash(const char *, CGEN_INSN_INT);
60#endif
e866a257 61
8ee9a8b2
NC
62/* -- */
63\f
64/* -- opc.c */
65unsigned int
66m32r_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
e866a257
AC
88/* -- */
89\f
90/* -- asm.c */
91static const char * parse_hash
33b71eeb 92 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
e866a257
AC
93static const char * parse_hi16
94 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
95static const char * parse_slo16
96 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
97static const char * parse_ulo16
98 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
99
100/* Handle '#' prefixes (i.e. skip over them). */
101
102static const char *
103parse_hash (cd, strp, opindex, valuep)
104 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
105 const char **strp;
106 int opindex ATTRIBUTE_UNUSED;
33b71eeb 107 long *valuep ATTRIBUTE_UNUSED;
e866a257
AC
108{
109 if (**strp == '#')
110 ++*strp;
111 return NULL;
112}
113
114/* Handle shigh(), high(). */
115
116static const char *
117parse_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)
f4453dfa
NC
154 {
155 value = value + (value & 0x8000 ? 0x10000 : 0);
156 value >>= 16;
157 }
e866a257
AC
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
169static const char *
170parse_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)
8ee9a8b2
NC
193 {
194 value &= 0xffff;
195 if (value & 0x8000)
196 value |= 0xffff0000;
197 }
e866a257
AC
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
221static const char *
222parse_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 */
256static void print_hash PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
257static 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
271static void
272print_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
287static int
288my_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;
8ee9a8b2
NC
297 int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
298 char *x;
e866a257
AC
299
300 /* Read the base part of the insn. */
301
8ee9a8b2
NC
302 status = (*info->read_memory_func) (pc - ((!big_p && (pc & 3) != 0) ? 2 : 0),
303 buf, buflen, info);
e866a257
AC
304 if (status != 0)
305 {
306 (*info->memory_error_func) (status, pc, info);
307 return -1;
308 }
309
310 /* 32 bit insn? */
8ee9a8b2
NC
311 x = (big_p ? &buf[0] : &buf[3]);
312 if ((pc & 3) == 0 && (*x & 0x80) != 0)
e866a257
AC
313 return print_insn (cd, pc, info, buf, buflen);
314
315 /* Print the first insn. */
316 if ((pc & 3) == 0)
317 {
8ee9a8b2 318 buf += (big_p ? 0 : 2);
e866a257
AC
319 if (print_insn (cd, pc, info, buf, 2) == 0)
320 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
8ee9a8b2 321 buf += (big_p ? 2 : -2);
e866a257
AC
322 }
323
8ee9a8b2
NC
324 x = (big_p ? &buf[0] : &buf[1]);
325 if (*x & 0x80)
e866a257
AC
326 {
327 /* Parallel. */
328 (*info->fprintf_func) (info->stream, " || ");
8ee9a8b2 329 *x &= 0x7f;
e866a257
AC
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.10171 seconds and 4 git commands to generate.