binutils ChangeLog:
[deliverable/binutils-gdb.git] / cpu / m32r.opc
... / ...
CommitLineData
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)
58extern unsigned int m32r_cgen_dis_hash(const char *, CGEN_INSN_INT);
59#endif
60
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
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)
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
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)
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
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;
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.036428 seconds and 4 git commands to generate.