make use of meabi_flags be ELF specific
[deliverable/binutils-gdb.git] / cpu / m32r.opc
CommitLineData
e866a257
AC
1/* M32R opcode support. -*- C -*-
2
3 Copyright 1998, 1999, 2000, 2001 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*/
29
e866a257
AC
30/* This file is an addendum to m32r.cpu. Heavy use of C code isn't
31 appropriate in .cpu files, so it resides here. This especially applies
32 to assembly/disassembly where parsing/printing can be quite involved.
33 Such things aren't really part of the specification of the cpu, per se,
34 so .cpu files provide the general framework and .opc files handle the
35 nitty-gritty details as necessary.
36
37 Each section is delimited with start and end markers.
38
39 <arch>-opc.h additions use: "-- opc.h"
40 <arch>-opc.c additions use: "-- opc.c"
41 <arch>-asm.c additions use: "-- asm.c"
42 <arch>-dis.c additions use: "-- dis.c"
43 <arch>-ibd.h additions use: "-- ibd.h"
44*/
45\f
46/* -- opc.h */
47
48#undef CGEN_DIS_HASH_SIZE
49#define CGEN_DIS_HASH_SIZE 256
50#undef CGEN_DIS_HASH
8ee9a8b2 51#if 0
e866a257
AC
52#define X(b) (((unsigned char *) (b))[0] & 0xf0)
53#define CGEN_DIS_HASH(buffer, value) \
54(X (buffer) | \
55 (X (buffer) == 0x40 || X (buffer) == 0xe0 || X (buffer) == 0x60 || X (buffer) == 0x50 ? 0 \
56 : X (buffer) == 0x70 || X (buffer) == 0xf0 ? (((unsigned char *) (buffer))[0] & 0xf) \
57 : X (buffer) == 0x30 ? ((((unsigned char *) (buffer))[1] & 0x70) >> 4) \
58 : ((((unsigned char *) (buffer))[1] & 0xf0) >> 4)))
8ee9a8b2
NC
59#else
60#define CGEN_DIS_HASH(buffer, value) m32r_cgen_dis_hash(buffer, value)
61extern unsigned int m32r_cgen_dis_hash(const char *, CGEN_INSN_INT);
62#endif
e866a257 63
8ee9a8b2
NC
64/* -- */
65\f
66/* -- opc.c */
67unsigned int
68m32r_cgen_dis_hash (buf, value)
69 const char * buf ATTRIBUTE_UNUSED;
70 CGEN_INSN_INT value;
71{
72 unsigned int x;
73
74 if (value & 0xffff0000) /* 32bit instructions */
75 value = (value >> 16) & 0xffff;
76
77 x = (value>>8) & 0xf0;
78 if (x == 0x40 || x == 0xe0 || x == 0x60 || x == 0x50)
79 return x;
80
81 if (x == 0x70 || x == 0xf0)
82 return x | ((value>>8) & 0x0f);
83
84 if (x == 0x30)
85 return x | ((value & 0x70) >> 4);
86 else
87 return x | ((value & 0xf0) >> 4);
88}
89
e866a257
AC
90/* -- */
91\f
92/* -- asm.c */
93static const char * parse_hash
94 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
95static const char * parse_hi16
96 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
97static const char * parse_slo16
98 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
99static const char * parse_ulo16
100 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
101
102/* Handle '#' prefixes (i.e. skip over them). */
103
104static const char *
105parse_hash (cd, strp, opindex, valuep)
106 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
107 const char **strp;
108 int opindex ATTRIBUTE_UNUSED;
109 unsigned long *valuep ATTRIBUTE_UNUSED;
110{
111 if (**strp == '#')
112 ++*strp;
113 return NULL;
114}
115
116/* Handle shigh(), high(). */
117
118static const char *
119parse_hi16 (cd, strp, opindex, valuep)
120 CGEN_CPU_DESC cd;
121 const char **strp;
122 int opindex;
123 unsigned long *valuep;
124{
125 const char *errmsg;
126 enum cgen_parse_operand_result result_type;
127 bfd_vma value;
128
129 if (**strp == '#')
130 ++*strp;
131
132 if (strncasecmp (*strp, "high(", 5) == 0)
133 {
134 *strp += 5;
135 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
136 &result_type, &value);
137 if (**strp != ')')
138 return "missing `)'";
139 ++*strp;
140 if (errmsg == NULL
141 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
142 value >>= 16;
143 *valuep = value;
144 return errmsg;
145 }
146 else if (strncasecmp (*strp, "shigh(", 6) == 0)
147 {
148 *strp += 6;
149 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
150 &result_type, &value);
151 if (**strp != ')')
152 return "missing `)'";
153 ++*strp;
154 if (errmsg == NULL
155 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
156 value = (value >> 16) + (value & 0x8000 ? 1 : 0);
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.039759 seconds and 4 git commands to generate.