Back to index

cell-binutils  2.17cvs20070401
frv-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 "frv-desc.h"
00037 #include "frv-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 static void
00063 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00064          void * dis_info,
00065          long reloc_ann ATTRIBUTE_UNUSED,
00066          long value ATTRIBUTE_UNUSED,
00067          bfd_vma pc ATTRIBUTE_UNUSED,
00068          int length ATTRIBUTE_UNUSED)
00069 {
00070   disassemble_info *info = (disassemble_info *) dis_info;
00071 
00072   (*info->fprintf_func) (info->stream, "@");
00073 }  
00074 
00075 static void
00076 print_spr (CGEN_CPU_DESC cd,
00077           void * dis_info,
00078           CGEN_KEYWORD *names,
00079           long regno,
00080           unsigned int attrs)
00081 {
00082   /* Use the register index format for any unnamed registers.  */
00083   if (cgen_keyword_lookup_value (names, regno) == NULL)
00084     {
00085       disassemble_info *info = (disassemble_info *) dis_info;
00086       (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
00087     }
00088   else
00089     print_keyword (cd, dis_info, names, regno, attrs);
00090 }
00091 
00092 static void
00093 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00094          void * dis_info,
00095          long value,
00096          unsigned int attrs ATTRIBUTE_UNUSED,
00097          bfd_vma pc ATTRIBUTE_UNUSED,
00098          int length ATTRIBUTE_UNUSED)
00099 {
00100   disassemble_info *info = (disassemble_info *) dis_info;
00101 
00102   (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
00103 }
00104 
00105 static void
00106 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00107          void * dis_info,
00108          long value,
00109          unsigned int attrs ATTRIBUTE_UNUSED,
00110          bfd_vma pc ATTRIBUTE_UNUSED,
00111          int length ATTRIBUTE_UNUSED)
00112 {
00113   disassemble_info *info = (disassemble_info *) dis_info;
00114   if (value)
00115     (*info->fprintf_func) (info->stream, "0x%lx", value);
00116   else
00117     (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
00118 }
00119 
00120 /* -- */
00121 
00122 void frv_cgen_print_operand
00123   (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
00124 
00125 /* Main entry point for printing operands.
00126    XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
00127    of dis-asm.h on cgen.h.
00128 
00129    This function is basically just a big switch statement.  Earlier versions
00130    used tables to look up the function to use, but
00131    - if the table contains both assembler and disassembler functions then
00132      the disassembler contains much of the assembler and vice-versa,
00133    - there's a lot of inlining possibilities as things grow,
00134    - using a switch statement avoids the function call overhead.
00135 
00136    This function could be moved into `print_insn_normal', but keeping it
00137    separate makes clear the interface between `print_insn_normal' and each of
00138    the handlers.  */
00139 
00140 void
00141 frv_cgen_print_operand (CGEN_CPU_DESC cd,
00142                         int opindex,
00143                         void * xinfo,
00144                         CGEN_FIELDS *fields,
00145                         void const *attrs ATTRIBUTE_UNUSED,
00146                         bfd_vma pc,
00147                         int length)
00148 {
00149   disassemble_info *info = (disassemble_info *) xinfo;
00150 
00151   switch (opindex)
00152     {
00153     case FRV_OPERAND_A0 :
00154       print_normal (cd, info, fields->f_A, 0, pc, length);
00155       break;
00156     case FRV_OPERAND_A1 :
00157       print_normal (cd, info, fields->f_A, 0, pc, length);
00158       break;
00159     case FRV_OPERAND_ACC40SI :
00160       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Si, 0);
00161       break;
00162     case FRV_OPERAND_ACC40SK :
00163       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Sk, 0);
00164       break;
00165     case FRV_OPERAND_ACC40UI :
00166       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Ui, 0);
00167       break;
00168     case FRV_OPERAND_ACC40UK :
00169       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Uk, 0);
00170       break;
00171     case FRV_OPERAND_ACCGI :
00172       print_keyword (cd, info, & frv_cgen_opval_accg_names, fields->f_ACCGi, 0);
00173       break;
00174     case FRV_OPERAND_ACCGK :
00175       print_keyword (cd, info, & frv_cgen_opval_accg_names, fields->f_ACCGk, 0);
00176       break;
00177     case FRV_OPERAND_CCI :
00178       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CCi, 0);
00179       break;
00180     case FRV_OPERAND_CPRDOUBLEK :
00181       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRk, 0);
00182       break;
00183     case FRV_OPERAND_CPRI :
00184       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRi, 0);
00185       break;
00186     case FRV_OPERAND_CPRJ :
00187       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRj, 0);
00188       break;
00189     case FRV_OPERAND_CPRK :
00190       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRk, 0);
00191       break;
00192     case FRV_OPERAND_CRI :
00193       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRi, 0);
00194       break;
00195     case FRV_OPERAND_CRJ :
00196       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj, 0);
00197       break;
00198     case FRV_OPERAND_CRJ_FLOAT :
00199       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj_float, 0);
00200       break;
00201     case FRV_OPERAND_CRJ_INT :
00202       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj_int, 0);
00203       break;
00204     case FRV_OPERAND_CRK :
00205       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRk, 0);
00206       break;
00207     case FRV_OPERAND_FCCI_1 :
00208       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_1, 0);
00209       break;
00210     case FRV_OPERAND_FCCI_2 :
00211       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_2, 0);
00212       break;
00213     case FRV_OPERAND_FCCI_3 :
00214       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_3, 0);
00215       break;
00216     case FRV_OPERAND_FCCK :
00217       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCk, 0);
00218       break;
00219     case FRV_OPERAND_FRDOUBLEI :
00220       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
00221       break;
00222     case FRV_OPERAND_FRDOUBLEJ :
00223       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
00224       break;
00225     case FRV_OPERAND_FRDOUBLEK :
00226       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
00227       break;
00228     case FRV_OPERAND_FRI :
00229       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
00230       break;
00231     case FRV_OPERAND_FRINTI :
00232       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
00233       break;
00234     case FRV_OPERAND_FRINTIEVEN :
00235       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
00236       break;
00237     case FRV_OPERAND_FRINTJ :
00238       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
00239       break;
00240     case FRV_OPERAND_FRINTJEVEN :
00241       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
00242       break;
00243     case FRV_OPERAND_FRINTK :
00244       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
00245       break;
00246     case FRV_OPERAND_FRINTKEVEN :
00247       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
00248       break;
00249     case FRV_OPERAND_FRJ :
00250       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
00251       break;
00252     case FRV_OPERAND_FRK :
00253       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
00254       break;
00255     case FRV_OPERAND_FRKHI :
00256       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
00257       break;
00258     case FRV_OPERAND_FRKLO :
00259       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
00260       break;
00261     case FRV_OPERAND_GRDOUBLEK :
00262       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
00263       break;
00264     case FRV_OPERAND_GRI :
00265       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRi, 0);
00266       break;
00267     case FRV_OPERAND_GRJ :
00268       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRj, 0);
00269       break;
00270     case FRV_OPERAND_GRK :
00271       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
00272       break;
00273     case FRV_OPERAND_GRKHI :
00274       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
00275       break;
00276     case FRV_OPERAND_GRKLO :
00277       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
00278       break;
00279     case FRV_OPERAND_ICCI_1 :
00280       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_1, 0);
00281       break;
00282     case FRV_OPERAND_ICCI_2 :
00283       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_2, 0);
00284       break;
00285     case FRV_OPERAND_ICCI_3 :
00286       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_3, 0);
00287       break;
00288     case FRV_OPERAND_LI :
00289       print_normal (cd, info, fields->f_LI, 0, pc, length);
00290       break;
00291     case FRV_OPERAND_LRAD :
00292       print_normal (cd, info, fields->f_LRAD, 0, pc, length);
00293       break;
00294     case FRV_OPERAND_LRAE :
00295       print_normal (cd, info, fields->f_LRAE, 0, pc, length);
00296       break;
00297     case FRV_OPERAND_LRAS :
00298       print_normal (cd, info, fields->f_LRAS, 0, pc, length);
00299       break;
00300     case FRV_OPERAND_TLBPRL :
00301       print_normal (cd, info, fields->f_TLBPRL, 0, pc, length);
00302       break;
00303     case FRV_OPERAND_TLBPROPX :
00304       print_normal (cd, info, fields->f_TLBPRopx, 0, pc, length);
00305       break;
00306     case FRV_OPERAND_AE :
00307       print_normal (cd, info, fields->f_ae, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00308       break;
00309     case FRV_OPERAND_CALLANN :
00310       print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
00311       break;
00312     case FRV_OPERAND_CCOND :
00313       print_normal (cd, info, fields->f_ccond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00314       break;
00315     case FRV_OPERAND_COND :
00316       print_normal (cd, info, fields->f_cond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00317       break;
00318     case FRV_OPERAND_D12 :
00319       print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00320       break;
00321     case FRV_OPERAND_DEBUG :
00322       print_normal (cd, info, fields->f_debug, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00323       break;
00324     case FRV_OPERAND_EIR :
00325       print_normal (cd, info, fields->f_eir, 0, pc, length);
00326       break;
00327     case FRV_OPERAND_HINT :
00328       print_normal (cd, info, fields->f_hint, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00329       break;
00330     case FRV_OPERAND_HINT_NOT_TAKEN :
00331       print_keyword (cd, info, & frv_cgen_opval_h_hint_not_taken, fields->f_hint, 0);
00332       break;
00333     case FRV_OPERAND_HINT_TAKEN :
00334       print_keyword (cd, info, & frv_cgen_opval_h_hint_taken, fields->f_hint, 0);
00335       break;
00336     case FRV_OPERAND_LABEL16 :
00337       print_address (cd, info, fields->f_label16, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00338       break;
00339     case FRV_OPERAND_LABEL24 :
00340       print_address (cd, info, fields->f_label24, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
00341       break;
00342     case FRV_OPERAND_LDANN :
00343       print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
00344       break;
00345     case FRV_OPERAND_LDDANN :
00346       print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
00347       break;
00348     case FRV_OPERAND_LOCK :
00349       print_normal (cd, info, fields->f_lock, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00350       break;
00351     case FRV_OPERAND_PACK :
00352       print_keyword (cd, info, & frv_cgen_opval_h_pack, fields->f_pack, 0);
00353       break;
00354     case FRV_OPERAND_S10 :
00355       print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00356       break;
00357     case FRV_OPERAND_S12 :
00358       print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00359       break;
00360     case FRV_OPERAND_S16 :
00361       print_normal (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00362       break;
00363     case FRV_OPERAND_S5 :
00364       print_normal (cd, info, fields->f_s5, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00365       break;
00366     case FRV_OPERAND_S6 :
00367       print_normal (cd, info, fields->f_s6, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00368       break;
00369     case FRV_OPERAND_S6_1 :
00370       print_normal (cd, info, fields->f_s6_1, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00371       break;
00372     case FRV_OPERAND_SLO16 :
00373       print_lo (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00374       break;
00375     case FRV_OPERAND_SPR :
00376       print_spr (cd, info, & frv_cgen_opval_spr_names, fields->f_spr, 0|(1<<CGEN_OPERAND_VIRTUAL));
00377       break;
00378     case FRV_OPERAND_U12 :
00379       print_normal (cd, info, fields->f_u12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
00380       break;
00381     case FRV_OPERAND_U16 :
00382       print_normal (cd, info, fields->f_u16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00383       break;
00384     case FRV_OPERAND_U6 :
00385       print_normal (cd, info, fields->f_u6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00386       break;
00387     case FRV_OPERAND_UHI16 :
00388       print_hi (cd, info, fields->f_u16, 0, pc, length);
00389       break;
00390     case FRV_OPERAND_ULO16 :
00391       print_lo (cd, info, fields->f_u16, 0, pc, length);
00392       break;
00393 
00394     default :
00395       /* xgettext:c-format */
00396       fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
00397               opindex);
00398     abort ();
00399   }
00400 }
00401 
00402 cgen_print_fn * const frv_cgen_print_handlers[] = 
00403 {
00404   print_insn_normal,
00405 };
00406 
00407 
00408 void
00409 frv_cgen_init_dis (CGEN_CPU_DESC cd)
00410 {
00411   frv_cgen_init_opcode_table (cd);
00412   frv_cgen_init_ibld_table (cd);
00413   cd->print_handlers = & frv_cgen_print_handlers[0];
00414   cd->print_operand = frv_cgen_print_operand;
00415 }
00416 
00417 
00418 /* Default print handler.  */
00419 
00420 static void
00421 print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00422              void *dis_info,
00423              long value,
00424              unsigned int attrs,
00425              bfd_vma pc ATTRIBUTE_UNUSED,
00426              int length ATTRIBUTE_UNUSED)
00427 {
00428   disassemble_info *info = (disassemble_info *) dis_info;
00429 
00430 #ifdef CGEN_PRINT_NORMAL
00431   CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
00432 #endif
00433 
00434   /* Print the operand as directed by the attributes.  */
00435   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
00436     ; /* nothing to do */
00437   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
00438     (*info->fprintf_func) (info->stream, "%ld", value);
00439   else
00440     (*info->fprintf_func) (info->stream, "0x%lx", value);
00441 }
00442 
00443 /* Default address handler.  */
00444 
00445 static void
00446 print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00447               void *dis_info,
00448               bfd_vma value,
00449               unsigned int attrs,
00450               bfd_vma pc ATTRIBUTE_UNUSED,
00451               int length ATTRIBUTE_UNUSED)
00452 {
00453   disassemble_info *info = (disassemble_info *) dis_info;
00454 
00455 #ifdef CGEN_PRINT_ADDRESS
00456   CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
00457 #endif
00458 
00459   /* Print the operand as directed by the attributes.  */
00460   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
00461     ; /* Nothing to do.  */
00462   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
00463     (*info->print_address_func) (value, info);
00464   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
00465     (*info->print_address_func) (value, info);
00466   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
00467     (*info->fprintf_func) (info->stream, "%ld", (long) value);
00468   else
00469     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
00470 }
00471 
00472 /* Keyword print handler.  */
00473 
00474 static void
00475 print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00476               void *dis_info,
00477               CGEN_KEYWORD *keyword_table,
00478               long value,
00479               unsigned int attrs ATTRIBUTE_UNUSED)
00480 {
00481   disassemble_info *info = (disassemble_info *) dis_info;
00482   const CGEN_KEYWORD_ENTRY *ke;
00483 
00484   ke = cgen_keyword_lookup_value (keyword_table, value);
00485   if (ke != NULL)
00486     (*info->fprintf_func) (info->stream, "%s", ke->name);
00487   else
00488     (*info->fprintf_func) (info->stream, "???");
00489 }
00490 
00491 /* Default insn printer.
00492 
00493    DIS_INFO is defined as `void *' so the disassembler needn't know anything
00494    about disassemble_info.  */
00495 
00496 static void
00497 print_insn_normal (CGEN_CPU_DESC cd,
00498                  void *dis_info,
00499                  const CGEN_INSN *insn,
00500                  CGEN_FIELDS *fields,
00501                  bfd_vma pc,
00502                  int length)
00503 {
00504   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00505   disassemble_info *info = (disassemble_info *) dis_info;
00506   const CGEN_SYNTAX_CHAR_TYPE *syn;
00507 
00508   CGEN_INIT_PRINT (cd);
00509 
00510   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
00511     {
00512       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
00513        {
00514          (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
00515          continue;
00516        }
00517       if (CGEN_SYNTAX_CHAR_P (*syn))
00518        {
00519          (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
00520          continue;
00521        }
00522 
00523       /* We have an operand.  */
00524       frv_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
00525                              fields, CGEN_INSN_ATTRS (insn), pc, length);
00526     }
00527 }
00528 
00529 /* Subroutine of print_insn. Reads an insn into the given buffers and updates
00530    the extract info.
00531    Returns 0 if all is well, non-zero otherwise.  */
00532 
00533 static int
00534 read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00535           bfd_vma pc,
00536           disassemble_info *info,
00537           bfd_byte *buf,
00538           int buflen,
00539           CGEN_EXTRACT_INFO *ex_info,
00540           unsigned long *insn_value)
00541 {
00542   int status = (*info->read_memory_func) (pc, buf, buflen, info);
00543 
00544   if (status != 0)
00545     {
00546       (*info->memory_error_func) (status, pc, info);
00547       return -1;
00548     }
00549 
00550   ex_info->dis_info = info;
00551   ex_info->valid = (1 << buflen) - 1;
00552   ex_info->insn_bytes = buf;
00553 
00554   *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
00555   return 0;
00556 }
00557 
00558 /* Utility to print an insn.
00559    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
00560    The result is the size of the insn in bytes or zero for an unknown insn
00561    or -1 if an error occurs fetching data (memory_error_func will have
00562    been called).  */
00563 
00564 static int
00565 print_insn (CGEN_CPU_DESC cd,
00566            bfd_vma pc,
00567            disassemble_info *info,
00568            bfd_byte *buf,
00569            unsigned int buflen)
00570 {
00571   CGEN_INSN_INT insn_value;
00572   const CGEN_INSN_LIST *insn_list;
00573   CGEN_EXTRACT_INFO ex_info;
00574   int basesize;
00575 
00576   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
00577   basesize = cd->base_insn_bitsize < buflen * 8 ?
00578                                      cd->base_insn_bitsize : buflen * 8;
00579   insn_value = cgen_get_insn_value (cd, buf, basesize);
00580 
00581 
00582   /* Fill in ex_info fields like read_insn would.  Don't actually call
00583      read_insn, since the incoming buffer is already read (and possibly
00584      modified a la m32r).  */
00585   ex_info.valid = (1 << buflen) - 1;
00586   ex_info.dis_info = info;
00587   ex_info.insn_bytes = buf;
00588 
00589   /* The instructions are stored in hash lists.
00590      Pick the first one and keep trying until we find the right one.  */
00591 
00592   insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
00593   while (insn_list != NULL)
00594     {
00595       const CGEN_INSN *insn = insn_list->insn;
00596       CGEN_FIELDS fields;
00597       int length;
00598       unsigned long insn_value_cropped;
00599 
00600 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
00601       /* Not needed as insn shouldn't be in hash lists if not supported.  */
00602       /* Supported by this cpu?  */
00603       if (! frv_cgen_insn_supported (cd, insn))
00604         {
00605           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
00606          continue;
00607         }
00608 #endif
00609 
00610       /* Basic bit mask must be correct.  */
00611       /* ??? May wish to allow target to defer this check until the extract
00612         handler.  */
00613 
00614       /* Base size may exceed this instruction's size.  Extract the
00615          relevant part from the buffer. */
00616       if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
00617          (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
00618        insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 
00619                                       info->endian == BFD_ENDIAN_BIG);
00620       else
00621        insn_value_cropped = insn_value;
00622 
00623       if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
00624          == CGEN_INSN_BASE_VALUE (insn))
00625        {
00626          /* Printing is handled in two passes.  The first pass parses the
00627             machine insn and extracts the fields.  The second pass prints
00628             them.  */
00629 
00630          /* Make sure the entire insn is loaded into insn_value, if it
00631             can fit.  */
00632          if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
00633              (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
00634            {
00635              unsigned long full_insn_value;
00636              int rc = read_insn (cd, pc, info, buf,
00637                               CGEN_INSN_BITSIZE (insn) / 8,
00638                               & ex_info, & full_insn_value);
00639              if (rc != 0)
00640               return rc;
00641              length = CGEN_EXTRACT_FN (cd, insn)
00642               (cd, insn, &ex_info, full_insn_value, &fields, pc);
00643            }
00644          else
00645            length = CGEN_EXTRACT_FN (cd, insn)
00646              (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
00647 
00648          /* Length < 0 -> error.  */
00649          if (length < 0)
00650            return length;
00651          if (length > 0)
00652            {
00653              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
00654              /* Length is in bits, result is in bytes.  */
00655              return length / 8;
00656            }
00657        }
00658 
00659       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
00660     }
00661 
00662   return 0;
00663 }
00664 
00665 /* Default value for CGEN_PRINT_INSN.
00666    The result is the size of the insn in bytes or zero for an unknown insn
00667    or -1 if an error occured fetching bytes.  */
00668 
00669 #ifndef CGEN_PRINT_INSN
00670 #define CGEN_PRINT_INSN default_print_insn
00671 #endif
00672 
00673 static int
00674 default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
00675 {
00676   bfd_byte buf[CGEN_MAX_INSN_SIZE];
00677   int buflen;
00678   int status;
00679 
00680   /* Attempt to read the base part of the insn.  */
00681   buflen = cd->base_insn_bitsize / 8;
00682   status = (*info->read_memory_func) (pc, buf, buflen, info);
00683 
00684   /* Try again with the minimum part, if min < base.  */
00685   if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
00686     {
00687       buflen = cd->min_insn_bitsize / 8;
00688       status = (*info->read_memory_func) (pc, buf, buflen, info);
00689     }
00690 
00691   if (status != 0)
00692     {
00693       (*info->memory_error_func) (status, pc, info);
00694       return -1;
00695     }
00696 
00697   return print_insn (cd, pc, info, buf, buflen);
00698 }
00699 
00700 /* Main entry point.
00701    Print one instruction from PC on INFO->STREAM.
00702    Return the size of the instruction (in bytes).  */
00703 
00704 typedef struct cpu_desc_list
00705 {
00706   struct cpu_desc_list *next;
00707   CGEN_BITSET *isa;
00708   int mach;
00709   int endian;
00710   CGEN_CPU_DESC cd;
00711 } cpu_desc_list;
00712 
00713 int
00714 print_insn_frv (bfd_vma pc, disassemble_info *info)
00715 {
00716   static cpu_desc_list *cd_list = 0;
00717   cpu_desc_list *cl = 0;
00718   static CGEN_CPU_DESC cd = 0;
00719   static CGEN_BITSET *prev_isa;
00720   static int prev_mach;
00721   static int prev_endian;
00722   int length;
00723   CGEN_BITSET *isa;
00724   int mach;
00725   int endian = (info->endian == BFD_ENDIAN_BIG
00726               ? CGEN_ENDIAN_BIG
00727               : CGEN_ENDIAN_LITTLE);
00728   enum bfd_architecture arch;
00729 
00730   /* ??? gdb will set mach but leave the architecture as "unknown" */
00731 #ifndef CGEN_BFD_ARCH
00732 #define CGEN_BFD_ARCH bfd_arch_frv
00733 #endif
00734   arch = info->arch;
00735   if (arch == bfd_arch_unknown)
00736     arch = CGEN_BFD_ARCH;
00737    
00738   /* There's no standard way to compute the machine or isa number
00739      so we leave it to the target.  */
00740 #ifdef CGEN_COMPUTE_MACH
00741   mach = CGEN_COMPUTE_MACH (info);
00742 #else
00743   mach = info->mach;
00744 #endif
00745 
00746 #ifdef CGEN_COMPUTE_ISA
00747   {
00748     static CGEN_BITSET *permanent_isa;
00749 
00750     if (!permanent_isa)
00751       permanent_isa = cgen_bitset_create (MAX_ISAS);
00752     isa = permanent_isa;
00753     cgen_bitset_clear (isa);
00754     cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
00755   }
00756 #else
00757   isa = info->insn_sets;
00758 #endif
00759 
00760   /* If we've switched cpu's, try to find a handle we've used before */
00761   if (cd
00762       && (cgen_bitset_compare (isa, prev_isa) != 0
00763          || mach != prev_mach
00764          || endian != prev_endian))
00765     {
00766       cd = 0;
00767       for (cl = cd_list; cl; cl = cl->next)
00768        {
00769          if (cgen_bitset_compare (cl->isa, isa) == 0 &&
00770              cl->mach == mach &&
00771              cl->endian == endian)
00772            {
00773              cd = cl->cd;
00774              prev_isa = cd->isas;
00775              break;
00776            }
00777        }
00778     } 
00779 
00780   /* If we haven't initialized yet, initialize the opcode table.  */
00781   if (! cd)
00782     {
00783       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
00784       const char *mach_name;
00785 
00786       if (!arch_type)
00787        abort ();
00788       mach_name = arch_type->printable_name;
00789 
00790       prev_isa = cgen_bitset_copy (isa);
00791       prev_mach = mach;
00792       prev_endian = endian;
00793       cd = frv_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
00794                              CGEN_CPU_OPEN_BFDMACH, mach_name,
00795                              CGEN_CPU_OPEN_ENDIAN, prev_endian,
00796                              CGEN_CPU_OPEN_END);
00797       if (!cd)
00798        abort ();
00799 
00800       /* Save this away for future reference.  */
00801       cl = xmalloc (sizeof (struct cpu_desc_list));
00802       cl->cd = cd;
00803       cl->isa = prev_isa;
00804       cl->mach = mach;
00805       cl->endian = endian;
00806       cl->next = cd_list;
00807       cd_list = cl;
00808 
00809       frv_cgen_init_dis (cd);
00810     }
00811 
00812   /* We try to have as much common code as possible.
00813      But at this point some targets need to take over.  */
00814   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
00815      but if not possible try to move this hook elsewhere rather than
00816      have two hooks.  */
00817   length = CGEN_PRINT_INSN (cd, pc, info);
00818   if (length > 0)
00819     return length;
00820   if (length < 0)
00821     return -1;
00822 
00823   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
00824   return cd->default_insn_bitsize / 8;
00825 }