* cgen-asm.in (insert_normal): Use CGEN_BOOL_ATTR.
[deliverable/binutils-gdb.git] / opcodes / m32r-dis.c
CommitLineData
9c03036a
DE
1/* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
1c8f439e 4THIS FILE IS USED TO GENERATE m32r-dis.c.
9c03036a 5
1294c286 6Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
9c03036a
DE
7
8This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10This program is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
1c8f439e
DE
21along with this program; if not, write to the Free Software Foundation, Inc.,
2259 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
9c03036a 23
23cf992f 24#include "sysdep.h"
9c03036a
DE
25#include <stdio.h>
26#include "ansidecl.h"
27#include "dis-asm.h"
9c03036a 28#include "bfd.h"
0bf55db8 29#include "symcat.h"
23cf992f 30#include "m32r-opc.h"
1c8f439e 31#include "opintl.h"
9c03036a 32
1c8f439e
DE
33#undef INLINE
34#ifdef __GNUC__
35#define INLINE __inline__
36#else
37#define INLINE
9c03036a
DE
38#endif
39
1c8f439e
DE
40/* Default text to print if an instruction isn't recognized. */
41#define UNKNOWN_INSN_MSG _("*unknown*")
9c03036a 42
5730d39d
DE
43/* Used by the ifield rtx function. */
44#define FLD(f) (fields->f)
45
1294c286 46static int extract_normal
5730d39d
DE
47 PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
48 unsigned int, unsigned int, unsigned int, unsigned int,
49 unsigned int, unsigned int, bfd_vma, long *));
1294c286 50static void print_normal
1c8f439e
DE
51 PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int));
52static void print_address
53 PARAMS ((CGEN_OPCODE_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
1294c286 54static void print_keyword
1c8f439e 55 PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
9c03036a 56static int extract_insn_normal
1c8f439e 57 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
5730d39d 58 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
9c03036a 59static void print_insn_normal
1c8f439e
DE
60 PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
61 bfd_vma, int));
62static int print_insn PARAMS ((CGEN_OPCODE_DESC, bfd_vma,
63 disassemble_info *, char *, int));
64static int default_print_insn
65 PARAMS ((CGEN_OPCODE_DESC, bfd_vma, disassemble_info *));
9c03036a 66\f
1294c286
DE
67/* -- disassembler routines inserted here */
68/* -- dis.c */
9c03036a 69
1294c286 70/* Immediate values are prefixed with '#'. */
0bf55db8 71
1c8f439e 72#define CGEN_PRINT_NORMAL(od, info, value, attrs, pc, length) \
1294c286
DE
73do { \
74 if ((attrs) & (1 << CGEN_OPERAND_HASH_PREFIX)) \
75 (*info->fprintf_func) (info->stream, "#"); \
76} while (0)
9c03036a 77
1294c286 78/* Handle '#' prefixes as operands. */
9c03036a
DE
79
80static void
1c8f439e
DE
81print_hash (od, dis_info, value, attrs, pc, length)
82 CGEN_OPCODE_DESC od;
ab0bd049 83 PTR dis_info;
853713a7
DE
84 long value;
85 unsigned int attrs;
1c8f439e 86 bfd_vma pc;
853713a7 87 int length;
9c03036a 88{
853713a7 89 disassemble_info *info = dis_info;
1294c286 90 (*info->fprintf_func) (info->stream, "#");
9c03036a
DE
91}
92
853713a7
DE
93#undef CGEN_PRINT_INSN
94#define CGEN_PRINT_INSN my_print_insn
95
96static int
1c8f439e
DE
97my_print_insn (od, pc, info)
98 CGEN_OPCODE_DESC od;
853713a7
DE
99 bfd_vma pc;
100 disassemble_info *info;
853713a7 101{
1c8f439e
DE
102 char buffer[CGEN_MAX_INSN_SIZE];
103 char *buf = buffer;
104 int status;
105 int buflen = (pc & 3) == 0 ? 4 : 2;
106
107 /* Read the base part of the insn. */
108
109 status = (*info->read_memory_func) (pc, buf, buflen, info);
110 if (status != 0)
111 {
112 (*info->memory_error_func) (status, pc, info);
113 return -1;
114 }
115
853713a7
DE
116 /* 32 bit insn? */
117 if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
1c8f439e 118 return print_insn (od, pc, info, buf, buflen);
853713a7
DE
119
120 /* Print the first insn. */
121 if ((pc & 3) == 0)
122 {
1c8f439e 123 if (print_insn (od, pc, info, buf, 2) == 0)
853713a7
DE
124 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
125 buf += 2;
126 }
127
128 if (buf[0] & 0x80)
129 {
130 /* Parallel. */
131 (*info->fprintf_func) (info->stream, " || ");
132 buf[0] &= 0x7f;
133 }
134 else
135 (*info->fprintf_func) (info->stream, " -> ");
136
1c8f439e
DE
137 /* The "& 3" is to pass a consistent address.
138 Parallel insns arguably both begin on the word boundary.
139 Also, branch insns are calculated relative to the word boundary. */
140 if (print_insn (od, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
853713a7
DE
141 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
142
143 return (pc & 3) ? 2 : 4;
144}
145
146/* -- */
147
148/* Main entry point for operand extraction.
149
150 This function is basically just a big switch statement. Earlier versions
151 used tables to look up the function to use, but
152 - if the table contains both assembler and disassembler functions then
153 the disassembler contains much of the assembler and vice-versa,
154 - there's a lot of inlining possibilities as things grow,
155 - using a switch statement avoids the function call overhead.
156
157 This function could be moved into `print_insn_normal', but keeping it
158 separate makes clear the interface between `print_insn_normal' and each of
159 the handlers.
160*/
161
0bf55db8 162int
1c8f439e
DE
163m32r_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc)
164 CGEN_OPCODE_DESC od;
5d07b6cf 165 int opindex;
1c8f439e 166 CGEN_EXTRACT_INFO *ex_info;
5730d39d 167 CGEN_INSN_INT insn_value;
853713a7 168 CGEN_FIELDS * fields;
1c8f439e 169 bfd_vma pc;
853713a7
DE
170{
171 int length;
5730d39d 172 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
853713a7
DE
173
174 switch (opindex)
175 {
176 case M32R_OPERAND_SR :
5730d39d 177 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 32, total_length, pc, & fields->f_r2);
853713a7
DE
178 break;
179 case M32R_OPERAND_DR :
5730d39d 180 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 4, 32, total_length, pc, & fields->f_r1);
853713a7
DE
181 break;
182 case M32R_OPERAND_SRC1 :
5730d39d 183 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 4, 32, total_length, pc, & fields->f_r1);
853713a7
DE
184 break;
185 case M32R_OPERAND_SRC2 :
5730d39d 186 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 32, total_length, pc, & fields->f_r2);
853713a7
DE
187 break;
188 case M32R_OPERAND_SCR :
5730d39d 189 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 32, total_length, pc, & fields->f_r2);
853713a7
DE
190 break;
191 case M32R_OPERAND_DCR :
5730d39d 192 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 4, 32, total_length, pc, & fields->f_r1);
853713a7
DE
193 break;
194 case M32R_OPERAND_SIMM8 :
5730d39d 195 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 8, 8, 32, total_length, pc, & fields->f_simm8);
853713a7
DE
196 break;
197 case M32R_OPERAND_SIMM16 :
5730d39d 198 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 0, 16, 16, 32, total_length, pc, & fields->f_simm16);
853713a7
DE
199 break;
200 case M32R_OPERAND_UIMM4 :
5730d39d 201 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 4, 32, total_length, pc, & fields->f_uimm4);
853713a7
DE
202 break;
203 case M32R_OPERAND_UIMM5 :
5730d39d 204 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 11, 5, 32, total_length, pc, & fields->f_uimm5);
853713a7
DE
205 break;
206 case M32R_OPERAND_UIMM16 :
5730d39d 207 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_uimm16);
853713a7 208 break;
ab0bd049
DE
209/* start-sanitize-m32rx */
210 case M32R_OPERAND_IMM1 :
0bf55db8
DE
211 {
212 long value;
5730d39d 213 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 0, 15, 1, 32, total_length, pc, & value);
1c8f439e
DE
214 value = ((value) + (1));
215 fields->f_imm1 = value;
0bf55db8 216 }
ab0bd049
DE
217 break;
218/* end-sanitize-m32rx */
219/* start-sanitize-m32rx */
220 case M32R_OPERAND_ACCD :
5730d39d 221 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 4, 2, 32, total_length, pc, & fields->f_accd);
ab0bd049
DE
222 break;
223/* end-sanitize-m32rx */
224/* start-sanitize-m32rx */
225 case M32R_OPERAND_ACCS :
5730d39d 226 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 12, 2, 32, total_length, pc, & fields->f_accs);
ab0bd049
DE
227 break;
228/* end-sanitize-m32rx */
229/* start-sanitize-m32rx */
230 case M32R_OPERAND_ACC :
5730d39d 231 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 1, 32, total_length, pc, & fields->f_acc);
ab0bd049
DE
232 break;
233/* end-sanitize-m32rx */
1294c286 234 case M32R_OPERAND_HASH :
5730d39d 235 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, 0, 0, total_length, pc, & fields->f_nil);
1294c286 236 break;
853713a7 237 case M32R_OPERAND_HI16 :
5730d39d 238 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_hi16);
853713a7
DE
239 break;
240 case M32R_OPERAND_SLO16 :
5730d39d 241 length = extract_normal (od, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_simm16);
853713a7
DE
242 break;
243 case M32R_OPERAND_ULO16 :
5730d39d 244 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_uimm16);
853713a7
DE
245 break;
246 case M32R_OPERAND_UIMM24 :
5730d39d 247 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 0, 8, 24, 32, total_length, pc, & fields->f_uimm24);
853713a7
DE
248 break;
249 case M32R_OPERAND_DISP8 :
0bf55db8
DE
250 {
251 long value;
5730d39d 252 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value);
1c8f439e
DE
253 value = ((((value) << (2))) + (((pc) & (-4))));
254 fields->f_disp8 = value;
0bf55db8 255 }
853713a7
DE
256 break;
257 case M32R_OPERAND_DISP16 :
0bf55db8
DE
258 {
259 long value;
5730d39d 260 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 16, 16, 32, total_length, pc, & value);
1c8f439e
DE
261 value = ((((value) << (2))) + (pc));
262 fields->f_disp16 = value;
0bf55db8 263 }
853713a7
DE
264 break;
265 case M32R_OPERAND_DISP24 :
0bf55db8
DE
266 {
267 long value;
5730d39d 268 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 0, 8, 24, 32, total_length, pc, & value);
1c8f439e
DE
269 value = ((((value) << (2))) + (pc));
270 fields->f_disp24 = value;
0bf55db8 271 }
853713a7
DE
272 break;
273
274 default :
1c8f439e
DE
275 /* xgettext:c-format */
276 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
853713a7
DE
277 opindex);
278 abort ();
279 }
280
281 return length;
282}
283
284/* Main entry point for printing operands.
285
286 This function is basically just a big switch statement. Earlier versions
287 used tables to look up the function to use, but
288 - if the table contains both assembler and disassembler functions then
289 the disassembler contains much of the assembler and vice-versa,
290 - there's a lot of inlining possibilities as things grow,
291 - using a switch statement avoids the function call overhead.
292
293 This function could be moved into `print_insn_normal', but keeping it
294 separate makes clear the interface between `print_insn_normal' and each of
295 the handlers.
296*/
297
0bf55db8 298void
1c8f439e
DE
299m32r_cgen_print_operand (od, opindex, info, fields, attrs, pc, length)
300 CGEN_OPCODE_DESC od;
5d07b6cf 301 int opindex;
853713a7 302 disassemble_info * info;
5d07b6cf
DE
303 CGEN_FIELDS * fields;
304 void const * attrs;
305 bfd_vma pc;
306 int length;
853713a7
DE
307{
308 switch (opindex)
309 {
310 case M32R_OPERAND_SR :
1c8f439e 311 print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
853713a7
DE
312 break;
313 case M32R_OPERAND_DR :
1c8f439e 314 print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
853713a7
DE
315 break;
316 case M32R_OPERAND_SRC1 :
1c8f439e 317 print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
853713a7
DE
318 break;
319 case M32R_OPERAND_SRC2 :
1c8f439e 320 print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
853713a7
DE
321 break;
322 case M32R_OPERAND_SCR :
1c8f439e 323 print_keyword (od, info, & m32r_cgen_opval_h_cr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
853713a7
DE
324 break;
325 case M32R_OPERAND_DCR :
1c8f439e 326 print_keyword (od, info, & m32r_cgen_opval_h_cr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
853713a7
DE
327 break;
328 case M32R_OPERAND_SIMM8 :
1c8f439e 329 print_normal (od, info, fields->f_simm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
853713a7
DE
330 break;
331 case M32R_OPERAND_SIMM16 :
1c8f439e 332 print_normal (od, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
853713a7
DE
333 break;
334 case M32R_OPERAND_UIMM4 :
1c8f439e 335 print_normal (od, info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
853713a7
DE
336 break;
337 case M32R_OPERAND_UIMM5 :
1c8f439e 338 print_normal (od, info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
853713a7
DE
339 break;
340 case M32R_OPERAND_UIMM16 :
1c8f439e 341 print_normal (od, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
853713a7 342 break;
ab0bd049
DE
343/* start-sanitize-m32rx */
344 case M32R_OPERAND_IMM1 :
1c8f439e 345 print_normal (od, info, fields->f_imm1, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
ab0bd049
DE
346 break;
347/* end-sanitize-m32rx */
348/* start-sanitize-m32rx */
349 case M32R_OPERAND_ACCD :
1c8f439e 350 print_keyword (od, info, & m32r_cgen_opval_h_accums, fields->f_accd, 0|(1<<CGEN_OPERAND_UNSIGNED));
ab0bd049
DE
351 break;
352/* end-sanitize-m32rx */
353/* start-sanitize-m32rx */
354 case M32R_OPERAND_ACCS :
1c8f439e 355 print_keyword (od, info, & m32r_cgen_opval_h_accums, fields->f_accs, 0|(1<<CGEN_OPERAND_UNSIGNED));
ab0bd049
DE
356 break;
357/* end-sanitize-m32rx */
358/* start-sanitize-m32rx */
359 case M32R_OPERAND_ACC :
1c8f439e 360 print_keyword (od, info, & m32r_cgen_opval_h_accums, fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED));
ab0bd049
DE
361 break;
362/* end-sanitize-m32rx */
1294c286 363 case M32R_OPERAND_HASH :
1c8f439e 364 print_hash (od, info, fields->f_nil, 0, pc, length);
1294c286 365 break;
853713a7 366 case M32R_OPERAND_HI16 :
1c8f439e 367 print_normal (od, info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
853713a7
DE
368 break;
369 case M32R_OPERAND_SLO16 :
1c8f439e 370 print_normal (od, info, fields->f_simm16, 0, pc, length);
853713a7
DE
371 break;
372 case M32R_OPERAND_ULO16 :
1c8f439e 373 print_normal (od, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
853713a7
DE
374 break;
375 case M32R_OPERAND_UIMM24 :
1c8f439e 376 print_address (od, info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
853713a7
DE
377 break;
378 case M32R_OPERAND_DISP8 :
1c8f439e 379 print_address (od, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
853713a7
DE
380 break;
381 case M32R_OPERAND_DISP16 :
1c8f439e 382 print_address (od, info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
853713a7
DE
383 break;
384 case M32R_OPERAND_DISP24 :
1c8f439e 385 print_address (od, info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
853713a7
DE
386 break;
387
388 default :
1c8f439e
DE
389 /* xgettext:c-format */
390 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
853713a7
DE
391 opindex);
392 abort ();
393 }
394}
395
1c8f439e 396cgen_extract_fn * const m32r_cgen_extract_handlers[] =
5d07b6cf
DE
397{
398 0, /* default */
853713a7
DE
399 extract_insn_normal,
400};
401
1c8f439e 402cgen_print_fn * const m32r_cgen_print_handlers[] =
5d07b6cf
DE
403{
404 0, /* default */
853713a7
DE
405 print_insn_normal,
406};
407
408
409void
1c8f439e
DE
410m32r_cgen_init_dis (od)
411 CGEN_OPCODE_DESC od;
853713a7 412{
853713a7
DE
413}
414
1294c286 415\f
1c8f439e
DE
416#if ! CGEN_INT_INSN_P
417
5730d39d
DE
418/* Subroutine of extract_normal.
419 Ensure sufficient bytes are cached in EX_INFO.
420 OFFSET is the offset in bytes from the start of the insn of the value.
421 BYTES is the length of the needed value.
422 Returns 1 for success, 0 for failure. */
423
424static INLINE int
425fill_cache (od, ex_info, offset, bytes, pc)
426 CGEN_OPCODE_DESC od;
427 CGEN_EXTRACT_INFO *ex_info;
428 int offset, bytes;
429 bfd_vma pc;
430{
431 /* It's doubtful that the middle part has already been fetched so
432 we don't optimize that case. kiss. */
433 int mask;
434 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
435
436 /* First do a quick check. */
437 mask = (1 << bytes) - 1;
438 if (((ex_info->valid >> offset) & mask) == mask)
439 return 1;
440
441 /* Search for the first byte we need to read. */
442 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
443 if (! (mask & ex_info->valid))
444 break;
445
446 if (bytes)
447 {
448 int status;
449
450 pc += offset;
451 status = (*info->read_memory_func)
452 (pc, ex_info->insn_bytes + offset, bytes, info);
453
454 if (status != 0)
455 {
456 (*info->memory_error_func) (status, pc, info);
457 return 0;
458 }
459
460 ex_info->valid |= ((1 << bytes) - 1) << offset;
461 }
462
463 return 1;
464}
465
1c8f439e
DE
466/* Subroutine of extract_normal. */
467
468static INLINE long
5730d39d 469extract_1 (od, ex_info, start, length, word_length, bufp, pc)
1c8f439e 470 CGEN_OPCODE_DESC od;
5730d39d 471 CGEN_EXTRACT_INFO *ex_info;
1c8f439e
DE
472 int start,length,word_length;
473 unsigned char *bufp;
5730d39d 474 bfd_vma pc;
1c8f439e
DE
475{
476 unsigned long x,mask;
477 int shift;
478 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
479
1c8f439e
DE
480 switch (word_length)
481 {
482 case 8:
483 x = *bufp;
484 break;
485 case 16:
486 if (big_p)
487 x = bfd_getb16 (bufp);
488 else
489 x = bfd_getl16 (bufp);
490 break;
491 case 24:
492 /* ??? This may need reworking as these cases don't necessarily
493 want the first byte and the last two bytes handled like this. */
494 if (big_p)
5730d39d 495 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
1c8f439e 496 else
5730d39d 497 x = bfd_getl16 (bufp) | (bufp[2] << 16);
1c8f439e
DE
498 break;
499 case 32:
500 if (big_p)
501 x = bfd_getb32 (bufp);
502 else
503 x = bfd_getl32 (bufp);
504 break;
505 default :
506 abort ();
507 }
508
509 /* Written this way to avoid undefined behaviour. */
510 mask = (((1L << (length - 1)) - 1) << 1) | 1;
511 if (CGEN_INSN_LSB0_P)
5730d39d 512 shift = (start + 1) - length;
1c8f439e
DE
513 else
514 shift = (word_length - (start + length));
515 return (x >> shift) & mask;
516}
517
518#endif /* ! CGEN_INT_INSN_P */
519
1294c286
DE
520/* Default extraction routine.
521
5730d39d
DE
522 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bits of the insn in host order,
523 or sometimes less for cases like the m32r where the base insn size is 32
524 but some insns are 16 bits.
525 ATTRS is a mask of the boolean attributes. We only need `UNSIGNED',
526 but for generality we take a bitmask of all of them.
527 WORD_OFFSET is the offset in bits from the start of the insn of the value.
528 WORD_LENGTH is the length of the word in bits in which the value resides.
529 START is the starting bit number in the word, architecture origin.
530 LENGTH is the length of VALUE in bits.
531 TOTAL_LENGTH is the total length of the insn in bits.
532
533 Returns 1 for success, 0 for failure. */
534
535/* ??? The return code isn't properly used. wip. */
1294c286 536
1c8f439e
DE
537/* ??? This doesn't handle bfd_vma's. Create another function when
538 necessary. */
539
1294c286 540static int
5730d39d
DE
541extract_normal (od, ex_info, insn_value, attrs, word_offset, start, length,
542 word_length, total_length, pc, valuep)
1c8f439e
DE
543 CGEN_OPCODE_DESC od;
544 CGEN_EXTRACT_INFO *ex_info;
5730d39d 545 CGEN_INSN_INT insn_value;
1294c286 546 unsigned int attrs;
5730d39d
DE
547 unsigned int word_offset, start, length, word_length, total_length;
548 bfd_vma pc;
1294c286
DE
549 long *valuep;
550{
5730d39d 551 CGEN_INSN_INT value;
1c8f439e
DE
552
553 /* If LENGTH is zero, this operand doesn't contribute to the value
554 so give it a standard value of zero. */
555 if (length == 0)
556 {
557 *valuep = 0;
558 return 1;
559 }
560
5730d39d
DE
561 if (CGEN_INT_INSN_P
562 && word_offset != 0)
563 abort ();
1c8f439e 564
5730d39d
DE
565 if (word_length > 32)
566 abort ();
1c8f439e 567
5730d39d
DE
568 /* For architectures with insns smaller than the insn-base-bitsize,
569 word_length may be too big. */
570#if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE
571 if (word_offset == 0
572 && word_length > total_length)
573 word_length = total_length;
574#endif
1c8f439e 575
5730d39d 576 /* Does the value reside in INSN_VALUE? */
1c8f439e 577
5730d39d 578 if (word_offset == 0)
1c8f439e 579 {
5730d39d
DE
580 /* Written this way to avoid undefined behaviour. */
581 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
582
583 if (CGEN_INSN_LSB0_P)
584 value = insn_value >> ((start + 1) - length);
585 else
586 value = insn_value >> (word_length - (start + length));
587 value &= mask;
588 /* sign extend? */
589 if (! CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED)
590 && (value & (1L << (length - 1))))
591 value |= ~mask;
1c8f439e 592 }
5730d39d
DE
593
594#if ! CGEN_INT_INSN_P
595
1c8f439e
DE
596 else
597 {
5730d39d 598 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
1c8f439e 599
5730d39d 600 if (word_length > 32)
1c8f439e
DE
601 abort ();
602
5730d39d
DE
603 if (fill_cache (od, ex_info, word_offset / 8, word_length / 8, pc) == 0)
604 return 0;
1c8f439e 605
5730d39d 606 value = extract_1 (od, ex_info, start, length, word_length, bufp, pc);
1c8f439e
DE
607 }
608
609#endif /* ! CGEN_INT_INSN_P */
1294c286
DE
610
611 *valuep = value;
612
1294c286
DE
613 return 1;
614}
615
616/* Default print handler. */
617
618static void
1c8f439e
DE
619print_normal (od, dis_info, value, attrs, pc, length)
620 CGEN_OPCODE_DESC od;
1294c286
DE
621 PTR dis_info;
622 long value;
623 unsigned int attrs;
1c8f439e 624 bfd_vma pc;
1294c286
DE
625 int length;
626{
1c8f439e 627 disassemble_info *info = (disassemble_info *) dis_info;
1294c286
DE
628
629#ifdef CGEN_PRINT_NORMAL
1c8f439e 630 CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length);
1294c286
DE
631#endif
632
633 /* Print the operand as directed by the attributes. */
1c8f439e
DE
634 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
635 ; /* nothing to do */
1294c286
DE
636 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
637 (*info->fprintf_func) (info->stream, "0x%lx", value);
638 else
639 (*info->fprintf_func) (info->stream, "%ld", value);
640}
641
1c8f439e
DE
642/* Default address handler. */
643
644static void
645print_address (od, dis_info, value, attrs, pc, length)
646 CGEN_OPCODE_DESC od;
647 PTR dis_info;
648 bfd_vma value;
649 unsigned int attrs;
650 bfd_vma pc;
651 int length;
652{
653 disassemble_info *info = (disassemble_info *) dis_info;
654
655#ifdef CGEN_PRINT_ADDRESS
656 CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length);
657#endif
658
659 /* Print the operand as directed by the attributes. */
660 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
661 ; /* nothing to do */
662 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
663 (*info->print_address_func) (value, info);
664 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
665 (*info->print_address_func) (value, info);
666 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
667 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
668 else
669 (*info->fprintf_func) (info->stream, "%ld", (long) value);
670}
671
1294c286
DE
672/* Keyword print handler. */
673
674static void
1c8f439e
DE
675print_keyword (od, dis_info, keyword_table, value, attrs)
676 CGEN_OPCODE_DESC od;
1294c286
DE
677 PTR dis_info;
678 CGEN_KEYWORD *keyword_table;
679 long value;
680 unsigned int attrs;
681{
1c8f439e 682 disassemble_info *info = (disassemble_info *) dis_info;
1294c286
DE
683 const CGEN_KEYWORD_ENTRY *ke;
684
685 ke = cgen_keyword_lookup_value (keyword_table, value);
686 if (ke != NULL)
687 (*info->fprintf_func) (info->stream, "%s", ke->name);
688 else
689 (*info->fprintf_func) (info->stream, "???");
690}
9c03036a
DE
691\f
692/* Default insn extractor.
693
1c8f439e
DE
694 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order.
695 The extracted fields are stored in FIELDS.
696 EX_INFO is used to handle reading variable length insns.
697 Return the length of the insn in bits, or 0 if no match,
698 or -1 if an error occurs fetching data (memory_error_func will have
699 been called). */
9c03036a
DE
700
701static int
1c8f439e
DE
702extract_insn_normal (od, insn, ex_info, insn_value, fields, pc)
703 CGEN_OPCODE_DESC od;
853713a7 704 const CGEN_INSN *insn;
1c8f439e 705 CGEN_EXTRACT_INFO *ex_info;
5730d39d 706 CGEN_INSN_INT insn_value;
853713a7 707 CGEN_FIELDS *fields;
1c8f439e 708 bfd_vma pc;
9c03036a 709{
853713a7
DE
710 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
711 const unsigned char *syn;
9c03036a 712
9c03036a
DE
713 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
714
1c8f439e 715 CGEN_INIT_EXTRACT (od);
9c03036a 716
853713a7 717 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
9c03036a
DE
718 {
719 int length;
720
853713a7 721 if (CGEN_SYNTAX_CHAR_P (*syn))
9c03036a
DE
722 continue;
723
1c8f439e
DE
724 length = m32r_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn),
725 ex_info, insn_value, fields, pc);
726 if (length <= 0)
727 return length;
9c03036a
DE
728 }
729
23cf992f
NC
730 /* We recognized and successfully extracted this insn. */
731 return CGEN_INSN_BITSIZE (insn);
9c03036a
DE
732}
733
734/* Default insn printer.
735
ab0bd049 736 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
1c8f439e 737 about disassemble_info. */
9c03036a
DE
738
739static void
1c8f439e
DE
740print_insn_normal (od, dis_info, insn, fields, pc, length)
741 CGEN_OPCODE_DESC od;
ab0bd049 742 PTR dis_info;
853713a7
DE
743 const CGEN_INSN *insn;
744 CGEN_FIELDS *fields;
745 bfd_vma pc;
746 int length;
9c03036a 747{
853713a7 748 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
1c8f439e 749 disassemble_info *info = (disassemble_info *) dis_info;
853713a7 750 const unsigned char *syn;
9c03036a 751
1c8f439e 752 CGEN_INIT_PRINT (od);
9c03036a 753
853713a7 754 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
9c03036a 755 {
853713a7 756 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
23cf992f 757 {
853713a7 758 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
23cf992f
NC
759 continue;
760 }
853713a7 761 if (CGEN_SYNTAX_CHAR_P (*syn))
9c03036a 762 {
853713a7 763 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
9c03036a
DE
764 continue;
765 }
766
767 /* We have an operand. */
1c8f439e
DE
768 m32r_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info,
769 fields, CGEN_INSN_ATTRS (insn), pc, length);
9c03036a
DE
770 }
771}
772\f
1c8f439e
DE
773/* Utility to print an insn.
774 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
775 The result is the size of the insn in bytes or zero for an unknown insn
776 or -1 if an error occurs fetching data (memory_error_func will have
777 been called). */
9c03036a
DE
778
779static int
1c8f439e
DE
780print_insn (od, pc, info, buf, buflen)
781 CGEN_OPCODE_DESC od;
853713a7
DE
782 bfd_vma pc;
783 disassemble_info *info;
784 char *buf;
785 int buflen;
9c03036a 786{
853713a7
DE
787 unsigned long insn_value;
788 const CGEN_INSN_LIST *insn_list;
1c8f439e
DE
789 CGEN_EXTRACT_INFO ex_info;
790
791 ex_info.dis_info = info;
792 ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1;
5730d39d 793 ex_info.insn_bytes = buf;
853713a7 794
9c03036a
DE
795 switch (buflen)
796 {
1c8f439e 797 case 1:
9c03036a
DE
798 insn_value = buf[0];
799 break;
1c8f439e 800 case 2:
9c03036a
DE
801 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
802 break;
1c8f439e 803 case 4:
9c03036a
DE
804 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
805 break;
806 default:
807 abort ();
808 }
809
810 /* The instructions are stored in hash lists.
811 Pick the first one and keep trying until we find the right one. */
812
1c8f439e 813 insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value);
9c03036a
DE
814 while (insn_list != NULL)
815 {
853713a7 816 const CGEN_INSN *insn = insn_list->insn;
853713a7
DE
817 CGEN_FIELDS fields;
818 int length;
9c03036a
DE
819
820#if 0 /* not needed as insn shouldn't be in hash lists if not supported */
821 /* Supported by this cpu? */
1c8f439e 822 if (! m32r_cgen_insn_supported (od, insn))
9c03036a
DE
823 continue;
824#endif
825
826 /* Basic bit mask must be correct. */
827 /* ??? May wish to allow target to defer this check until the extract
828 handler. */
5730d39d
DE
829 if ((insn_value & CGEN_INSN_BASE_MASK (insn))
830 == CGEN_INSN_BASE_VALUE (insn))
9c03036a
DE
831 {
832 /* Printing is handled in two passes. The first pass parses the
833 machine insn and extracts the fields. The second pass prints
834 them. */
835
1c8f439e
DE
836 length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value,
837 &fields, pc);
838 /* length < 0 -> error */
839 if (length < 0)
840 return length;
9c03036a
DE
841 if (length > 0)
842 {
1c8f439e 843 (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length);
9c03036a 844 /* length is in bits, result is in bytes */
853713a7 845 return length / 8;
9c03036a
DE
846 }
847 }
853713a7 848
9c03036a
DE
849 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
850 }
851
853713a7 852 return 0;
9c03036a
DE
853}
854
1c8f439e
DE
855/* Default value for CGEN_PRINT_INSN.
856 The result is the size of the insn in bytes or zero for an unknown insn
857 or -1 if an error occured fetching bytes. */
858
859#ifndef CGEN_PRINT_INSN
860#define CGEN_PRINT_INSN default_print_insn
861#endif
862
863static int
864default_print_insn (od, pc, info)
865 CGEN_OPCODE_DESC od;
866 bfd_vma pc;
867 disassemble_info *info;
868{
869 char buf[CGEN_MAX_INSN_SIZE];
870 int status;
871
872 /* Read the base part of the insn. */
873
874 status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info);
875 if (status != 0)
876 {
877 (*info->memory_error_func) (status, pc, info);
878 return -1;
879 }
880
881 return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE);
882}
883
9c03036a
DE
884/* Main entry point.
885 Print one instruction from PC on INFO->STREAM.
886 Return the size of the instruction (in bytes). */
887
888int
889print_insn_m32r (pc, info)
853713a7
DE
890 bfd_vma pc;
891 disassemble_info *info;
9c03036a 892{
1c8f439e
DE
893 int length;
894 static CGEN_OPCODE_DESC od = 0;
853713a7
DE
895 int mach = info->mach;
896 int big_p = info->endian == BFD_ENDIAN_BIG;
9c03036a 897
1c8f439e
DE
898 /* If we haven't initialized yet, initialize the opcode table. */
899 if (! od)
9c03036a 900 {
1c8f439e
DE
901 od = m32r_cgen_opcode_open (mach,
902 big_p ?
903 CGEN_ENDIAN_BIG
904 : CGEN_ENDIAN_LITTLE);
905 m32r_cgen_init_dis (od);
9c03036a 906 }
1c8f439e
DE
907 /* If we've switched cpu's, re-initialize. */
908 /* ??? Perhaps we should use BFD_ENDIAN. */
909 else if (mach != CGEN_OPCODE_MACH (od)
910 || (CGEN_OPCODE_ENDIAN (od)
911 != (big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE)))
9c03036a 912 {
1c8f439e 913 cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
9c03036a
DE
914 }
915
916 /* We try to have as much common code as possible.
917 But at this point some targets need to take over. */
918 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
23cf992f 919 but if not possible try to move this hook elsewhere rather than
9c03036a 920 have two hooks. */
1c8f439e
DE
921 length = CGEN_PRINT_INSN (od, pc, info);
922 if (length > 0)
9c03036a 923 return length;
1c8f439e
DE
924 if (length < 0)
925 return -1;
9c03036a 926
853713a7 927 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
9c03036a
DE
928 return CGEN_DEFAULT_INSN_SIZE;
929}
This page took 0.127832 seconds and 4 git commands to generate.