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. */
30 /* ??? The layout of this stuff is still work in progress.
31 For speed in assembly/disassembly, we use inline functions. That of course
32 will only work for GCC. When this stuff is finished, we can decide whether
33 to keep the inline functions (and only get the performance increase when
34 compiled with GCC), or switch to macros, or use something else.
37 /* Default text to print if an instruction isn't recognized. */
38 #define UNKNOWN_INSN_MSG "*unknown*"
40 /* FIXME: Machine generate. */
41 #ifndef CGEN_PCREL_OFFSET
42 #define CGEN_PCREL_OFFSET 0
45 static int print_insn PARAMS ((bfd_vma, disassemble_info *, char *, int));
47 static int extract_insn_normal
48 PARAMS ((const struct cgen_insn *, void *, cgen_insn_t, struct cgen_fields *));
49 static void print_insn_normal
50 PARAMS ((void *, const struct cgen_insn *, struct cgen_fields *, bfd_vma, int));
52 /* Default extraction routine.
54 ATTRS is a mask of the boolean attributes. We only need `unsigned',
55 but for generality we take a bitmask of all of them. */
58 extract_normal (buf_ctrl, insn_value, attrs, start, length, shift, total_length, valuep)
60 cgen_insn_t insn_value;
62 int start, length, shift, total_length;
69 value = ((insn_value >> (CGEN_BASE_INSN_BITSIZE - (start + length)))
70 & ((1 << length) - 1));
72 value = ((insn_value >> (total_length - (start + length)))
73 & ((1 << length) - 1));
75 if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
76 && (value & (1 << (length - 1))))
79 /* FIXME: unfinished */
82 /* This is backwards as we undo the effects of insert_normal. */
92 /* Default print handler. */
95 print_normal (dis_info, value, attrs, pc, length)
99 unsigned long pc; /* FIXME: should be bfd_vma */
102 disassemble_info *info = dis_info;
104 /* Print the operand as directed by the attributes. */
105 if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_FAKE))
106 ; /* nothing to do (??? at least not yet) */
107 else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_PCREL_ADDR))
108 (*info->print_address_func) (pc + CGEN_PCREL_OFFSET + value, info);
109 /* ??? Not all cases of this are currently caught. */
110 else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_ABS_ADDR))
111 /* FIXME: Why & 0xffffffff? */
112 (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
113 else if (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
114 (*info->fprintf_func) (info->stream, "0x%lx", value);
116 (*info->fprintf_func) (info->stream, "%ld", value);
119 /* Keyword print handler. */
122 print_keyword (dis_info, keyword_table, value, attrs)
124 struct cgen_keyword *keyword_table;
128 disassemble_info *info = dis_info;
129 const struct cgen_keyword_entry *ke;
131 ke = cgen_keyword_lookup_value (keyword_table, value);
133 (*info->fprintf_func) (info->stream, "%s", ke->name);
135 (*info->fprintf_func) (info->stream, "???");
138 /* -- disassembler routines inserted here */
141 #undef CGEN_PRINT_INSN
142 #define CGEN_PRINT_INSN my_print_insn
145 my_print_insn (pc, info, buf, buflen)
147 disassemble_info *info;
151 unsigned long insn_value;
154 if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
155 return print_insn (pc, info, buf, buflen);
157 /* Print the first insn. */
160 if (print_insn (pc, info, buf, 16) == 0)
161 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
168 (*info->fprintf_func) (info->stream, " || ");
172 (*info->fprintf_func) (info->stream, " -> ");
174 /* The "& 3" is to ensure the branch address is computed correctly
175 [if it is a branch]. */
176 if (print_insn (pc & ~ (bfd_vma) 3, info, buf, 16) == 0)
177 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
179 return (pc & 3) ? 2 : 4;
184 /* Main entry point for operand extraction.
186 This function is basically just a big switch statement. Earlier versions
187 used tables to look up the function to use, but
188 - if the table contains both assembler and disassembler functions then
189 the disassembler contains much of the assembler and vice-versa,
190 - there's a lot of inlining possibilities as things grow,
191 - using a switch statement avoids the function call overhead.
193 This function could be moved into `print_insn_normal', but keeping it
194 separate makes clear the interface between `print_insn_normal' and each of
199 m32r_cgen_extract_operand (opindex, buf_ctrl, insn_value, fields)
202 cgen_insn_t insn_value;
203 struct cgen_fields *fields;
210 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2);
213 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1);
216 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1);
219 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2);
222 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r2);
225 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_r1);
228 length = extract_normal (NULL /*FIXME*/, insn_value, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm8);
231 length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm16);
234 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm4);
237 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm5);
240 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm16);
243 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);
246 length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_simm16);
249 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), &fields->f_uimm16);
252 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);
255 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp8);
258 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp16);
261 length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, 2, CGEN_FIELDS_BITSIZE (fields), &fields->f_disp24);
265 fprintf (stderr, "Unrecognized field %d while decoding insn.\n",
273 /* Main entry point for printing operands.
275 This function is basically just a big switch statement. Earlier versions
276 used tables to look up the function to use, but
277 - if the table contains both assembler and disassembler functions then
278 the disassembler contains much of the assembler and vice-versa,
279 - there's a lot of inlining possibilities as things grow,
280 - using a switch statement avoids the function call overhead.
282 This function could be moved into `print_insn_normal', but keeping it
283 separate makes clear the interface between `print_insn_normal' and each of
288 m32r_cgen_print_operand (opindex, info, fields, attrs, pc, length)
290 disassemble_info *info;
291 struct cgen_fields *fields;
299 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
302 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
305 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
308 print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
311 print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
314 print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
317 print_normal (info, fields->f_simm8, 0, pc, length);
320 print_normal (info, fields->f_simm16, 0, pc, length);
323 print_normal (info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
326 print_normal (info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
329 print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
332 print_normal (info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
335 print_normal (info, fields->f_simm16, 0, pc, length);
338 print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
341 print_normal (info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
344 print_normal (info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
347 print_normal (info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
350 print_normal (info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
354 fprintf (stderr, "Unrecognized field %d while printing insn.\n",
360 cgen_extract_fn *m32r_cgen_extract_handlers[] = {
365 cgen_print_fn *m32r_cgen_print_handlers[] = {
372 m32r_cgen_init_dis (mach, endian)
374 enum cgen_endian endian;
376 m32r_cgen_init_tables (mach);
377 cgen_set_cpu (& m32r_cgen_opcode_data, mach, endian);
382 /* Default insn extractor.
384 The extracted fields are stored in DIS_FLDS.
385 BUF_CTRL is used to handle reading variable length insns (FIXME: not done).
386 Return the length of the insn in bits, or 0 if no match. */
389 extract_insn_normal (insn, buf_ctrl, insn_value, fields)
390 const struct cgen_insn *insn;
392 cgen_insn_t insn_value;
393 struct cgen_fields *fields;
395 const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn);
396 const unsigned char *syn;
398 /* ??? Some of the operand extract routines need to know the insn length,
399 which might be computed as we go. Set a default value and it'll be
400 modified as necessary. */
401 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
403 CGEN_INIT_EXTRACT ();
405 for (syn = syntax->syntax; *syn; ++syn)
409 if (CGEN_SYNTAX_CHAR_P (*syn))
412 length = m32r_cgen_extract_operand (CGEN_SYNTAX_FIELD (*syn),
413 buf_ctrl, insn_value, fields);
418 /* We recognized and successfully extracted this insn.
419 If a length is recorded with this insn, it has a fixed length.
420 Otherwise we require the syntax string to have a fake operand which
421 sets the `length' field in `flds'. */
423 if (syntax->length > 0)
424 return syntax->length;
425 return fields->length;
428 /* Default insn printer.
430 DIS_INFO is defined as `void *' so the disassembler needn't know anything
431 about disassemble_info.
435 print_insn_normal (dis_info, insn, fields, pc, length)
437 const struct cgen_insn *insn;
438 struct cgen_fields *fields;
442 const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn);
443 disassemble_info *info = dis_info;
444 const unsigned char *syn;
448 for (syn = syntax->syntax; *syn; ++syn)
450 if (CGEN_SYNTAX_CHAR_P (*syn))
452 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
456 /* We have an operand. */
457 m32r_cgen_print_operand (CGEN_SYNTAX_FIELD (*syn), info,
458 fields, CGEN_INSN_ATTRS (insn), pc, length);
462 /* Default value for CGEN_PRINT_INSN.
463 Given BUFLEN bytes (target byte order) read into BUF, look up the
464 insn in the instruction table and disassemble it.
466 The result is the size of the insn in bytes. */
468 #ifndef CGEN_PRINT_INSN
469 #define CGEN_PRINT_INSN print_insn
473 print_insn (pc, info, buf, buflen)
475 disassemble_info *info;
480 unsigned long insn_value;
481 const CGEN_INSN_LIST *insn_list;
489 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
492 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
498 /* The instructions are stored in hash lists.
499 Pick the first one and keep trying until we find the right one. */
501 insn_list = CGEN_DIS_LOOKUP_INSN (buf, insn_value);
502 while (insn_list != NULL)
504 const CGEN_INSN *insn = insn_list->insn;
505 const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn);
506 struct cgen_fields fields;
509 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
510 /* Supported by this cpu? */
511 if (! m32r_cgen_insn_supported (insn))
515 /* Basic bit mask must be correct. */
516 /* ??? May wish to allow target to defer this check until the extract
518 if ((insn_value & syntax->mask) == syntax->value)
520 /* Printing is handled in two passes. The first pass parses the
521 machine insn and extracts the fields. The second pass prints
524 length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, &fields);
527 (*CGEN_PRINT_FN (insn)) (info, insn, &fields, pc, length);
528 /* length is in bits, result is in bytes */
533 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
540 Print one instruction from PC on INFO->STREAM.
541 Return the size of the instruction (in bytes). */
544 print_insn_m32r (pc, info)
546 disassemble_info *info;
548 char buffer[CGEN_MAX_INSN_SIZE];
550 static int initialized = 0;
551 static int current_mach = 0;
552 static int current_big_p = 0;
553 int mach = info->mach;
554 int big_p = info->endian == BFD_ENDIAN_BIG;
556 /* If we haven't initialized yet, or if we've switched cpu's, initialize. */
557 if (!initialized || mach != current_mach || big_p != current_big_p)
561 current_big_p = big_p;
562 m32r_cgen_init_dis (mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
565 /* Read enough of the insn so we can look it up in the hash lists. */
567 status = (*info->read_memory_func) (pc, buffer, CGEN_BASE_INSN_SIZE, info);
570 (*info->memory_error_func) (status, pc, info);
574 /* We try to have as much common code as possible.
575 But at this point some targets need to take over. */
576 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
577 but if not possible, try to move this hook elsewhere rather than
579 length = CGEN_PRINT_INSN (pc, info, buffer, CGEN_BASE_INSN_BITSIZE);
583 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
584 return CGEN_DEFAULT_INSN_SIZE;