1fddef416Sniklas /* Disassembler interface for targets using CGEN. -*- C -*- 2fddef416Sniklas CGEN: Cpu tools GENerator 3fddef416Sniklas 4*f7cc78ecSespie THIS FILE IS MACHINE GENERATED WITH CGEN. 5*f7cc78ecSespie - the resultant file is machine generated, cgen-dis.in isn't 6fddef416Sniklas 7*f7cc78ecSespie Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. 8fddef416Sniklas 9fddef416Sniklas This file is part of the GNU Binutils and GDB, the GNU debugger. 10fddef416Sniklas 11fddef416Sniklas This program is free software; you can redistribute it and/or modify 12fddef416Sniklas it under the terms of the GNU General Public License as published by 13fddef416Sniklas the Free Software Foundation; either version 2, or (at your option) 14fddef416Sniklas any later version. 15fddef416Sniklas 16fddef416Sniklas This program is distributed in the hope that it will be useful, 17fddef416Sniklas but WITHOUT ANY WARRANTY; without even the implied warranty of 18fddef416Sniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19fddef416Sniklas GNU General Public License for more details. 20fddef416Sniklas 21fddef416Sniklas You should have received a copy of the GNU General Public License 22*f7cc78ecSespie along with this program; if not, write to the Free Software Foundation, Inc., 23*f7cc78ecSespie 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 24*f7cc78ecSespie 25*f7cc78ecSespie /* ??? Eventually more and more of this stuff can go to cpu-independent files. 26*f7cc78ecSespie Keep that in mind. */ 27fddef416Sniklas 28fddef416Sniklas #include "sysdep.h" 29fddef416Sniklas #include <stdio.h> 30fddef416Sniklas #include "ansidecl.h" 31fddef416Sniklas #include "dis-asm.h" 32fddef416Sniklas #include "bfd.h" 33*f7cc78ecSespie #include "symcat.h" 34*f7cc78ecSespie #include "m32r-desc.h" 35*f7cc78ecSespie #include "m32r-opc.h" 36*f7cc78ecSespie #include "opintl.h" 37fddef416Sniklas 38fddef416Sniklas /* Default text to print if an instruction isn't recognized. */ 39*f7cc78ecSespie #define UNKNOWN_INSN_MSG _("*unknown*") 40fddef416Sniklas 41*f7cc78ecSespie static void print_normal 42*f7cc78ecSespie PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int)); 43*f7cc78ecSespie static void print_address 44*f7cc78ecSespie PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int)); 45*f7cc78ecSespie static void print_keyword 46*f7cc78ecSespie PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int)); 47fddef416Sniklas static void print_insn_normal 48*f7cc78ecSespie PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *, 49*f7cc78ecSespie bfd_vma, int)); 50*f7cc78ecSespie static int print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma, 51*f7cc78ecSespie disassemble_info *, char *, int)); 52*f7cc78ecSespie static int default_print_insn 53*f7cc78ecSespie PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *)); 54fddef416Sniklas 55fddef416Sniklas /* -- disassembler routines inserted here */ 56*f7cc78ecSespie 57fddef416Sniklas /* -- dis.c */ 58fddef416Sniklas 59*f7cc78ecSespie /* Immediate values are prefixed with '#'. */ 60*f7cc78ecSespie 61*f7cc78ecSespie #define CGEN_PRINT_NORMAL(cd, info, value, attrs, pc, length) \ 62*f7cc78ecSespie do { \ 63*f7cc78ecSespie if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_HASH_PREFIX)) \ 64*f7cc78ecSespie (*info->fprintf_func) (info->stream, "#"); \ 65*f7cc78ecSespie } while (0) 66*f7cc78ecSespie 67*f7cc78ecSespie /* Handle '#' prefixes as operands. */ 68*f7cc78ecSespie 69*f7cc78ecSespie static void 70*f7cc78ecSespie print_hash (cd, dis_info, value, attrs, pc, length) 71*f7cc78ecSespie CGEN_CPU_DESC cd; 72*f7cc78ecSespie PTR dis_info; 73*f7cc78ecSespie long value; 74*f7cc78ecSespie unsigned int attrs; 75*f7cc78ecSespie bfd_vma pc; 76*f7cc78ecSespie int length; 77*f7cc78ecSespie { 78*f7cc78ecSespie disassemble_info *info = (disassemble_info *) dis_info; 79*f7cc78ecSespie (*info->fprintf_func) (info->stream, "#"); 80*f7cc78ecSespie } 81*f7cc78ecSespie 82fddef416Sniklas #undef CGEN_PRINT_INSN 83fddef416Sniklas #define CGEN_PRINT_INSN my_print_insn 84fddef416Sniklas 85fddef416Sniklas static int 86*f7cc78ecSespie my_print_insn (cd, pc, info) 87*f7cc78ecSespie CGEN_CPU_DESC cd; 88fddef416Sniklas bfd_vma pc; 89fddef416Sniklas disassemble_info *info; 90fddef416Sniklas { 91*f7cc78ecSespie char buffer[CGEN_MAX_INSN_SIZE]; 92*f7cc78ecSespie char *buf = buffer; 93*f7cc78ecSespie int status; 94*f7cc78ecSespie int buflen = (pc & 3) == 0 ? 4 : 2; 95*f7cc78ecSespie 96*f7cc78ecSespie /* Read the base part of the insn. */ 97*f7cc78ecSespie 98*f7cc78ecSespie status = (*info->read_memory_func) (pc, buf, buflen, info); 99*f7cc78ecSespie if (status != 0) 100*f7cc78ecSespie { 101*f7cc78ecSespie (*info->memory_error_func) (status, pc, info); 102*f7cc78ecSespie return -1; 103*f7cc78ecSespie } 104fddef416Sniklas 105fddef416Sniklas /* 32 bit insn? */ 106fddef416Sniklas if ((pc & 3) == 0 && (buf[0] & 0x80) != 0) 107*f7cc78ecSespie return print_insn (cd, pc, info, buf, buflen); 108fddef416Sniklas 109fddef416Sniklas /* Print the first insn. */ 110fddef416Sniklas if ((pc & 3) == 0) 111fddef416Sniklas { 112*f7cc78ecSespie if (print_insn (cd, pc, info, buf, 2) == 0) 113fddef416Sniklas (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 114fddef416Sniklas buf += 2; 115fddef416Sniklas } 116fddef416Sniklas 117fddef416Sniklas if (buf[0] & 0x80) 118fddef416Sniklas { 119fddef416Sniklas /* Parallel. */ 120fddef416Sniklas (*info->fprintf_func) (info->stream, " || "); 121fddef416Sniklas buf[0] &= 0x7f; 122fddef416Sniklas } 123fddef416Sniklas else 124fddef416Sniklas (*info->fprintf_func) (info->stream, " -> "); 125fddef416Sniklas 126*f7cc78ecSespie /* The "& 3" is to pass a consistent address. 127*f7cc78ecSespie Parallel insns arguably both begin on the word boundary. 128*f7cc78ecSespie Also, branch insns are calculated relative to the word boundary. */ 129*f7cc78ecSespie if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0) 130fddef416Sniklas (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 131fddef416Sniklas 132fddef416Sniklas return (pc & 3) ? 2 : 4; 133fddef416Sniklas } 134fddef416Sniklas 135fddef416Sniklas /* -- */ 136fddef416Sniklas 137fddef416Sniklas /* Main entry point for printing operands. 138*f7cc78ecSespie XINFO is a `void *' and not a `disassemble_info *' to not put a requirement 139*f7cc78ecSespie of dis-asm.h on cgen.h. 140fddef416Sniklas 141fddef416Sniklas This function is basically just a big switch statement. Earlier versions 142fddef416Sniklas used tables to look up the function to use, but 143fddef416Sniklas - if the table contains both assembler and disassembler functions then 144fddef416Sniklas the disassembler contains much of the assembler and vice-versa, 145fddef416Sniklas - there's a lot of inlining possibilities as things grow, 146fddef416Sniklas - using a switch statement avoids the function call overhead. 147fddef416Sniklas 148fddef416Sniklas This function could be moved into `print_insn_normal', but keeping it 149fddef416Sniklas separate makes clear the interface between `print_insn_normal' and each of 150fddef416Sniklas the handlers. 151fddef416Sniklas */ 152fddef416Sniklas 153*f7cc78ecSespie void 154*f7cc78ecSespie m32r_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length) 155*f7cc78ecSespie CGEN_CPU_DESC cd; 156fddef416Sniklas int opindex; 157*f7cc78ecSespie PTR xinfo; 158*f7cc78ecSespie CGEN_FIELDS *fields; 159*f7cc78ecSespie void const *attrs; 160fddef416Sniklas bfd_vma pc; 161fddef416Sniklas int length; 162fddef416Sniklas { 163*f7cc78ecSespie disassemble_info *info = (disassemble_info *) xinfo; 164*f7cc78ecSespie 165fddef416Sniklas switch (opindex) 166fddef416Sniklas { 167*f7cc78ecSespie case M32R_OPERAND_ACC : 168*f7cc78ecSespie print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_acc, 0); 169fddef416Sniklas break; 170*f7cc78ecSespie case M32R_OPERAND_ACCD : 171*f7cc78ecSespie print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accd, 0); 172fddef416Sniklas break; 173*f7cc78ecSespie case M32R_OPERAND_ACCS : 174*f7cc78ecSespie print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accs, 0); 175fddef416Sniklas break; 176*f7cc78ecSespie case M32R_OPERAND_DCR : 177*f7cc78ecSespie print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r1, 0); 178fddef416Sniklas break; 179*f7cc78ecSespie case M32R_OPERAND_DISP16 : 180*f7cc78ecSespie print_address (cd, info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); 181fddef416Sniklas break; 182*f7cc78ecSespie case M32R_OPERAND_DISP24 : 183*f7cc78ecSespie print_address (cd, info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); 184fddef416Sniklas break; 185*f7cc78ecSespie case M32R_OPERAND_DISP8 : 186*f7cc78ecSespie print_address (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); 187fddef416Sniklas break; 188*f7cc78ecSespie case M32R_OPERAND_DR : 189*f7cc78ecSespie print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0); 190fddef416Sniklas break; 191*f7cc78ecSespie case M32R_OPERAND_HASH : 192*f7cc78ecSespie print_hash (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 193fddef416Sniklas break; 194*f7cc78ecSespie case M32R_OPERAND_HI16 : 195*f7cc78ecSespie print_normal (cd, info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT), pc, length); 196fddef416Sniklas break; 197*f7cc78ecSespie case M32R_OPERAND_IMM1 : 198*f7cc78ecSespie print_normal (cd, info, fields->f_imm1, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length); 199fddef416Sniklas break; 200*f7cc78ecSespie case M32R_OPERAND_SCR : 201*f7cc78ecSespie print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r2, 0); 202fddef416Sniklas break; 203*f7cc78ecSespie case M32R_OPERAND_SIMM16 : 204*f7cc78ecSespie print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length); 205fddef416Sniklas break; 206*f7cc78ecSespie case M32R_OPERAND_SIMM8 : 207*f7cc78ecSespie print_normal (cd, info, fields->f_simm8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length); 208fddef416Sniklas break; 209*f7cc78ecSespie case M32R_OPERAND_SLO16 : 210*f7cc78ecSespie print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 211fddef416Sniklas break; 212*f7cc78ecSespie case M32R_OPERAND_SR : 213*f7cc78ecSespie print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0); 214fddef416Sniklas break; 215*f7cc78ecSespie case M32R_OPERAND_SRC1 : 216*f7cc78ecSespie print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0); 217fddef416Sniklas break; 218*f7cc78ecSespie case M32R_OPERAND_SRC2 : 219*f7cc78ecSespie print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0); 220*f7cc78ecSespie break; 221*f7cc78ecSespie case M32R_OPERAND_UIMM16 : 222*f7cc78ecSespie print_normal (cd, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length); 223*f7cc78ecSespie break; 224*f7cc78ecSespie case M32R_OPERAND_UIMM24 : 225*f7cc78ecSespie print_address (cd, info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length); 226*f7cc78ecSespie break; 227*f7cc78ecSespie case M32R_OPERAND_UIMM4 : 228*f7cc78ecSespie print_normal (cd, info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length); 229*f7cc78ecSespie break; 230*f7cc78ecSespie case M32R_OPERAND_UIMM5 : 231*f7cc78ecSespie print_normal (cd, info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length); 232*f7cc78ecSespie break; 233*f7cc78ecSespie case M32R_OPERAND_ULO16 : 234*f7cc78ecSespie print_normal (cd, info, fields->f_uimm16, 0, pc, length); 235fddef416Sniklas break; 236fddef416Sniklas 237fddef416Sniklas default : 238*f7cc78ecSespie /* xgettext:c-format */ 239*f7cc78ecSespie fprintf (stderr, _("Unrecognized field %d while printing insn.\n"), 240fddef416Sniklas opindex); 241fddef416Sniklas abort (); 242fddef416Sniklas } 243fddef416Sniklas } 244fddef416Sniklas 245*f7cc78ecSespie cgen_print_fn * const m32r_cgen_print_handlers[] = 246*f7cc78ecSespie { 247fddef416Sniklas print_insn_normal, 248fddef416Sniklas }; 249fddef416Sniklas 250fddef416Sniklas 251fddef416Sniklas void 252*f7cc78ecSespie m32r_cgen_init_dis (cd) 253*f7cc78ecSespie CGEN_CPU_DESC cd; 254fddef416Sniklas { 255*f7cc78ecSespie m32r_cgen_init_opcode_table (cd); 256*f7cc78ecSespie m32r_cgen_init_ibld_table (cd); 257*f7cc78ecSespie cd->print_handlers = & m32r_cgen_print_handlers[0]; 258*f7cc78ecSespie cd->print_operand = m32r_cgen_print_operand; 259fddef416Sniklas } 260fddef416Sniklas 261fddef416Sniklas 262*f7cc78ecSespie /* Default print handler. */ 263fddef416Sniklas 264fddef416Sniklas static void 265*f7cc78ecSespie print_normal (cd, dis_info, value, attrs, pc, length) 266*f7cc78ecSespie CGEN_CPU_DESC cd; 267*f7cc78ecSespie PTR dis_info; 268*f7cc78ecSespie long value; 269*f7cc78ecSespie unsigned int attrs; 270fddef416Sniklas bfd_vma pc; 271fddef416Sniklas int length; 272fddef416Sniklas { 273*f7cc78ecSespie disassemble_info *info = (disassemble_info *) dis_info; 274*f7cc78ecSespie 275*f7cc78ecSespie #ifdef CGEN_PRINT_NORMAL 276*f7cc78ecSespie CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length); 277*f7cc78ecSespie #endif 278*f7cc78ecSespie 279*f7cc78ecSespie /* Print the operand as directed by the attributes. */ 280*f7cc78ecSespie if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY)) 281*f7cc78ecSespie ; /* nothing to do */ 282*f7cc78ecSespie else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED)) 283*f7cc78ecSespie (*info->fprintf_func) (info->stream, "%ld", value); 284*f7cc78ecSespie else 285*f7cc78ecSespie (*info->fprintf_func) (info->stream, "0x%lx", value); 286*f7cc78ecSespie } 287*f7cc78ecSespie 288*f7cc78ecSespie /* Default address handler. */ 289*f7cc78ecSespie 290*f7cc78ecSespie static void 291*f7cc78ecSespie print_address (cd, dis_info, value, attrs, pc, length) 292*f7cc78ecSespie CGEN_CPU_DESC cd; 293*f7cc78ecSespie PTR dis_info; 294*f7cc78ecSespie bfd_vma value; 295*f7cc78ecSespie unsigned int attrs; 296*f7cc78ecSespie bfd_vma pc; 297*f7cc78ecSespie int length; 298*f7cc78ecSespie { 299*f7cc78ecSespie disassemble_info *info = (disassemble_info *) dis_info; 300*f7cc78ecSespie 301*f7cc78ecSespie #ifdef CGEN_PRINT_ADDRESS 302*f7cc78ecSespie CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length); 303*f7cc78ecSespie #endif 304*f7cc78ecSespie 305*f7cc78ecSespie /* Print the operand as directed by the attributes. */ 306*f7cc78ecSespie if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY)) 307*f7cc78ecSespie ; /* nothing to do */ 308*f7cc78ecSespie else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR)) 309*f7cc78ecSespie (*info->print_address_func) (value, info); 310*f7cc78ecSespie else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR)) 311*f7cc78ecSespie (*info->print_address_func) (value, info); 312*f7cc78ecSespie else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED)) 313*f7cc78ecSespie (*info->fprintf_func) (info->stream, "%ld", (long) value); 314*f7cc78ecSespie else 315*f7cc78ecSespie (*info->fprintf_func) (info->stream, "0x%lx", (long) value); 316*f7cc78ecSespie } 317*f7cc78ecSespie 318*f7cc78ecSespie /* Keyword print handler. */ 319*f7cc78ecSespie 320*f7cc78ecSespie static void 321*f7cc78ecSespie print_keyword (cd, dis_info, keyword_table, value, attrs) 322*f7cc78ecSespie CGEN_CPU_DESC cd; 323*f7cc78ecSespie PTR dis_info; 324*f7cc78ecSespie CGEN_KEYWORD *keyword_table; 325*f7cc78ecSespie long value; 326*f7cc78ecSespie unsigned int attrs; 327*f7cc78ecSespie { 328*f7cc78ecSespie disassemble_info *info = (disassemble_info *) dis_info; 329*f7cc78ecSespie const CGEN_KEYWORD_ENTRY *ke; 330*f7cc78ecSespie 331*f7cc78ecSespie ke = cgen_keyword_lookup_value (keyword_table, value); 332*f7cc78ecSespie if (ke != NULL) 333*f7cc78ecSespie (*info->fprintf_func) (info->stream, "%s", ke->name); 334*f7cc78ecSespie else 335*f7cc78ecSespie (*info->fprintf_func) (info->stream, "???"); 336*f7cc78ecSespie } 337*f7cc78ecSespie 338*f7cc78ecSespie /* Default insn printer. 339*f7cc78ecSespie 340*f7cc78ecSespie DIS_INFO is defined as `PTR' so the disassembler needn't know anything 341*f7cc78ecSespie about disassemble_info. */ 342*f7cc78ecSespie 343*f7cc78ecSespie static void 344*f7cc78ecSespie print_insn_normal (cd, dis_info, insn, fields, pc, length) 345*f7cc78ecSespie CGEN_CPU_DESC cd; 346*f7cc78ecSespie PTR dis_info; 347*f7cc78ecSespie const CGEN_INSN *insn; 348*f7cc78ecSespie CGEN_FIELDS *fields; 349*f7cc78ecSespie bfd_vma pc; 350*f7cc78ecSespie int length; 351*f7cc78ecSespie { 352*f7cc78ecSespie const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 353*f7cc78ecSespie disassemble_info *info = (disassemble_info *) dis_info; 354fddef416Sniklas const unsigned char *syn; 355fddef416Sniklas 356*f7cc78ecSespie CGEN_INIT_PRINT (cd); 357fddef416Sniklas 358*f7cc78ecSespie for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn) 359fddef416Sniklas { 360*f7cc78ecSespie if (CGEN_SYNTAX_MNEMONIC_P (*syn)) 361*f7cc78ecSespie { 362*f7cc78ecSespie (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn)); 363*f7cc78ecSespie continue; 364*f7cc78ecSespie } 365fddef416Sniklas if (CGEN_SYNTAX_CHAR_P (*syn)) 366fddef416Sniklas { 367fddef416Sniklas (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn)); 368fddef416Sniklas continue; 369fddef416Sniklas } 370fddef416Sniklas 371fddef416Sniklas /* We have an operand. */ 372*f7cc78ecSespie m32r_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info, 373fddef416Sniklas fields, CGEN_INSN_ATTRS (insn), pc, length); 374fddef416Sniklas } 375fddef416Sniklas } 376fddef416Sniklas 377*f7cc78ecSespie /* Utility to print an insn. 378*f7cc78ecSespie BUF is the base part of the insn, target byte order, BUFLEN bytes long. 379*f7cc78ecSespie The result is the size of the insn in bytes or zero for an unknown insn 380*f7cc78ecSespie or -1 if an error occurs fetching data (memory_error_func will have 381*f7cc78ecSespie been called). */ 382fddef416Sniklas 383fddef416Sniklas static int 384*f7cc78ecSespie print_insn (cd, pc, info, buf, buflen) 385*f7cc78ecSespie CGEN_CPU_DESC cd; 386fddef416Sniklas bfd_vma pc; 387fddef416Sniklas disassemble_info *info; 388fddef416Sniklas char *buf; 389fddef416Sniklas int buflen; 390fddef416Sniklas { 391fddef416Sniklas unsigned long insn_value; 392fddef416Sniklas const CGEN_INSN_LIST *insn_list; 393*f7cc78ecSespie CGEN_EXTRACT_INFO ex_info; 394*f7cc78ecSespie 395*f7cc78ecSespie ex_info.dis_info = info; 396*f7cc78ecSespie ex_info.valid = (1 << (cd->base_insn_bitsize / 8)) - 1; 397*f7cc78ecSespie ex_info.insn_bytes = buf; 398fddef416Sniklas 399fddef416Sniklas switch (buflen) 400fddef416Sniklas { 401*f7cc78ecSespie case 1: 402fddef416Sniklas insn_value = buf[0]; 403fddef416Sniklas break; 404*f7cc78ecSespie case 2: 405fddef416Sniklas insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf); 406fddef416Sniklas break; 407*f7cc78ecSespie case 4: 408fddef416Sniklas insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf); 409fddef416Sniklas break; 410fddef416Sniklas default: 411fddef416Sniklas abort (); 412fddef416Sniklas } 413fddef416Sniklas 414fddef416Sniklas /* The instructions are stored in hash lists. 415fddef416Sniklas Pick the first one and keep trying until we find the right one. */ 416fddef416Sniklas 417*f7cc78ecSespie insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value); 418fddef416Sniklas while (insn_list != NULL) 419fddef416Sniklas { 420fddef416Sniklas const CGEN_INSN *insn = insn_list->insn; 421*f7cc78ecSespie CGEN_FIELDS fields; 422fddef416Sniklas int length; 423fddef416Sniklas 424*f7cc78ecSespie #ifdef CGEN_VALIDATE_INSN_SUPPORTED 425*f7cc78ecSespie /* not needed as insn shouldn't be in hash lists if not supported */ 426fddef416Sniklas /* Supported by this cpu? */ 427*f7cc78ecSespie if (! m32r_cgen_insn_supported (cd, insn)) 428*f7cc78ecSespie { 429*f7cc78ecSespie insn_list = CGEN_DIS_NEXT_INSN (insn_list); 430fddef416Sniklas continue; 431*f7cc78ecSespie } 432fddef416Sniklas #endif 433fddef416Sniklas 434fddef416Sniklas /* Basic bit mask must be correct. */ 435fddef416Sniklas /* ??? May wish to allow target to defer this check until the extract 436fddef416Sniklas handler. */ 437*f7cc78ecSespie if ((insn_value & CGEN_INSN_BASE_MASK (insn)) 438*f7cc78ecSespie == CGEN_INSN_BASE_VALUE (insn)) 439fddef416Sniklas { 440fddef416Sniklas /* Printing is handled in two passes. The first pass parses the 441fddef416Sniklas machine insn and extracts the fields. The second pass prints 442fddef416Sniklas them. */ 443fddef416Sniklas 444*f7cc78ecSespie length = CGEN_EXTRACT_FN (cd, insn) 445*f7cc78ecSespie (cd, insn, &ex_info, insn_value, &fields, pc); 446*f7cc78ecSespie /* length < 0 -> error */ 447*f7cc78ecSespie if (length < 0) 448*f7cc78ecSespie return length; 449fddef416Sniklas if (length > 0) 450fddef416Sniklas { 451*f7cc78ecSespie CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length); 452fddef416Sniklas /* length is in bits, result is in bytes */ 453fddef416Sniklas return length / 8; 454fddef416Sniklas } 455fddef416Sniklas } 456fddef416Sniklas 457fddef416Sniklas insn_list = CGEN_DIS_NEXT_INSN (insn_list); 458fddef416Sniklas } 459fddef416Sniklas 460fddef416Sniklas return 0; 461fddef416Sniklas } 462fddef416Sniklas 463*f7cc78ecSespie /* Default value for CGEN_PRINT_INSN. 464*f7cc78ecSespie The result is the size of the insn in bytes or zero for an unknown insn 465*f7cc78ecSespie or -1 if an error occured fetching bytes. */ 466*f7cc78ecSespie 467*f7cc78ecSespie #ifndef CGEN_PRINT_INSN 468*f7cc78ecSespie #define CGEN_PRINT_INSN default_print_insn 469*f7cc78ecSespie #endif 470*f7cc78ecSespie 471*f7cc78ecSespie static int 472*f7cc78ecSespie default_print_insn (cd, pc, info) 473*f7cc78ecSespie CGEN_CPU_DESC cd; 474*f7cc78ecSespie bfd_vma pc; 475*f7cc78ecSespie disassemble_info *info; 476*f7cc78ecSespie { 477*f7cc78ecSespie char buf[CGEN_MAX_INSN_SIZE]; 478*f7cc78ecSespie int status; 479*f7cc78ecSespie 480*f7cc78ecSespie /* Read the base part of the insn. */ 481*f7cc78ecSespie 482*f7cc78ecSespie status = (*info->read_memory_func) (pc, buf, cd->base_insn_bitsize / 8, info); 483*f7cc78ecSespie if (status != 0) 484*f7cc78ecSespie { 485*f7cc78ecSespie (*info->memory_error_func) (status, pc, info); 486*f7cc78ecSespie return -1; 487*f7cc78ecSespie } 488*f7cc78ecSespie 489*f7cc78ecSespie return print_insn (cd, pc, info, buf, cd->base_insn_bitsize / 8); 490*f7cc78ecSespie } 491*f7cc78ecSespie 492fddef416Sniklas /* Main entry point. 493fddef416Sniklas Print one instruction from PC on INFO->STREAM. 494fddef416Sniklas Return the size of the instruction (in bytes). */ 495fddef416Sniklas 496fddef416Sniklas int 497fddef416Sniklas print_insn_m32r (pc, info) 498fddef416Sniklas bfd_vma pc; 499fddef416Sniklas disassemble_info *info; 500fddef416Sniklas { 501*f7cc78ecSespie static CGEN_CPU_DESC cd = 0; 502*f7cc78ecSespie static prev_isa,prev_mach,prev_endian; 503*f7cc78ecSespie int length; 504*f7cc78ecSespie int isa,mach; 505*f7cc78ecSespie int endian = (info->endian == BFD_ENDIAN_BIG 506*f7cc78ecSespie ? CGEN_ENDIAN_BIG 507*f7cc78ecSespie : CGEN_ENDIAN_LITTLE); 508*f7cc78ecSespie enum bfd_architecture arch; 509fddef416Sniklas 510*f7cc78ecSespie /* ??? gdb will set mach but leave the architecture as "unknown" */ 511*f7cc78ecSespie #ifndef CGEN_BFD_ARCH 512*f7cc78ecSespie #define CGEN_BFD_ARCH bfd_arch_m32r 513*f7cc78ecSespie #endif 514*f7cc78ecSespie arch = info->arch; 515*f7cc78ecSespie if (arch == bfd_arch_unknown) 516*f7cc78ecSespie arch = CGEN_BFD_ARCH; 517*f7cc78ecSespie 518*f7cc78ecSespie /* There's no standard way to compute the isa number (e.g. for arm thumb) 519*f7cc78ecSespie so we leave it to the target. */ 520*f7cc78ecSespie #ifdef CGEN_COMPUTE_ISA 521*f7cc78ecSespie isa = CGEN_COMPUTE_ISA (info); 522*f7cc78ecSespie #else 523*f7cc78ecSespie isa = 0; 524*f7cc78ecSespie #endif 525*f7cc78ecSespie 526*f7cc78ecSespie mach = info->mach; 527*f7cc78ecSespie 528*f7cc78ecSespie /* If we've switched cpu's, close the current table and open a new one. */ 529*f7cc78ecSespie if (cd 530*f7cc78ecSespie && (isa != prev_isa 531*f7cc78ecSespie || mach != prev_mach 532*f7cc78ecSespie || endian != prev_endian)) 533fddef416Sniklas { 534*f7cc78ecSespie m32r_cgen_cpu_close (cd); 535*f7cc78ecSespie cd = 0; 536fddef416Sniklas } 537fddef416Sniklas 538*f7cc78ecSespie /* If we haven't initialized yet, initialize the opcode table. */ 539*f7cc78ecSespie if (! cd) 540fddef416Sniklas { 541*f7cc78ecSespie const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach); 542*f7cc78ecSespie const char *mach_name; 543*f7cc78ecSespie 544*f7cc78ecSespie if (!arch_type) 545*f7cc78ecSespie abort (); 546*f7cc78ecSespie mach_name = arch_type->printable_name; 547*f7cc78ecSespie 548*f7cc78ecSespie prev_isa = isa; 549*f7cc78ecSespie prev_mach = mach; 550*f7cc78ecSespie prev_endian = endian; 551*f7cc78ecSespie cd = m32r_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa, 552*f7cc78ecSespie CGEN_CPU_OPEN_BFDMACH, mach_name, 553*f7cc78ecSespie CGEN_CPU_OPEN_ENDIAN, prev_endian, 554*f7cc78ecSespie CGEN_CPU_OPEN_END); 555*f7cc78ecSespie if (!cd) 556*f7cc78ecSespie abort (); 557*f7cc78ecSespie m32r_cgen_init_dis (cd); 558fddef416Sniklas } 559fddef416Sniklas 560fddef416Sniklas /* We try to have as much common code as possible. 561fddef416Sniklas But at this point some targets need to take over. */ 562fddef416Sniklas /* ??? Some targets may need a hook elsewhere. Try to avoid this, 563*f7cc78ecSespie but if not possible try to move this hook elsewhere rather than 564fddef416Sniklas have two hooks. */ 565*f7cc78ecSespie length = CGEN_PRINT_INSN (cd, pc, info); 566*f7cc78ecSespie if (length > 0) 567fddef416Sniklas return length; 568*f7cc78ecSespie if (length < 0) 569*f7cc78ecSespie return -1; 570fddef416Sniklas 571fddef416Sniklas (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 572*f7cc78ecSespie return cd->default_insn_bitsize / 8; 573fddef416Sniklas } 574