1 /* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
4 This file is used to generate m32r-dis.c.
6 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
32 /* ??? The layout of this stuff is still work in progress.
33 For speed in assembly/disassembly, we use inline functions. That of course
34 will only work for GCC. When this stuff is finished, we can decide whether
35 to keep the inline functions (and only get the performance increase when
36 compiled with GCC), or switch to macros, or use something else.
39 /* Default text to print if an instruction isn't recognized. */
40 #define UNKNOWN_INSN_MSG "*unknown*"
42 /* FIXME: Machine generate. */
43 #ifndef CGEN_PCREL_OFFSET
44 #define CGEN_PCREL_OFFSET 0
47 static int print_insn PARAMS ((bfd_vma, disassemble_info *, char *, int));
49 static int extract_insn_normal
50 PARAMS ((const CGEN_INSN *, void *, cgen_insn_t, CGEN_FIELDS *));
51 static void print_insn_normal
52 PARAMS ((void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int));
54 /* Default extraction routine.
56 ATTRS is a mask of the boolean attributes. We only need `unsigned',
57 but for generality we take a bitmask of all of them. */
60 extract_normal (buf_ctrl, insn_value, attrs, start, length, shift, total_length, valuep)
62 cgen_insn_t insn_value;
64 int start, length, shift, total_length;
71 value = ((insn_value >> (CGEN_BASE_INSN_BITSIZE - (start + length)))
72 & ((1 << length) - 1));
74 value = ((insn_value >> (total_length - (start + length)))
75 & ((1 << length) - 1));
77 if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
78 && (value & (1 << (length - 1))))
81 /* FIXME: unfinished */
84 /* This is backwards as we undo the effects of insert_normal. */
96 /* Default print handler. */
99 print_normal (dis_info, value, attrs, pc, length)
103 unsigned long pc; /* FIXME: should be bfd_vma */
106 disassemble_info *info = dis_info;
108 /* Print the operand as directed by the attributes. */
109 if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_FAKE))
110 ; /* nothing to do (??? at least not yet) */
111 else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_PCREL_ADDR))
112 (*info->print_address_func) (pc + CGEN_PCREL_OFFSET + value, info);
113 /* ??? Not all cases of this are currently caught. */
114 else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_ABS_ADDR))
115 /* FIXME: Why & 0xffffffff? */
116 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
117 else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
118 (*info->fprintf_func) (info->stream, "0x%lx", value);
120 (*info->fprintf_func) (info->stream, "%ld", value);
123 /* Keyword print handler. */
126 print_keyword (dis_info, keyword_table, value, attrs)
128 CGEN_KEYWORD *keyword_table;
132 disassemble_info *info = dis_info;
133 const CGEN_KEYWORD_ENTRY *ke;
135 ke = cgen_keyword_lookup_value (keyword_table, value);
137 (*info->fprintf_func) (info->stream, "%s", ke->name);
139 (*info->fprintf_func) (info->stream, "???");
142 /* -- disassembler routines inserted here */
145 #undef CGEN_PRINT_INSN
146 #define CGEN_PRINT_INSN my_print_insn
149 my_print_insn (pc, info, buf, buflen)
151 disassemble_info *info;
156 if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
157 return print_insn (pc, info, buf, buflen);
159 /* Print the first insn. */
162 if (print_insn (pc, info, buf, 16) == 0)
163 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
170 (*info->fprintf_func) (info->stream, " || ");
174 (*info->fprintf_func) (info->stream, " -> ");
176 /* The "& 3" is to ensure the branch address is computed correctly
177 [if it is a branch]. */
178 if (print_insn (pc & ~ (bfd_vma) 3, info, buf, 16) == 0)
179 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
181 return (pc & 3) ? 2 : 4;
186 /* Main entry point for operand extraction.
188 This function is basically just a big switch statement. Earlier versions
189 used tables to look up the function to use, but
190 - if the table contains both assembler and disassembler functions then
191 the disassembler contains much of the assembler and vice-versa,
192 - there's a lot of inlining possibilities as things grow,
193 - using a switch statement avoids the function call overhead.
195 This function could be moved into `print_insn_normal', but keeping it
196 separate makes clear the interface between `print_insn_normal' and each of
201 m32r_cgen_extract_operand (opindex, buf_ctrl, insn_value, fields)
204 cgen_insn_t insn_value;
205 CGEN_FIELDS * fields;
211 case M32R_OPERAND_SR :
212 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
214 case M32R_OPERAND_DR :
215 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
217 case M32R_OPERAND_SRC1 :
218 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
220 case M32R_OPERAND_SRC2 :
221 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
223 case M32R_OPERAND_SCR :
224 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
226 case M32R_OPERAND_DCR :
227 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
229 case M32R_OPERAND_SIMM8 :
230 length = extract_normal (NULL /*FIXME*/, insn_value, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm8);
232 case M32R_OPERAND_SIMM16 :
233 length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm16);
235 case M32R_OPERAND_UIMM4 :
236 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm4);
238 case M32R_OPERAND_UIMM5 :
239 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm5);
241 case M32R_OPERAND_UIMM16 :
242 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm16);
244 /* start-sanitize-m32rx */
245 case M32R_OPERAND_IMM1 :
248 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 15, 1, 0, CGEN_FIELDS_BITSIZE (fields), & value);
249 fields->f_imm1 = ((value) + (1));
252 /* end-sanitize-m32rx */
253 /* start-sanitize-m32rx */
254 case M32R_OPERAND_ACCD :
255 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 2, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_accd);
257 /* end-sanitize-m32rx */
258 /* start-sanitize-m32rx */
259 case M32R_OPERAND_ACCS :
260 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 2, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_accs);
262 /* end-sanitize-m32rx */
263 /* start-sanitize-m32rx */
264 case M32R_OPERAND_ACC :
265 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 1, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_acc);
267 /* end-sanitize-m32rx */
268 case M32R_OPERAND_HI16 :
269 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_hi16);
271 case M32R_OPERAND_SLO16 :
272 length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm16);
274 case M32R_OPERAND_ULO16 :
275 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm16);
277 case M32R_OPERAND_UIMM24 :
278 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm24);
280 case M32R_OPERAND_DISP8 :
283 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, 0, CGEN_FIELDS_BITSIZE (fields), & value);
284 fields->f_disp8 = ((value) << (2));
287 case M32R_OPERAND_DISP16 :
290 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), & value);
291 fields->f_disp16 = ((value) << (2));
294 case M32R_OPERAND_DISP24 :
297 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, 0, CGEN_FIELDS_BITSIZE (fields), & value);
298 fields->f_disp24 = ((value) << (2));
303 fprintf (stderr, "Unrecognized field %d while decoding insn.\n",
311 /* Main entry point for printing operands.
313 This function is basically just a big switch statement. Earlier versions
314 used tables to look up the function to use, but
315 - if the table contains both assembler and disassembler functions then
316 the disassembler contains much of the assembler and vice-versa,
317 - there's a lot of inlining possibilities as things grow,
318 - using a switch statement avoids the function call overhead.
320 This function could be moved into `print_insn_normal', but keeping it
321 separate makes clear the interface between `print_insn_normal' and each of
326 m32r_cgen_print_operand (opindex, info, fields, attrs, pc, length)
328 disassemble_info * info;
329 CGEN_FIELDS * fields;
336 case M32R_OPERAND_SR :
337 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
339 case M32R_OPERAND_DR :
340 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
342 case M32R_OPERAND_SRC1 :
343 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
345 case M32R_OPERAND_SRC2 :
346 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
348 case M32R_OPERAND_SCR :
349 print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
351 case M32R_OPERAND_DCR :
352 print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
354 case M32R_OPERAND_SIMM8 :
355 print_normal (info, fields->f_simm8, 0, pc, length);
357 case M32R_OPERAND_SIMM16 :
358 print_normal (info, fields->f_simm16, 0, pc, length);
360 case M32R_OPERAND_UIMM4 :
361 print_normal (info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
363 case M32R_OPERAND_UIMM5 :
364 print_normal (info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
366 case M32R_OPERAND_UIMM16 :
367 print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
369 /* start-sanitize-m32rx */
370 case M32R_OPERAND_IMM1 :
371 print_normal (info, fields->f_imm1, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
373 /* end-sanitize-m32rx */
374 /* start-sanitize-m32rx */
375 case M32R_OPERAND_ACCD :
376 print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_accd, 0|(1<<CGEN_OPERAND_UNSIGNED));
378 /* end-sanitize-m32rx */
379 /* start-sanitize-m32rx */
380 case M32R_OPERAND_ACCS :
381 print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_accs, 0|(1<<CGEN_OPERAND_UNSIGNED));
383 /* end-sanitize-m32rx */
384 /* start-sanitize-m32rx */
385 case M32R_OPERAND_ACC :
386 print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED));
388 /* end-sanitize-m32rx */
389 case M32R_OPERAND_HI16 :
390 print_normal (info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
392 case M32R_OPERAND_SLO16 :
393 print_normal (info, fields->f_simm16, 0, pc, length);
395 case M32R_OPERAND_ULO16 :
396 print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
398 case M32R_OPERAND_UIMM24 :
399 print_normal (info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
401 case M32R_OPERAND_DISP8 :
402 print_normal (info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
404 case M32R_OPERAND_DISP16 :
405 print_normal (info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
407 case M32R_OPERAND_DISP24 :
408 print_normal (info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
412 fprintf (stderr, "Unrecognized field %d while printing insn.\n",
418 cgen_extract_fn * m32r_cgen_extract_handlers[] =
424 cgen_print_fn * m32r_cgen_print_handlers[] =
432 m32r_cgen_init_dis (mach, endian)
434 enum cgen_endian endian;
436 m32r_cgen_init_tables (mach);
437 cgen_set_cpu (& m32r_cgen_opcode_data, mach, endian);
442 /* Default insn extractor.
444 The extracted fields are stored in DIS_FLDS.
445 BUF_CTRL is used to handle reading variable length insns (FIXME: not done).
446 Return the length of the insn in bits, or 0 if no match. */
449 extract_insn_normal (insn, buf_ctrl, insn_value, fields)
450 const CGEN_INSN *insn;
452 cgen_insn_t insn_value;
455 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
456 const unsigned char *syn;
458 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
460 CGEN_INIT_EXTRACT ();
462 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
466 if (CGEN_SYNTAX_CHAR_P (*syn))
469 length = m32r_cgen_extract_operand (CGEN_SYNTAX_FIELD (*syn),
470 buf_ctrl, insn_value, fields);
475 /* We recognized and successfully extracted this insn. */
476 return CGEN_INSN_BITSIZE (insn);
479 /* Default insn printer.
481 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
482 about disassemble_info.
486 print_insn_normal (dis_info, insn, fields, pc, length)
488 const CGEN_INSN *insn;
493 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
494 disassemble_info *info = dis_info;
495 const unsigned char *syn;
499 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
501 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
503 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
506 if (CGEN_SYNTAX_CHAR_P (*syn))
508 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
512 /* We have an operand. */
513 m32r_cgen_print_operand (CGEN_SYNTAX_FIELD (*syn), info,
514 fields, CGEN_INSN_ATTRS (insn), pc, length);
518 /* Default value for CGEN_PRINT_INSN.
519 Given BUFLEN bits (target byte order) read into BUF, look up the
520 insn in the instruction table and disassemble it.
522 The result is the size of the insn in bytes. */
524 #ifndef CGEN_PRINT_INSN
525 #define CGEN_PRINT_INSN print_insn
529 print_insn (pc, info, buf, buflen)
531 disassemble_info *info;
535 unsigned long insn_value;
536 const CGEN_INSN_LIST *insn_list;
544 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
547 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
553 /* The instructions are stored in hash lists.
554 Pick the first one and keep trying until we find the right one. */
556 insn_list = CGEN_DIS_LOOKUP_INSN (buf, insn_value);
557 while (insn_list != NULL)
559 const CGEN_INSN *insn = insn_list->insn;
563 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
564 /* Supported by this cpu? */
565 if (! m32r_cgen_insn_supported (insn))
569 /* Basic bit mask must be correct. */
570 /* ??? May wish to allow target to defer this check until the extract
572 if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
574 /* Printing is handled in two passes. The first pass parses the
575 machine insn and extracts the fields. The second pass prints
578 length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, &fields);
581 (*CGEN_PRINT_FN (insn)) (info, insn, &fields, pc, length);
582 /* length is in bits, result is in bytes */
587 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
594 Print one instruction from PC on INFO->STREAM.
595 Return the size of the instruction (in bytes). */
598 print_insn_m32r (pc, info)
600 disassemble_info *info;
602 char buffer[CGEN_MAX_INSN_SIZE];
604 static int initialized = 0;
605 static int current_mach = 0;
606 static int current_big_p = 0;
607 int mach = info->mach;
608 int big_p = info->endian == BFD_ENDIAN_BIG;
610 /* If we haven't initialized yet, or if we've switched cpu's, initialize. */
611 if (!initialized || mach != current_mach || big_p != current_big_p)
615 current_big_p = big_p;
616 m32r_cgen_init_dis (mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
619 /* Read enough of the insn so we can look it up in the hash lists. */
621 status = (*info->read_memory_func) (pc, buffer, CGEN_BASE_INSN_SIZE, info);
624 (*info->memory_error_func) (status, pc, info);
628 /* We try to have as much common code as possible.
629 But at this point some targets need to take over. */
630 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
631 but if not possible try to move this hook elsewhere rather than
633 length = CGEN_PRINT_INSN (pc, info, buffer, CGEN_BASE_INSN_BITSIZE);
637 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
638 return CGEN_DEFAULT_INSN_SIZE;