(root)/
binutils-2.41/
opcodes/
or1k-dis.c
       1  /* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
       2  /* Disassembler interface for targets using CGEN. -*- C -*-
       3     CGEN: Cpu tools GENerator
       4  
       5     THIS FILE IS MACHINE GENERATED WITH CGEN.
       6     - the resultant file is machine generated, cgen-dis.in isn't
       7  
       8     Copyright (C) 1996-2023 Free Software Foundation, Inc.
       9  
      10     This file is part of libopcodes.
      11  
      12     This library is free software; you can redistribute it and/or modify
      13     it under the terms of the GNU General Public License as published by
      14     the Free Software Foundation; either version 3, or (at your option)
      15     any later version.
      16  
      17     It is distributed in the hope that it will be useful, but WITHOUT
      18     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      19     or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      20     License for more details.
      21  
      22     You should have received a copy of the GNU General Public License
      23     along with this program; if not, write to the Free Software Foundation, Inc.,
      24     51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
      25  
      26  /* ??? Eventually more and more of this stuff can go to cpu-independent files.
      27     Keep that in mind.  */
      28  
      29  #include "sysdep.h"
      30  #include <stdio.h>
      31  #include "ansidecl.h"
      32  #include "disassemble.h"
      33  #include "bfd.h"
      34  #include "symcat.h"
      35  #include "libiberty.h"
      36  #include "or1k-desc.h"
      37  #include "or1k-opc.h"
      38  #include "opintl.h"
      39  
      40  /* Default text to print if an instruction isn't recognized.  */
      41  #define UNKNOWN_INSN_MSG _("*unknown*")
      42  
      43  static void print_normal
      44    (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
      45  static void print_address
      46    (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
      47  static void print_keyword
      48    (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
      49  static void print_insn_normal
      50    (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
      51  static int print_insn
      52    (CGEN_CPU_DESC, bfd_vma,  disassemble_info *, bfd_byte *, unsigned);
      53  static int default_print_insn
      54    (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
      55  static int read_insn
      56    (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
      57     unsigned long *);
      58  
      59  /* -- disassembler routines inserted here.  */
      60  
      61  /* -- dis.c */
      62  
      63  static void
      64  print_regpair (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
      65  	       void * dis_info,
      66  	       long value,
      67  	       unsigned int attrs ATTRIBUTE_UNUSED,
      68  	       bfd_vma pc ATTRIBUTE_UNUSED,
      69  	       int length ATTRIBUTE_UNUSED)
      70  {
      71    disassemble_info *info = dis_info;
      72    char reg1_index;
      73    char reg2_index;
      74  
      75    reg1_index = value & 0x1f;
      76    reg2_index = reg1_index + ((value & (1 << 5)) ? 2 : 1);
      77  
      78    (*info->fprintf_func) (info->stream, "r%d,r%d", reg1_index, reg2_index);
      79  }
      80  
      81  /* -- */
      82  
      83  void or1k_cgen_print_operand
      84    (CGEN_CPU_DESC, int, void *, CGEN_FIELDS *, void const *, bfd_vma, int);
      85  
      86  /* Main entry point for printing operands.
      87     XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
      88     of dis-asm.h on cgen.h.
      89  
      90     This function is basically just a big switch statement.  Earlier versions
      91     used tables to look up the function to use, but
      92     - if the table contains both assembler and disassembler functions then
      93       the disassembler contains much of the assembler and vice-versa,
      94     - there's a lot of inlining possibilities as things grow,
      95     - using a switch statement avoids the function call overhead.
      96  
      97     This function could be moved into `print_insn_normal', but keeping it
      98     separate makes clear the interface between `print_insn_normal' and each of
      99     the handlers.  */
     100  
     101  void
     102  or1k_cgen_print_operand (CGEN_CPU_DESC cd,
     103  			   int opindex,
     104  			   void * xinfo,
     105  			   CGEN_FIELDS *fields,
     106  			   void const *attrs ATTRIBUTE_UNUSED,
     107  			   bfd_vma pc,
     108  			   int length)
     109  {
     110    disassemble_info *info = (disassemble_info *) xinfo;
     111  
     112    switch (opindex)
     113      {
     114      case OR1K_OPERAND_DISP21 :
     115        print_address (cd, info, fields->f_disp21, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
     116        break;
     117      case OR1K_OPERAND_DISP26 :
     118        print_address (cd, info, fields->f_disp26, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
     119        break;
     120      case OR1K_OPERAND_RA :
     121        print_keyword (cd, info, & or1k_cgen_opval_h_gpr, fields->f_r2, 0);
     122        break;
     123      case OR1K_OPERAND_RAD32F :
     124        print_regpair (cd, info, fields->f_rad32, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
     125        break;
     126      case OR1K_OPERAND_RADI :
     127        print_regpair (cd, info, fields->f_rad32, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
     128        break;
     129      case OR1K_OPERAND_RASF :
     130        print_keyword (cd, info, & or1k_cgen_opval_h_fsr, fields->f_r2, 0);
     131        break;
     132      case OR1K_OPERAND_RB :
     133        print_keyword (cd, info, & or1k_cgen_opval_h_gpr, fields->f_r3, 0);
     134        break;
     135      case OR1K_OPERAND_RBD32F :
     136        print_regpair (cd, info, fields->f_rbd32, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
     137        break;
     138      case OR1K_OPERAND_RBDI :
     139        print_regpair (cd, info, fields->f_rbd32, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
     140        break;
     141      case OR1K_OPERAND_RBSF :
     142        print_keyword (cd, info, & or1k_cgen_opval_h_fsr, fields->f_r3, 0);
     143        break;
     144      case OR1K_OPERAND_RD :
     145        print_keyword (cd, info, & or1k_cgen_opval_h_gpr, fields->f_r1, 0);
     146        break;
     147      case OR1K_OPERAND_RDD32F :
     148        print_regpair (cd, info, fields->f_rdd32, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
     149        break;
     150      case OR1K_OPERAND_RDDI :
     151        print_regpair (cd, info, fields->f_rdd32, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
     152        break;
     153      case OR1K_OPERAND_RDSF :
     154        print_keyword (cd, info, & or1k_cgen_opval_h_fsr, fields->f_r1, 0);
     155        break;
     156      case OR1K_OPERAND_SIMM16 :
     157        print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
     158        break;
     159      case OR1K_OPERAND_SIMM16_SPLIT :
     160        print_normal (cd, info, fields->f_simm16_split, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
     161        break;
     162      case OR1K_OPERAND_UIMM16 :
     163        print_normal (cd, info, fields->f_uimm16, 0, pc, length);
     164        break;
     165      case OR1K_OPERAND_UIMM16_SPLIT :
     166        print_normal (cd, info, fields->f_uimm16_split, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
     167        break;
     168      case OR1K_OPERAND_UIMM6 :
     169        print_normal (cd, info, fields->f_uimm6, 0, pc, length);
     170        break;
     171  
     172      default :
     173        /* xgettext:c-format */
     174        opcodes_error_handler
     175  	(_("internal error: unrecognized field %d while printing insn"),
     176  	 opindex);
     177        abort ();
     178    }
     179  }
     180  
     181  cgen_print_fn * const or1k_cgen_print_handlers[] =
     182  {
     183    print_insn_normal,
     184  };
     185  
     186  
     187  void
     188  or1k_cgen_init_dis (CGEN_CPU_DESC cd)
     189  {
     190    or1k_cgen_init_opcode_table (cd);
     191    or1k_cgen_init_ibld_table (cd);
     192    cd->print_handlers = & or1k_cgen_print_handlers[0];
     193    cd->print_operand = or1k_cgen_print_operand;
     194  }
     195  
     196  
     197  /* Default print handler.  */
     198  
     199  static void
     200  print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
     201  	      void *dis_info,
     202  	      long value,
     203  	      unsigned int attrs,
     204  	      bfd_vma pc ATTRIBUTE_UNUSED,
     205  	      int length ATTRIBUTE_UNUSED)
     206  {
     207    disassemble_info *info = (disassemble_info *) dis_info;
     208  
     209    /* Print the operand as directed by the attributes.  */
     210    if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
     211      ; /* nothing to do */
     212    else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
     213      (*info->fprintf_func) (info->stream, "%ld", value);
     214    else
     215      (*info->fprintf_func) (info->stream, "0x%lx", value);
     216  }
     217  
     218  /* Default address handler.  */
     219  
     220  static void
     221  print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
     222  	       void *dis_info,
     223  	       bfd_vma value,
     224  	       unsigned int attrs,
     225  	       bfd_vma pc ATTRIBUTE_UNUSED,
     226  	       int length ATTRIBUTE_UNUSED)
     227  {
     228    disassemble_info *info = (disassemble_info *) dis_info;
     229  
     230    /* Print the operand as directed by the attributes.  */
     231    if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
     232      ; /* Nothing to do.  */
     233    else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
     234      (*info->print_address_func) (value, info);
     235    else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
     236      (*info->print_address_func) (value, info);
     237    else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
     238      (*info->fprintf_func) (info->stream, "%ld", (long) value);
     239    else
     240      (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
     241  }
     242  
     243  /* Keyword print handler.  */
     244  
     245  static void
     246  print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
     247  	       void *dis_info,
     248  	       CGEN_KEYWORD *keyword_table,
     249  	       long value,
     250  	       unsigned int attrs ATTRIBUTE_UNUSED)
     251  {
     252    disassemble_info *info = (disassemble_info *) dis_info;
     253    const CGEN_KEYWORD_ENTRY *ke;
     254  
     255    ke = cgen_keyword_lookup_value (keyword_table, value);
     256    if (ke != NULL)
     257      (*info->fprintf_func) (info->stream, "%s", ke->name);
     258    else
     259      (*info->fprintf_func) (info->stream, "???");
     260  }
     261  
     262  /* Default insn printer.
     263  
     264     DIS_INFO is defined as `void *' so the disassembler needn't know anything
     265     about disassemble_info.  */
     266  
     267  static void
     268  print_insn_normal (CGEN_CPU_DESC cd,
     269  		   void *dis_info,
     270  		   const CGEN_INSN *insn,
     271  		   CGEN_FIELDS *fields,
     272  		   bfd_vma pc,
     273  		   int length)
     274  {
     275    const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
     276    disassemble_info *info = (disassemble_info *) dis_info;
     277    const CGEN_SYNTAX_CHAR_TYPE *syn;
     278  
     279    CGEN_INIT_PRINT (cd);
     280  
     281    for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
     282      {
     283        if (CGEN_SYNTAX_MNEMONIC_P (*syn))
     284  	{
     285  	  (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
     286  	  continue;
     287  	}
     288        if (CGEN_SYNTAX_CHAR_P (*syn))
     289  	{
     290  	  (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
     291  	  continue;
     292  	}
     293  
     294        /* We have an operand.  */
     295        or1k_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
     296  				 fields, CGEN_INSN_ATTRS (insn), pc, length);
     297      }
     298  }
     299  
     300  /* Subroutine of print_insn. Reads an insn into the given buffers and updates
     301     the extract info.
     302     Returns 0 if all is well, non-zero otherwise.  */
     303  
     304  static int
     305  read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
     306  	   bfd_vma pc,
     307  	   disassemble_info *info,
     308  	   bfd_byte *buf,
     309  	   int buflen,
     310  	   CGEN_EXTRACT_INFO *ex_info,
     311  	   unsigned long *insn_value)
     312  {
     313    int status = (*info->read_memory_func) (pc, buf, buflen, info);
     314  
     315    if (status != 0)
     316      {
     317        (*info->memory_error_func) (status, pc, info);
     318        return -1;
     319      }
     320  
     321    ex_info->dis_info = info;
     322    ex_info->valid = (1 << buflen) - 1;
     323    ex_info->insn_bytes = buf;
     324  
     325    *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
     326    return 0;
     327  }
     328  
     329  /* Utility to print an insn.
     330     BUF is the base part of the insn, target byte order, BUFLEN bytes long.
     331     The result is the size of the insn in bytes or zero for an unknown insn
     332     or -1 if an error occurs fetching data (memory_error_func will have
     333     been called).  */
     334  
     335  static int
     336  print_insn (CGEN_CPU_DESC cd,
     337  	    bfd_vma pc,
     338  	    disassemble_info *info,
     339  	    bfd_byte *buf,
     340  	    unsigned int buflen)
     341  {
     342    CGEN_INSN_INT insn_value;
     343    const CGEN_INSN_LIST *insn_list;
     344    CGEN_EXTRACT_INFO ex_info;
     345    int basesize;
     346  
     347    /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
     348    basesize = cd->base_insn_bitsize < buflen * 8 ?
     349                                       cd->base_insn_bitsize : buflen * 8;
     350    insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
     351  
     352  
     353    /* Fill in ex_info fields like read_insn would.  Don't actually call
     354       read_insn, since the incoming buffer is already read (and possibly
     355       modified a la m32r).  */
     356    ex_info.valid = (1 << buflen) - 1;
     357    ex_info.dis_info = info;
     358    ex_info.insn_bytes = buf;
     359  
     360    /* The instructions are stored in hash lists.
     361       Pick the first one and keep trying until we find the right one.  */
     362  
     363    insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
     364    while (insn_list != NULL)
     365      {
     366        const CGEN_INSN *insn = insn_list->insn;
     367        CGEN_FIELDS fields;
     368        int length;
     369        unsigned long insn_value_cropped;
     370  
     371  #ifdef CGEN_VALIDATE_INSN_SUPPORTED
     372        /* Not needed as insn shouldn't be in hash lists if not supported.  */
     373        /* Supported by this cpu?  */
     374        if (! or1k_cgen_insn_supported (cd, insn))
     375          {
     376            insn_list = CGEN_DIS_NEXT_INSN (insn_list);
     377  	  continue;
     378          }
     379  #endif
     380  
     381        /* Basic bit mask must be correct.  */
     382        /* ??? May wish to allow target to defer this check until the extract
     383  	 handler.  */
     384  
     385        /* Base size may exceed this instruction's size.  Extract the
     386           relevant part from the buffer. */
     387        if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
     388  	  (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
     389  	insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
     390  					   info->endian == BFD_ENDIAN_BIG);
     391        else
     392  	insn_value_cropped = insn_value;
     393  
     394        if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
     395  	  == CGEN_INSN_BASE_VALUE (insn))
     396  	{
     397  	  /* Printing is handled in two passes.  The first pass parses the
     398  	     machine insn and extracts the fields.  The second pass prints
     399  	     them.  */
     400  
     401  	  /* Make sure the entire insn is loaded into insn_value, if it
     402  	     can fit.  */
     403  	  if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
     404  	      (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
     405  	    {
     406  	      unsigned long full_insn_value;
     407  	      int rc = read_insn (cd, pc, info, buf,
     408  				  CGEN_INSN_BITSIZE (insn) / 8,
     409  				  & ex_info, & full_insn_value);
     410  	      if (rc != 0)
     411  		return rc;
     412  	      length = CGEN_EXTRACT_FN (cd, insn)
     413  		(cd, insn, &ex_info, full_insn_value, &fields, pc);
     414  	    }
     415  	  else
     416  	    length = CGEN_EXTRACT_FN (cd, insn)
     417  	      (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
     418  
     419  	  /* Length < 0 -> error.  */
     420  	  if (length < 0)
     421  	    return length;
     422  	  if (length > 0)
     423  	    {
     424  	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
     425  	      /* Length is in bits, result is in bytes.  */
     426  	      return length / 8;
     427  	    }
     428  	}
     429  
     430        insn_list = CGEN_DIS_NEXT_INSN (insn_list);
     431      }
     432  
     433    return 0;
     434  }
     435  
     436  /* Default value for CGEN_PRINT_INSN.
     437     The result is the size of the insn in bytes or zero for an unknown insn
     438     or -1 if an error occured fetching bytes.  */
     439  
     440  #ifndef CGEN_PRINT_INSN
     441  #define CGEN_PRINT_INSN default_print_insn
     442  #endif
     443  
     444  static int
     445  default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
     446  {
     447    bfd_byte buf[CGEN_MAX_INSN_SIZE];
     448    int buflen;
     449    int status;
     450  
     451    /* Attempt to read the base part of the insn.  */
     452    buflen = cd->base_insn_bitsize / 8;
     453    status = (*info->read_memory_func) (pc, buf, buflen, info);
     454  
     455    /* Try again with the minimum part, if min < base.  */
     456    if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
     457      {
     458        buflen = cd->min_insn_bitsize / 8;
     459        status = (*info->read_memory_func) (pc, buf, buflen, info);
     460      }
     461  
     462    if (status != 0)
     463      {
     464        (*info->memory_error_func) (status, pc, info);
     465        return -1;
     466      }
     467  
     468    return print_insn (cd, pc, info, buf, buflen);
     469  }
     470  
     471  /* Main entry point.
     472     Print one instruction from PC on INFO->STREAM.
     473     Return the size of the instruction (in bytes).  */
     474  
     475  typedef struct cpu_desc_list
     476  {
     477    struct cpu_desc_list *next;
     478    CGEN_BITSET *isa;
     479    int mach;
     480    int endian;
     481    int insn_endian;
     482    CGEN_CPU_DESC cd;
     483  } cpu_desc_list;
     484  
     485  int
     486  print_insn_or1k (bfd_vma pc, disassemble_info *info)
     487  {
     488    static cpu_desc_list *cd_list = 0;
     489    cpu_desc_list *cl = 0;
     490    static CGEN_CPU_DESC cd = 0;
     491    static CGEN_BITSET *prev_isa;
     492    static int prev_mach;
     493    static int prev_endian;
     494    static int prev_insn_endian;
     495    int length;
     496    CGEN_BITSET *isa;
     497    int mach;
     498    int endian = (info->endian == BFD_ENDIAN_BIG
     499  		? CGEN_ENDIAN_BIG
     500  		: CGEN_ENDIAN_LITTLE);
     501    int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
     502                       ? CGEN_ENDIAN_BIG
     503                       : CGEN_ENDIAN_LITTLE);
     504    enum bfd_architecture arch;
     505  
     506    /* ??? gdb will set mach but leave the architecture as "unknown" */
     507  #ifndef CGEN_BFD_ARCH
     508  #define CGEN_BFD_ARCH bfd_arch_or1k
     509  #endif
     510    arch = info->arch;
     511    if (arch == bfd_arch_unknown)
     512      arch = CGEN_BFD_ARCH;
     513  
     514    /* There's no standard way to compute the machine or isa number
     515       so we leave it to the target.  */
     516  #ifdef CGEN_COMPUTE_MACH
     517    mach = CGEN_COMPUTE_MACH (info);
     518  #else
     519    mach = info->mach;
     520  #endif
     521  
     522  #ifdef CGEN_COMPUTE_ISA
     523    {
     524      static CGEN_BITSET *permanent_isa;
     525  
     526      if (!permanent_isa)
     527        permanent_isa = cgen_bitset_create (MAX_ISAS);
     528      isa = permanent_isa;
     529      cgen_bitset_clear (isa);
     530      cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
     531    }
     532  #else
     533    isa = info->private_data;
     534  #endif
     535  
     536    /* If we've switched cpu's, try to find a handle we've used before */
     537    if (cd
     538        && (cgen_bitset_compare (isa, prev_isa) != 0
     539  	  || mach != prev_mach
     540  	  || endian != prev_endian))
     541      {
     542        cd = 0;
     543        for (cl = cd_list; cl; cl = cl->next)
     544  	{
     545  	  if (cgen_bitset_compare (cl->isa, isa) == 0 &&
     546  	      cl->mach == mach &&
     547  	      cl->endian == endian)
     548  	    {
     549  	      cd = cl->cd;
     550   	      prev_isa = cd->isas;
     551  	      break;
     552  	    }
     553  	}
     554      }
     555  
     556    /* If we haven't initialized yet, initialize the opcode table.  */
     557    if (! cd)
     558      {
     559        const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
     560        const char *mach_name;
     561  
     562        if (!arch_type)
     563  	abort ();
     564        mach_name = arch_type->printable_name;
     565  
     566        prev_isa = cgen_bitset_copy (isa);
     567        prev_mach = mach;
     568        prev_endian = endian;
     569        prev_insn_endian = insn_endian;
     570        cd = or1k_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
     571  				 CGEN_CPU_OPEN_BFDMACH, mach_name,
     572  				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
     573                                   CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
     574  				 CGEN_CPU_OPEN_END);
     575        if (!cd)
     576  	abort ();
     577  
     578        /* Save this away for future reference.  */
     579        cl = xmalloc (sizeof (struct cpu_desc_list));
     580        cl->cd = cd;
     581        cl->isa = prev_isa;
     582        cl->mach = mach;
     583        cl->endian = endian;
     584        cl->next = cd_list;
     585        cd_list = cl;
     586  
     587        or1k_cgen_init_dis (cd);
     588      }
     589  
     590    /* We try to have as much common code as possible.
     591       But at this point some targets need to take over.  */
     592    /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
     593       but if not possible try to move this hook elsewhere rather than
     594       have two hooks.  */
     595    length = CGEN_PRINT_INSN (cd, pc, info);
     596    if (length > 0)
     597      return length;
     598    if (length < 0)
     599      return -1;
     600  
     601    (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
     602    return cd->default_insn_bitsize / 8;
     603  }