1214571Sdim/* Disassembler interface for targets using CGEN. -*- C -*- 2214571Sdim CGEN: Cpu tools GENerator 3214571Sdim 4214571Sdim THIS FILE IS MACHINE GENERATED WITH CGEN. 5214571Sdim - the resultant file is machine generated, cgen-dis.in isn't 6214571Sdim 7214571Sdim Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 8214571Sdim Free Software Foundation, Inc. 9214571Sdim 10214571Sdim This file is part of the GNU Binutils and GDB, the GNU debugger. 11214571Sdim 12214571Sdim This program is free software; you can redistribute it and/or modify 13214571Sdim it under the terms of the GNU General Public License as published by 14214571Sdim the Free Software Foundation; either version 2, or (at your option) 15214571Sdim any later version. 16214571Sdim 17214571Sdim This program is distributed in the hope that it will be useful, 18214571Sdim but WITHOUT ANY WARRANTY; without even the implied warranty of 19214571Sdim MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20214571Sdim GNU General Public License for more details. 21214571Sdim 22214571Sdim You should have received a copy of the GNU General Public License 23214571Sdim along with this program; if not, write to the Free Software Foundation, Inc., 24214571Sdim 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 25214571Sdim 26214571Sdim/* ??? Eventually more and more of this stuff can go to cpu-independent files. 27214571Sdim Keep that in mind. */ 28214571Sdim 29214571Sdim#include "sysdep.h" 30214571Sdim#include <stdio.h> 31214571Sdim#include "ansidecl.h" 32214571Sdim#include "dis-asm.h" 33214571Sdim#include "bfd.h" 34214571Sdim#include "symcat.h" 35214571Sdim#include "libiberty.h" 36214571Sdim#include "mep-desc.h" 37214571Sdim#include "mep-opc.h" 38214571Sdim#include "opintl.h" 39214571Sdim 40214571Sdim/* Default text to print if an instruction isn't recognized. */ 41214571Sdim#define UNKNOWN_INSN_MSG _("*unknown*") 42214571Sdim 43214571Sdimstatic void print_normal 44214571Sdim (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int); 45214571Sdimstatic void print_address 46214571Sdim (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED; 47214571Sdimstatic void print_keyword 48214571Sdim (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED; 49214571Sdimstatic void print_insn_normal 50214571Sdim (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int); 51214571Sdimstatic int print_insn 52214571Sdim (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, unsigned); 53214571Sdimstatic int default_print_insn 54214571Sdim (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED; 55214571Sdimstatic int read_insn 56214571Sdim (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *, 57214571Sdim unsigned long *); 58214571Sdim 59214571Sdim/* -- disassembler routines inserted here. */ 60214571Sdim 61214571Sdim/* -- dis.c */ 62214571Sdim 63214571Sdim#include "elf/mep.h" 64214571Sdim#include "elf-bfd.h" 65214571Sdim 66214571Sdim#define CGEN_VALIDATE_INSN_SUPPORTED 67214571Sdim 68214571Sdimstatic void print_tpreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int); 69214571Sdimstatic void print_spreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int); 70214571Sdim 71214571Sdimstatic void 72214571Sdimprint_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info, 73214571Sdim CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED, 74214571Sdim unsigned int flags ATTRIBUTE_UNUSED) 75214571Sdim{ 76214571Sdim disassemble_info *info = (disassemble_info *) dis_info; 77214571Sdim 78214571Sdim (*info->fprintf_func) (info->stream, "$tp"); 79214571Sdim} 80214571Sdim 81214571Sdimstatic void 82214571Sdimprint_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info, 83214571Sdim CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED, 84214571Sdim unsigned int flags ATTRIBUTE_UNUSED) 85214571Sdim{ 86214571Sdim disassemble_info *info = (disassemble_info *) dis_info; 87214571Sdim 88214571Sdim (*info->fprintf_func) (info->stream, "$sp"); 89214571Sdim} 90214571Sdim 91214571Sdim/* begin-cop-ip-print-handlers */ 92214571Sdimstatic void 93214571Sdimprint_fmax_cr (CGEN_CPU_DESC cd, 94214571Sdim void *dis_info, 95214571Sdim CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 96214571Sdim long value, 97214571Sdim unsigned int attrs) 98214571Sdim{ 99214571Sdim print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_fmax, value, attrs); 100214571Sdim} 101214571Sdimstatic void 102214571Sdimprint_fmax_ccr (CGEN_CPU_DESC cd, 103214571Sdim void *dis_info, 104214571Sdim CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED, 105214571Sdim long value, 106214571Sdim unsigned int attrs) 107214571Sdim{ 108214571Sdim print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_fmax, value, attrs); 109214571Sdim} 110214571Sdim/* end-cop-ip-print-handlers */ 111214571Sdim 112214571Sdim/************************************************************\ 113214571Sdim*********************** Experimental ************************* 114214571Sdim\************************************************************/ 115214571Sdim 116214571Sdim#undef CGEN_PRINT_INSN 117214571Sdim#define CGEN_PRINT_INSN mep_print_insn 118214571Sdim 119214571Sdimstatic int 120214571Sdimmep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info, 121214571Sdim bfd_byte *buf, int corelength, int copro1length, 122214571Sdim int copro2length ATTRIBUTE_UNUSED) 123214571Sdim{ 124214571Sdim int i; 125214571Sdim int status = 0; 126214571Sdim /* char insnbuf[CGEN_MAX_INSN_SIZE]; */ 127214571Sdim bfd_byte insnbuf[64]; 128214571Sdim 129214571Sdim /* If corelength > 0 then there is a core insn present. It 130214571Sdim will be at the beginning of the buffer. After printing 131214571Sdim the core insn, we need to print the + on the next line. */ 132214571Sdim if (corelength > 0) 133214571Sdim { 134214571Sdim int my_status = 0; 135214571Sdim 136214571Sdim for (i = 0; i < corelength; i++ ) 137214571Sdim insnbuf[i] = buf[i]; 138214571Sdim cd->isas = & MEP_CORE_ISA; 139214571Sdim 140214571Sdim my_status = print_insn (cd, pc, info, insnbuf, corelength); 141214571Sdim if (my_status != corelength) 142214571Sdim { 143214571Sdim (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 144214571Sdim my_status = corelength; 145214571Sdim } 146214571Sdim status += my_status; 147214571Sdim 148214571Sdim /* Print the + to indicate that the following copro insn is */ 149214571Sdim /* part of a vliw group. */ 150214571Sdim if (copro1length > 0) 151214571Sdim (*info->fprintf_func) (info->stream, " + "); 152214571Sdim } 153214571Sdim 154214571Sdim /* Now all that is left to be processed is the coprocessor insns 155214571Sdim In vliw mode, there will always be one. Its positioning will 156214571Sdim be from byte corelength to byte corelength+copro1length -1. 157214571Sdim No need to check for existence. Also, the first vliw insn, 158214571Sdim will, as spec'd, always be at least as long as the core insn 159214571Sdim so we don't need to flush the buffer. */ 160214571Sdim if (copro1length > 0) 161214571Sdim { 162214571Sdim int my_status = 0; 163214571Sdim 164214571Sdim for (i = corelength; i < corelength + copro1length; i++ ) 165214571Sdim insnbuf[i - corelength] = buf[i]; 166214571Sdim 167214571Sdim switch (copro1length) 168214571Sdim { 169214571Sdim case 0: 170214571Sdim break; 171214571Sdim case 2: 172214571Sdim cd->isas = & MEP_COP16_ISA; 173214571Sdim break; 174214571Sdim case 4: 175214571Sdim cd->isas = & MEP_COP32_ISA; 176214571Sdim break; 177214571Sdim case 6: 178214571Sdim cd->isas = & MEP_COP48_ISA; 179214571Sdim break; 180214571Sdim case 8: 181214571Sdim cd->isas = & MEP_COP64_ISA; 182214571Sdim break; 183214571Sdim default: 184214571Sdim /* Shouldn't be anything but 16,32,48,64. */ 185214571Sdim break; 186214571Sdim } 187214571Sdim 188214571Sdim my_status = print_insn (cd, pc, info, insnbuf, copro1length); 189214571Sdim 190214571Sdim if (my_status != copro1length) 191214571Sdim { 192214571Sdim (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 193214571Sdim my_status = copro1length; 194214571Sdim } 195214571Sdim status += my_status; 196214571Sdim } 197214571Sdim 198214571Sdim#if 0 199214571Sdim /* Now we need to process the second copro insn if it exists. We 200214571Sdim have no guarantee that the second copro insn will be longer 201214571Sdim than the first, so we have to flush the buffer if we are have 202214571Sdim a second copro insn to process. If present, this insn will 203214571Sdim be in the position from byte corelength+copro1length to byte 204214571Sdim corelength+copro1length+copro2length-1 (which better equal 8 205214571Sdim or else we're in big trouble. */ 206214571Sdim if (copro2length > 0) 207214571Sdim { 208214571Sdim int my_status = 0; 209214571Sdim 210214571Sdim for (i = 0; i < 64 ; i++) 211214571Sdim insnbuf[i] = 0; 212214571Sdim 213214571Sdim for (i = corelength + copro1length; i < 64; i++) 214214571Sdim insnbuf[i - (corelength + copro1length)] = buf[i]; 215214571Sdim 216214571Sdim switch (copro2length) 217214571Sdim { 218214571Sdim case 2: 219214571Sdim cd->isas = 1 << ISA_EXT_COP1_16; 220214571Sdim break; 221214571Sdim case 4: 222214571Sdim cd->isas = 1 << ISA_EXT_COP1_32; 223214571Sdim break; 224214571Sdim case 6: 225214571Sdim cd->isas = 1 << ISA_EXT_COP1_48; 226214571Sdim break; 227214571Sdim case 8: 228214571Sdim cd->isas = 1 << ISA_EXT_COP1_64; 229214571Sdim break; 230214571Sdim default: 231214571Sdim /* Shouldn't be anything but 16,32,48,64. */ 232214571Sdim break; 233214571Sdim } 234214571Sdim 235214571Sdim my_status = print_insn (cd, pc, info, insnbuf, copro2length); 236214571Sdim 237214571Sdim if (my_status != copro2length) 238214571Sdim { 239214571Sdim (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 240214571Sdim my_status = copro2length; 241214571Sdim } 242214571Sdim 243214571Sdim status += my_status; 244214571Sdim } 245214571Sdim#endif 246214571Sdim 247214571Sdim /* Status should now be the number of bytes that were printed 248214571Sdim which should be 4 for VLIW32 mode and 64 for VLIW64 mode. */ 249214571Sdim 250214571Sdim if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8))) 251214571Sdim return -1; 252214571Sdim else 253214571Sdim return status; 254214571Sdim} 255214571Sdim 256214571Sdim/* The two functions mep_examine_vliw[32,64]_insns are used find out 257214571Sdim which vliw combinaion (16 bit core with 48 bit copro, 32 bit core 258214571Sdim with 32 bit copro, etc.) is present. Later on, when internally 259214571Sdim parallel coprocessors are handled, only these functions should 260214571Sdim need to be changed. 261214571Sdim 262214571Sdim At this time only the following combinations are supported: 263214571Sdim 264214571Sdim VLIW32 Mode: 265214571Sdim 16 bit core insn (core) and 16 bit coprocessor insn (cop1) 266214571Sdim 32 bit core insn (core) 267214571Sdim 32 bit coprocessor insn (cop1) 268214571Sdim Note: As of this time, I do not believe we have enough information 269214571Sdim to distinguish a 32 bit core insn from a 32 bit cop insn. Also, 270214571Sdim no 16 bit coprocessor insns have been specified. 271214571Sdim 272214571Sdim VLIW64 Mode: 273214571Sdim 16 bit core insn (core) and 48 bit coprocessor insn (cop1) 274214571Sdim 32 bit core insn (core) and 32 bit coprocessor insn (cop1) 275214571Sdim 64 bit coprocessor insn (cop1) 276214571Sdim 277214571Sdim The framework for an internally parallel coprocessor is also 278214571Sdim present (2nd coprocessor insn is cop2), but at this time it 279214571Sdim is not used. This only appears to be valid in VLIW64 mode. */ 280214571Sdim 281214571Sdimstatic int 282214571Sdimmep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 283214571Sdim{ 284214571Sdim int status; 285214571Sdim int buflength; 286214571Sdim int corebuflength; 287214571Sdim int cop1buflength; 288214571Sdim int cop2buflength; 289214571Sdim bfd_byte buf[CGEN_MAX_INSN_SIZE]; 290214571Sdim char indicator16[1]; 291214571Sdim char indicatorcop32[2]; 292214571Sdim 293214571Sdim /* At this time we're not supporting internally parallel coprocessors, 294214571Sdim so cop2buflength will always be 0. */ 295214571Sdim cop2buflength = 0; 296214571Sdim 297214571Sdim /* Read in 32 bits. */ 298214571Sdim buflength = 4; /* VLIW insn spans 4 bytes. */ 299214571Sdim status = (*info->read_memory_func) (pc, buf, buflength, info); 300214571Sdim 301214571Sdim if (status != 0) 302214571Sdim { 303214571Sdim (*info->memory_error_func) (status, pc, info); 304214571Sdim return -1; 305214571Sdim } 306214571Sdim 307214571Sdim /* Put the big endian representation of the bytes to be examined 308214571Sdim in the temporary buffers for examination. */ 309214571Sdim 310214571Sdim if (info->endian == BFD_ENDIAN_BIG) 311214571Sdim { 312214571Sdim indicator16[0] = buf[0]; 313214571Sdim indicatorcop32[0] = buf[0]; 314214571Sdim indicatorcop32[1] = buf[1]; 315214571Sdim } 316214571Sdim else 317214571Sdim { 318214571Sdim indicator16[0] = buf[1]; 319214571Sdim indicatorcop32[0] = buf[1]; 320214571Sdim indicatorcop32[1] = buf[0]; 321214571Sdim } 322214571Sdim 323214571Sdim /* If the two high order bits are 00, 01 or 10, we have a 16 bit 324214571Sdim core insn and a 48 bit copro insn. */ 325214571Sdim 326214571Sdim if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40)) 327214571Sdim { 328214571Sdim if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07) 329214571Sdim { 330214571Sdim /* We have a 32 bit copro insn. */ 331214571Sdim corebuflength = 0; 332214571Sdim /* All 4 4ytes are one copro insn. */ 333214571Sdim cop1buflength = 4; 334214571Sdim } 335214571Sdim else 336214571Sdim { 337214571Sdim /* We have a 32 bit core. */ 338214571Sdim corebuflength = 4; 339214571Sdim cop1buflength = 0; 340214571Sdim } 341214571Sdim } 342214571Sdim else 343214571Sdim { 344214571Sdim /* We have a 16 bit core insn and a 16 bit copro insn. */ 345214571Sdim corebuflength = 2; 346214571Sdim cop1buflength = 2; 347214571Sdim } 348214571Sdim 349214571Sdim /* Now we have the distrubution set. Print them out. */ 350214571Sdim status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength, 351214571Sdim cop1buflength, cop2buflength); 352214571Sdim 353214571Sdim return status; 354214571Sdim} 355214571Sdim 356214571Sdimstatic int 357214571Sdimmep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 358214571Sdim{ 359214571Sdim int status; 360214571Sdim int buflength; 361214571Sdim int corebuflength; 362214571Sdim int cop1buflength; 363214571Sdim int cop2buflength; 364214571Sdim bfd_byte buf[CGEN_MAX_INSN_SIZE]; 365214571Sdim char indicator16[1]; 366214571Sdim char indicator64[4]; 367214571Sdim 368214571Sdim /* At this time we're not supporting internally parallel 369214571Sdim coprocessors, so cop2buflength will always be 0. */ 370214571Sdim cop2buflength = 0; 371214571Sdim 372214571Sdim /* Read in 64 bits. */ 373214571Sdim buflength = 8; /* VLIW insn spans 8 bytes. */ 374214571Sdim status = (*info->read_memory_func) (pc, buf, buflength, info); 375214571Sdim 376214571Sdim if (status != 0) 377214571Sdim { 378214571Sdim (*info->memory_error_func) (status, pc, info); 379214571Sdim return -1; 380214571Sdim } 381214571Sdim 382214571Sdim /* We have all 64 bits in the buffer now. We have to figure out 383214571Sdim what combination of instruction sizes are present. The two 384214571Sdim high order bits will indicate whether or not we have a 16 bit 385214571Sdim core insn or not. If not, then we have to look at the 7,8th 386214571Sdim bytes to tell whether we have 64 bit copro insn or a 32 bit 387214571Sdim core insn with a 32 bit copro insn. Endianness will make a 388214571Sdim difference here. */ 389214571Sdim 390214571Sdim /* Put the big endian representation of the bytes to be examined 391214571Sdim in the temporary buffers for examination. */ 392214571Sdim 393214571Sdim /* indicator16[0] = buf[0]; */ 394214571Sdim if (info->endian == BFD_ENDIAN_BIG) 395214571Sdim { 396214571Sdim indicator16[0] = buf[0]; 397214571Sdim indicator64[0] = buf[0]; 398214571Sdim indicator64[1] = buf[1]; 399214571Sdim indicator64[2] = buf[2]; 400214571Sdim indicator64[3] = buf[3]; 401214571Sdim } 402214571Sdim else 403214571Sdim { 404214571Sdim indicator16[0] = buf[1]; 405214571Sdim indicator64[0] = buf[1]; 406214571Sdim indicator64[1] = buf[0]; 407214571Sdim indicator64[2] = buf[3]; 408214571Sdim indicator64[3] = buf[2]; 409214571Sdim } 410214571Sdim 411214571Sdim /* If the two high order bits are 00, 01 or 10, we have a 16 bit 412214571Sdim core insn and a 48 bit copro insn. */ 413214571Sdim 414214571Sdim if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40)) 415214571Sdim { 416214571Sdim if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07 417214571Sdim && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0)) 418214571Sdim { 419214571Sdim /* We have a 64 bit copro insn. */ 420214571Sdim corebuflength = 0; 421214571Sdim /* All 8 bytes are one copro insn. */ 422214571Sdim cop1buflength = 8; 423214571Sdim } 424214571Sdim else 425214571Sdim { 426214571Sdim /* We have a 32 bit core insn and a 32 bit copro insn. */ 427214571Sdim corebuflength = 4; 428214571Sdim cop1buflength = 4; 429214571Sdim } 430214571Sdim } 431214571Sdim else 432214571Sdim { 433214571Sdim /* We have a 16 bit core insn and a 48 bit copro insn. */ 434214571Sdim corebuflength = 2; 435214571Sdim cop1buflength = 6; 436214571Sdim } 437214571Sdim 438214571Sdim /* Now we have the distrubution set. Print them out. */ 439214571Sdim status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength, 440214571Sdim cop1buflength, cop2buflength); 441214571Sdim 442214571Sdim return status; 443214571Sdim} 444214571Sdim 445214571Sdimstatic int 446214571Sdimmep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 447214571Sdim{ 448214571Sdim int status; 449214571Sdim 450214571Sdim /* Extract and adapt to configuration number, if available. */ 451214571Sdim if (info->section && info->section->owner) 452214571Sdim { 453214571Sdim bfd *abfd = info->section->owner; 454214571Sdim mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK; 455214571Sdim /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */ 456214571Sdim } 457214571Sdim 458214571Sdim /* Picking the right ISA bitmask for the current context is tricky. */ 459214571Sdim if (info->section) 460214571Sdim { 461214571Sdim if (info->section->flags & SEC_MEP_VLIW) 462214571Sdim { 463214571Sdim /* Are we in 32 or 64 bit vliw mode? */ 464214571Sdim if (MEP_VLIW64) 465214571Sdim status = mep_examine_vliw64_insns (cd, pc, info); 466214571Sdim else 467214571Sdim status = mep_examine_vliw32_insns (cd, pc, info); 468214571Sdim /* Both the above branches set their own isa bitmasks. */ 469214571Sdim } 470214571Sdim else 471214571Sdim { 472214571Sdim cd->isas = & MEP_CORE_ISA; 473214571Sdim status = default_print_insn (cd, pc, info); 474214571Sdim } 475214571Sdim } 476214571Sdim else /* sid or gdb */ 477214571Sdim { 478214571Sdim status = default_print_insn (cd, pc, info); 479214571Sdim } 480214571Sdim 481214571Sdim return status; 482214571Sdim} 483214571Sdim 484214571Sdim 485214571Sdim/* -- opc.c */ 486214571Sdim 487214571Sdimvoid mep_cgen_print_operand 488214571Sdim (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int); 489214571Sdim 490214571Sdim/* Main entry point for printing operands. 491214571Sdim XINFO is a `void *' and not a `disassemble_info *' to not put a requirement 492214571Sdim of dis-asm.h on cgen.h. 493214571Sdim 494214571Sdim This function is basically just a big switch statement. Earlier versions 495214571Sdim used tables to look up the function to use, but 496214571Sdim - if the table contains both assembler and disassembler functions then 497214571Sdim the disassembler contains much of the assembler and vice-versa, 498214571Sdim - there's a lot of inlining possibilities as things grow, 499214571Sdim - using a switch statement avoids the function call overhead. 500214571Sdim 501214571Sdim This function could be moved into `print_insn_normal', but keeping it 502214571Sdim separate makes clear the interface between `print_insn_normal' and each of 503214571Sdim the handlers. */ 504214571Sdim 505214571Sdimvoid 506214571Sdimmep_cgen_print_operand (CGEN_CPU_DESC cd, 507214571Sdim int opindex, 508214571Sdim void * xinfo, 509214571Sdim CGEN_FIELDS *fields, 510214571Sdim void const *attrs ATTRIBUTE_UNUSED, 511214571Sdim bfd_vma pc, 512214571Sdim int length) 513214571Sdim{ 514214571Sdim disassemble_info *info = (disassemble_info *) xinfo; 515214571Sdim 516214571Sdim switch (opindex) 517214571Sdim { 518214571Sdim case MEP_OPERAND_ADDR24A4 : 519214571Sdim print_normal (cd, info, fields->f_24u8a4n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length); 520214571Sdim break; 521214571Sdim case MEP_OPERAND_CALLNUM : 522214571Sdim print_normal (cd, info, fields->f_callnum, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length); 523214571Sdim break; 524214571Sdim case MEP_OPERAND_CCCC : 525214571Sdim print_normal (cd, info, fields->f_rm, 0, pc, length); 526214571Sdim break; 527214571Sdim case MEP_OPERAND_CCRN : 528214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_ccr, fields->f_ccrn, 0|(1<<CGEN_OPERAND_VIRTUAL)); 529214571Sdim break; 530214571Sdim case MEP_OPERAND_CDISP8 : 531214571Sdim print_normal (cd, info, fields->f_8s24, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 532214571Sdim break; 533214571Sdim case MEP_OPERAND_CDISP8A2 : 534214571Sdim print_normal (cd, info, fields->f_8s24a2, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 535214571Sdim break; 536214571Sdim case MEP_OPERAND_CDISP8A4 : 537214571Sdim print_normal (cd, info, fields->f_8s24a4, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 538214571Sdim break; 539214571Sdim case MEP_OPERAND_CDISP8A8 : 540214571Sdim print_normal (cd, info, fields->f_8s24a8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 541214571Sdim break; 542214571Sdim case MEP_OPERAND_CIMM4 : 543214571Sdim print_normal (cd, info, fields->f_rn, 0, pc, length); 544214571Sdim break; 545214571Sdim case MEP_OPERAND_CIMM5 : 546214571Sdim print_normal (cd, info, fields->f_5u24, 0, pc, length); 547214571Sdim break; 548214571Sdim case MEP_OPERAND_CODE16 : 549214571Sdim print_normal (cd, info, fields->f_16u16, 0, pc, length); 550214571Sdim break; 551214571Sdim case MEP_OPERAND_CODE24 : 552214571Sdim print_normal (cd, info, fields->f_24u4n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length); 553214571Sdim break; 554214571Sdim case MEP_OPERAND_CP_FLAG : 555214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_ccr, 0, 0); 556214571Sdim break; 557214571Sdim case MEP_OPERAND_CRN : 558214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_cr, fields->f_crn, 0); 559214571Sdim break; 560214571Sdim case MEP_OPERAND_CRN64 : 561214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_cr64, fields->f_crn, 0); 562214571Sdim break; 563214571Sdim case MEP_OPERAND_CRNX : 564214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_cr, fields->f_crnx, 0|(1<<CGEN_OPERAND_VIRTUAL)); 565214571Sdim break; 566214571Sdim case MEP_OPERAND_CRNX64 : 567214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_cr64, fields->f_crnx, 0|(1<<CGEN_OPERAND_VIRTUAL)); 568214571Sdim break; 569214571Sdim case MEP_OPERAND_CSRN : 570214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, fields->f_csrn, 0|(1<<CGEN_OPERAND_VIRTUAL)); 571214571Sdim break; 572214571Sdim case MEP_OPERAND_CSRN_IDX : 573214571Sdim print_normal (cd, info, fields->f_csrn, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length); 574214571Sdim break; 575214571Sdim case MEP_OPERAND_DBG : 576214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 577214571Sdim break; 578214571Sdim case MEP_OPERAND_DEPC : 579214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 580214571Sdim break; 581214571Sdim case MEP_OPERAND_EPC : 582214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 583214571Sdim break; 584214571Sdim case MEP_OPERAND_EXC : 585214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 586214571Sdim break; 587214571Sdim case MEP_OPERAND_FMAX_CCRN : 588214571Sdim print_fmax_ccr (cd, info, & mep_cgen_opval_h_ccr, fields->f_fmax_4_4, 0); 589214571Sdim break; 590214571Sdim case MEP_OPERAND_FMAX_FRD : 591214571Sdim print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frd, 0|(1<<CGEN_OPERAND_VIRTUAL)); 592214571Sdim break; 593214571Sdim case MEP_OPERAND_FMAX_FRD_INT : 594214571Sdim print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frd, 0|(1<<CGEN_OPERAND_VIRTUAL)); 595214571Sdim break; 596214571Sdim case MEP_OPERAND_FMAX_FRM : 597214571Sdim print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frm, 0|(1<<CGEN_OPERAND_VIRTUAL)); 598214571Sdim break; 599214571Sdim case MEP_OPERAND_FMAX_FRN : 600214571Sdim print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frn, 0|(1<<CGEN_OPERAND_VIRTUAL)); 601214571Sdim break; 602214571Sdim case MEP_OPERAND_FMAX_FRN_INT : 603214571Sdim print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frn, 0|(1<<CGEN_OPERAND_VIRTUAL)); 604214571Sdim break; 605214571Sdim case MEP_OPERAND_FMAX_RM : 606214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_fmax_rm, 0); 607214571Sdim break; 608214571Sdim case MEP_OPERAND_HI : 609214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 610214571Sdim break; 611214571Sdim case MEP_OPERAND_LO : 612214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 613214571Sdim break; 614214571Sdim case MEP_OPERAND_LP : 615214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 616214571Sdim break; 617214571Sdim case MEP_OPERAND_MB0 : 618214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 619214571Sdim break; 620214571Sdim case MEP_OPERAND_MB1 : 621214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 622214571Sdim break; 623214571Sdim case MEP_OPERAND_ME0 : 624214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 625214571Sdim break; 626214571Sdim case MEP_OPERAND_ME1 : 627214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 628214571Sdim break; 629214571Sdim case MEP_OPERAND_NPC : 630214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 631214571Sdim break; 632214571Sdim case MEP_OPERAND_OPT : 633214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 634214571Sdim break; 635214571Sdim case MEP_OPERAND_PCABS24A2 : 636214571Sdim print_address (cd, info, fields->f_24u5a2n, 0|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length); 637214571Sdim break; 638214571Sdim case MEP_OPERAND_PCREL12A2 : 639214571Sdim print_address (cd, info, fields->f_12s4a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); 640214571Sdim break; 641214571Sdim case MEP_OPERAND_PCREL17A2 : 642214571Sdim print_address (cd, info, fields->f_17s16a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); 643214571Sdim break; 644214571Sdim case MEP_OPERAND_PCREL24A2 : 645214571Sdim print_address (cd, info, fields->f_24s5a2n, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length); 646214571Sdim break; 647214571Sdim case MEP_OPERAND_PCREL8A2 : 648214571Sdim print_address (cd, info, fields->f_8s8a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length); 649214571Sdim break; 650214571Sdim case MEP_OPERAND_PSW : 651214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 652214571Sdim break; 653214571Sdim case MEP_OPERAND_R0 : 654214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0); 655214571Sdim break; 656214571Sdim case MEP_OPERAND_R1 : 657214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0); 658214571Sdim break; 659214571Sdim case MEP_OPERAND_RL : 660214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rl, 0); 661214571Sdim break; 662214571Sdim case MEP_OPERAND_RM : 663214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rm, 0); 664214571Sdim break; 665214571Sdim case MEP_OPERAND_RMA : 666214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rm, 0); 667214571Sdim break; 668214571Sdim case MEP_OPERAND_RN : 669214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0); 670214571Sdim break; 671214571Sdim case MEP_OPERAND_RN3 : 672214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0); 673214571Sdim break; 674214571Sdim case MEP_OPERAND_RN3C : 675214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0); 676214571Sdim break; 677214571Sdim case MEP_OPERAND_RN3L : 678214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0); 679214571Sdim break; 680214571Sdim case MEP_OPERAND_RN3S : 681214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0); 682214571Sdim break; 683214571Sdim case MEP_OPERAND_RN3UC : 684214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0); 685214571Sdim break; 686214571Sdim case MEP_OPERAND_RN3UL : 687214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0); 688214571Sdim break; 689214571Sdim case MEP_OPERAND_RN3US : 690214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0); 691214571Sdim break; 692214571Sdim case MEP_OPERAND_RNC : 693214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0); 694214571Sdim break; 695214571Sdim case MEP_OPERAND_RNL : 696214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0); 697214571Sdim break; 698214571Sdim case MEP_OPERAND_RNS : 699214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0); 700214571Sdim break; 701214571Sdim case MEP_OPERAND_RNUC : 702214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0); 703214571Sdim break; 704214571Sdim case MEP_OPERAND_RNUL : 705214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0); 706214571Sdim break; 707214571Sdim case MEP_OPERAND_RNUS : 708214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0); 709214571Sdim break; 710214571Sdim case MEP_OPERAND_SAR : 711214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0); 712214571Sdim break; 713214571Sdim case MEP_OPERAND_SDISP16 : 714214571Sdim print_normal (cd, info, fields->f_16s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 715214571Sdim break; 716214571Sdim case MEP_OPERAND_SIMM16 : 717214571Sdim print_normal (cd, info, fields->f_16s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 718214571Sdim break; 719214571Sdim case MEP_OPERAND_SIMM6 : 720214571Sdim print_normal (cd, info, fields->f_6s8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 721214571Sdim break; 722214571Sdim case MEP_OPERAND_SIMM8 : 723214571Sdim print_normal (cd, info, fields->f_8s8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELOC_IMPLIES_OVERFLOW), pc, length); 724214571Sdim break; 725214571Sdim case MEP_OPERAND_SP : 726214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0); 727214571Sdim break; 728214571Sdim case MEP_OPERAND_SPR : 729214571Sdim print_spreg (cd, info, & mep_cgen_opval_h_gpr, 0, 0); 730214571Sdim break; 731214571Sdim case MEP_OPERAND_TP : 732214571Sdim print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0); 733214571Sdim break; 734214571Sdim case MEP_OPERAND_TPR : 735214571Sdim print_tpreg (cd, info, & mep_cgen_opval_h_gpr, 0, 0); 736214571Sdim break; 737214571Sdim case MEP_OPERAND_UDISP2 : 738214571Sdim print_normal (cd, info, fields->f_2u6, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 739214571Sdim break; 740214571Sdim case MEP_OPERAND_UDISP7 : 741214571Sdim print_normal (cd, info, fields->f_7u9, 0, pc, length); 742214571Sdim break; 743214571Sdim case MEP_OPERAND_UDISP7A2 : 744214571Sdim print_normal (cd, info, fields->f_7u9a2, 0, pc, length); 745214571Sdim break; 746214571Sdim case MEP_OPERAND_UDISP7A4 : 747214571Sdim print_normal (cd, info, fields->f_7u9a4, 0, pc, length); 748214571Sdim break; 749214571Sdim case MEP_OPERAND_UIMM16 : 750214571Sdim print_normal (cd, info, fields->f_16u16, 0, pc, length); 751214571Sdim break; 752214571Sdim case MEP_OPERAND_UIMM2 : 753214571Sdim print_normal (cd, info, fields->f_2u10, 0, pc, length); 754214571Sdim break; 755214571Sdim case MEP_OPERAND_UIMM24 : 756214571Sdim print_normal (cd, info, fields->f_24u8n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length); 757214571Sdim break; 758214571Sdim case MEP_OPERAND_UIMM3 : 759214571Sdim print_normal (cd, info, fields->f_3u5, 0, pc, length); 760214571Sdim break; 761214571Sdim case MEP_OPERAND_UIMM4 : 762214571Sdim print_normal (cd, info, fields->f_4u8, 0, pc, length); 763214571Sdim break; 764214571Sdim case MEP_OPERAND_UIMM5 : 765214571Sdim print_normal (cd, info, fields->f_5u8, 0, pc, length); 766214571Sdim break; 767214571Sdim case MEP_OPERAND_UIMM7A4 : 768214571Sdim print_normal (cd, info, fields->f_7u9a4, 0, pc, length); 769214571Sdim break; 770214571Sdim case MEP_OPERAND_ZERO : 771214571Sdim print_normal (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length); 772214571Sdim break; 773214571Sdim 774214571Sdim default : 775214571Sdim /* xgettext:c-format */ 776214571Sdim fprintf (stderr, _("Unrecognized field %d while printing insn.\n"), 777214571Sdim opindex); 778214571Sdim abort (); 779214571Sdim } 780214571Sdim} 781214571Sdim 782214571Sdimcgen_print_fn * const mep_cgen_print_handlers[] = 783214571Sdim{ 784214571Sdim print_insn_normal, 785214571Sdim}; 786214571Sdim 787214571Sdim 788214571Sdimvoid 789214571Sdimmep_cgen_init_dis (CGEN_CPU_DESC cd) 790214571Sdim{ 791214571Sdim mep_cgen_init_opcode_table (cd); 792214571Sdim mep_cgen_init_ibld_table (cd); 793214571Sdim cd->print_handlers = & mep_cgen_print_handlers[0]; 794214571Sdim cd->print_operand = mep_cgen_print_operand; 795214571Sdim} 796214571Sdim 797214571Sdim 798214571Sdim/* Default print handler. */ 799214571Sdim 800214571Sdimstatic void 801214571Sdimprint_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 802214571Sdim void *dis_info, 803214571Sdim long value, 804214571Sdim unsigned int attrs, 805214571Sdim bfd_vma pc ATTRIBUTE_UNUSED, 806214571Sdim int length ATTRIBUTE_UNUSED) 807214571Sdim{ 808214571Sdim disassemble_info *info = (disassemble_info *) dis_info; 809214571Sdim 810214571Sdim#ifdef CGEN_PRINT_NORMAL 811214571Sdim CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length); 812214571Sdim#endif 813214571Sdim 814214571Sdim /* Print the operand as directed by the attributes. */ 815214571Sdim if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY)) 816214571Sdim ; /* nothing to do */ 817214571Sdim else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED)) 818214571Sdim (*info->fprintf_func) (info->stream, "%ld", value); 819214571Sdim else 820214571Sdim (*info->fprintf_func) (info->stream, "0x%lx", value); 821214571Sdim} 822214571Sdim 823214571Sdim/* Default address handler. */ 824214571Sdim 825214571Sdimstatic void 826214571Sdimprint_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 827214571Sdim void *dis_info, 828214571Sdim bfd_vma value, 829214571Sdim unsigned int attrs, 830214571Sdim bfd_vma pc ATTRIBUTE_UNUSED, 831214571Sdim int length ATTRIBUTE_UNUSED) 832214571Sdim{ 833214571Sdim disassemble_info *info = (disassemble_info *) dis_info; 834214571Sdim 835214571Sdim#ifdef CGEN_PRINT_ADDRESS 836214571Sdim CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length); 837214571Sdim#endif 838214571Sdim 839214571Sdim /* Print the operand as directed by the attributes. */ 840214571Sdim if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY)) 841214571Sdim ; /* Nothing to do. */ 842214571Sdim else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR)) 843214571Sdim (*info->print_address_func) (value, info); 844214571Sdim else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR)) 845214571Sdim (*info->print_address_func) (value, info); 846214571Sdim else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED)) 847214571Sdim (*info->fprintf_func) (info->stream, "%ld", (long) value); 848214571Sdim else 849214571Sdim (*info->fprintf_func) (info->stream, "0x%lx", (long) value); 850214571Sdim} 851214571Sdim 852214571Sdim/* Keyword print handler. */ 853214571Sdim 854214571Sdimstatic void 855214571Sdimprint_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 856214571Sdim void *dis_info, 857214571Sdim CGEN_KEYWORD *keyword_table, 858214571Sdim long value, 859214571Sdim unsigned int attrs ATTRIBUTE_UNUSED) 860214571Sdim{ 861214571Sdim disassemble_info *info = (disassemble_info *) dis_info; 862214571Sdim const CGEN_KEYWORD_ENTRY *ke; 863214571Sdim 864214571Sdim ke = cgen_keyword_lookup_value (keyword_table, value); 865214571Sdim if (ke != NULL) 866214571Sdim (*info->fprintf_func) (info->stream, "%s", ke->name); 867214571Sdim else 868214571Sdim (*info->fprintf_func) (info->stream, "???"); 869214571Sdim} 870214571Sdim 871214571Sdim/* Default insn printer. 872214571Sdim 873214571Sdim DIS_INFO is defined as `void *' so the disassembler needn't know anything 874214571Sdim about disassemble_info. */ 875214571Sdim 876214571Sdimstatic void 877214571Sdimprint_insn_normal (CGEN_CPU_DESC cd, 878214571Sdim void *dis_info, 879214571Sdim const CGEN_INSN *insn, 880214571Sdim CGEN_FIELDS *fields, 881214571Sdim bfd_vma pc, 882214571Sdim int length) 883214571Sdim{ 884214571Sdim const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn); 885214571Sdim disassemble_info *info = (disassemble_info *) dis_info; 886214571Sdim const CGEN_SYNTAX_CHAR_TYPE *syn; 887214571Sdim 888214571Sdim CGEN_INIT_PRINT (cd); 889214571Sdim 890214571Sdim for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn) 891214571Sdim { 892214571Sdim if (CGEN_SYNTAX_MNEMONIC_P (*syn)) 893214571Sdim { 894214571Sdim (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn)); 895214571Sdim continue; 896214571Sdim } 897214571Sdim if (CGEN_SYNTAX_CHAR_P (*syn)) 898214571Sdim { 899214571Sdim (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn)); 900214571Sdim continue; 901214571Sdim } 902214571Sdim 903214571Sdim /* We have an operand. */ 904214571Sdim mep_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info, 905214571Sdim fields, CGEN_INSN_ATTRS (insn), pc, length); 906214571Sdim } 907214571Sdim} 908214571Sdim 909214571Sdim/* Subroutine of print_insn. Reads an insn into the given buffers and updates 910214571Sdim the extract info. 911214571Sdim Returns 0 if all is well, non-zero otherwise. */ 912214571Sdim 913214571Sdimstatic int 914214571Sdimread_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, 915214571Sdim bfd_vma pc, 916214571Sdim disassemble_info *info, 917214571Sdim bfd_byte *buf, 918214571Sdim int buflen, 919214571Sdim CGEN_EXTRACT_INFO *ex_info, 920214571Sdim unsigned long *insn_value) 921214571Sdim{ 922214571Sdim int status = (*info->read_memory_func) (pc, buf, buflen, info); 923214571Sdim 924214571Sdim if (status != 0) 925214571Sdim { 926214571Sdim (*info->memory_error_func) (status, pc, info); 927214571Sdim return -1; 928214571Sdim } 929214571Sdim 930214571Sdim ex_info->dis_info = info; 931214571Sdim ex_info->valid = (1 << buflen) - 1; 932214571Sdim ex_info->insn_bytes = buf; 933214571Sdim 934214571Sdim *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG); 935214571Sdim return 0; 936214571Sdim} 937214571Sdim 938214571Sdim/* Utility to print an insn. 939214571Sdim BUF is the base part of the insn, target byte order, BUFLEN bytes long. 940214571Sdim The result is the size of the insn in bytes or zero for an unknown insn 941214571Sdim or -1 if an error occurs fetching data (memory_error_func will have 942214571Sdim been called). */ 943214571Sdim 944214571Sdimstatic int 945214571Sdimprint_insn (CGEN_CPU_DESC cd, 946214571Sdim bfd_vma pc, 947214571Sdim disassemble_info *info, 948214571Sdim bfd_byte *buf, 949214571Sdim unsigned int buflen) 950214571Sdim{ 951214571Sdim CGEN_INSN_INT insn_value; 952214571Sdim const CGEN_INSN_LIST *insn_list; 953214571Sdim CGEN_EXTRACT_INFO ex_info; 954214571Sdim int basesize; 955214571Sdim 956214571Sdim /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */ 957214571Sdim basesize = cd->base_insn_bitsize < buflen * 8 ? 958214571Sdim cd->base_insn_bitsize : buflen * 8; 959214571Sdim insn_value = cgen_get_insn_value (cd, buf, basesize); 960214571Sdim 961214571Sdim 962214571Sdim /* Fill in ex_info fields like read_insn would. Don't actually call 963214571Sdim read_insn, since the incoming buffer is already read (and possibly 964214571Sdim modified a la m32r). */ 965214571Sdim ex_info.valid = (1 << buflen) - 1; 966214571Sdim ex_info.dis_info = info; 967214571Sdim ex_info.insn_bytes = buf; 968214571Sdim 969214571Sdim /* The instructions are stored in hash lists. 970214571Sdim Pick the first one and keep trying until we find the right one. */ 971214571Sdim 972214571Sdim insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value); 973214571Sdim while (insn_list != NULL) 974214571Sdim { 975214571Sdim const CGEN_INSN *insn = insn_list->insn; 976214571Sdim CGEN_FIELDS fields; 977214571Sdim int length; 978214571Sdim unsigned long insn_value_cropped; 979214571Sdim 980214571Sdim#ifdef CGEN_VALIDATE_INSN_SUPPORTED 981214571Sdim /* Not needed as insn shouldn't be in hash lists if not supported. */ 982214571Sdim /* Supported by this cpu? */ 983214571Sdim if (! mep_cgen_insn_supported (cd, insn)) 984214571Sdim { 985214571Sdim insn_list = CGEN_DIS_NEXT_INSN (insn_list); 986214571Sdim continue; 987214571Sdim } 988214571Sdim#endif 989214571Sdim 990214571Sdim /* Basic bit mask must be correct. */ 991214571Sdim /* ??? May wish to allow target to defer this check until the extract 992214571Sdim handler. */ 993214571Sdim 994214571Sdim /* Base size may exceed this instruction's size. Extract the 995214571Sdim relevant part from the buffer. */ 996214571Sdim if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen && 997214571Sdim (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long)) 998214571Sdim insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 999214571Sdim info->endian == BFD_ENDIAN_BIG); 1000214571Sdim else 1001214571Sdim insn_value_cropped = insn_value; 1002214571Sdim 1003214571Sdim if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn)) 1004214571Sdim == CGEN_INSN_BASE_VALUE (insn)) 1005214571Sdim { 1006214571Sdim /* Printing is handled in two passes. The first pass parses the 1007214571Sdim machine insn and extracts the fields. The second pass prints 1008214571Sdim them. */ 1009214571Sdim 1010214571Sdim /* Make sure the entire insn is loaded into insn_value, if it 1011214571Sdim can fit. */ 1012214571Sdim if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) && 1013214571Sdim (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long)) 1014214571Sdim { 1015214571Sdim unsigned long full_insn_value; 1016214571Sdim int rc = read_insn (cd, pc, info, buf, 1017214571Sdim CGEN_INSN_BITSIZE (insn) / 8, 1018214571Sdim & ex_info, & full_insn_value); 1019214571Sdim if (rc != 0) 1020214571Sdim return rc; 1021214571Sdim length = CGEN_EXTRACT_FN (cd, insn) 1022214571Sdim (cd, insn, &ex_info, full_insn_value, &fields, pc); 1023214571Sdim } 1024214571Sdim else 1025214571Sdim length = CGEN_EXTRACT_FN (cd, insn) 1026214571Sdim (cd, insn, &ex_info, insn_value_cropped, &fields, pc); 1027214571Sdim 1028214571Sdim /* Length < 0 -> error. */ 1029214571Sdim if (length < 0) 1030214571Sdim return length; 1031214571Sdim if (length > 0) 1032214571Sdim { 1033214571Sdim CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length); 1034214571Sdim /* Length is in bits, result is in bytes. */ 1035214571Sdim return length / 8; 1036214571Sdim } 1037214571Sdim } 1038214571Sdim 1039214571Sdim insn_list = CGEN_DIS_NEXT_INSN (insn_list); 1040214571Sdim } 1041214571Sdim 1042214571Sdim return 0; 1043214571Sdim} 1044214571Sdim 1045214571Sdim/* Default value for CGEN_PRINT_INSN. 1046214571Sdim The result is the size of the insn in bytes or zero for an unknown insn 1047214571Sdim or -1 if an error occured fetching bytes. */ 1048214571Sdim 1049214571Sdim#ifndef CGEN_PRINT_INSN 1050214571Sdim#define CGEN_PRINT_INSN default_print_insn 1051214571Sdim#endif 1052214571Sdim 1053214571Sdimstatic int 1054214571Sdimdefault_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info) 1055214571Sdim{ 1056214571Sdim bfd_byte buf[CGEN_MAX_INSN_SIZE]; 1057214571Sdim int buflen; 1058214571Sdim int status; 1059214571Sdim 1060214571Sdim /* Attempt to read the base part of the insn. */ 1061214571Sdim buflen = cd->base_insn_bitsize / 8; 1062214571Sdim status = (*info->read_memory_func) (pc, buf, buflen, info); 1063214571Sdim 1064214571Sdim /* Try again with the minimum part, if min < base. */ 1065214571Sdim if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize)) 1066214571Sdim { 1067214571Sdim buflen = cd->min_insn_bitsize / 8; 1068214571Sdim status = (*info->read_memory_func) (pc, buf, buflen, info); 1069214571Sdim } 1070214571Sdim 1071214571Sdim if (status != 0) 1072214571Sdim { 1073214571Sdim (*info->memory_error_func) (status, pc, info); 1074214571Sdim return -1; 1075214571Sdim } 1076214571Sdim 1077214571Sdim return print_insn (cd, pc, info, buf, buflen); 1078214571Sdim} 1079214571Sdim 1080214571Sdim/* Main entry point. 1081214571Sdim Print one instruction from PC on INFO->STREAM. 1082214571Sdim Return the size of the instruction (in bytes). */ 1083214571Sdim 1084214571Sdimtypedef struct cpu_desc_list 1085214571Sdim{ 1086214571Sdim struct cpu_desc_list *next; 1087214571Sdim CGEN_BITSET *isa; 1088214571Sdim int mach; 1089214571Sdim int endian; 1090214571Sdim CGEN_CPU_DESC cd; 1091214571Sdim} cpu_desc_list; 1092214571Sdim 1093214571Sdimint 1094214571Sdimprint_insn_mep (bfd_vma pc, disassemble_info *info) 1095214571Sdim{ 1096214571Sdim static cpu_desc_list *cd_list = 0; 1097214571Sdim cpu_desc_list *cl = 0; 1098214571Sdim static CGEN_CPU_DESC cd = 0; 1099214571Sdim static CGEN_BITSET *prev_isa; 1100214571Sdim static int prev_mach; 1101214571Sdim static int prev_endian; 1102214571Sdim int length; 1103214571Sdim CGEN_BITSET *isa; 1104214571Sdim int mach; 1105214571Sdim int endian = (info->endian == BFD_ENDIAN_BIG 1106214571Sdim ? CGEN_ENDIAN_BIG 1107214571Sdim : CGEN_ENDIAN_LITTLE); 1108214571Sdim enum bfd_architecture arch; 1109214571Sdim 1110214571Sdim /* ??? gdb will set mach but leave the architecture as "unknown" */ 1111214571Sdim#ifndef CGEN_BFD_ARCH 1112214571Sdim#define CGEN_BFD_ARCH bfd_arch_mep 1113214571Sdim#endif 1114214571Sdim arch = info->arch; 1115214571Sdim if (arch == bfd_arch_unknown) 1116214571Sdim arch = CGEN_BFD_ARCH; 1117214571Sdim 1118214571Sdim /* There's no standard way to compute the machine or isa number 1119214571Sdim so we leave it to the target. */ 1120214571Sdim#ifdef CGEN_COMPUTE_MACH 1121214571Sdim mach = CGEN_COMPUTE_MACH (info); 1122214571Sdim#else 1123214571Sdim mach = info->mach; 1124214571Sdim#endif 1125214571Sdim 1126214571Sdim#ifdef CGEN_COMPUTE_ISA 1127214571Sdim { 1128214571Sdim static CGEN_BITSET *permanent_isa; 1129214571Sdim 1130214571Sdim if (!permanent_isa) 1131214571Sdim permanent_isa = cgen_bitset_create (MAX_ISAS); 1132214571Sdim isa = permanent_isa; 1133214571Sdim cgen_bitset_clear (isa); 1134214571Sdim cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info)); 1135214571Sdim } 1136214571Sdim#else 1137214571Sdim isa = info->insn_sets; 1138214571Sdim#endif 1139214571Sdim 1140214571Sdim /* If we've switched cpu's, try to find a handle we've used before */ 1141214571Sdim if (cd 1142214571Sdim && (cgen_bitset_compare (isa, prev_isa) != 0 1143214571Sdim || mach != prev_mach 1144214571Sdim || endian != prev_endian)) 1145214571Sdim { 1146214571Sdim cd = 0; 1147214571Sdim for (cl = cd_list; cl; cl = cl->next) 1148214571Sdim { 1149214571Sdim if (cgen_bitset_compare (cl->isa, isa) == 0 && 1150214571Sdim cl->mach == mach && 1151214571Sdim cl->endian == endian) 1152214571Sdim { 1153214571Sdim cd = cl->cd; 1154214571Sdim prev_isa = cd->isas; 1155214571Sdim break; 1156214571Sdim } 1157214571Sdim } 1158214571Sdim } 1159214571Sdim 1160214571Sdim /* If we haven't initialized yet, initialize the opcode table. */ 1161214571Sdim if (! cd) 1162214571Sdim { 1163214571Sdim const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach); 1164214571Sdim const char *mach_name; 1165214571Sdim 1166214571Sdim if (!arch_type) 1167214571Sdim abort (); 1168214571Sdim mach_name = arch_type->printable_name; 1169214571Sdim 1170214571Sdim prev_isa = cgen_bitset_copy (isa); 1171214571Sdim prev_mach = mach; 1172214571Sdim prev_endian = endian; 1173214571Sdim cd = mep_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa, 1174214571Sdim CGEN_CPU_OPEN_BFDMACH, mach_name, 1175214571Sdim CGEN_CPU_OPEN_ENDIAN, prev_endian, 1176214571Sdim CGEN_CPU_OPEN_END); 1177214571Sdim if (!cd) 1178214571Sdim abort (); 1179214571Sdim 1180214571Sdim /* Save this away for future reference. */ 1181214571Sdim cl = xmalloc (sizeof (struct cpu_desc_list)); 1182214571Sdim cl->cd = cd; 1183214571Sdim cl->isa = prev_isa; 1184214571Sdim cl->mach = mach; 1185214571Sdim cl->endian = endian; 1186214571Sdim cl->next = cd_list; 1187214571Sdim cd_list = cl; 1188214571Sdim 1189214571Sdim mep_cgen_init_dis (cd); 1190214571Sdim } 1191214571Sdim 1192214571Sdim /* We try to have as much common code as possible. 1193214571Sdim But at this point some targets need to take over. */ 1194214571Sdim /* ??? Some targets may need a hook elsewhere. Try to avoid this, 1195214571Sdim but if not possible try to move this hook elsewhere rather than 1196214571Sdim have two hooks. */ 1197214571Sdim length = CGEN_PRINT_INSN (cd, pc, info); 1198214571Sdim if (length > 0) 1199214571Sdim return length; 1200214571Sdim if (length < 0) 1201214571Sdim return -1; 1202214571Sdim 1203214571Sdim (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG); 1204214571Sdim return cd->default_insn_bitsize / 8; 1205214571Sdim} 1206