2004-02-20 Andrew Cagney <cagney@redhat.com>
[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
30
31/* This file is an addendum to m32r.cpu. Heavy use of C code isn't
32 appropriate in .cpu files, so it resides here. This especially applies
33 to assembly/disassembly where parsing/printing can be quite involved.
34 Such things aren't really part of the specification of the cpu, per se,
35 so .cpu files provide the general framework and .opc files handle the
36 nitty-gritty details as necessary.
37
38 Each section is delimited with start and end markers.
39
40 <arch>-opc.h additions use: "-- opc.h"
41 <arch>-opc.c additions use: "-- opc.c"
42 <arch>-asm.c additions use: "-- asm.c"
43 <arch>-dis.c additions use: "-- dis.c"
44 <arch>-ibd.h additions use: "-- ibd.h"
45*/
46\f
47/* -- opc.h */
48
49#undef CGEN_DIS_HASH_SIZE
50#define CGEN_DIS_HASH_SIZE 256
51#undef CGEN_DIS_HASH
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)))
59
60/* -- */
61\f
62/* -- asm.c */
63static const char * parse_hash
64 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
65static const char * parse_hi16
66 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
67static const char * parse_slo16
68 PARAMS ((CGEN_CPU_DESC, const char **, int, long *));
69static const char * parse_ulo16
70 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
71
72/* Handle '#' prefixes (i.e. skip over them). */
73
74static const char *
75parse_hash (cd, strp, opindex, valuep)
76 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
77 const char **strp;
78 int opindex ATTRIBUTE_UNUSED;
79 unsigned long *valuep ATTRIBUTE_UNUSED;
80{
81 if (**strp == '#')
82 ++*strp;
83 return NULL;
84}
85
86/* Handle shigh(), high(). */
87
88static const char *
89parse_hi16 (cd, strp, opindex, valuep)
90 CGEN_CPU_DESC cd;
91 const char **strp;
92 int opindex;
93 unsigned long *valuep;
94{
95 const char *errmsg;
96 enum cgen_parse_operand_result result_type;
97 bfd_vma value;
98
99 if (**strp == '#')
100 ++*strp;
101
102 if (strncasecmp (*strp, "high(", 5) == 0)
103 {
104 *strp += 5;
105 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_ULO,
106 &result_type, &value);
107 if (**strp != ')')
108 return "missing `)'";
109 ++*strp;
110 if (errmsg == NULL
111 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
112 value >>= 16;
113 *valuep = value;
114 return errmsg;
115 }
116 else if (strncasecmp (*strp, "shigh(", 6) == 0)
117 {
118 *strp += 6;
119 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_HI16_SLO,
120 &result_type, &value);
121 if (**strp != ')')
122 return "missing `)'";
123 ++*strp;
124 if (errmsg == NULL
125 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
126 value = (value >> 16) + (value & 0x8000 ? 1 : 0);
127 *valuep = value;
128 return errmsg;
129 }
130
131 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
132}
133
134/* Handle low() in a signed context. Also handle sda().
135 The signedness of the value doesn't matter to low(), but this also
136 handles the case where low() isn't present. */
137
138static const char *
139parse_slo16 (cd, strp, opindex, valuep)
140 CGEN_CPU_DESC cd;
141 const char **strp;
142 int opindex;
143 long *valuep;
144{
145 const char *errmsg;
146 enum cgen_parse_operand_result result_type;
147 bfd_vma value;
148
149 if (**strp == '#')
150 ++*strp;
151
152 if (strncasecmp (*strp, "low(", 4) == 0)
153 {
154 *strp += 4;
155 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
156 &result_type, &value);
157 if (**strp != ')')
158 return "missing `)'";
159 ++*strp;
160 if (errmsg == NULL
161 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
162 value &= 0xffff;
163 *valuep = value;
164 return errmsg;
165 }
166
167 if (strncasecmp (*strp, "sda(", 4) == 0)
168 {
169 *strp += 4;
170 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_SDA16,
171 NULL, &value);
172 if (**strp != ')')
173 return "missing `)'";
174 ++*strp;
175 *valuep = value;
176 return errmsg;
177 }
178
179 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
180}
181
182/* Handle low() in an unsigned context.
183 The signedness of the value doesn't matter to low(), but this also
184 handles the case where low() isn't present. */
185
186static const char *
187parse_ulo16 (cd, strp, opindex, valuep)
188 CGEN_CPU_DESC cd;
189 const char **strp;
190 int opindex;
191 unsigned long *valuep;
192{
193 const char *errmsg;
194 enum cgen_parse_operand_result result_type;
195 bfd_vma value;
196
197 if (**strp == '#')
198 ++*strp;
199
200 if (strncasecmp (*strp, "low(", 4) == 0)
201 {
202 *strp += 4;
203 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_M32R_LO16,
204 &result_type, &value);
205 if (**strp != ')')
206 return "missing `)'";
207 ++*strp;
208 if (errmsg == NULL
209 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
210 value &= 0xffff;
211 *valuep = value;
212 return errmsg;
213 }
214
215 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
216}
217
218/* -- */
219\f
220/* -- dis.c */
221static void print_hash PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
222static int my_print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
223
224/* Immediate values are prefixed with '#'. */
225
226#define CGEN_PRINT_NORMAL(cd, info, value, attrs, pc, length) \
227 do \
228 { \
229 if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_HASH_PREFIX)) \
230 (*info->fprintf_func) (info->stream, "#"); \
231 } \
232 while (0)
233
234/* Handle '#' prefixes as operands. */
235
236static void
237print_hash (cd, dis_info, value, attrs, pc, length)
238 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
239 PTR dis_info;
240 long value ATTRIBUTE_UNUSED;
241 unsigned int attrs ATTRIBUTE_UNUSED;
242 bfd_vma pc ATTRIBUTE_UNUSED;
243 int length ATTRIBUTE_UNUSED;
244{
245 disassemble_info *info = (disassemble_info *) dis_info;
246 (*info->fprintf_func) (info->stream, "#");
247}
248
249#undef CGEN_PRINT_INSN
250#define CGEN_PRINT_INSN my_print_insn
251
252static int
253my_print_insn (cd, pc, info)
254 CGEN_CPU_DESC cd;
255 bfd_vma pc;
256 disassemble_info *info;
257{
258 char buffer[CGEN_MAX_INSN_SIZE];
259 char *buf = buffer;
260 int status;
261 int buflen = (pc & 3) == 0 ? 4 : 2;
262
263 /* Read the base part of the insn. */
264
265 status = (*info->read_memory_func) (pc, buf, buflen, info);
266 if (status != 0)
267 {
268 (*info->memory_error_func) (status, pc, info);
269 return -1;
270 }
271
272 /* 32 bit insn? */
273 if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
274 return print_insn (cd, pc, info, buf, buflen);
275
276 /* Print the first insn. */
277 if ((pc & 3) == 0)
278 {
279 if (print_insn (cd, pc, info, buf, 2) == 0)
280 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
281 buf += 2;
282 }
283
284 if (buf[0] & 0x80)
285 {
286 /* Parallel. */
287 (*info->fprintf_func) (info->stream, " || ");
288 buf[0] &= 0x7f;
289 }
290 else
291 (*info->fprintf_func) (info->stream, " -> ");
292
293 /* The "& 3" is to pass a consistent address.
294 Parallel insns arguably both begin on the word boundary.
295 Also, branch insns are calculated relative to the word boundary. */
296 if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
297 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
298
299 return (pc & 3) ? 2 : 4;
300}
301
302/* -- */
This page took 0.033727 seconds and 4 git commands to generate.