185815Sobrien/* Disassembler interface for targets using CGEN. -*- C -*-
285815Sobrien   CGEN: Cpu tools GENerator
385815Sobrien
4218822Sdim   THIS FILE IS MACHINE GENERATED WITH CGEN.
5218822Sdim   - the resultant file is machine generated, cgen-dis.in isn't
685815Sobrien
7218822Sdim   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005
8218822Sdim   Free Software Foundation, Inc.
985815Sobrien
10218822Sdim   This file is part of the GNU Binutils and GDB, the GNU debugger.
1185815Sobrien
12218822Sdim   This program is free software; you can redistribute it and/or modify
13218822Sdim   it under the terms of the GNU General Public License as published by
14218822Sdim   the Free Software Foundation; either version 2, or (at your option)
15218822Sdim   any later version.
1685815Sobrien
17218822Sdim   This program is distributed in the hope that it will be useful,
18218822Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
19218822Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20218822Sdim   GNU General Public License for more details.
2185815Sobrien
22218822Sdim   You should have received a copy of the GNU General Public License
23218822Sdim   along with this program; if not, write to the Free Software Foundation, Inc.,
24218822Sdim   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2585815Sobrien
2685815Sobrien/* ??? Eventually more and more of this stuff can go to cpu-independent files.
2785815Sobrien   Keep that in mind.  */
2885815Sobrien
2985815Sobrien#include "sysdep.h"
3085815Sobrien#include <stdio.h>
3185815Sobrien#include "ansidecl.h"
3285815Sobrien#include "dis-asm.h"
3385815Sobrien#include "bfd.h"
3485815Sobrien#include "symcat.h"
35130561Sobrien#include "libiberty.h"
3685815Sobrien#include "@prefix@-desc.h"
3785815Sobrien#include "@prefix@-opc.h"
3885815Sobrien#include "opintl.h"
3985815Sobrien
4085815Sobrien/* Default text to print if an instruction isn't recognized.  */
4185815Sobrien#define UNKNOWN_INSN_MSG _("*unknown*")
4285815Sobrien
4385815Sobrienstatic void print_normal
44130561Sobrien  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
4585815Sobrienstatic void print_address
46218822Sdim  (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
4785815Sobrienstatic void print_keyword
48218822Sdim  (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
4985815Sobrienstatic void print_insn_normal
50130561Sobrien  (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
5189857Sobrienstatic int print_insn
52218822Sdim  (CGEN_CPU_DESC, bfd_vma,  disassemble_info *, bfd_byte *, unsigned);
5385815Sobrienstatic int default_print_insn
54218822Sdim  (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
5589857Sobrienstatic int read_insn
56218822Sdim  (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
57130561Sobrien   unsigned long *);
5885815Sobrien
59218822Sdim/* -- disassembler routines inserted here.  */
6085815Sobrien
6185815Sobrien/* Default print handler.  */
6285815Sobrien
6385815Sobrienstatic void
64130561Sobrienprint_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
65130561Sobrien	      void *dis_info,
66130561Sobrien	      long value,
67130561Sobrien	      unsigned int attrs,
68130561Sobrien	      bfd_vma pc ATTRIBUTE_UNUSED,
69130561Sobrien	      int length ATTRIBUTE_UNUSED)
7085815Sobrien{
7185815Sobrien  disassemble_info *info = (disassemble_info *) dis_info;
7285815Sobrien
7385815Sobrien#ifdef CGEN_PRINT_NORMAL
7485815Sobrien  CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
7585815Sobrien#endif
7685815Sobrien
7785815Sobrien  /* Print the operand as directed by the attributes.  */
7885815Sobrien  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
7985815Sobrien    ; /* nothing to do */
8085815Sobrien  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
8185815Sobrien    (*info->fprintf_func) (info->stream, "%ld", value);
8285815Sobrien  else
8385815Sobrien    (*info->fprintf_func) (info->stream, "0x%lx", value);
8485815Sobrien}
8585815Sobrien
8685815Sobrien/* Default address handler.  */
8785815Sobrien
8885815Sobrienstatic void
89130561Sobrienprint_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
90130561Sobrien	       void *dis_info,
91130561Sobrien	       bfd_vma value,
92130561Sobrien	       unsigned int attrs,
93130561Sobrien	       bfd_vma pc ATTRIBUTE_UNUSED,
94130561Sobrien	       int length ATTRIBUTE_UNUSED)
9585815Sobrien{
9685815Sobrien  disassemble_info *info = (disassemble_info *) dis_info;
9785815Sobrien
9885815Sobrien#ifdef CGEN_PRINT_ADDRESS
9985815Sobrien  CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
10085815Sobrien#endif
10185815Sobrien
10285815Sobrien  /* Print the operand as directed by the attributes.  */
10385815Sobrien  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
104218822Sdim    ; /* Nothing to do.  */
10585815Sobrien  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
10685815Sobrien    (*info->print_address_func) (value, info);
10785815Sobrien  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
10885815Sobrien    (*info->print_address_func) (value, info);
10985815Sobrien  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
11085815Sobrien    (*info->fprintf_func) (info->stream, "%ld", (long) value);
11185815Sobrien  else
11285815Sobrien    (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
11385815Sobrien}
11485815Sobrien
11585815Sobrien/* Keyword print handler.  */
11685815Sobrien
11785815Sobrienstatic void
118130561Sobrienprint_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
119130561Sobrien	       void *dis_info,
120130561Sobrien	       CGEN_KEYWORD *keyword_table,
121130561Sobrien	       long value,
122130561Sobrien	       unsigned int attrs ATTRIBUTE_UNUSED)
12385815Sobrien{
12485815Sobrien  disassemble_info *info = (disassemble_info *) dis_info;
12585815Sobrien  const CGEN_KEYWORD_ENTRY *ke;
12685815Sobrien
12785815Sobrien  ke = cgen_keyword_lookup_value (keyword_table, value);
12885815Sobrien  if (ke != NULL)
12985815Sobrien    (*info->fprintf_func) (info->stream, "%s", ke->name);
13085815Sobrien  else
13185815Sobrien    (*info->fprintf_func) (info->stream, "???");
13285815Sobrien}
13385815Sobrien
13485815Sobrien/* Default insn printer.
13585815Sobrien
136130561Sobrien   DIS_INFO is defined as `void *' so the disassembler needn't know anything
13785815Sobrien   about disassemble_info.  */
13885815Sobrien
13985815Sobrienstatic void
140130561Sobrienprint_insn_normal (CGEN_CPU_DESC cd,
141130561Sobrien		   void *dis_info,
142130561Sobrien		   const CGEN_INSN *insn,
143130561Sobrien		   CGEN_FIELDS *fields,
144130561Sobrien		   bfd_vma pc,
145130561Sobrien		   int length)
14685815Sobrien{
14785815Sobrien  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
14885815Sobrien  disassemble_info *info = (disassemble_info *) dis_info;
14985815Sobrien  const CGEN_SYNTAX_CHAR_TYPE *syn;
15085815Sobrien
15185815Sobrien  CGEN_INIT_PRINT (cd);
15285815Sobrien
15385815Sobrien  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
15485815Sobrien    {
15585815Sobrien      if (CGEN_SYNTAX_MNEMONIC_P (*syn))
15685815Sobrien	{
15785815Sobrien	  (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
15885815Sobrien	  continue;
15985815Sobrien	}
16085815Sobrien      if (CGEN_SYNTAX_CHAR_P (*syn))
16185815Sobrien	{
16285815Sobrien	  (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
16385815Sobrien	  continue;
16485815Sobrien	}
16585815Sobrien
16685815Sobrien      /* We have an operand.  */
16785815Sobrien      @arch@_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
16885815Sobrien				 fields, CGEN_INSN_ATTRS (insn), pc, length);
16985815Sobrien    }
17085815Sobrien}
17185815Sobrien
17285815Sobrien/* Subroutine of print_insn. Reads an insn into the given buffers and updates
17385815Sobrien   the extract info.
17485815Sobrien   Returns 0 if all is well, non-zero otherwise.  */
17589857Sobrien
17685815Sobrienstatic int
177130561Sobrienread_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
178130561Sobrien	   bfd_vma pc,
179130561Sobrien	   disassemble_info *info,
180218822Sdim	   bfd_byte *buf,
181130561Sobrien	   int buflen,
182130561Sobrien	   CGEN_EXTRACT_INFO *ex_info,
183130561Sobrien	   unsigned long *insn_value)
18485815Sobrien{
18585815Sobrien  int status = (*info->read_memory_func) (pc, buf, buflen, info);
186218822Sdim
18785815Sobrien  if (status != 0)
18885815Sobrien    {
18985815Sobrien      (*info->memory_error_func) (status, pc, info);
19085815Sobrien      return -1;
19185815Sobrien    }
19285815Sobrien
19385815Sobrien  ex_info->dis_info = info;
19485815Sobrien  ex_info->valid = (1 << buflen) - 1;
19585815Sobrien  ex_info->insn_bytes = buf;
19685815Sobrien
19785815Sobrien  *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
19885815Sobrien  return 0;
19985815Sobrien}
20085815Sobrien
20185815Sobrien/* Utility to print an insn.
20285815Sobrien   BUF is the base part of the insn, target byte order, BUFLEN bytes long.
20385815Sobrien   The result is the size of the insn in bytes or zero for an unknown insn
20485815Sobrien   or -1 if an error occurs fetching data (memory_error_func will have
20585815Sobrien   been called).  */
20685815Sobrien
20785815Sobrienstatic int
208130561Sobrienprint_insn (CGEN_CPU_DESC cd,
209130561Sobrien	    bfd_vma pc,
210130561Sobrien	    disassemble_info *info,
211218822Sdim	    bfd_byte *buf,
212130561Sobrien	    unsigned int buflen)
21385815Sobrien{
21489857Sobrien  CGEN_INSN_INT insn_value;
21585815Sobrien  const CGEN_INSN_LIST *insn_list;
21685815Sobrien  CGEN_EXTRACT_INFO ex_info;
21789857Sobrien  int basesize;
21885815Sobrien
21989857Sobrien  /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
22089857Sobrien  basesize = cd->base_insn_bitsize < buflen * 8 ?
22189857Sobrien                                     cd->base_insn_bitsize : buflen * 8;
22289857Sobrien  insn_value = cgen_get_insn_value (cd, buf, basesize);
22385815Sobrien
22489857Sobrien
22589857Sobrien  /* Fill in ex_info fields like read_insn would.  Don't actually call
22689857Sobrien     read_insn, since the incoming buffer is already read (and possibly
22789857Sobrien     modified a la m32r).  */
22889857Sobrien  ex_info.valid = (1 << buflen) - 1;
22989857Sobrien  ex_info.dis_info = info;
23089857Sobrien  ex_info.insn_bytes = buf;
23189857Sobrien
23285815Sobrien  /* The instructions are stored in hash lists.
23385815Sobrien     Pick the first one and keep trying until we find the right one.  */
23485815Sobrien
235218822Sdim  insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
23685815Sobrien  while (insn_list != NULL)
23785815Sobrien    {
23885815Sobrien      const CGEN_INSN *insn = insn_list->insn;
23985815Sobrien      CGEN_FIELDS fields;
24085815Sobrien      int length;
24189857Sobrien      unsigned long insn_value_cropped;
24285815Sobrien
24385815Sobrien#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
24489857Sobrien      /* Not needed as insn shouldn't be in hash lists if not supported.  */
24585815Sobrien      /* Supported by this cpu?  */
24685815Sobrien      if (! @arch@_cgen_insn_supported (cd, insn))
24785815Sobrien        {
24885815Sobrien          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
24985815Sobrien	  continue;
25085815Sobrien        }
25185815Sobrien#endif
25285815Sobrien
25385815Sobrien      /* Basic bit mask must be correct.  */
25485815Sobrien      /* ??? May wish to allow target to defer this check until the extract
25585815Sobrien	 handler.  */
25689857Sobrien
25789857Sobrien      /* Base size may exceed this instruction's size.  Extract the
25889857Sobrien         relevant part from the buffer. */
25989857Sobrien      if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
26089857Sobrien	  (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
26189857Sobrien	insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 
26289857Sobrien					   info->endian == BFD_ENDIAN_BIG);
26389857Sobrien      else
26489857Sobrien	insn_value_cropped = insn_value;
26589857Sobrien
26689857Sobrien      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
26785815Sobrien	  == CGEN_INSN_BASE_VALUE (insn))
26885815Sobrien	{
26985815Sobrien	  /* Printing is handled in two passes.  The first pass parses the
27085815Sobrien	     machine insn and extracts the fields.  The second pass prints
27185815Sobrien	     them.  */
27285815Sobrien
27385815Sobrien	  /* Make sure the entire insn is loaded into insn_value, if it
27485815Sobrien	     can fit.  */
27589857Sobrien	  if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
27689857Sobrien	      (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
27785815Sobrien	    {
27885815Sobrien	      unsigned long full_insn_value;
27985815Sobrien	      int rc = read_insn (cd, pc, info, buf,
28085815Sobrien				  CGEN_INSN_BITSIZE (insn) / 8,
28185815Sobrien				  & ex_info, & full_insn_value);
28285815Sobrien	      if (rc != 0)
28385815Sobrien		return rc;
28485815Sobrien	      length = CGEN_EXTRACT_FN (cd, insn)
28585815Sobrien		(cd, insn, &ex_info, full_insn_value, &fields, pc);
28685815Sobrien	    }
28785815Sobrien	  else
28885815Sobrien	    length = CGEN_EXTRACT_FN (cd, insn)
28989857Sobrien	      (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
29085815Sobrien
291218822Sdim	  /* Length < 0 -> error.  */
29285815Sobrien	  if (length < 0)
29385815Sobrien	    return length;
29485815Sobrien	  if (length > 0)
29585815Sobrien	    {
29685815Sobrien	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
297218822Sdim	      /* Length is in bits, result is in bytes.  */
29885815Sobrien	      return length / 8;
29985815Sobrien	    }
30085815Sobrien	}
30185815Sobrien
30285815Sobrien      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
30385815Sobrien    }
30485815Sobrien
30585815Sobrien  return 0;
30685815Sobrien}
30785815Sobrien
30885815Sobrien/* Default value for CGEN_PRINT_INSN.
30985815Sobrien   The result is the size of the insn in bytes or zero for an unknown insn
31085815Sobrien   or -1 if an error occured fetching bytes.  */
31185815Sobrien
31285815Sobrien#ifndef CGEN_PRINT_INSN
31385815Sobrien#define CGEN_PRINT_INSN default_print_insn
31485815Sobrien#endif
31585815Sobrien
31685815Sobrienstatic int
317130561Sobriendefault_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
31885815Sobrien{
319218822Sdim  bfd_byte buf[CGEN_MAX_INSN_SIZE];
32089857Sobrien  int buflen;
32185815Sobrien  int status;
32285815Sobrien
32389857Sobrien  /* Attempt to read the base part of the insn.  */
32489857Sobrien  buflen = cd->base_insn_bitsize / 8;
32589857Sobrien  status = (*info->read_memory_func) (pc, buf, buflen, info);
32685815Sobrien
32789857Sobrien  /* Try again with the minimum part, if min < base.  */
32889857Sobrien  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
32989857Sobrien    {
33089857Sobrien      buflen = cd->min_insn_bitsize / 8;
33189857Sobrien      status = (*info->read_memory_func) (pc, buf, buflen, info);
33289857Sobrien    }
33389857Sobrien
33485815Sobrien  if (status != 0)
33585815Sobrien    {
33685815Sobrien      (*info->memory_error_func) (status, pc, info);
33785815Sobrien      return -1;
33885815Sobrien    }
33985815Sobrien
34089857Sobrien  return print_insn (cd, pc, info, buf, buflen);
34185815Sobrien}
34285815Sobrien
34385815Sobrien/* Main entry point.
34485815Sobrien   Print one instruction from PC on INFO->STREAM.
34585815Sobrien   Return the size of the instruction (in bytes).  */
34685815Sobrien
347218822Sdimtypedef struct cpu_desc_list
348218822Sdim{
349104834Sobrien  struct cpu_desc_list *next;
350218822Sdim  CGEN_BITSET *isa;
351104834Sobrien  int mach;
352104834Sobrien  int endian;
353104834Sobrien  CGEN_CPU_DESC cd;
354104834Sobrien} cpu_desc_list;
355104834Sobrien
35685815Sobrienint
357130561Sobrienprint_insn_@arch@ (bfd_vma pc, disassemble_info *info)
35885815Sobrien{
359104834Sobrien  static cpu_desc_list *cd_list = 0;
360104834Sobrien  cpu_desc_list *cl = 0;
36185815Sobrien  static CGEN_CPU_DESC cd = 0;
362218822Sdim  static CGEN_BITSET *prev_isa;
36385815Sobrien  static int prev_mach;
36485815Sobrien  static int prev_endian;
36585815Sobrien  int length;
366218822Sdim  CGEN_BITSET *isa;
367218822Sdim  int mach;
36885815Sobrien  int endian = (info->endian == BFD_ENDIAN_BIG
36985815Sobrien		? CGEN_ENDIAN_BIG
37085815Sobrien		: CGEN_ENDIAN_LITTLE);
37185815Sobrien  enum bfd_architecture arch;
37285815Sobrien
37385815Sobrien  /* ??? gdb will set mach but leave the architecture as "unknown" */
37485815Sobrien#ifndef CGEN_BFD_ARCH
37585815Sobrien#define CGEN_BFD_ARCH bfd_arch_@arch@
37685815Sobrien#endif
37785815Sobrien  arch = info->arch;
37885815Sobrien  if (arch == bfd_arch_unknown)
37985815Sobrien    arch = CGEN_BFD_ARCH;
38089857Sobrien   
38189857Sobrien  /* There's no standard way to compute the machine or isa number
38285815Sobrien     so we leave it to the target.  */
38389857Sobrien#ifdef CGEN_COMPUTE_MACH
38489857Sobrien  mach = CGEN_COMPUTE_MACH (info);
38589857Sobrien#else
38689857Sobrien  mach = info->mach;
38789857Sobrien#endif
38889857Sobrien
38985815Sobrien#ifdef CGEN_COMPUTE_ISA
390218822Sdim  {
391218822Sdim    static CGEN_BITSET *permanent_isa;
392218822Sdim
393218822Sdim    if (!permanent_isa)
394218822Sdim      permanent_isa = cgen_bitset_create (MAX_ISAS);
395218822Sdim    isa = permanent_isa;
396218822Sdim    cgen_bitset_clear (isa);
397218822Sdim    cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
398218822Sdim  }
39985815Sobrien#else
40091041Sobrien  isa = info->insn_sets;
40185815Sobrien#endif
40285815Sobrien
403104834Sobrien  /* If we've switched cpu's, try to find a handle we've used before */
40485815Sobrien  if (cd
405218822Sdim      && (cgen_bitset_compare (isa, prev_isa) != 0
40685815Sobrien	  || mach != prev_mach
40785815Sobrien	  || endian != prev_endian))
40885815Sobrien    {
40985815Sobrien      cd = 0;
410104834Sobrien      for (cl = cd_list; cl; cl = cl->next)
411104834Sobrien	{
412218822Sdim	  if (cgen_bitset_compare (cl->isa, isa) == 0 &&
413104834Sobrien	      cl->mach == mach &&
414104834Sobrien	      cl->endian == endian)
415104834Sobrien	    {
416104834Sobrien	      cd = cl->cd;
417218822Sdim 	      prev_isa = cd->isas;
418104834Sobrien	      break;
419104834Sobrien	    }
420104834Sobrien	}
421104834Sobrien    } 
42285815Sobrien
42385815Sobrien  /* If we haven't initialized yet, initialize the opcode table.  */
42485815Sobrien  if (! cd)
42585815Sobrien    {
42685815Sobrien      const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
42785815Sobrien      const char *mach_name;
42885815Sobrien
42985815Sobrien      if (!arch_type)
43085815Sobrien	abort ();
43185815Sobrien      mach_name = arch_type->printable_name;
43285815Sobrien
433218822Sdim      prev_isa = cgen_bitset_copy (isa);
43485815Sobrien      prev_mach = mach;
43585815Sobrien      prev_endian = endian;
43685815Sobrien      cd = @arch@_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
43785815Sobrien				 CGEN_CPU_OPEN_BFDMACH, mach_name,
43885815Sobrien				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
43985815Sobrien				 CGEN_CPU_OPEN_END);
44085815Sobrien      if (!cd)
44185815Sobrien	abort ();
442104834Sobrien
443218822Sdim      /* Save this away for future reference.  */
444104834Sobrien      cl = xmalloc (sizeof (struct cpu_desc_list));
445104834Sobrien      cl->cd = cd;
446218822Sdim      cl->isa = prev_isa;
447104834Sobrien      cl->mach = mach;
448104834Sobrien      cl->endian = endian;
449104834Sobrien      cl->next = cd_list;
450104834Sobrien      cd_list = cl;
451104834Sobrien
45285815Sobrien      @arch@_cgen_init_dis (cd);
45385815Sobrien    }
45485815Sobrien
45585815Sobrien  /* We try to have as much common code as possible.
45685815Sobrien     But at this point some targets need to take over.  */
45785815Sobrien  /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
45885815Sobrien     but if not possible try to move this hook elsewhere rather than
45985815Sobrien     have two hooks.  */
46085815Sobrien  length = CGEN_PRINT_INSN (cd, pc, info);
46185815Sobrien  if (length > 0)
46285815Sobrien    return length;
46385815Sobrien  if (length < 0)
46485815Sobrien    return -1;
46585815Sobrien
46685815Sobrien  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
46785815Sobrien  return cd->default_insn_bitsize / 8;
46885815Sobrien}
469