Home | History | Annotate | Download | only in opcodes
      1 /* Disassembler interface for targets using CGEN. -*- C -*-
      2    CGEN: Cpu tools GENerator
      3 
      4    THIS FILE IS MACHINE GENERATED WITH CGEN.
      5    - the resultant file is machine generated, cgen-dis.in isn't
      6 
      7    Copyright (C) 1996-2014 Free Software Foundation, Inc.
      8 
      9    This file is part of libopcodes.
     10 
     11    This library is free software; you can redistribute it and/or modify
     12    it under the terms of the GNU General Public License as published by
     13    the Free Software Foundation; either version 3, or (at your option)
     14    any later version.
     15 
     16    It is distributed in the hope that it will be useful, but WITHOUT
     17    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     18    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     19    License for more details.
     20 
     21    You should have received a copy of the GNU General Public License
     22    along with this program; if not, write to the Free Software Foundation, Inc.,
     23    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
     24 
     25 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
     26    Keep that in mind.  */
     27 
     28 #include "sysdep.h"
     29 #include <stdio.h>
     30 #include "ansidecl.h"
     31 #include "dis-asm.h"
     32 #include "bfd.h"
     33 #include "symcat.h"
     34 #include "libiberty.h"
     35 #include "frv-desc.h"
     36 #include "frv-opc.h"
     37 #include "opintl.h"
     38 
     39 /* Default text to print if an instruction isn't recognized.  */
     40 #define UNKNOWN_INSN_MSG _("*unknown*")
     41 
     42 static void print_normal
     43   (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
     44 static void print_address
     45   (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
     46 static void print_keyword
     47   (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
     48 static void print_insn_normal
     49   (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
     50 static int print_insn
     51   (CGEN_CPU_DESC, bfd_vma,  disassemble_info *, bfd_byte *, unsigned);
     52 static int default_print_insn
     53   (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
     54 static int read_insn
     55   (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
     56    unsigned long *);
     57 
     58 /* -- disassembler routines inserted here.  */
     60 
     61 /* -- dis.c */
     62 static void
     63 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
     64 	  void * dis_info,
     65 	  long reloc_ann ATTRIBUTE_UNUSED,
     66 	  long value ATTRIBUTE_UNUSED,
     67 	  bfd_vma pc ATTRIBUTE_UNUSED,
     68 	  int length ATTRIBUTE_UNUSED)
     69 {
     70   disassemble_info *info = (disassemble_info *) dis_info;
     71 
     72   (*info->fprintf_func) (info->stream, "@");
     73 }
     74 
     75 static void
     76 print_spr (CGEN_CPU_DESC cd,
     77 	   void * dis_info,
     78 	   CGEN_KEYWORD *names,
     79 	   long regno,
     80 	   unsigned int attrs)
     81 {
     82   /* Use the register index format for any unnamed registers.  */
     83   if (cgen_keyword_lookup_value (names, regno) == NULL)
     84     {
     85       disassemble_info *info = (disassemble_info *) dis_info;
     86       (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
     87     }
     88   else
     89     print_keyword (cd, dis_info, names, regno, attrs);
     90 }
     91 
     92 static void
     93 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
     94 	  void * dis_info,
     95 	  long value,
     96 	  unsigned int attrs ATTRIBUTE_UNUSED,
     97 	  bfd_vma pc ATTRIBUTE_UNUSED,
     98 	  int length ATTRIBUTE_UNUSED)
     99 {
    100   disassemble_info *info = (disassemble_info *) dis_info;
    101 
    102   (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
    103 }
    104 
    105 static void
    106 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    107 	  void * dis_info,
    108 	  long value,
    109 	  unsigned int attrs ATTRIBUTE_UNUSED,
    110 	  bfd_vma pc ATTRIBUTE_UNUSED,
    111 	  int length ATTRIBUTE_UNUSED)
    112 {
    113   disassemble_info *info = (disassemble_info *) dis_info;
    114   if (value)
    115     (*info->fprintf_func) (info->stream, "0x%lx", value);
    116   else
    117     (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
    118 }
    119 
    120 /* -- */
    121 
    122 void frv_cgen_print_operand
    123   (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
    124 
    125 /* Main entry point for printing operands.
    126    XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
    127    of dis-asm.h on cgen.h.
    128 
    129    This function is basically just a big switch statement.  Earlier versions
    130    used tables to look up the function to use, but
    131    - if the table contains both assembler and disassembler functions then
    132      the disassembler contains much of the assembler and vice-versa,
    133    - there's a lot of inlining possibilities as things grow,
    134    - using a switch statement avoids the function call overhead.
    135 
    136    This function could be moved into `print_insn_normal', but keeping it
    137    separate makes clear the interface between `print_insn_normal' and each of
    138    the handlers.  */
    139 
    140 void
    141 frv_cgen_print_operand (CGEN_CPU_DESC cd,
    142 			   int opindex,
    143 			   void * xinfo,
    144 			   CGEN_FIELDS *fields,
    145 			   void const *attrs ATTRIBUTE_UNUSED,
    146 			   bfd_vma pc,
    147 			   int length)
    148 {
    149   disassemble_info *info = (disassemble_info *) xinfo;
    150 
    151   switch (opindex)
    152     {
    153     case FRV_OPERAND_A0 :
    154       print_normal (cd, info, fields->f_A, 0, pc, length);
    155       break;
    156     case FRV_OPERAND_A1 :
    157       print_normal (cd, info, fields->f_A, 0, pc, length);
    158       break;
    159     case FRV_OPERAND_ACC40SI :
    160       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Si, 0);
    161       break;
    162     case FRV_OPERAND_ACC40SK :
    163       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Sk, 0);
    164       break;
    165     case FRV_OPERAND_ACC40UI :
    166       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Ui, 0);
    167       break;
    168     case FRV_OPERAND_ACC40UK :
    169       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Uk, 0);
    170       break;
    171     case FRV_OPERAND_ACCGI :
    172       print_keyword (cd, info, & frv_cgen_opval_accg_names, fields->f_ACCGi, 0);
    173       break;
    174     case FRV_OPERAND_ACCGK :
    175       print_keyword (cd, info, & frv_cgen_opval_accg_names, fields->f_ACCGk, 0);
    176       break;
    177     case FRV_OPERAND_CCI :
    178       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CCi, 0);
    179       break;
    180     case FRV_OPERAND_CPRDOUBLEK :
    181       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRk, 0);
    182       break;
    183     case FRV_OPERAND_CPRI :
    184       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRi, 0);
    185       break;
    186     case FRV_OPERAND_CPRJ :
    187       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRj, 0);
    188       break;
    189     case FRV_OPERAND_CPRK :
    190       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRk, 0);
    191       break;
    192     case FRV_OPERAND_CRI :
    193       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRi, 0);
    194       break;
    195     case FRV_OPERAND_CRJ :
    196       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj, 0);
    197       break;
    198     case FRV_OPERAND_CRJ_FLOAT :
    199       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj_float, 0);
    200       break;
    201     case FRV_OPERAND_CRJ_INT :
    202       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj_int, 0);
    203       break;
    204     case FRV_OPERAND_CRK :
    205       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRk, 0);
    206       break;
    207     case FRV_OPERAND_FCCI_1 :
    208       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_1, 0);
    209       break;
    210     case FRV_OPERAND_FCCI_2 :
    211       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_2, 0);
    212       break;
    213     case FRV_OPERAND_FCCI_3 :
    214       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_3, 0);
    215       break;
    216     case FRV_OPERAND_FCCK :
    217       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCk, 0);
    218       break;
    219     case FRV_OPERAND_FRDOUBLEI :
    220       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
    221       break;
    222     case FRV_OPERAND_FRDOUBLEJ :
    223       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
    224       break;
    225     case FRV_OPERAND_FRDOUBLEK :
    226       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
    227       break;
    228     case FRV_OPERAND_FRI :
    229       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
    230       break;
    231     case FRV_OPERAND_FRINTI :
    232       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
    233       break;
    234     case FRV_OPERAND_FRINTIEVEN :
    235       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
    236       break;
    237     case FRV_OPERAND_FRINTJ :
    238       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
    239       break;
    240     case FRV_OPERAND_FRINTJEVEN :
    241       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
    242       break;
    243     case FRV_OPERAND_FRINTK :
    244       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
    245       break;
    246     case FRV_OPERAND_FRINTKEVEN :
    247       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
    248       break;
    249     case FRV_OPERAND_FRJ :
    250       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
    251       break;
    252     case FRV_OPERAND_FRK :
    253       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
    254       break;
    255     case FRV_OPERAND_FRKHI :
    256       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
    257       break;
    258     case FRV_OPERAND_FRKLO :
    259       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
    260       break;
    261     case FRV_OPERAND_GRDOUBLEK :
    262       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
    263       break;
    264     case FRV_OPERAND_GRI :
    265       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRi, 0);
    266       break;
    267     case FRV_OPERAND_GRJ :
    268       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRj, 0);
    269       break;
    270     case FRV_OPERAND_GRK :
    271       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
    272       break;
    273     case FRV_OPERAND_GRKHI :
    274       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
    275       break;
    276     case FRV_OPERAND_GRKLO :
    277       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
    278       break;
    279     case FRV_OPERAND_ICCI_1 :
    280       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_1, 0);
    281       break;
    282     case FRV_OPERAND_ICCI_2 :
    283       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_2, 0);
    284       break;
    285     case FRV_OPERAND_ICCI_3 :
    286       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_3, 0);
    287       break;
    288     case FRV_OPERAND_LI :
    289       print_normal (cd, info, fields->f_LI, 0, pc, length);
    290       break;
    291     case FRV_OPERAND_LRAD :
    292       print_normal (cd, info, fields->f_LRAD, 0, pc, length);
    293       break;
    294     case FRV_OPERAND_LRAE :
    295       print_normal (cd, info, fields->f_LRAE, 0, pc, length);
    296       break;
    297     case FRV_OPERAND_LRAS :
    298       print_normal (cd, info, fields->f_LRAS, 0, pc, length);
    299       break;
    300     case FRV_OPERAND_TLBPRL :
    301       print_normal (cd, info, fields->f_TLBPRL, 0, pc, length);
    302       break;
    303     case FRV_OPERAND_TLBPROPX :
    304       print_normal (cd, info, fields->f_TLBPRopx, 0, pc, length);
    305       break;
    306     case FRV_OPERAND_AE :
    307       print_normal (cd, info, fields->f_ae, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    308       break;
    309     case FRV_OPERAND_CALLANN :
    310       print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
    311       break;
    312     case FRV_OPERAND_CCOND :
    313       print_normal (cd, info, fields->f_ccond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    314       break;
    315     case FRV_OPERAND_COND :
    316       print_normal (cd, info, fields->f_cond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    317       break;
    318     case FRV_OPERAND_D12 :
    319       print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
    320       break;
    321     case FRV_OPERAND_DEBUG :
    322       print_normal (cd, info, fields->f_debug, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    323       break;
    324     case FRV_OPERAND_EIR :
    325       print_normal (cd, info, fields->f_eir, 0, pc, length);
    326       break;
    327     case FRV_OPERAND_HINT :
    328       print_normal (cd, info, fields->f_hint, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    329       break;
    330     case FRV_OPERAND_HINT_NOT_TAKEN :
    331       print_keyword (cd, info, & frv_cgen_opval_h_hint_not_taken, fields->f_hint, 0);
    332       break;
    333     case FRV_OPERAND_HINT_TAKEN :
    334       print_keyword (cd, info, & frv_cgen_opval_h_hint_taken, fields->f_hint, 0);
    335       break;
    336     case FRV_OPERAND_LABEL16 :
    337       print_address (cd, info, fields->f_label16, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
    338       break;
    339     case FRV_OPERAND_LABEL24 :
    340       print_address (cd, info, fields->f_label24, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
    341       break;
    342     case FRV_OPERAND_LDANN :
    343       print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
    344       break;
    345     case FRV_OPERAND_LDDANN :
    346       print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
    347       break;
    348     case FRV_OPERAND_LOCK :
    349       print_normal (cd, info, fields->f_lock, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    350       break;
    351     case FRV_OPERAND_PACK :
    352       print_keyword (cd, info, & frv_cgen_opval_h_pack, fields->f_pack, 0);
    353       break;
    354     case FRV_OPERAND_S10 :
    355       print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    356       break;
    357     case FRV_OPERAND_S12 :
    358       print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    359       break;
    360     case FRV_OPERAND_S16 :
    361       print_normal (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    362       break;
    363     case FRV_OPERAND_S5 :
    364       print_normal (cd, info, fields->f_s5, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    365       break;
    366     case FRV_OPERAND_S6 :
    367       print_normal (cd, info, fields->f_s6, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    368       break;
    369     case FRV_OPERAND_S6_1 :
    370       print_normal (cd, info, fields->f_s6_1, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    371       break;
    372     case FRV_OPERAND_SLO16 :
    373       print_lo (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
    374       break;
    375     case FRV_OPERAND_SPR :
    376       print_spr (cd, info, & frv_cgen_opval_spr_names, fields->f_spr, 0|(1<<CGEN_OPERAND_VIRTUAL));
    377       break;
    378     case FRV_OPERAND_U12 :
    379       print_normal (cd, info, fields->f_u12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
    380       break;
    381     case FRV_OPERAND_U16 :
    382       print_normal (cd, info, fields->f_u16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    383       break;
    384     case FRV_OPERAND_U6 :
    385       print_normal (cd, info, fields->f_u6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
    386       break;
    387     case FRV_OPERAND_UHI16 :
    388       print_hi (cd, info, fields->f_u16, 0, pc, length);
    389       break;
    390     case FRV_OPERAND_ULO16 :
    391       print_lo (cd, info, fields->f_u16, 0, pc, length);
    392       break;
    393 
    394     default :
    395       /* xgettext:c-format */
    396       fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
    397 	       opindex);
    398     abort ();
    399   }
    400 }
    401 
    402 cgen_print_fn * const frv_cgen_print_handlers[] =
    403 {
    404   print_insn_normal,
    405 };
    406 
    407 
    408 void
    409 frv_cgen_init_dis (CGEN_CPU_DESC cd)
    410 {
    411   frv_cgen_init_opcode_table (cd);
    412   frv_cgen_init_ibld_table (cd);
    413   cd->print_handlers = & frv_cgen_print_handlers[0];
    414   cd->print_operand = frv_cgen_print_operand;
    415 }
    416 
    417 
    418 /* Default print handler.  */
    420 
    421 static void
    422 print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    423 	      void *dis_info,
    424 	      long value,
    425 	      unsigned int attrs,
    426 	      bfd_vma pc ATTRIBUTE_UNUSED,
    427 	      int length ATTRIBUTE_UNUSED)
    428 {
    429   disassemble_info *info = (disassemble_info *) dis_info;
    430 
    431   /* Print the operand as directed by the attributes.  */
    432   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
    433     ; /* nothing to do */
    434   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
    435     (*info->fprintf_func) (info->stream, "%ld", value);
    436   else
    437     (*info->fprintf_func) (info->stream, "0x%lx", value);
    438 }
    439 
    440 /* Default address handler.  */
    441 
    442 static void
    443 print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    444 	       void *dis_info,
    445 	       bfd_vma value,
    446 	       unsigned int attrs,
    447 	       bfd_vma pc ATTRIBUTE_UNUSED,
    448 	       int length ATTRIBUTE_UNUSED)
    449 {
    450   disassemble_info *info = (disassemble_info *) dis_info;
    451 
    452   /* Print the operand as directed by the attributes.  */
    453   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
    454     ; /* Nothing to do.  */
    455   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
    456     (*info->print_address_func) (value, info);
    457   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
    458     (*info->print_address_func) (value, info);
    459   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
    460     (*info->fprintf_func) (info->stream, "%ld", (long) value);
    461   else
    462     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
    463 }
    464 
    465 /* Keyword print handler.  */
    466 
    467 static void
    468 print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    469 	       void *dis_info,
    470 	       CGEN_KEYWORD *keyword_table,
    471 	       long value,
    472 	       unsigned int attrs ATTRIBUTE_UNUSED)
    473 {
    474   disassemble_info *info = (disassemble_info *) dis_info;
    475   const CGEN_KEYWORD_ENTRY *ke;
    476 
    477   ke = cgen_keyword_lookup_value (keyword_table, value);
    478   if (ke != NULL)
    479     (*info->fprintf_func) (info->stream, "%s", ke->name);
    480   else
    481     (*info->fprintf_func) (info->stream, "???");
    482 }
    483 
    484 /* Default insn printer.
    486 
    487    DIS_INFO is defined as `void *' so the disassembler needn't know anything
    488    about disassemble_info.  */
    489 
    490 static void
    491 print_insn_normal (CGEN_CPU_DESC cd,
    492 		   void *dis_info,
    493 		   const CGEN_INSN *insn,
    494 		   CGEN_FIELDS *fields,
    495 		   bfd_vma pc,
    496 		   int length)
    497 {
    498   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
    499   disassemble_info *info = (disassemble_info *) dis_info;
    500   const CGEN_SYNTAX_CHAR_TYPE *syn;
    501 
    502   CGEN_INIT_PRINT (cd);
    503 
    504   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
    505     {
    506       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
    507 	{
    508 	  (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
    509 	  continue;
    510 	}
    511       if (CGEN_SYNTAX_CHAR_P (*syn))
    512 	{
    513 	  (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
    514 	  continue;
    515 	}
    516 
    517       /* We have an operand.  */
    518       frv_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
    519 				 fields, CGEN_INSN_ATTRS (insn), pc, length);
    520     }
    521 }
    522 
    523 /* Subroutine of print_insn. Reads an insn into the given buffers and updates
    525    the extract info.
    526    Returns 0 if all is well, non-zero otherwise.  */
    527 
    528 static int
    529 read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
    530 	   bfd_vma pc,
    531 	   disassemble_info *info,
    532 	   bfd_byte *buf,
    533 	   int buflen,
    534 	   CGEN_EXTRACT_INFO *ex_info,
    535 	   unsigned long *insn_value)
    536 {
    537   int status = (*info->read_memory_func) (pc, buf, buflen, info);
    538 
    539   if (status != 0)
    540     {
    541       (*info->memory_error_func) (status, pc, info);
    542       return -1;
    543     }
    544 
    545   ex_info->dis_info = info;
    546   ex_info->valid = (1 << buflen) - 1;
    547   ex_info->insn_bytes = buf;
    548 
    549   *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
    550   return 0;
    551 }
    552 
    553 /* Utility to print an insn.
    554    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
    555    The result is the size of the insn in bytes or zero for an unknown insn
    556    or -1 if an error occurs fetching data (memory_error_func will have
    557    been called).  */
    558 
    559 static int
    560 print_insn (CGEN_CPU_DESC cd,
    561 	    bfd_vma pc,
    562 	    disassemble_info *info,
    563 	    bfd_byte *buf,
    564 	    unsigned int buflen)
    565 {
    566   CGEN_INSN_INT insn_value;
    567   const CGEN_INSN_LIST *insn_list;
    568   CGEN_EXTRACT_INFO ex_info;
    569   int basesize;
    570 
    571   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
    572   basesize = cd->base_insn_bitsize < buflen * 8 ?
    573                                      cd->base_insn_bitsize : buflen * 8;
    574   insn_value = cgen_get_insn_value (cd, buf, basesize);
    575 
    576 
    577   /* Fill in ex_info fields like read_insn would.  Don't actually call
    578      read_insn, since the incoming buffer is already read (and possibly
    579      modified a la m32r).  */
    580   ex_info.valid = (1 << buflen) - 1;
    581   ex_info.dis_info = info;
    582   ex_info.insn_bytes = buf;
    583 
    584   /* The instructions are stored in hash lists.
    585      Pick the first one and keep trying until we find the right one.  */
    586 
    587   insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
    588   while (insn_list != NULL)
    589     {
    590       const CGEN_INSN *insn = insn_list->insn;
    591       CGEN_FIELDS fields;
    592       int length;
    593       unsigned long insn_value_cropped;
    594 
    595 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
    596       /* Not needed as insn shouldn't be in hash lists if not supported.  */
    597       /* Supported by this cpu?  */
    598       if (! frv_cgen_insn_supported (cd, insn))
    599         {
    600           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
    601 	  continue;
    602         }
    603 #endif
    604 
    605       /* Basic bit mask must be correct.  */
    606       /* ??? May wish to allow target to defer this check until the extract
    607 	 handler.  */
    608 
    609       /* Base size may exceed this instruction's size.  Extract the
    610          relevant part from the buffer. */
    611       if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
    612 	  (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
    613 	insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
    614 					   info->endian == BFD_ENDIAN_BIG);
    615       else
    616 	insn_value_cropped = insn_value;
    617 
    618       if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
    619 	  == CGEN_INSN_BASE_VALUE (insn))
    620 	{
    621 	  /* Printing is handled in two passes.  The first pass parses the
    622 	     machine insn and extracts the fields.  The second pass prints
    623 	     them.  */
    624 
    625 	  /* Make sure the entire insn is loaded into insn_value, if it
    626 	     can fit.  */
    627 	  if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
    628 	      (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
    629 	    {
    630 	      unsigned long full_insn_value;
    631 	      int rc = read_insn (cd, pc, info, buf,
    632 				  CGEN_INSN_BITSIZE (insn) / 8,
    633 				  & ex_info, & full_insn_value);
    634 	      if (rc != 0)
    635 		return rc;
    636 	      length = CGEN_EXTRACT_FN (cd, insn)
    637 		(cd, insn, &ex_info, full_insn_value, &fields, pc);
    638 	    }
    639 	  else
    640 	    length = CGEN_EXTRACT_FN (cd, insn)
    641 	      (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
    642 
    643 	  /* Length < 0 -> error.  */
    644 	  if (length < 0)
    645 	    return length;
    646 	  if (length > 0)
    647 	    {
    648 	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
    649 	      /* Length is in bits, result is in bytes.  */
    650 	      return length / 8;
    651 	    }
    652 	}
    653 
    654       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
    655     }
    656 
    657   return 0;
    658 }
    659 
    660 /* Default value for CGEN_PRINT_INSN.
    661    The result is the size of the insn in bytes or zero for an unknown insn
    662    or -1 if an error occured fetching bytes.  */
    663 
    664 #ifndef CGEN_PRINT_INSN
    665 #define CGEN_PRINT_INSN default_print_insn
    666 #endif
    667 
    668 static int
    669 default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
    670 {
    671   bfd_byte buf[CGEN_MAX_INSN_SIZE];
    672   int buflen;
    673   int status;
    674 
    675   /* Attempt to read the base part of the insn.  */
    676   buflen = cd->base_insn_bitsize / 8;
    677   status = (*info->read_memory_func) (pc, buf, buflen, info);
    678 
    679   /* Try again with the minimum part, if min < base.  */
    680   if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
    681     {
    682       buflen = cd->min_insn_bitsize / 8;
    683       status = (*info->read_memory_func) (pc, buf, buflen, info);
    684     }
    685 
    686   if (status != 0)
    687     {
    688       (*info->memory_error_func) (status, pc, info);
    689       return -1;
    690     }
    691 
    692   return print_insn (cd, pc, info, buf, buflen);
    693 }
    694 
    695 /* Main entry point.
    696    Print one instruction from PC on INFO->STREAM.
    697    Return the size of the instruction (in bytes).  */
    698 
    699 typedef struct cpu_desc_list
    700 {
    701   struct cpu_desc_list *next;
    702   CGEN_BITSET *isa;
    703   int mach;
    704   int endian;
    705   CGEN_CPU_DESC cd;
    706 } cpu_desc_list;
    707 
    708 int
    709 print_insn_frv (bfd_vma pc, disassemble_info *info)
    710 {
    711   static cpu_desc_list *cd_list = 0;
    712   cpu_desc_list *cl = 0;
    713   static CGEN_CPU_DESC cd = 0;
    714   static CGEN_BITSET *prev_isa;
    715   static int prev_mach;
    716   static int prev_endian;
    717   int length;
    718   CGEN_BITSET *isa;
    719   int mach;
    720   int endian = (info->endian == BFD_ENDIAN_BIG
    721 		? CGEN_ENDIAN_BIG
    722 		: CGEN_ENDIAN_LITTLE);
    723   enum bfd_architecture arch;
    724 
    725   /* ??? gdb will set mach but leave the architecture as "unknown" */
    726 #ifndef CGEN_BFD_ARCH
    727 #define CGEN_BFD_ARCH bfd_arch_frv
    728 #endif
    729   arch = info->arch;
    730   if (arch == bfd_arch_unknown)
    731     arch = CGEN_BFD_ARCH;
    732 
    733   /* There's no standard way to compute the machine or isa number
    734      so we leave it to the target.  */
    735 #ifdef CGEN_COMPUTE_MACH
    736   mach = CGEN_COMPUTE_MACH (info);
    737 #else
    738   mach = info->mach;
    739 #endif
    740 
    741 #ifdef CGEN_COMPUTE_ISA
    742   {
    743     static CGEN_BITSET *permanent_isa;
    744 
    745     if (!permanent_isa)
    746       permanent_isa = cgen_bitset_create (MAX_ISAS);
    747     isa = permanent_isa;
    748     cgen_bitset_clear (isa);
    749     cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
    750   }
    751 #else
    752   isa = info->insn_sets;
    753 #endif
    754 
    755   /* If we've switched cpu's, try to find a handle we've used before */
    756   if (cd
    757       && (cgen_bitset_compare (isa, prev_isa) != 0
    758 	  || mach != prev_mach
    759 	  || endian != prev_endian))
    760     {
    761       cd = 0;
    762       for (cl = cd_list; cl; cl = cl->next)
    763 	{
    764 	  if (cgen_bitset_compare (cl->isa, isa) == 0 &&
    765 	      cl->mach == mach &&
    766 	      cl->endian == endian)
    767 	    {
    768 	      cd = cl->cd;
    769  	      prev_isa = cd->isas;
    770 	      break;
    771 	    }
    772 	}
    773     }
    774 
    775   /* If we haven't initialized yet, initialize the opcode table.  */
    776   if (! cd)
    777     {
    778       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
    779       const char *mach_name;
    780 
    781       if (!arch_type)
    782 	abort ();
    783       mach_name = arch_type->printable_name;
    784 
    785       prev_isa = cgen_bitset_copy (isa);
    786       prev_mach = mach;
    787       prev_endian = endian;
    788       cd = frv_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
    789 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
    790 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
    791 				 CGEN_CPU_OPEN_END);
    792       if (!cd)
    793 	abort ();
    794 
    795       /* Save this away for future reference.  */
    796       cl = xmalloc (sizeof (struct cpu_desc_list));
    797       cl->cd = cd;
    798       cl->isa = prev_isa;
    799       cl->mach = mach;
    800       cl->endian = endian;
    801       cl->next = cd_list;
    802       cd_list = cl;
    803 
    804       frv_cgen_init_dis (cd);
    805     }
    806 
    807   /* We try to have as much common code as possible.
    808      But at this point some targets need to take over.  */
    809   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
    810      but if not possible try to move this hook elsewhere rather than
    811      have two hooks.  */
    812   length = CGEN_PRINT_INSN (cd, pc, info);
    813   if (length > 0)
    814     return length;
    815   if (length < 0)
    816     return -1;
    817 
    818   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
    819   return cd->default_insn_bitsize / 8;
    820 }
    821