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