Back to index

cell-binutils  2.17cvs20070401
mep-dis.c
Go to the documentation of this file.
00001 /* Disassembler interface for targets using CGEN. -*- C -*-
00002    CGEN: Cpu tools GENerator
00003 
00004    THIS FILE IS MACHINE GENERATED WITH CGEN.
00005    - the resultant file is machine generated, cgen-dis.in isn't
00006 
00007    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005
00008    Free Software Foundation, Inc.
00009 
00010    This file is part of the GNU Binutils and GDB, the GNU debugger.
00011 
00012    This program is free software; you can redistribute it and/or modify
00013    it under the terms of the GNU General Public License as published by
00014    the Free Software Foundation; either version 2, or (at your option)
00015    any later version.
00016 
00017    This program is distributed in the hope that it will be useful,
00018    but WITHOUT ANY WARRANTY; without even the implied warranty of
00019    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020    GNU General Public License for more details.
00021 
00022    You should have received a copy of the GNU General Public License
00023    along with this program; if not, write to the Free Software Foundation, Inc.,
00024    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00025 
00026 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
00027    Keep that in mind.  */
00028 
00029 #include "sysdep.h"
00030 #include <stdio.h>
00031 #include "ansidecl.h"
00032 #include "dis-asm.h"
00033 #include "bfd.h"
00034 #include "symcat.h"
00035 #include "libiberty.h"
00036 #include "mep-desc.h"
00037 #include "mep-opc.h"
00038 #include "opintl.h"
00039 
00040 /* Default text to print if an instruction isn't recognized.  */
00041 #define UNKNOWN_INSN_MSG _("*unknown*")
00042 
00043 static void print_normal
00044   (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
00045 static void print_address
00046   (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
00047 static void print_keyword
00048   (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
00049 static void print_insn_normal
00050   (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
00051 static int print_insn
00052   (CGEN_CPU_DESC, bfd_vma,  disassemble_info *, bfd_byte *, unsigned);
00053 static int default_print_insn
00054   (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
00055 static int read_insn
00056   (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
00057    unsigned long *);
00058 
00059 /* -- disassembler routines inserted here.  */
00060 
00061 /* -- dis.c */
00062 
00063 #include "elf/mep.h"
00064 #include "elf-bfd.h"
00065 
00066 #define CGEN_VALIDATE_INSN_SUPPORTED
00067 
00068 static void print_tpreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
00069 static void print_spreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
00070 
00071 static void
00072 print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
00073             CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
00074             unsigned int flags ATTRIBUTE_UNUSED)
00075 {
00076   disassemble_info *info = (disassemble_info *) dis_info;
00077 
00078   (*info->fprintf_func) (info->stream, "$tp");
00079 }
00080 
00081 static void
00082 print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info, 
00083             CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
00084             unsigned int flags ATTRIBUTE_UNUSED)
00085 {
00086   disassemble_info *info = (disassemble_info *) dis_info;
00087 
00088   (*info->fprintf_func) (info->stream, "$sp");
00089 }
00090 
00091 /* begin-cop-ip-print-handlers */
00092 static void
00093 print_fmax_cr (CGEN_CPU_DESC cd,
00094        void *dis_info,
00095        CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
00096        long value,
00097        unsigned int attrs)
00098 {
00099   print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_fmax, value, attrs);
00100 }
00101 static void
00102 print_fmax_ccr (CGEN_CPU_DESC cd,
00103        void *dis_info,
00104        CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
00105        long value,
00106        unsigned int attrs)
00107 {
00108   print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_fmax, value, attrs);
00109 }
00110 /* end-cop-ip-print-handlers */
00111 
00112 /************************************************************\
00113 *********************** Experimental *************************
00114 \************************************************************/
00115 
00116 #undef  CGEN_PRINT_INSN
00117 #define CGEN_PRINT_INSN mep_print_insn
00118 
00119 static int
00120 mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
00121                     bfd_byte *buf, int corelength, int copro1length,
00122                     int copro2length ATTRIBUTE_UNUSED)
00123 {
00124   int i;
00125   int status = 0;
00126   /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
00127   bfd_byte insnbuf[64];
00128 
00129   /* If corelength > 0 then there is a core insn present. It
00130      will be at the beginning of the buffer.  After printing
00131      the core insn, we need to print the + on the next line.  */
00132   if (corelength > 0)
00133     {
00134       int my_status = 0;
00135         
00136       for (i = 0; i < corelength; i++ )
00137        insnbuf[i] = buf[i];
00138       cd->isas = & MEP_CORE_ISA;
00139         
00140       my_status = print_insn (cd, pc, info, insnbuf, corelength);
00141       if (my_status != corelength)
00142        {
00143          (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
00144          my_status = corelength;
00145        }
00146       status += my_status;
00147 
00148       /* Print the + to indicate that the following copro insn is   */
00149       /* part of a vliw group.                                      */
00150       if (copro1length > 0)
00151        (*info->fprintf_func) (info->stream, " + "); 
00152     }
00153 
00154   /* Now all that is left to be processed is the coprocessor insns
00155      In vliw mode, there will always be one.  Its positioning will
00156      be from byte corelength to byte corelength+copro1length -1.
00157      No need to check for existence.   Also, the first vliw insn,
00158      will, as spec'd, always be at least as long as the core insn
00159      so we don't need to flush the buffer.  */
00160   if (copro1length > 0)
00161     {
00162       int my_status = 0;
00163         
00164       for (i = corelength; i < corelength + copro1length; i++ )
00165        insnbuf[i - corelength] = buf[i];
00166 
00167       switch (copro1length)
00168        {
00169        case 0:
00170          break;
00171        case 2:
00172          cd->isas = & MEP_COP16_ISA;
00173          break;
00174        case 4:
00175          cd->isas = & MEP_COP32_ISA;
00176          break;
00177        case 6:
00178          cd->isas = & MEP_COP48_ISA;
00179          break;
00180        case 8:
00181          cd->isas = & MEP_COP64_ISA;
00182          break; 
00183        default:
00184          /* Shouldn't be anything but 16,32,48,64.  */
00185          break;
00186        }
00187 
00188       my_status = print_insn (cd, pc, info, insnbuf, copro1length);
00189 
00190       if (my_status != copro1length)
00191        {
00192          (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
00193          my_status = copro1length;
00194        }
00195       status += my_status;
00196     }
00197 
00198 #if 0
00199   /* Now we need to process the second copro insn if it exists. We
00200      have no guarantee that the second copro insn will be longer
00201      than the first, so we have to flush the buffer if we are have
00202      a second copro insn to process.  If present, this insn will
00203      be in the position from byte corelength+copro1length to byte
00204      corelength+copro1length+copro2length-1 (which better equal 8
00205      or else we're in big trouble.  */
00206   if (copro2length > 0)
00207     {
00208       int my_status = 0;
00209 
00210       for (i = 0; i < 64 ; i++)
00211        insnbuf[i] = 0;
00212 
00213       for (i = corelength + copro1length; i < 64; i++)
00214        insnbuf[i - (corelength + copro1length)] = buf[i];
00215       
00216       switch (copro2length)
00217        {
00218        case 2:
00219          cd->isas = 1 << ISA_EXT_COP1_16;
00220          break;
00221        case 4:
00222          cd->isas = 1 << ISA_EXT_COP1_32;
00223          break;
00224        case 6:
00225          cd->isas = 1 << ISA_EXT_COP1_48;
00226          break;
00227        case 8:
00228          cd->isas = 1 << ISA_EXT_COP1_64; 
00229          break;
00230        default:
00231          /* Shouldn't be anything but 16,32,48,64.  */
00232          break;
00233        }
00234 
00235       my_status = print_insn (cd, pc, info, insnbuf, copro2length);
00236 
00237       if (my_status != copro2length)
00238        {
00239          (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
00240          my_status = copro2length;
00241        }
00242 
00243       status += my_status;
00244     }
00245 #endif
00246 
00247   /* Status should now be the number of bytes that were printed
00248      which should be 4 for VLIW32 mode and 64 for VLIW64 mode.  */
00249 
00250   if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
00251     return -1;
00252   else
00253     return status;
00254 }
00255 
00256 /* The two functions mep_examine_vliw[32,64]_insns are used find out 
00257    which vliw combinaion (16 bit core with 48 bit copro, 32 bit core 
00258    with 32 bit copro, etc.) is present.  Later on, when internally   
00259    parallel coprocessors are handled, only these functions should    
00260    need to be changed.                                               
00261 
00262    At this time only the following combinations are supported: 
00263    
00264    VLIW32 Mode:
00265    16 bit core insn (core) and 16 bit coprocessor insn (cop1)
00266    32 bit core insn (core)
00267    32 bit coprocessor insn (cop1)
00268    Note: As of this time, I do not believe we have enough information
00269          to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
00270          no 16 bit coprocessor insns have been specified.  
00271 
00272    VLIW64 Mode:
00273    16 bit core insn (core) and 48 bit coprocessor insn (cop1)
00274    32 bit core insn (core) and 32 bit coprocessor insn (cop1)
00275    64 bit coprocessor insn (cop1)
00276   
00277    The framework for an internally parallel coprocessor is also
00278    present (2nd coprocessor insn is cop2), but at this time it 
00279    is not used.  This only appears to be valid in VLIW64 mode.  */
00280 
00281 static int
00282 mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
00283 {
00284   int status;
00285   int buflength;
00286   int corebuflength;
00287   int cop1buflength;
00288   int cop2buflength;
00289   bfd_byte buf[CGEN_MAX_INSN_SIZE];  
00290   char indicator16[1];
00291   char indicatorcop32[2]; 
00292 
00293   /* At this time we're not supporting internally parallel coprocessors,
00294      so cop2buflength will always be 0.  */
00295   cop2buflength = 0;
00296 
00297   /* Read in 32 bits.  */
00298   buflength = 4; /* VLIW insn spans 4 bytes.  */
00299   status = (*info->read_memory_func) (pc, buf, buflength, info);
00300 
00301   if (status != 0)
00302     {
00303       (*info->memory_error_func) (status, pc, info);
00304       return -1;
00305     }
00306 
00307   /* Put the big endian representation of the bytes to be examined
00308      in the temporary buffers for examination.  */
00309 
00310   if (info->endian == BFD_ENDIAN_BIG)
00311     {
00312       indicator16[0] = buf[0];
00313       indicatorcop32[0] = buf[0];
00314       indicatorcop32[1] = buf[1];
00315     }
00316   else
00317     {
00318       indicator16[0] = buf[1];
00319       indicatorcop32[0] = buf[1];
00320       indicatorcop32[1] = buf[0];
00321     }
00322 
00323   /* If the two high order bits are 00, 01 or 10, we have a 16 bit
00324      core insn and a 48 bit copro insn.  */
00325 
00326   if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
00327     {
00328       if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
00329        {
00330           /* We have a 32 bit copro insn.  */
00331           corebuflength = 0;
00332          /* All 4 4ytes are one copro insn. */
00333           cop1buflength = 4;
00334        }
00335       else
00336        {
00337           /* We have a 32 bit core.  */
00338           corebuflength = 4;
00339           cop1buflength = 0;
00340        }
00341     }
00342   else
00343     {
00344       /* We have a 16 bit core insn and a 16 bit copro insn.  */
00345       corebuflength = 2;
00346       cop1buflength = 2;
00347     }
00348 
00349   /* Now we have the distrubution set.  Print them out.  */
00350   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
00351                              cop1buflength, cop2buflength);
00352 
00353   return status;
00354 }
00355 
00356 static int
00357 mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
00358 {
00359   int status;
00360   int buflength;
00361   int corebuflength;
00362   int cop1buflength;
00363   int cop2buflength;
00364   bfd_byte buf[CGEN_MAX_INSN_SIZE];
00365   char indicator16[1];
00366   char indicator64[4];
00367 
00368   /* At this time we're not supporting internally parallel
00369      coprocessors, so cop2buflength will always be 0.  */
00370   cop2buflength = 0;
00371 
00372   /* Read in 64 bits.  */
00373   buflength = 8; /* VLIW insn spans 8 bytes.  */
00374   status = (*info->read_memory_func) (pc, buf, buflength, info);
00375 
00376   if (status != 0)
00377     {
00378       (*info->memory_error_func) (status, pc, info);
00379       return -1;
00380     }
00381 
00382   /* We have all 64 bits in the buffer now.  We have to figure out
00383      what combination of instruction sizes are present.  The two
00384      high order bits will indicate whether or not we have a 16 bit
00385      core insn or not.  If not, then we have to look at the 7,8th
00386      bytes to tell whether we have 64 bit copro insn or a 32 bit
00387      core insn with a 32 bit copro insn.  Endianness will make a
00388      difference here.  */
00389 
00390   /* Put the big endian representation of the bytes to be examined
00391      in the temporary buffers for examination.  */
00392 
00393   /* indicator16[0] = buf[0];  */
00394   if (info->endian == BFD_ENDIAN_BIG)
00395     {
00396       indicator16[0] = buf[0];
00397       indicator64[0] = buf[0];
00398       indicator64[1] = buf[1];
00399       indicator64[2] = buf[2];
00400       indicator64[3] = buf[3];
00401     }
00402   else
00403     {
00404       indicator16[0] = buf[1];
00405       indicator64[0] = buf[1];
00406       indicator64[1] = buf[0];
00407       indicator64[2] = buf[3];
00408       indicator64[3] = buf[2];
00409     }
00410 
00411   /* If the two high order bits are 00, 01 or 10, we have a 16 bit
00412      core insn and a 48 bit copro insn.  */
00413 
00414   if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
00415     {
00416       if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
00417          && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
00418        {
00419           /* We have a 64 bit copro insn.  */
00420           corebuflength = 0;
00421          /* All 8 bytes are one copro insn.  */
00422           cop1buflength = 8;
00423        }
00424       else
00425        {
00426           /* We have a 32 bit core insn and a 32 bit copro insn.  */
00427           corebuflength = 4;
00428           cop1buflength = 4;
00429        }
00430     }
00431   else
00432     {
00433       /* We have a 16 bit core insn and a 48 bit copro insn.  */
00434       corebuflength = 2;
00435       cop1buflength = 6;
00436     }
00437 
00438   /* Now we have the distrubution set.  Print them out. */
00439   status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
00440                              cop1buflength, cop2buflength);
00441 
00442   return status;
00443 }
00444 
00445 static int
00446 mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
00447 {
00448   int status;
00449 
00450   /* Extract and adapt to configuration number, if available. */
00451   if (info->section && info->section->owner)
00452     {
00453       bfd *abfd = info->section->owner;
00454       mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
00455       /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
00456     }
00457 
00458   /* Picking the right ISA bitmask for the current context is tricky.  */
00459   if (info->section)
00460     {
00461       if (info->section->flags & SEC_MEP_VLIW)
00462        {
00463          /* Are we in 32 or 64 bit vliw mode?  */
00464          if (MEP_VLIW64)
00465            status = mep_examine_vliw64_insns (cd, pc, info);
00466          else
00467            status = mep_examine_vliw32_insns (cd, pc, info);
00468          /* Both the above branches set their own isa bitmasks.  */
00469        }
00470       else
00471        {
00472          cd->isas = & MEP_CORE_ISA;
00473          status = default_print_insn (cd, pc, info);
00474        }
00475     }
00476   else /* sid or gdb */
00477     {
00478       status = default_print_insn (cd, pc, info);
00479     }
00480 
00481   return status;
00482 }
00483 
00484 
00485 /* -- opc.c */
00486 
00487 void mep_cgen_print_operand
00488   (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
00489 
00490 /* Main entry point for printing operands.
00491    XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
00492    of dis-asm.h on cgen.h.
00493 
00494    This function is basically just a big switch statement.  Earlier versions
00495    used tables to look up the function to use, but
00496    - if the table contains both assembler and disassembler functions then
00497      the disassembler contains much of the assembler and vice-versa,
00498    - there's a lot of inlining possibilities as things grow,
00499    - using a switch statement avoids the function call overhead.
00500 
00501    This function could be moved into `print_insn_normal', but keeping it
00502    separate makes clear the interface between `print_insn_normal' and each of
00503    the handlers.  */
00504 
00505 void
00506 mep_cgen_print_operand (CGEN_CPU_DESC cd,
00507                         int opindex,
00508                         void * xinfo,
00509                         CGEN_FIELDS *fields,
00510                         void const *attrs ATTRIBUTE_UNUSED,
00511                         bfd_vma pc,
00512                         int length)
00513 {
00514   disassemble_info *info = (disassemble_info *) xinfo;
00515 
00516   switch (opindex)
00517     {
00518     case MEP_OPERAND_ADDR24A4 :
00519       print_normal (cd, info, fields->f_24u8a4n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
00520       break;
00521     case MEP_OPERAND_CALLNUM :
00522       print_normal (cd, info, fields->f_callnum, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
00523       break;
00524     case MEP_OPERAND_CCCC :
00525       print_normal (cd, info, fields->f_rm, 0, pc, length);
00526       break;
00527     case MEP_OPERAND_CCRN :
00528       print_keyword (cd, info, & mep_cgen_opval_h_ccr, fields->f_ccrn, 0|(1<<CGEN_OPERAND_VIRTUAL));
00529       break;
00530     case MEP_OPERAND_CDISP8 :
00531       print_normal (cd, info, fields->f_8s24, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00532       break;
00533     case MEP_OPERAND_CDISP8A2 :
00534       print_normal (cd, info, fields->f_8s24a2, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00535       break;
00536     case MEP_OPERAND_CDISP8A4 :
00537       print_normal (cd, info, fields->f_8s24a4, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00538       break;
00539     case MEP_OPERAND_CDISP8A8 :
00540       print_normal (cd, info, fields->f_8s24a8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00541       break;
00542     case MEP_OPERAND_CIMM4 :
00543       print_normal (cd, info, fields->f_rn, 0, pc, length);
00544       break;
00545     case MEP_OPERAND_CIMM5 :
00546       print_normal (cd, info, fields->f_5u24, 0, pc, length);
00547       break;
00548     case MEP_OPERAND_CODE16 :
00549       print_normal (cd, info, fields->f_16u16, 0, pc, length);
00550       break;
00551     case MEP_OPERAND_CODE24 :
00552       print_normal (cd, info, fields->f_24u4n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
00553       break;
00554     case MEP_OPERAND_CP_FLAG :
00555       print_keyword (cd, info, & mep_cgen_opval_h_ccr, 0, 0);
00556       break;
00557     case MEP_OPERAND_CRN :
00558       print_keyword (cd, info, & mep_cgen_opval_h_cr, fields->f_crn, 0);
00559       break;
00560     case MEP_OPERAND_CRN64 :
00561       print_keyword (cd, info, & mep_cgen_opval_h_cr64, fields->f_crn, 0);
00562       break;
00563     case MEP_OPERAND_CRNX :
00564       print_keyword (cd, info, & mep_cgen_opval_h_cr, fields->f_crnx, 0|(1<<CGEN_OPERAND_VIRTUAL));
00565       break;
00566     case MEP_OPERAND_CRNX64 :
00567       print_keyword (cd, info, & mep_cgen_opval_h_cr64, fields->f_crnx, 0|(1<<CGEN_OPERAND_VIRTUAL));
00568       break;
00569     case MEP_OPERAND_CSRN :
00570       print_keyword (cd, info, & mep_cgen_opval_h_csr, fields->f_csrn, 0|(1<<CGEN_OPERAND_VIRTUAL));
00571       break;
00572     case MEP_OPERAND_CSRN_IDX :
00573       print_normal (cd, info, fields->f_csrn, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
00574       break;
00575     case MEP_OPERAND_DBG :
00576       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00577       break;
00578     case MEP_OPERAND_DEPC :
00579       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00580       break;
00581     case MEP_OPERAND_EPC :
00582       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00583       break;
00584     case MEP_OPERAND_EXC :
00585       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00586       break;
00587     case MEP_OPERAND_FMAX_CCRN :
00588       print_fmax_ccr (cd, info, & mep_cgen_opval_h_ccr, fields->f_fmax_4_4, 0);
00589       break;
00590     case MEP_OPERAND_FMAX_FRD :
00591       print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frd, 0|(1<<CGEN_OPERAND_VIRTUAL));
00592       break;
00593     case MEP_OPERAND_FMAX_FRD_INT :
00594       print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frd, 0|(1<<CGEN_OPERAND_VIRTUAL));
00595       break;
00596     case MEP_OPERAND_FMAX_FRM :
00597       print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frm, 0|(1<<CGEN_OPERAND_VIRTUAL));
00598       break;
00599     case MEP_OPERAND_FMAX_FRN :
00600       print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frn, 0|(1<<CGEN_OPERAND_VIRTUAL));
00601       break;
00602     case MEP_OPERAND_FMAX_FRN_INT :
00603       print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frn, 0|(1<<CGEN_OPERAND_VIRTUAL));
00604       break;
00605     case MEP_OPERAND_FMAX_RM :
00606       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_fmax_rm, 0);
00607       break;
00608     case MEP_OPERAND_HI :
00609       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00610       break;
00611     case MEP_OPERAND_LO :
00612       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00613       break;
00614     case MEP_OPERAND_LP :
00615       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00616       break;
00617     case MEP_OPERAND_MB0 :
00618       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00619       break;
00620     case MEP_OPERAND_MB1 :
00621       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00622       break;
00623     case MEP_OPERAND_ME0 :
00624       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00625       break;
00626     case MEP_OPERAND_ME1 :
00627       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00628       break;
00629     case MEP_OPERAND_NPC :
00630       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00631       break;
00632     case MEP_OPERAND_OPT :
00633       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00634       break;
00635     case MEP_OPERAND_PCABS24A2 :
00636       print_address (cd, info, fields->f_24u5a2n, 0|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
00637       break;
00638     case MEP_OPERAND_PCREL12A2 :
00639       print_address (cd, info, fields->f_12s4a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00640       break;
00641     case MEP_OPERAND_PCREL17A2 :
00642       print_address (cd, info, fields->f_17s16a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00643       break;
00644     case MEP_OPERAND_PCREL24A2 :
00645       print_address (cd, info, fields->f_24s5a2n, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
00646       break;
00647     case MEP_OPERAND_PCREL8A2 :
00648       print_address (cd, info, fields->f_8s8a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00649       break;
00650     case MEP_OPERAND_PSW :
00651       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00652       break;
00653     case MEP_OPERAND_R0 :
00654       print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
00655       break;
00656     case MEP_OPERAND_R1 :
00657       print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
00658       break;
00659     case MEP_OPERAND_RL :
00660       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rl, 0);
00661       break;
00662     case MEP_OPERAND_RM :
00663       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rm, 0);
00664       break;
00665     case MEP_OPERAND_RMA :
00666       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rm, 0);
00667       break;
00668     case MEP_OPERAND_RN :
00669       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
00670       break;
00671     case MEP_OPERAND_RN3 :
00672       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
00673       break;
00674     case MEP_OPERAND_RN3C :
00675       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
00676       break;
00677     case MEP_OPERAND_RN3L :
00678       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
00679       break;
00680     case MEP_OPERAND_RN3S :
00681       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
00682       break;
00683     case MEP_OPERAND_RN3UC :
00684       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
00685       break;
00686     case MEP_OPERAND_RN3UL :
00687       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
00688       break;
00689     case MEP_OPERAND_RN3US :
00690       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
00691       break;
00692     case MEP_OPERAND_RNC :
00693       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
00694       break;
00695     case MEP_OPERAND_RNL :
00696       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
00697       break;
00698     case MEP_OPERAND_RNS :
00699       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
00700       break;
00701     case MEP_OPERAND_RNUC :
00702       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
00703       break;
00704     case MEP_OPERAND_RNUL :
00705       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
00706       break;
00707     case MEP_OPERAND_RNUS :
00708       print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
00709       break;
00710     case MEP_OPERAND_SAR :
00711       print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
00712       break;
00713     case MEP_OPERAND_SDISP16 :
00714       print_normal (cd, info, fields->f_16s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00715       break;
00716     case MEP_OPERAND_SIMM16 :
00717       print_normal (cd, info, fields->f_16s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00718       break;
00719     case MEP_OPERAND_SIMM6 :
00720       print_normal (cd, info, fields->f_6s8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00721       break;
00722     case MEP_OPERAND_SIMM8 :
00723       print_normal (cd, info, fields->f_8s8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELOC_IMPLIES_OVERFLOW), pc, length);
00724       break;
00725     case MEP_OPERAND_SP :
00726       print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
00727       break;
00728     case MEP_OPERAND_SPR :
00729       print_spreg (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
00730       break;
00731     case MEP_OPERAND_TP :
00732       print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
00733       break;
00734     case MEP_OPERAND_TPR :
00735       print_tpreg (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
00736       break;
00737     case MEP_OPERAND_UDISP2 :
00738       print_normal (cd, info, fields->f_2u6, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00739       break;
00740     case MEP_OPERAND_UDISP7 :
00741       print_normal (cd, info, fields->f_7u9, 0, pc, length);
00742       break;
00743     case MEP_OPERAND_UDISP7A2 :
00744       print_normal (cd, info, fields->f_7u9a2, 0, pc, length);
00745       break;
00746     case MEP_OPERAND_UDISP7A4 :
00747       print_normal (cd, info, fields->f_7u9a4, 0, pc, length);
00748       break;
00749     case MEP_OPERAND_UIMM16 :
00750       print_normal (cd, info, fields->f_16u16, 0, pc, length);
00751       break;
00752     case MEP_OPERAND_UIMM2 :
00753       print_normal (cd, info, fields->f_2u10, 0, pc, length);
00754       break;
00755     case MEP_OPERAND_UIMM24 :
00756       print_normal (cd, info, fields->f_24u8n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
00757       break;
00758     case MEP_OPERAND_UIMM3 :
00759       print_normal (cd, info, fields->f_3u5, 0, pc, length);
00760       break;
00761     case MEP_OPERAND_UIMM4 :
00762       print_normal (cd, info, fields->f_4u8, 0, pc, length);
00763       break;
00764     case MEP_OPERAND_UIMM5 :
00765       print_normal (cd, info, fields->f_5u8, 0, pc, length);
00766       break;
00767     case MEP_OPERAND_UIMM7A4 :
00768       print_normal (cd, info, fields->f_7u9a4, 0, pc, length);
00769       break;
00770     case MEP_OPERAND_ZERO :
00771       print_normal (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00772       break;
00773 
00774     default :
00775       /* xgettext:c-format */
00776       fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
00777               opindex);
00778     abort ();
00779   }
00780 }
00781 
00782 cgen_print_fn * const mep_cgen_print_handlers[] = 
00783 {
00784   print_insn_normal,
00785 };
00786 
00787 
00788 void
00789 mep_cgen_init_dis (CGEN_CPU_DESC cd)
00790 {
00791   mep_cgen_init_opcode_table (cd);
00792   mep_cgen_init_ibld_table (cd);
00793   cd->print_handlers = & mep_cgen_print_handlers[0];
00794   cd->print_operand = mep_cgen_print_operand;
00795 }
00796 
00797 
00798 /* Default print handler.  */
00799 
00800 static void
00801 print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00802              void *dis_info,
00803              long value,
00804              unsigned int attrs,
00805              bfd_vma pc ATTRIBUTE_UNUSED,
00806              int length ATTRIBUTE_UNUSED)
00807 {
00808   disassemble_info *info = (disassemble_info *) dis_info;
00809 
00810 #ifdef CGEN_PRINT_NORMAL
00811   CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
00812 #endif
00813 
00814   /* Print the operand as directed by the attributes.  */
00815   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
00816     ; /* nothing to do */
00817   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
00818     (*info->fprintf_func) (info->stream, "%ld", value);
00819   else
00820     (*info->fprintf_func) (info->stream, "0x%lx", value);
00821 }
00822 
00823 /* Default address handler.  */
00824 
00825 static void
00826 print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00827               void *dis_info,
00828               bfd_vma value,
00829               unsigned int attrs,
00830               bfd_vma pc ATTRIBUTE_UNUSED,
00831               int length ATTRIBUTE_UNUSED)
00832 {
00833   disassemble_info *info = (disassemble_info *) dis_info;
00834 
00835 #ifdef CGEN_PRINT_ADDRESS
00836   CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
00837 #endif
00838 
00839   /* Print the operand as directed by the attributes.  */
00840   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
00841     ; /* Nothing to do.  */
00842   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
00843     (*info->print_address_func) (value, info);
00844   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
00845     (*info->print_address_func) (value, info);
00846   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
00847     (*info->fprintf_func) (info->stream, "%ld", (long) value);
00848   else
00849     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
00850 }
00851 
00852 /* Keyword print handler.  */
00853 
00854 static void
00855 print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00856               void *dis_info,
00857               CGEN_KEYWORD *keyword_table,
00858               long value,
00859               unsigned int attrs ATTRIBUTE_UNUSED)
00860 {
00861   disassemble_info *info = (disassemble_info *) dis_info;
00862   const CGEN_KEYWORD_ENTRY *ke;
00863 
00864   ke = cgen_keyword_lookup_value (keyword_table, value);
00865   if (ke != NULL)
00866     (*info->fprintf_func) (info->stream, "%s", ke->name);
00867   else
00868     (*info->fprintf_func) (info->stream, "???");
00869 }
00870 
00871 /* Default insn printer.
00872 
00873    DIS_INFO is defined as `void *' so the disassembler needn't know anything
00874    about disassemble_info.  */
00875 
00876 static void
00877 print_insn_normal (CGEN_CPU_DESC cd,
00878                  void *dis_info,
00879                  const CGEN_INSN *insn,
00880                  CGEN_FIELDS *fields,
00881                  bfd_vma pc,
00882                  int length)
00883 {
00884   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00885   disassemble_info *info = (disassemble_info *) dis_info;
00886   const CGEN_SYNTAX_CHAR_TYPE *syn;
00887 
00888   CGEN_INIT_PRINT (cd);
00889 
00890   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
00891     {
00892       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
00893        {
00894          (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
00895          continue;
00896        }
00897       if (CGEN_SYNTAX_CHAR_P (*syn))
00898        {
00899          (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
00900          continue;
00901        }
00902 
00903       /* We have an operand.  */
00904       mep_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
00905                              fields, CGEN_INSN_ATTRS (insn), pc, length);
00906     }
00907 }
00908 
00909 /* Subroutine of print_insn. Reads an insn into the given buffers and updates
00910    the extract info.
00911    Returns 0 if all is well, non-zero otherwise.  */
00912 
00913 static int
00914 read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00915           bfd_vma pc,
00916           disassemble_info *info,
00917           bfd_byte *buf,
00918           int buflen,
00919           CGEN_EXTRACT_INFO *ex_info,
00920           unsigned long *insn_value)
00921 {
00922   int status = (*info->read_memory_func) (pc, buf, buflen, info);
00923 
00924   if (status != 0)
00925     {
00926       (*info->memory_error_func) (status, pc, info);
00927       return -1;
00928     }
00929 
00930   ex_info->dis_info = info;
00931   ex_info->valid = (1 << buflen) - 1;
00932   ex_info->insn_bytes = buf;
00933 
00934   *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
00935   return 0;
00936 }
00937 
00938 /* Utility to print an insn.
00939    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
00940    The result is the size of the insn in bytes or zero for an unknown insn
00941    or -1 if an error occurs fetching data (memory_error_func will have
00942    been called).  */
00943 
00944 static int
00945 print_insn (CGEN_CPU_DESC cd,
00946            bfd_vma pc,
00947            disassemble_info *info,
00948            bfd_byte *buf,
00949            unsigned int buflen)
00950 {
00951   CGEN_INSN_INT insn_value;
00952   const CGEN_INSN_LIST *insn_list;
00953   CGEN_EXTRACT_INFO ex_info;
00954   int basesize;
00955 
00956   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
00957   basesize = cd->base_insn_bitsize < buflen * 8 ?
00958                                      cd->base_insn_bitsize : buflen * 8;
00959   insn_value = cgen_get_insn_value (cd, buf, basesize);
00960 
00961 
00962   /* Fill in ex_info fields like read_insn would.  Don't actually call
00963      read_insn, since the incoming buffer is already read (and possibly
00964      modified a la m32r).  */
00965   ex_info.valid = (1 << buflen) - 1;
00966   ex_info.dis_info = info;
00967   ex_info.insn_bytes = buf;
00968 
00969   /* The instructions are stored in hash lists.
00970      Pick the first one and keep trying until we find the right one.  */
00971 
00972   insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
00973   while (insn_list != NULL)
00974     {
00975       const CGEN_INSN *insn = insn_list->insn;
00976       CGEN_FIELDS fields;
00977       int length;
00978       unsigned long insn_value_cropped;
00979 
00980 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
00981       /* Not needed as insn shouldn't be in hash lists if not supported.  */
00982       /* Supported by this cpu?  */
00983       if (! mep_cgen_insn_supported (cd, insn))
00984         {
00985           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
00986          continue;
00987         }
00988 #endif
00989 
00990       /* Basic bit mask must be correct.  */
00991       /* ??? May wish to allow target to defer this check until the extract
00992         handler.  */
00993 
00994       /* Base size may exceed this instruction's size.  Extract the
00995          relevant part from the buffer. */
00996       if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
00997          (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
00998        insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 
00999                                       info->endian == BFD_ENDIAN_BIG);
01000       else
01001        insn_value_cropped = insn_value;
01002 
01003       if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
01004          == CGEN_INSN_BASE_VALUE (insn))
01005        {
01006          /* Printing is handled in two passes.  The first pass parses the
01007             machine insn and extracts the fields.  The second pass prints
01008             them.  */
01009 
01010          /* Make sure the entire insn is loaded into insn_value, if it
01011             can fit.  */
01012          if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
01013              (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
01014            {
01015              unsigned long full_insn_value;
01016              int rc = read_insn (cd, pc, info, buf,
01017                               CGEN_INSN_BITSIZE (insn) / 8,
01018                               & ex_info, & full_insn_value);
01019              if (rc != 0)
01020               return rc;
01021              length = CGEN_EXTRACT_FN (cd, insn)
01022               (cd, insn, &ex_info, full_insn_value, &fields, pc);
01023            }
01024          else
01025            length = CGEN_EXTRACT_FN (cd, insn)
01026              (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
01027 
01028          /* Length < 0 -> error.  */
01029          if (length < 0)
01030            return length;
01031          if (length > 0)
01032            {
01033              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
01034              /* Length is in bits, result is in bytes.  */
01035              return length / 8;
01036            }
01037        }
01038 
01039       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
01040     }
01041 
01042   return 0;
01043 }
01044 
01045 /* Default value for CGEN_PRINT_INSN.
01046    The result is the size of the insn in bytes or zero for an unknown insn
01047    or -1 if an error occured fetching bytes.  */
01048 
01049 #ifndef CGEN_PRINT_INSN
01050 #define CGEN_PRINT_INSN default_print_insn
01051 #endif
01052 
01053 static int
01054 default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
01055 {
01056   bfd_byte buf[CGEN_MAX_INSN_SIZE];
01057   int buflen;
01058   int status;
01059 
01060   /* Attempt to read the base part of the insn.  */
01061   buflen = cd->base_insn_bitsize / 8;
01062   status = (*info->read_memory_func) (pc, buf, buflen, info);
01063 
01064   /* Try again with the minimum part, if min < base.  */
01065   if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
01066     {
01067       buflen = cd->min_insn_bitsize / 8;
01068       status = (*info->read_memory_func) (pc, buf, buflen, info);
01069     }
01070 
01071   if (status != 0)
01072     {
01073       (*info->memory_error_func) (status, pc, info);
01074       return -1;
01075     }
01076 
01077   return print_insn (cd, pc, info, buf, buflen);
01078 }
01079 
01080 /* Main entry point.
01081    Print one instruction from PC on INFO->STREAM.
01082    Return the size of the instruction (in bytes).  */
01083 
01084 typedef struct cpu_desc_list
01085 {
01086   struct cpu_desc_list *next;
01087   CGEN_BITSET *isa;
01088   int mach;
01089   int endian;
01090   CGEN_CPU_DESC cd;
01091 } cpu_desc_list;
01092 
01093 int
01094 print_insn_mep (bfd_vma pc, disassemble_info *info)
01095 {
01096   static cpu_desc_list *cd_list = 0;
01097   cpu_desc_list *cl = 0;
01098   static CGEN_CPU_DESC cd = 0;
01099   static CGEN_BITSET *prev_isa;
01100   static int prev_mach;
01101   static int prev_endian;
01102   int length;
01103   CGEN_BITSET *isa;
01104   int mach;
01105   int endian = (info->endian == BFD_ENDIAN_BIG
01106               ? CGEN_ENDIAN_BIG
01107               : CGEN_ENDIAN_LITTLE);
01108   enum bfd_architecture arch;
01109 
01110   /* ??? gdb will set mach but leave the architecture as "unknown" */
01111 #ifndef CGEN_BFD_ARCH
01112 #define CGEN_BFD_ARCH bfd_arch_mep
01113 #endif
01114   arch = info->arch;
01115   if (arch == bfd_arch_unknown)
01116     arch = CGEN_BFD_ARCH;
01117    
01118   /* There's no standard way to compute the machine or isa number
01119      so we leave it to the target.  */
01120 #ifdef CGEN_COMPUTE_MACH
01121   mach = CGEN_COMPUTE_MACH (info);
01122 #else
01123   mach = info->mach;
01124 #endif
01125 
01126 #ifdef CGEN_COMPUTE_ISA
01127   {
01128     static CGEN_BITSET *permanent_isa;
01129 
01130     if (!permanent_isa)
01131       permanent_isa = cgen_bitset_create (MAX_ISAS);
01132     isa = permanent_isa;
01133     cgen_bitset_clear (isa);
01134     cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
01135   }
01136 #else
01137   isa = info->insn_sets;
01138 #endif
01139 
01140   /* If we've switched cpu's, try to find a handle we've used before */
01141   if (cd
01142       && (cgen_bitset_compare (isa, prev_isa) != 0
01143          || mach != prev_mach
01144          || endian != prev_endian))
01145     {
01146       cd = 0;
01147       for (cl = cd_list; cl; cl = cl->next)
01148        {
01149          if (cgen_bitset_compare (cl->isa, isa) == 0 &&
01150              cl->mach == mach &&
01151              cl->endian == endian)
01152            {
01153              cd = cl->cd;
01154              prev_isa = cd->isas;
01155              break;
01156            }
01157        }
01158     } 
01159 
01160   /* If we haven't initialized yet, initialize the opcode table.  */
01161   if (! cd)
01162     {
01163       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
01164       const char *mach_name;
01165 
01166       if (!arch_type)
01167        abort ();
01168       mach_name = arch_type->printable_name;
01169 
01170       prev_isa = cgen_bitset_copy (isa);
01171       prev_mach = mach;
01172       prev_endian = endian;
01173       cd = mep_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
01174                              CGEN_CPU_OPEN_BFDMACH, mach_name,
01175                              CGEN_CPU_OPEN_ENDIAN, prev_endian,
01176                              CGEN_CPU_OPEN_END);
01177       if (!cd)
01178        abort ();
01179 
01180       /* Save this away for future reference.  */
01181       cl = xmalloc (sizeof (struct cpu_desc_list));
01182       cl->cd = cd;
01183       cl->isa = prev_isa;
01184       cl->mach = mach;
01185       cl->endian = endian;
01186       cl->next = cd_list;
01187       cd_list = cl;
01188 
01189       mep_cgen_init_dis (cd);
01190     }
01191 
01192   /* We try to have as much common code as possible.
01193      But at this point some targets need to take over.  */
01194   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
01195      but if not possible try to move this hook elsewhere rather than
01196      have two hooks.  */
01197   length = CGEN_PRINT_INSN (cd, pc, info);
01198   if (length > 0)
01199     return length;
01200   if (length < 0)
01201     return -1;
01202 
01203   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
01204   return cd->default_insn_bitsize / 8;
01205 }