/* tilegx-dis.c. Disassembly routines for the TILE-Gx architecture. Copyright (C) 2011-2016 Free Software Foundation, Inc. This file is part of the GNU opcodes library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sysdep.h" #include #include #include "bfd.h" #include "elf/tilegx.h" #include "elf-bfd.h" #include "dis-asm.h" #include "opcode/tilegx.h" int print_insn_tilegx (bfd_vma memaddr, disassemble_info *info) { struct tilegx_decoded_instruction decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; bfd_byte opbuf[TILEGX_BUNDLE_SIZE_IN_BYTES]; int status, i, num_instructions, num_printed; tilegx_mnemonic padding_mnemonic; status = (*info->read_memory_func) (memaddr, opbuf, TILEGX_BUNDLE_SIZE_IN_BYTES, info); if (status != 0) { (*info->memory_error_func) (status, memaddr, info); return -1; } info->bytes_per_line = TILEGX_BUNDLE_SIZE_IN_BYTES; info->bytes_per_chunk = TILEGX_BUNDLE_SIZE_IN_BYTES; info->octets_per_byte = 1; info->display_endian = BFD_ENDIAN_LITTLE; /* Parse the instructions in the bundle. */ num_instructions = parse_insn_tilegx (bfd_getl64 (opbuf), memaddr, decoded); /* Print the instructions in the bundle. */ info->fprintf_func (info->stream, "{ "); num_printed = 0; /* Determine which nop opcode is used for padding and should be skipped. */ padding_mnemonic = TILEGX_OPC_FNOP; for (i = 0; i < num_instructions; i++) { if (!decoded[i].opcode->can_bundle) { /* Instructions that cannot be bundled are padded out with nops, rather than fnops. Displaying them is always clutter. */ padding_mnemonic = TILEGX_OPC_NOP; break; } } for (i = 0; i < num_instructions; i++) { const struct tilegx_opcode *opcode = decoded[i].opcode; const char *name; int j; /* Do not print out fnops, unless everything is an fnop, in which case we will print out just the last one. */ if (opcode->mnemonic == padding_mnemonic && (num_printed > 0 || i + 1 < num_instructions)) continue; if (num_printed > 0) info->fprintf_func (info->stream, " ; "); ++num_printed; name = opcode->name; if (name == NULL) name = ""; info->fprintf_func (info->stream, "%s", name); for (j = 0; j < opcode->num_operands; j++) { bfd_vma num; const struct tilegx_operand *op; const char *spr_name; if (j > 0) info->fprintf_func (info->stream, ","); info->fprintf_func (info->stream, " "); num = decoded[i].operand_values[j]; op = decoded[i].operands[j]; switch (op->type) { case TILEGX_OP_TYPE_REGISTER: info->fprintf_func (info->stream, "%s", tilegx_register_names[(int) num]); break; case TILEGX_OP_TYPE_SPR: spr_name = get_tilegx_spr_name (num); if (spr_name != NULL) info->fprintf_func (info->stream, "%s", spr_name); else info->fprintf_func (info->stream, "%d", (int)num); break; case TILEGX_OP_TYPE_IMMEDIATE: info->fprintf_func (info->stream, "%d", (int)num); break; case TILEGX_OP_TYPE_ADDRESS: info->print_address_func (num, info); break; default: abort (); } } } info->fprintf_func (info->stream, " }"); return TILEGX_BUNDLE_SIZE_IN_BYTES; }