1 /* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
4 THIS FILE IS MACHINE GENERATED WITH CGEN.
5 - the resultant file is machine generated, cgen-dis.in isn't
7 Copyright (C) 1996-2016 Free Software Foundation, Inc.
9 This file is part of libopcodes.
11 This library is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3, or (at your option)
16 It is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
25 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
34 #include "libiberty.h"
35 #include "xc16x-desc.h"
36 #include "xc16x-opc.h"
39 /* Default text to print if an instruction isn't recognized. */
40 #define UNKNOWN_INSN_MSG _("*unknown*")
42 static void print_normal
43 (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
44 static void print_address
45 (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
46 static void print_keyword
47 (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
48 static void print_insn_normal
49 (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
51 (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, unsigned);
52 static int default_print_insn
53 (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
55 (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
58 /* -- disassembler routines inserted here. */
62 /* Print an operand with a "." prefix.
63 NOTE: This prints the operand in hex.
64 ??? This exists to maintain disassembler compatibility with previous
65 versions. Ideally we'd print the "." in print_dot. */
68 print_with_dot_prefix (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
71 unsigned attrs ATTRIBUTE_UNUSED,
72 bfd_vma pc ATTRIBUTE_UNUSED,
73 int length ATTRIBUTE_UNUSED)
75 disassemble_info *info = (disassemble_info *) dis_info;
77 info->fprintf_func (info->stream, ".");
78 info->fprintf_func (info->stream, "0x%lx", value);
81 /* Print an operand with a "#pof:" prefix.
82 NOTE: This prints the operand as an address.
83 ??? This exists to maintain disassembler compatibility with previous
84 versions. Ideally we'd print "#pof:" in print_pof. */
87 print_with_pof_prefix (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
90 unsigned attrs ATTRIBUTE_UNUSED,
91 bfd_vma pc ATTRIBUTE_UNUSED,
92 int length ATTRIBUTE_UNUSED)
94 disassemble_info *info = (disassemble_info *) dis_info;
96 info->fprintf_func (info->stream, "#pof:");
97 info->fprintf_func (info->stream, "0x%lx", (long) value);
100 /* Print an operand with a "#pag:" prefix.
101 NOTE: This prints the operand in hex.
102 ??? This exists to maintain disassembler compatibility with previous
103 versions. Ideally we'd print "#pag:" in print_pag. */
106 print_with_pag_prefix (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
109 unsigned attrs ATTRIBUTE_UNUSED,
110 bfd_vma pc ATTRIBUTE_UNUSED,
111 int length ATTRIBUTE_UNUSED)
113 disassemble_info *info = (disassemble_info *) dis_info;
115 info->fprintf_func (info->stream, "#pag:");
116 info->fprintf_func (info->stream, "0x%lx", value);
119 /* Print a 'pof:' prefix to an operand. */
122 print_pof (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
123 void * dis_info ATTRIBUTE_UNUSED,
124 long value ATTRIBUTE_UNUSED,
125 unsigned int attrs ATTRIBUTE_UNUSED,
126 bfd_vma pc ATTRIBUTE_UNUSED,
127 int length ATTRIBUTE_UNUSED)
131 /* Print a 'pag:' prefix to an operand. */
134 print_pag (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
135 void * dis_info ATTRIBUTE_UNUSED,
136 long value ATTRIBUTE_UNUSED,
137 unsigned int attrs ATTRIBUTE_UNUSED,
138 bfd_vma pc ATTRIBUTE_UNUSED,
139 int length ATTRIBUTE_UNUSED)
143 /* Print a 'sof:' prefix to an operand. */
146 print_sof (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
148 long value ATTRIBUTE_UNUSED,
149 unsigned int attrs ATTRIBUTE_UNUSED,
150 bfd_vma pc ATTRIBUTE_UNUSED,
151 int length ATTRIBUTE_UNUSED)
153 disassemble_info *info = (disassemble_info *) dis_info;
155 info->fprintf_func (info->stream, "sof:");
158 /* Print a 'seg:' prefix to an operand. */
161 print_seg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
163 long value ATTRIBUTE_UNUSED,
164 unsigned int attrs ATTRIBUTE_UNUSED,
165 bfd_vma pc ATTRIBUTE_UNUSED,
166 int length ATTRIBUTE_UNUSED)
168 disassemble_info *info = (disassemble_info *) dis_info;
170 info->fprintf_func (info->stream, "seg:");
173 /* Print a '#' prefix to an operand. */
176 print_hash (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
178 long value ATTRIBUTE_UNUSED,
179 unsigned int attrs ATTRIBUTE_UNUSED,
180 bfd_vma pc ATTRIBUTE_UNUSED,
181 int length ATTRIBUTE_UNUSED)
183 disassemble_info *info = (disassemble_info *) dis_info;
185 info->fprintf_func (info->stream, "#");
188 /* Print a '.' prefix to an operand. */
191 print_dot (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
192 void * dis_info ATTRIBUTE_UNUSED,
193 long value ATTRIBUTE_UNUSED,
194 unsigned int attrs ATTRIBUTE_UNUSED,
195 bfd_vma pc ATTRIBUTE_UNUSED,
196 int length ATTRIBUTE_UNUSED)
202 void xc16x_cgen_print_operand
203 (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
205 /* Main entry point for printing operands.
206 XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
207 of dis-asm.h on cgen.h.
209 This function is basically just a big switch statement. Earlier versions
210 used tables to look up the function to use, but
211 - if the table contains both assembler and disassembler functions then
212 the disassembler contains much of the assembler and vice-versa,
213 - there's a lot of inlining possibilities as things grow,
214 - using a switch statement avoids the function call overhead.
216 This function could be moved into `print_insn_normal', but keeping it
217 separate makes clear the interface between `print_insn_normal' and each of
221 xc16x_cgen_print_operand (CGEN_CPU_DESC cd,
225 void const *attrs ATTRIBUTE_UNUSED,
229 disassemble_info *info = (disassemble_info *) xinfo;
233 case XC16X_OPERAND_REGNAM :
234 print_keyword (cd, info, & xc16x_cgen_opval_psw_names, fields->f_reg8, 0);
236 case XC16X_OPERAND_BIT01 :
237 print_normal (cd, info, fields->f_op_1bit, 0, pc, length);
239 case XC16X_OPERAND_BIT1 :
240 print_normal (cd, info, fields->f_op_bit1, 0, pc, length);
242 case XC16X_OPERAND_BIT2 :
243 print_normal (cd, info, fields->f_op_bit2, 0, pc, length);
245 case XC16X_OPERAND_BIT4 :
246 print_normal (cd, info, fields->f_op_bit4, 0, pc, length);
248 case XC16X_OPERAND_BIT8 :
249 print_normal (cd, info, fields->f_op_bit8, 0, pc, length);
251 case XC16X_OPERAND_BITONE :
252 print_normal (cd, info, fields->f_op_onebit, 0, pc, length);
254 case XC16X_OPERAND_CADDR :
255 print_address (cd, info, fields->f_offset16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
257 case XC16X_OPERAND_COND :
258 print_keyword (cd, info, & xc16x_cgen_opval_conditioncode_names, fields->f_condcode, 0);
260 case XC16X_OPERAND_DATA8 :
261 print_normal (cd, info, fields->f_data8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
263 case XC16X_OPERAND_DATAHI8 :
264 print_normal (cd, info, fields->f_datahi8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
266 case XC16X_OPERAND_DOT :
267 print_dot (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
269 case XC16X_OPERAND_DR :
270 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r1, 0);
272 case XC16X_OPERAND_DRB :
273 print_keyword (cd, info, & xc16x_cgen_opval_grb_names, fields->f_r1, 0);
275 case XC16X_OPERAND_DRI :
276 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r4, 0);
278 case XC16X_OPERAND_EXTCOND :
279 print_keyword (cd, info, & xc16x_cgen_opval_extconditioncode_names, fields->f_extccode, 0);
281 case XC16X_OPERAND_GENREG :
282 print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_regb8, 0);
284 case XC16X_OPERAND_HASH :
285 print_hash (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
287 case XC16X_OPERAND_ICOND :
288 print_keyword (cd, info, & xc16x_cgen_opval_conditioncode_names, fields->f_icondcode, 0);
290 case XC16X_OPERAND_LBIT2 :
291 print_normal (cd, info, fields->f_op_lbit2, 0, pc, length);
293 case XC16X_OPERAND_LBIT4 :
294 print_normal (cd, info, fields->f_op_lbit4, 0, pc, length);
296 case XC16X_OPERAND_MASK8 :
297 print_normal (cd, info, fields->f_mask8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
299 case XC16X_OPERAND_MASKLO8 :
300 print_normal (cd, info, fields->f_datahi8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
302 case XC16X_OPERAND_MEMGR8 :
303 print_keyword (cd, info, & xc16x_cgen_opval_memgr8_names, fields->f_memgr8, 0);
305 case XC16X_OPERAND_MEMORY :
306 print_address (cd, info, fields->f_memory, 0, pc, length);
308 case XC16X_OPERAND_PAG :
309 print_pag (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
311 case XC16X_OPERAND_PAGENUM :
312 print_normal (cd, info, fields->f_pagenum, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
314 case XC16X_OPERAND_POF :
315 print_pof (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
317 case XC16X_OPERAND_QBIT :
318 print_with_dot_prefix (cd, info, fields->f_qbit, 0|(1<<CGEN_OPERAND_DOT_PREFIX), pc, length);
320 case XC16X_OPERAND_QHIBIT :
321 print_with_dot_prefix (cd, info, fields->f_qhibit, 0|(1<<CGEN_OPERAND_DOT_PREFIX), pc, length);
323 case XC16X_OPERAND_QLOBIT :
324 print_with_dot_prefix (cd, info, fields->f_qlobit, 0|(1<<CGEN_OPERAND_DOT_PREFIX), pc, length);
326 case XC16X_OPERAND_REG8 :
327 print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_reg8, 0);
329 case XC16X_OPERAND_REGB8 :
330 print_keyword (cd, info, & xc16x_cgen_opval_grb8_names, fields->f_regb8, 0);
332 case XC16X_OPERAND_REGBMEM8 :
333 print_keyword (cd, info, & xc16x_cgen_opval_regbmem8_names, fields->f_regmem8, 0);
335 case XC16X_OPERAND_REGHI8 :
336 print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_reghi8, 0);
338 case XC16X_OPERAND_REGMEM8 :
339 print_keyword (cd, info, & xc16x_cgen_opval_regmem8_names, fields->f_regmem8, 0);
341 case XC16X_OPERAND_REGOFF8 :
342 print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_regoff8, 0);
344 case XC16X_OPERAND_REL :
345 print_normal (cd, info, fields->f_rel8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
347 case XC16X_OPERAND_RELHI :
348 print_normal (cd, info, fields->f_relhi8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
350 case XC16X_OPERAND_SEG :
351 print_normal (cd, info, fields->f_seg8, 0, pc, length);
353 case XC16X_OPERAND_SEGHI8 :
354 print_normal (cd, info, fields->f_segnum8, 0, pc, length);
356 case XC16X_OPERAND_SEGM :
357 print_seg (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
359 case XC16X_OPERAND_SOF :
360 print_sof (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
362 case XC16X_OPERAND_SR :
363 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r2, 0);
365 case XC16X_OPERAND_SR2 :
366 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r0, 0);
368 case XC16X_OPERAND_SRB :
369 print_keyword (cd, info, & xc16x_cgen_opval_grb_names, fields->f_r2, 0);
371 case XC16X_OPERAND_SRC1 :
372 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r1, 0);
374 case XC16X_OPERAND_SRC2 :
375 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r2, 0);
377 case XC16X_OPERAND_SRDIV :
378 print_keyword (cd, info, & xc16x_cgen_opval_regdiv8_names, fields->f_reg8, 0);
380 case XC16X_OPERAND_U4 :
381 print_keyword (cd, info, & xc16x_cgen_opval_reg0_name, fields->f_uimm4, 0);
383 case XC16X_OPERAND_UIMM16 :
384 print_normal (cd, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
386 case XC16X_OPERAND_UIMM2 :
387 print_keyword (cd, info, & xc16x_cgen_opval_ext_names, fields->f_uimm2, 0|(1<<CGEN_OPERAND_HASH_PREFIX));
389 case XC16X_OPERAND_UIMM3 :
390 print_keyword (cd, info, & xc16x_cgen_opval_reg0_name1, fields->f_uimm3, 0|(1<<CGEN_OPERAND_HASH_PREFIX));
392 case XC16X_OPERAND_UIMM4 :
393 print_normal (cd, info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
395 case XC16X_OPERAND_UIMM7 :
396 print_normal (cd, info, fields->f_uimm7, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
398 case XC16X_OPERAND_UIMM8 :
399 print_normal (cd, info, fields->f_uimm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
401 case XC16X_OPERAND_UPAG16 :
402 print_with_pag_prefix (cd, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_PAG_PREFIX), pc, length);
404 case XC16X_OPERAND_UPOF16 :
405 print_with_pof_prefix (cd, info, fields->f_memory, 0|(1<<CGEN_OPERAND_POF_PREFIX), pc, length);
407 case XC16X_OPERAND_USEG16 :
408 print_normal (cd, info, fields->f_offset16, 0|(1<<CGEN_OPERAND_SEG_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
410 case XC16X_OPERAND_USEG8 :
411 print_normal (cd, info, fields->f_seg8, 0|(1<<CGEN_OPERAND_SEG_PREFIX), pc, length);
413 case XC16X_OPERAND_USOF16 :
414 print_normal (cd, info, fields->f_offset16, 0|(1<<CGEN_OPERAND_SOF_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
418 /* xgettext:c-format */
419 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
425 cgen_print_fn * const xc16x_cgen_print_handlers[] =
432 xc16x_cgen_init_dis (CGEN_CPU_DESC cd)
434 xc16x_cgen_init_opcode_table (cd);
435 xc16x_cgen_init_ibld_table (cd);
436 cd->print_handlers = & xc16x_cgen_print_handlers[0];
437 cd->print_operand = xc16x_cgen_print_operand;
441 /* Default print handler. */
444 print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
448 bfd_vma pc ATTRIBUTE_UNUSED,
449 int length ATTRIBUTE_UNUSED)
451 disassemble_info *info = (disassemble_info *) dis_info;
453 /* Print the operand as directed by the attributes. */
454 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
455 ; /* nothing to do */
456 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
457 (*info->fprintf_func) (info->stream, "%ld", value);
459 (*info->fprintf_func) (info->stream, "0x%lx", value);
462 /* Default address handler. */
465 print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
469 bfd_vma pc ATTRIBUTE_UNUSED,
470 int length ATTRIBUTE_UNUSED)
472 disassemble_info *info = (disassemble_info *) dis_info;
474 /* Print the operand as directed by the attributes. */
475 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
476 ; /* Nothing to do. */
477 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
478 (*info->print_address_func) (value, info);
479 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
480 (*info->print_address_func) (value, info);
481 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
482 (*info->fprintf_func) (info->stream, "%ld", (long) value);
484 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
487 /* Keyword print handler. */
490 print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
492 CGEN_KEYWORD *keyword_table,
494 unsigned int attrs ATTRIBUTE_UNUSED)
496 disassemble_info *info = (disassemble_info *) dis_info;
497 const CGEN_KEYWORD_ENTRY *ke;
499 ke = cgen_keyword_lookup_value (keyword_table, value);
501 (*info->fprintf_func) (info->stream, "%s", ke->name);
503 (*info->fprintf_func) (info->stream, "???");
506 /* Default insn printer.
508 DIS_INFO is defined as `void *' so the disassembler needn't know anything
509 about disassemble_info. */
512 print_insn_normal (CGEN_CPU_DESC cd,
514 const CGEN_INSN *insn,
519 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
520 disassemble_info *info = (disassemble_info *) dis_info;
521 const CGEN_SYNTAX_CHAR_TYPE *syn;
523 CGEN_INIT_PRINT (cd);
525 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
527 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
529 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
532 if (CGEN_SYNTAX_CHAR_P (*syn))
534 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
538 /* We have an operand. */
539 xc16x_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
540 fields, CGEN_INSN_ATTRS (insn), pc, length);
544 /* Subroutine of print_insn. Reads an insn into the given buffers and updates
546 Returns 0 if all is well, non-zero otherwise. */
549 read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
551 disassemble_info *info,
554 CGEN_EXTRACT_INFO *ex_info,
555 unsigned long *insn_value)
557 int status = (*info->read_memory_func) (pc, buf, buflen, info);
561 (*info->memory_error_func) (status, pc, info);
565 ex_info->dis_info = info;
566 ex_info->valid = (1 << buflen) - 1;
567 ex_info->insn_bytes = buf;
569 *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
573 /* Utility to print an insn.
574 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
575 The result is the size of the insn in bytes or zero for an unknown insn
576 or -1 if an error occurs fetching data (memory_error_func will have
580 print_insn (CGEN_CPU_DESC cd,
582 disassemble_info *info,
586 CGEN_INSN_INT insn_value;
587 const CGEN_INSN_LIST *insn_list;
588 CGEN_EXTRACT_INFO ex_info;
591 /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
592 basesize = cd->base_insn_bitsize < buflen * 8 ?
593 cd->base_insn_bitsize : buflen * 8;
594 insn_value = cgen_get_insn_value (cd, buf, basesize);
597 /* Fill in ex_info fields like read_insn would. Don't actually call
598 read_insn, since the incoming buffer is already read (and possibly
599 modified a la m32r). */
600 ex_info.valid = (1 << buflen) - 1;
601 ex_info.dis_info = info;
602 ex_info.insn_bytes = buf;
604 /* The instructions are stored in hash lists.
605 Pick the first one and keep trying until we find the right one. */
607 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
608 while (insn_list != NULL)
610 const CGEN_INSN *insn = insn_list->insn;
613 unsigned long insn_value_cropped;
615 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
616 /* Not needed as insn shouldn't be in hash lists if not supported. */
617 /* Supported by this cpu? */
618 if (! xc16x_cgen_insn_supported (cd, insn))
620 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
625 /* Basic bit mask must be correct. */
626 /* ??? May wish to allow target to defer this check until the extract
629 /* Base size may exceed this instruction's size. Extract the
630 relevant part from the buffer. */
631 if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
632 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
633 insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
634 info->endian == BFD_ENDIAN_BIG);
636 insn_value_cropped = insn_value;
638 if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
639 == CGEN_INSN_BASE_VALUE (insn))
641 /* Printing is handled in two passes. The first pass parses the
642 machine insn and extracts the fields. The second pass prints
645 /* Make sure the entire insn is loaded into insn_value, if it
647 if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
648 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
650 unsigned long full_insn_value;
651 int rc = read_insn (cd, pc, info, buf,
652 CGEN_INSN_BITSIZE (insn) / 8,
653 & ex_info, & full_insn_value);
656 length = CGEN_EXTRACT_FN (cd, insn)
657 (cd, insn, &ex_info, full_insn_value, &fields, pc);
660 length = CGEN_EXTRACT_FN (cd, insn)
661 (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
663 /* Length < 0 -> error. */
668 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
669 /* Length is in bits, result is in bytes. */
674 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
680 /* Default value for CGEN_PRINT_INSN.
681 The result is the size of the insn in bytes or zero for an unknown insn
682 or -1 if an error occured fetching bytes. */
684 #ifndef CGEN_PRINT_INSN
685 #define CGEN_PRINT_INSN default_print_insn
689 default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
691 bfd_byte buf[CGEN_MAX_INSN_SIZE];
695 /* Attempt to read the base part of the insn. */
696 buflen = cd->base_insn_bitsize / 8;
697 status = (*info->read_memory_func) (pc, buf, buflen, info);
699 /* Try again with the minimum part, if min < base. */
700 if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
702 buflen = cd->min_insn_bitsize / 8;
703 status = (*info->read_memory_func) (pc, buf, buflen, info);
708 (*info->memory_error_func) (status, pc, info);
712 return print_insn (cd, pc, info, buf, buflen);
716 Print one instruction from PC on INFO->STREAM.
717 Return the size of the instruction (in bytes). */
719 typedef struct cpu_desc_list
721 struct cpu_desc_list *next;
729 print_insn_xc16x (bfd_vma pc, disassemble_info *info)
731 static cpu_desc_list *cd_list = 0;
732 cpu_desc_list *cl = 0;
733 static CGEN_CPU_DESC cd = 0;
734 static CGEN_BITSET *prev_isa;
735 static int prev_mach;
736 static int prev_endian;
740 int endian = (info->endian == BFD_ENDIAN_BIG
742 : CGEN_ENDIAN_LITTLE);
743 enum bfd_architecture arch;
745 /* ??? gdb will set mach but leave the architecture as "unknown" */
746 #ifndef CGEN_BFD_ARCH
747 #define CGEN_BFD_ARCH bfd_arch_xc16x
750 if (arch == bfd_arch_unknown)
751 arch = CGEN_BFD_ARCH;
753 /* There's no standard way to compute the machine or isa number
754 so we leave it to the target. */
755 #ifdef CGEN_COMPUTE_MACH
756 mach = CGEN_COMPUTE_MACH (info);
761 #ifdef CGEN_COMPUTE_ISA
763 static CGEN_BITSET *permanent_isa;
766 permanent_isa = cgen_bitset_create (MAX_ISAS);
768 cgen_bitset_clear (isa);
769 cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
772 isa = info->insn_sets;
775 /* If we've switched cpu's, try to find a handle we've used before */
777 && (cgen_bitset_compare (isa, prev_isa) != 0
779 || endian != prev_endian))
782 for (cl = cd_list; cl; cl = cl->next)
784 if (cgen_bitset_compare (cl->isa, isa) == 0 &&
786 cl->endian == endian)
795 /* If we haven't initialized yet, initialize the opcode table. */
798 const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
799 const char *mach_name;
803 mach_name = arch_type->printable_name;
805 prev_isa = cgen_bitset_copy (isa);
807 prev_endian = endian;
808 cd = xc16x_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
809 CGEN_CPU_OPEN_BFDMACH, mach_name,
810 CGEN_CPU_OPEN_ENDIAN, prev_endian,
815 /* Save this away for future reference. */
816 cl = xmalloc (sizeof (struct cpu_desc_list));
824 xc16x_cgen_init_dis (cd);
827 /* We try to have as much common code as possible.
828 But at this point some targets need to take over. */
829 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
830 but if not possible try to move this hook elsewhere rather than
832 length = CGEN_PRINT_INSN (cd, pc, info);
838 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
839 return cd->default_insn_bitsize / 8;