From 54f1b3cf509cd889905287cb8ce6c5ae33911a21 Mon Sep 17 00:00:00 2001 From: Andrew Hsieh Date: Fri, 13 Jun 2014 12:38:00 -0700 Subject: Add upstream binutils-2.25 snapshot 4/4 2014 For MIPS -mmsa support Change-Id: I08c4f002fa7b33dec85ed75956e6ab551bb03c96 --- binutils-2.25/opcodes/tilepro-dis.c | 232 ++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 binutils-2.25/opcodes/tilepro-dis.c (limited to 'binutils-2.25/opcodes/tilepro-dis.c') diff --git a/binutils-2.25/opcodes/tilepro-dis.c b/binutils-2.25/opcodes/tilepro-dis.c new file mode 100644 index 00000000..a0a8c9a7 --- /dev/null +++ b/binutils-2.25/opcodes/tilepro-dis.c @@ -0,0 +1,232 @@ +/* tilepro-dis.c. Disassembly routines for the TILEPro architecture. + Copyright 2011, 2012 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/tilepro.h" +#include "elf-bfd.h" +#include "dis-asm.h" +#include "opcode/tilepro.h" + + +#define TREG_ZERO 63 + +static int +contains_insn (tilepro_mnemonic expected_mnemonic, + int expected_first_operand, + int expected_second_operand, + bfd_vma memaddr, + int *last_operand_ret, + disassemble_info *info) +{ + struct tilepro_decoded_instruction + decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE]; + bfd_byte opbuf[TILEPRO_BUNDLE_SIZE_IN_BYTES]; + int i, num_instructions; + + if ((*info->read_memory_func) (memaddr, opbuf, + TILEPRO_BUNDLE_SIZE_IN_BYTES, info) != 0) + /* If we cannot even read the memory, it obviously does not have the + instruction for which we are looking. */ + return 0; + + /* Parse the instructions in the bundle. */ + num_instructions = parse_insn_tilepro (bfd_getl64 (opbuf), memaddr, decoded); + + for (i = 0; i < num_instructions; i++) + { + const struct tilepro_opcode *opcode = decoded[i].opcode; + + if (opcode->mnemonic != expected_mnemonic) + continue; + + if (expected_first_operand != -1 + && decoded[i].operand_values[0] != expected_first_operand) + continue; + + if (expected_second_operand != -1 + && decoded[i].operand_values[1] != expected_second_operand) + continue; + + *last_operand_ret = decoded[i].operand_values[opcode->num_operands - 1]; + return 1; + } + + /* No match. */ + return 0; +} + + +int +print_insn_tilepro (bfd_vma memaddr, disassemble_info *info) +{ + struct tilepro_decoded_instruction + decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE]; + bfd_byte opbuf[TILEPRO_BUNDLE_SIZE_IN_BYTES]; + int status, i, num_instructions, num_printed; + tilepro_mnemonic padding_mnemonic; + + status = (*info->read_memory_func) (memaddr, opbuf, + TILEPRO_BUNDLE_SIZE_IN_BYTES, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + info->bytes_per_line = TILEPRO_BUNDLE_SIZE_IN_BYTES; + info->bytes_per_chunk = TILEPRO_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_tilepro (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 = TILEPRO_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 = TILEPRO_OPC_NOP; + break; + } + } + + for (i = 0; i < num_instructions; i++) + { + const struct tilepro_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++) + { + int num; + const struct tilepro_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 TILEPRO_OP_TYPE_REGISTER: + info->fprintf_func (info->stream, "%s", + tilepro_register_names[num]); + break; + + case TILEPRO_OP_TYPE_SPR: + spr_name = get_tilepro_spr_name(num); + if (spr_name != NULL) + info->fprintf_func (info->stream, "%s", spr_name); + else + info->fprintf_func (info->stream, "%d", num); + break; + + case TILEPRO_OP_TYPE_IMMEDIATE: + { + bfd_vma addr = 0; + int found_addr = 0; + int addr_piece; + + switch (opcode->mnemonic) + { + case TILEPRO_OPC_ADDLI: + if (contains_insn (TILEPRO_OPC_AULI, + decoded[i].operand_values[1], + TREG_ZERO, + memaddr - TILEPRO_BUNDLE_SIZE_IN_BYTES, + &addr_piece, + info)) + { + addr = num + (addr_piece << 16); + found_addr = 1; + } + break; + + case TILEPRO_OPC_AULI: + if (contains_insn (TILEPRO_OPC_MOVELI, + decoded[i].operand_values[1], + -1, + memaddr - TILEPRO_BUNDLE_SIZE_IN_BYTES, + &addr_piece, + info)) + { + addr = (num << 16) + addr_piece; + found_addr = 1; + } + break; + + default: + /* Operand does not look like a constructed address. */ + break; + } + + info->fprintf_func (info->stream, "%d", num); + + if (found_addr) + { + info->fprintf_func (info->stream, " /* "); + info->print_address_func (addr, info); + info->fprintf_func (info->stream, " */"); + } + } + break; + + case TILEPRO_OP_TYPE_ADDRESS: + info->print_address_func ((bfd_vma)(unsigned int) num, info); + break; + + default: + abort (); + } + } + } + info->fprintf_func (info->stream, " }"); + + return TILEPRO_BUNDLE_SIZE_IN_BYTES; +} -- cgit v1.2.3