daily update
[binutils.git] / opcodes / ip2k-dis.c
blob91aaa618ba44fc262ec9909b27e3f2114b33b30c
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 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
9 This file is part of the GNU Binutils and GDB, the GNU debugger.
11 This program 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 2, or (at your option)
14 any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public 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 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
25 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26 Keep that in mind. */
28 #include "sysdep.h"
29 #include <stdio.h>
30 #include "ansidecl.h"
31 #include "dis-asm.h"
32 #include "bfd.h"
33 #include "symcat.h"
34 #include "ip2k-desc.h"
35 #include "ip2k-opc.h"
36 #include "opintl.h"
38 /* Default text to print if an instruction isn't recognized. */
39 #define UNKNOWN_INSN_MSG _("*unknown*")
41 static void print_normal
42 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int));
43 static void print_address
44 PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
45 static void print_keyword
46 PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
47 static void print_insn_normal
48 PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
49 bfd_vma, int));
50 static int print_insn
51 PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, unsigned));
52 static int default_print_insn
53 PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
54 static int read_insn
55 PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, int,
56 CGEN_EXTRACT_INFO *, unsigned long *));
58 /* -- disassembler routines inserted here */
60 /* -- dis.c */
62 static void
63 print_fr (cd, dis_info, value, attrs, pc, length)
64 CGEN_CPU_DESC cd;
65 PTR dis_info;
66 long value;
67 unsigned int attrs;
68 bfd_vma pc;
69 int length;
71 disassemble_info *info = (disassemble_info *) dis_info;
72 const CGEN_KEYWORD_ENTRY *ke;
73 extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
74 long offsettest;
75 long offsetvalue;
77 if ( value == 0 ) /* This is (IP) */
79 (*info->fprintf_func) (info->stream, "%s", "(IP)");
80 return;
83 offsettest = value >> 7;
84 offsetvalue = value & 0x7F;
86 /* Check to see if first two bits are 10 -> (DP) */
87 if ( offsettest == 2 )
89 if ( offsetvalue == 0 )
90 (*info->fprintf_func) (info->stream, "%s","(DP)");
91 else
92 (*info->fprintf_func) (info->stream, "$%x%s",offsetvalue, "(DP)");
93 return;
96 /* Check to see if first two bits are 11 -> (SP) */
97 if ( offsettest == 3 )
99 if ( offsetvalue == 0 )
100 (*info->fprintf_func) (info->stream, "%s", "(SP)");
101 else
102 (*info->fprintf_func) (info->stream, "$%x%s", offsetvalue,"(SP)");
103 return;
106 /* Attempt to print as a register keyword. */
107 ke = cgen_keyword_lookup_value (& ip2k_cgen_opval_register_names, value);
108 if (ke != NULL)
110 (*info->fprintf_func) (info->stream, "%s", ke->name);
111 return;
114 /* Print as an address literal. */
115 (*info->fprintf_func) (info->stream, "$%02x", value);
118 static void
119 print_dollarhex (cd, dis_info, value, attrs, pc, length)
120 CGEN_CPU_DESC cd;
121 PTR dis_info;
122 long value;
123 unsigned int attrs;
124 bfd_vma pc;
125 int length;
127 disassemble_info *info = (disassemble_info *) dis_info;
129 (*info->fprintf_func) (info->stream, "$%x", value);
132 static void
133 print_dollarhex8 (cd, dis_info, value, attrs, pc, length)
134 CGEN_CPU_DESC cd;
135 PTR dis_info;
136 long value;
137 unsigned int attrs;
138 bfd_vma pc;
139 int length;
141 disassemble_info *info = (disassemble_info *) dis_info;
143 (*info->fprintf_func) (info->stream, "$%02x", value);
146 static void
147 print_dollarhex16 (cd, dis_info, value, attrs, pc, length)
148 CGEN_CPU_DESC cd;
149 PTR dis_info;
150 long value;
151 unsigned int attrs;
152 bfd_vma pc;
153 int length;
155 disassemble_info *info = (disassemble_info *) dis_info;
157 (*info->fprintf_func) (info->stream, "$%04x", value);
160 static void
161 print_dollarhex_addr16h (cd, dis_info, value, attrs, pc, length)
162 CGEN_CPU_DESC cd;
163 PTR dis_info;
164 long value;
165 unsigned int attrs;
166 bfd_vma pc;
167 int length;
169 disassemble_info *info = (disassemble_info *) dis_info;
171 /* This is a loadh instruction. Shift the value to the left */
172 /* by 8 bits so that disassembled code will reassemble properly. */
173 value = ((value << 8) & 0xFF00);
175 (*info->fprintf_func) (info->stream, "$%04x", value);
178 static void
179 print_dollarhex_addr16l (cd, dis_info, value, attrs, pc, length)
180 CGEN_CPU_DESC cd;
181 PTR dis_info;
182 long value;
183 unsigned int attrs;
184 bfd_vma pc;
185 int length;
187 disassemble_info *info = (disassemble_info *) dis_info;
189 (*info->fprintf_func) (info->stream, "$%04x", value);
192 static void
193 print_dollarhex_p (cd, dis_info, value, attrs, pc, length)
194 CGEN_CPU_DESC cd;
195 PTR dis_info;
196 long value;
197 unsigned int attrs;
198 bfd_vma pc;
199 int length;
201 disassemble_info *info = (disassemble_info *) dis_info;
203 value = ((value << 14) & 0x1C000);
204 ;value = (value & 0x1FFFF);
205 (*info->fprintf_func) (info->stream, "$%05x", value);
208 static void
209 print_dollarhex_cj (cd, dis_info, value, attrs, pc, length)
210 CGEN_CPU_DESC cd;
211 PTR dis_info;
212 long value;
213 unsigned int attrs;
214 bfd_vma pc;
215 int length;
217 disassemble_info *info = (disassemble_info *) dis_info;
219 value = ((value << 1) & 0x1FFFF);
220 (*info->fprintf_func) (info->stream, "$%05x", value);
224 static void
225 print_decimal (cd, dis_info, value, attrs, pc, length)
226 CGEN_CPU_DESC cd;
227 PTR dis_info;
228 long value;
229 unsigned int attrs;
230 bfd_vma pc;
231 int length;
233 disassemble_info *info = (disassemble_info *) dis_info;
235 (*info->fprintf_func) (info->stream, "%d", value);
240 /* -- */
242 void ip2k_cgen_print_operand
243 PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *,
244 void const *, bfd_vma, int));
246 /* Main entry point for printing operands.
247 XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
248 of dis-asm.h on cgen.h.
250 This function is basically just a big switch statement. Earlier versions
251 used tables to look up the function to use, but
252 - if the table contains both assembler and disassembler functions then
253 the disassembler contains much of the assembler and vice-versa,
254 - there's a lot of inlining possibilities as things grow,
255 - using a switch statement avoids the function call overhead.
257 This function could be moved into `print_insn_normal', but keeping it
258 separate makes clear the interface between `print_insn_normal' and each of
259 the handlers. */
261 void
262 ip2k_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
263 CGEN_CPU_DESC cd;
264 int opindex;
265 PTR xinfo;
266 CGEN_FIELDS *fields;
267 void const *attrs ATTRIBUTE_UNUSED;
268 bfd_vma pc;
269 int length;
271 disassemble_info *info = (disassemble_info *) xinfo;
273 switch (opindex)
275 case IP2K_OPERAND_ADDR16CJP :
276 print_dollarhex_cj (cd, info, fields->f_addr16cjp, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
277 break;
278 case IP2K_OPERAND_ADDR16H :
279 print_dollarhex_addr16h (cd, info, fields->f_imm8, 0, pc, length);
280 break;
281 case IP2K_OPERAND_ADDR16L :
282 print_dollarhex_addr16l (cd, info, fields->f_imm8, 0, pc, length);
283 break;
284 case IP2K_OPERAND_ADDR16P :
285 print_dollarhex_p (cd, info, fields->f_page3, 0, pc, length);
286 break;
287 case IP2K_OPERAND_BITNO :
288 print_decimal (cd, info, fields->f_bitno, 0, pc, length);
289 break;
290 case IP2K_OPERAND_CBIT :
291 print_normal (cd, info, 0, 0, pc, length);
292 break;
293 case IP2K_OPERAND_DCBIT :
294 print_normal (cd, info, 0, 0, pc, length);
295 break;
296 case IP2K_OPERAND_FR :
297 print_fr (cd, info, fields->f_reg, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
298 break;
299 case IP2K_OPERAND_LIT8 :
300 print_dollarhex8 (cd, info, fields->f_imm8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
301 break;
302 case IP2K_OPERAND_PABITS :
303 print_normal (cd, info, 0, 0, pc, length);
304 break;
305 case IP2K_OPERAND_RETI3 :
306 print_dollarhex (cd, info, fields->f_reti3, 0, pc, length);
307 break;
308 case IP2K_OPERAND_ZBIT :
309 print_normal (cd, info, 0, 0, pc, length);
310 break;
312 default :
313 /* xgettext:c-format */
314 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
315 opindex);
316 abort ();
320 cgen_print_fn * const ip2k_cgen_print_handlers[] =
322 print_insn_normal,
326 void
327 ip2k_cgen_init_dis (cd)
328 CGEN_CPU_DESC cd;
330 ip2k_cgen_init_opcode_table (cd);
331 ip2k_cgen_init_ibld_table (cd);
332 cd->print_handlers = & ip2k_cgen_print_handlers[0];
333 cd->print_operand = ip2k_cgen_print_operand;
337 /* Default print handler. */
339 static void
340 print_normal (cd, dis_info, value, attrs, pc, length)
341 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
342 PTR dis_info;
343 long value;
344 unsigned int attrs;
345 bfd_vma pc ATTRIBUTE_UNUSED;
346 int length ATTRIBUTE_UNUSED;
348 disassemble_info *info = (disassemble_info *) dis_info;
350 #ifdef CGEN_PRINT_NORMAL
351 CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
352 #endif
354 /* Print the operand as directed by the attributes. */
355 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
356 ; /* nothing to do */
357 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
358 (*info->fprintf_func) (info->stream, "%ld", value);
359 else
360 (*info->fprintf_func) (info->stream, "0x%lx", value);
363 /* Default address handler. */
365 static void
366 print_address (cd, dis_info, value, attrs, pc, length)
367 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
368 PTR dis_info;
369 bfd_vma value;
370 unsigned int attrs;
371 bfd_vma pc ATTRIBUTE_UNUSED;
372 int length ATTRIBUTE_UNUSED;
374 disassemble_info *info = (disassemble_info *) dis_info;
376 #ifdef CGEN_PRINT_ADDRESS
377 CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
378 #endif
380 /* Print the operand as directed by the attributes. */
381 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
382 ; /* nothing to do */
383 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
384 (*info->print_address_func) (value, info);
385 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
386 (*info->print_address_func) (value, info);
387 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
388 (*info->fprintf_func) (info->stream, "%ld", (long) value);
389 else
390 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
393 /* Keyword print handler. */
395 static void
396 print_keyword (cd, dis_info, keyword_table, value, attrs)
397 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
398 PTR dis_info;
399 CGEN_KEYWORD *keyword_table;
400 long value;
401 unsigned int attrs ATTRIBUTE_UNUSED;
403 disassemble_info *info = (disassemble_info *) dis_info;
404 const CGEN_KEYWORD_ENTRY *ke;
406 ke = cgen_keyword_lookup_value (keyword_table, value);
407 if (ke != NULL)
408 (*info->fprintf_func) (info->stream, "%s", ke->name);
409 else
410 (*info->fprintf_func) (info->stream, "???");
413 /* Default insn printer.
415 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
416 about disassemble_info. */
418 static void
419 print_insn_normal (cd, dis_info, insn, fields, pc, length)
420 CGEN_CPU_DESC cd;
421 PTR dis_info;
422 const CGEN_INSN *insn;
423 CGEN_FIELDS *fields;
424 bfd_vma pc;
425 int length;
427 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
428 disassemble_info *info = (disassemble_info *) dis_info;
429 const CGEN_SYNTAX_CHAR_TYPE *syn;
431 CGEN_INIT_PRINT (cd);
433 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
435 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
437 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
438 continue;
440 if (CGEN_SYNTAX_CHAR_P (*syn))
442 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
443 continue;
446 /* We have an operand. */
447 ip2k_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
448 fields, CGEN_INSN_ATTRS (insn), pc, length);
452 /* Subroutine of print_insn. Reads an insn into the given buffers and updates
453 the extract info.
454 Returns 0 if all is well, non-zero otherwise. */
456 static int
457 read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
458 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
459 bfd_vma pc;
460 disassemble_info *info;
461 char *buf;
462 int buflen;
463 CGEN_EXTRACT_INFO *ex_info;
464 unsigned long *insn_value;
466 int status = (*info->read_memory_func) (pc, buf, buflen, info);
467 if (status != 0)
469 (*info->memory_error_func) (status, pc, info);
470 return -1;
473 ex_info->dis_info = info;
474 ex_info->valid = (1 << buflen) - 1;
475 ex_info->insn_bytes = buf;
477 *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
478 return 0;
481 /* Utility to print an insn.
482 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
483 The result is the size of the insn in bytes or zero for an unknown insn
484 or -1 if an error occurs fetching data (memory_error_func will have
485 been called). */
487 static int
488 print_insn (cd, pc, info, buf, buflen)
489 CGEN_CPU_DESC cd;
490 bfd_vma pc;
491 disassemble_info *info;
492 char *buf;
493 unsigned int buflen;
495 CGEN_INSN_INT insn_value;
496 const CGEN_INSN_LIST *insn_list;
497 CGEN_EXTRACT_INFO ex_info;
498 int basesize;
500 /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
501 basesize = cd->base_insn_bitsize < buflen * 8 ?
502 cd->base_insn_bitsize : buflen * 8;
503 insn_value = cgen_get_insn_value (cd, buf, basesize);
506 /* Fill in ex_info fields like read_insn would. Don't actually call
507 read_insn, since the incoming buffer is already read (and possibly
508 modified a la m32r). */
509 ex_info.valid = (1 << buflen) - 1;
510 ex_info.dis_info = info;
511 ex_info.insn_bytes = buf;
513 /* The instructions are stored in hash lists.
514 Pick the first one and keep trying until we find the right one. */
516 insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
517 while (insn_list != NULL)
519 const CGEN_INSN *insn = insn_list->insn;
520 CGEN_FIELDS fields;
521 int length;
522 unsigned long insn_value_cropped;
524 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
525 /* Not needed as insn shouldn't be in hash lists if not supported. */
526 /* Supported by this cpu? */
527 if (! ip2k_cgen_insn_supported (cd, insn))
529 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
530 continue;
532 #endif
534 /* Basic bit mask must be correct. */
535 /* ??? May wish to allow target to defer this check until the extract
536 handler. */
538 /* Base size may exceed this instruction's size. Extract the
539 relevant part from the buffer. */
540 if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
541 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
542 insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
543 info->endian == BFD_ENDIAN_BIG);
544 else
545 insn_value_cropped = insn_value;
547 if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
548 == CGEN_INSN_BASE_VALUE (insn))
550 /* Printing is handled in two passes. The first pass parses the
551 machine insn and extracts the fields. The second pass prints
552 them. */
554 /* Make sure the entire insn is loaded into insn_value, if it
555 can fit. */
556 if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
557 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
559 unsigned long full_insn_value;
560 int rc = read_insn (cd, pc, info, buf,
561 CGEN_INSN_BITSIZE (insn) / 8,
562 & ex_info, & full_insn_value);
563 if (rc != 0)
564 return rc;
565 length = CGEN_EXTRACT_FN (cd, insn)
566 (cd, insn, &ex_info, full_insn_value, &fields, pc);
568 else
569 length = CGEN_EXTRACT_FN (cd, insn)
570 (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
572 /* length < 0 -> error */
573 if (length < 0)
574 return length;
575 if (length > 0)
577 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
578 /* length is in bits, result is in bytes */
579 return length / 8;
583 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
586 return 0;
589 /* Default value for CGEN_PRINT_INSN.
590 The result is the size of the insn in bytes or zero for an unknown insn
591 or -1 if an error occured fetching bytes. */
593 #ifndef CGEN_PRINT_INSN
594 #define CGEN_PRINT_INSN default_print_insn
595 #endif
597 static int
598 default_print_insn (cd, pc, info)
599 CGEN_CPU_DESC cd;
600 bfd_vma pc;
601 disassemble_info *info;
603 char buf[CGEN_MAX_INSN_SIZE];
604 int buflen;
605 int status;
607 /* Attempt to read the base part of the insn. */
608 buflen = cd->base_insn_bitsize / 8;
609 status = (*info->read_memory_func) (pc, buf, buflen, info);
611 /* Try again with the minimum part, if min < base. */
612 if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
614 buflen = cd->min_insn_bitsize / 8;
615 status = (*info->read_memory_func) (pc, buf, buflen, info);
618 if (status != 0)
620 (*info->memory_error_func) (status, pc, info);
621 return -1;
624 return print_insn (cd, pc, info, buf, buflen);
627 /* Main entry point.
628 Print one instruction from PC on INFO->STREAM.
629 Return the size of the instruction (in bytes). */
631 typedef struct cpu_desc_list {
632 struct cpu_desc_list *next;
633 int isa;
634 int mach;
635 int endian;
636 CGEN_CPU_DESC cd;
637 } cpu_desc_list;
640 print_insn_ip2k (pc, info)
641 bfd_vma pc;
642 disassemble_info *info;
644 static cpu_desc_list *cd_list = 0;
645 cpu_desc_list *cl = 0;
646 static CGEN_CPU_DESC cd = 0;
647 static int prev_isa;
648 static int prev_mach;
649 static int prev_endian;
650 int length;
651 int isa,mach;
652 int endian = (info->endian == BFD_ENDIAN_BIG
653 ? CGEN_ENDIAN_BIG
654 : CGEN_ENDIAN_LITTLE);
655 enum bfd_architecture arch;
657 /* ??? gdb will set mach but leave the architecture as "unknown" */
658 #ifndef CGEN_BFD_ARCH
659 #define CGEN_BFD_ARCH bfd_arch_ip2k
660 #endif
661 arch = info->arch;
662 if (arch == bfd_arch_unknown)
663 arch = CGEN_BFD_ARCH;
665 /* There's no standard way to compute the machine or isa number
666 so we leave it to the target. */
667 #ifdef CGEN_COMPUTE_MACH
668 mach = CGEN_COMPUTE_MACH (info);
669 #else
670 mach = info->mach;
671 #endif
673 #ifdef CGEN_COMPUTE_ISA
674 isa = CGEN_COMPUTE_ISA (info);
675 #else
676 isa = info->insn_sets;
677 #endif
679 /* If we've switched cpu's, try to find a handle we've used before */
680 if (cd
681 && (isa != prev_isa
682 || mach != prev_mach
683 || endian != prev_endian))
685 cd = 0;
686 for (cl = cd_list; cl; cl = cl->next)
688 if (cl->isa == isa &&
689 cl->mach == mach &&
690 cl->endian == endian)
692 cd = cl->cd;
693 break;
698 /* If we haven't initialized yet, initialize the opcode table. */
699 if (! cd)
701 const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
702 const char *mach_name;
704 if (!arch_type)
705 abort ();
706 mach_name = arch_type->printable_name;
708 prev_isa = isa;
709 prev_mach = mach;
710 prev_endian = endian;
711 cd = ip2k_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
712 CGEN_CPU_OPEN_BFDMACH, mach_name,
713 CGEN_CPU_OPEN_ENDIAN, prev_endian,
714 CGEN_CPU_OPEN_END);
715 if (!cd)
716 abort ();
718 /* save this away for future reference */
719 cl = xmalloc (sizeof (struct cpu_desc_list));
720 cl->cd = cd;
721 cl->isa = isa;
722 cl->mach = mach;
723 cl->endian = endian;
724 cl->next = cd_list;
725 cd_list = cl;
727 ip2k_cgen_init_dis (cd);
730 /* We try to have as much common code as possible.
731 But at this point some targets need to take over. */
732 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
733 but if not possible try to move this hook elsewhere rather than
734 have two hooks. */
735 length = CGEN_PRINT_INSN (cd, pc, info);
736 if (length > 0)
737 return length;
738 if (length < 0)
739 return -1;
741 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
742 return cd->default_insn_bitsize / 8;