1 /* tilegx-dis.c. Disassembly routines for the TILE-Gx architecture. 2 Copyright (C) 2011-2014 Free Software Foundation, Inc. 3 4 This file is part of the GNU opcodes library. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 #include "sysdep.h" 22 #include <stddef.h> 23 #include <assert.h> 24 #include "bfd.h" 25 #include "elf/tilegx.h" 26 #include "elf-bfd.h" 27 #include "dis-asm.h" 28 #include "opcode/tilegx.h" 29 30 31 int 32 print_insn_tilegx (bfd_vma memaddr, disassemble_info *info) 33 { 34 struct tilegx_decoded_instruction 35 decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE]; 36 bfd_byte opbuf[TILEGX_BUNDLE_SIZE_IN_BYTES]; 37 int status, i, num_instructions, num_printed; 38 tilegx_mnemonic padding_mnemonic; 39 40 status = (*info->read_memory_func) (memaddr, opbuf, 41 TILEGX_BUNDLE_SIZE_IN_BYTES, info); 42 if (status != 0) 43 { 44 (*info->memory_error_func) (status, memaddr, info); 45 return -1; 46 } 47 48 info->bytes_per_line = TILEGX_BUNDLE_SIZE_IN_BYTES; 49 info->bytes_per_chunk = TILEGX_BUNDLE_SIZE_IN_BYTES; 50 info->octets_per_byte = 1; 51 info->display_endian = BFD_ENDIAN_LITTLE; 52 53 /* Parse the instructions in the bundle. */ 54 num_instructions = 55 parse_insn_tilegx (bfd_getl64 (opbuf), memaddr, decoded); 56 57 /* Print the instructions in the bundle. */ 58 info->fprintf_func (info->stream, "{ "); 59 num_printed = 0; 60 61 /* Determine which nop opcode is used for padding and should be skipped. */ 62 padding_mnemonic = TILEGX_OPC_FNOP; 63 for (i = 0; i < num_instructions; i++) 64 { 65 if (!decoded[i].opcode->can_bundle) 66 { 67 /* Instructions that cannot be bundled are padded out with nops, 68 rather than fnops. Displaying them is always clutter. */ 69 padding_mnemonic = TILEGX_OPC_NOP; 70 break; 71 } 72 } 73 74 for (i = 0; i < num_instructions; i++) 75 { 76 const struct tilegx_opcode *opcode = decoded[i].opcode; 77 const char *name; 78 int j; 79 80 /* Do not print out fnops, unless everything is an fnop, in 81 which case we will print out just the last one. */ 82 if (opcode->mnemonic == padding_mnemonic 83 && (num_printed > 0 || i + 1 < num_instructions)) 84 continue; 85 86 if (num_printed > 0) 87 info->fprintf_func (info->stream, " ; "); 88 ++num_printed; 89 90 name = opcode->name; 91 if (name == NULL) 92 name = "<invalid>"; 93 info->fprintf_func (info->stream, "%s", name); 94 95 for (j = 0; j < opcode->num_operands; j++) 96 { 97 bfd_vma num; 98 const struct tilegx_operand *op; 99 const char *spr_name; 100 101 if (j > 0) 102 info->fprintf_func (info->stream, ","); 103 info->fprintf_func (info->stream, " "); 104 105 num = decoded[i].operand_values[j]; 106 107 op = decoded[i].operands[j]; 108 switch (op->type) 109 { 110 case TILEGX_OP_TYPE_REGISTER: 111 info->fprintf_func (info->stream, "%s", 112 tilegx_register_names[(int) num]); 113 break; 114 case TILEGX_OP_TYPE_SPR: 115 spr_name = get_tilegx_spr_name (num); 116 if (spr_name != NULL) 117 info->fprintf_func (info->stream, "%s", spr_name); 118 else 119 info->fprintf_func (info->stream, "%d", (int)num); 120 break; 121 case TILEGX_OP_TYPE_IMMEDIATE: 122 info->fprintf_func (info->stream, "%d", (int)num); 123 break; 124 case TILEGX_OP_TYPE_ADDRESS: 125 info->print_address_func (num, info); 126 break; 127 default: 128 abort (); 129 } 130 } 131 } 132 info->fprintf_func (info->stream, " }"); 133 134 return TILEGX_BUNDLE_SIZE_IN_BYTES; 135 } 136