diff options
Diffstat (limited to 'opcodes/tilegx-dis.c')
-rw-r--r-- | opcodes/tilegx-dis.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/opcodes/tilegx-dis.c b/opcodes/tilegx-dis.c new file mode 100644 index 0000000..3754756 --- /dev/null +++ b/opcodes/tilegx-dis.c @@ -0,0 +1,135 @@ +/* tilegx-dis.c. Disassembly routines for the TILE-Gx architecture. + Copyright 2011 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 <stddef.h> +#include <assert.h> +#include "bfd.h" +#include "elf/tilegx.h" +#include "elf-bfd.h" +#include "sysdep.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 = "<invalid>"; + 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; +} |