1 /* tilepro-dis.c. Disassembly routines for the TILEPro 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/tilepro.h" 26 #include "elf-bfd.h" 27 #include "dis-asm.h" 28 #include "opcode/tilepro.h" 29 30 31 #define TREG_ZERO 63 32 33 static int 34 contains_insn (tilepro_mnemonic expected_mnemonic, 35 int expected_first_operand, 36 int expected_second_operand, 37 bfd_vma memaddr, 38 int *last_operand_ret, 39 disassemble_info *info) 40 { 41 struct tilepro_decoded_instruction 42 decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE]; 43 bfd_byte opbuf[TILEPRO_BUNDLE_SIZE_IN_BYTES]; 44 int i, num_instructions; 45 46 if ((*info->read_memory_func) (memaddr, opbuf, 47 TILEPRO_BUNDLE_SIZE_IN_BYTES, info) != 0) 48 /* If we cannot even read the memory, it obviously does not have the 49 instruction for which we are looking. */ 50 return 0; 51 52 /* Parse the instructions in the bundle. */ 53 num_instructions = parse_insn_tilepro (bfd_getl64 (opbuf), memaddr, decoded); 54 55 for (i = 0; i < num_instructions; i++) 56 { 57 const struct tilepro_opcode *opcode = decoded[i].opcode; 58 59 if (opcode->mnemonic != expected_mnemonic) 60 continue; 61 62 if (expected_first_operand != -1 63 && decoded[i].operand_values[0] != expected_first_operand) 64 continue; 65 66 if (expected_second_operand != -1 67 && decoded[i].operand_values[1] != expected_second_operand) 68 continue; 69 70 *last_operand_ret = decoded[i].operand_values[opcode->num_operands - 1]; 71 return 1; 72 } 73 74 /* No match. */ 75 return 0; 76 } 77 78 79 int 80 print_insn_tilepro (bfd_vma memaddr, disassemble_info *info) 81 { 82 struct tilepro_decoded_instruction 83 decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE]; 84 bfd_byte opbuf[TILEPRO_BUNDLE_SIZE_IN_BYTES]; 85 int status, i, num_instructions, num_printed; 86 tilepro_mnemonic padding_mnemonic; 87 88 status = (*info->read_memory_func) (memaddr, opbuf, 89 TILEPRO_BUNDLE_SIZE_IN_BYTES, info); 90 if (status != 0) 91 { 92 (*info->memory_error_func) (status, memaddr, info); 93 return -1; 94 } 95 96 info->bytes_per_line = TILEPRO_BUNDLE_SIZE_IN_BYTES; 97 info->bytes_per_chunk = TILEPRO_BUNDLE_SIZE_IN_BYTES; 98 info->octets_per_byte = 1; 99 info->display_endian = BFD_ENDIAN_LITTLE; 100 101 /* Parse the instructions in the bundle. */ 102 num_instructions = parse_insn_tilepro (bfd_getl64 (opbuf), memaddr, decoded); 103 104 /* Print the instructions in the bundle. */ 105 info->fprintf_func (info->stream, "{ "); 106 num_printed = 0; 107 108 /* Determine which nop opcode is used for padding and should be skipped. */ 109 padding_mnemonic = TILEPRO_OPC_FNOP; 110 for (i = 0; i < num_instructions; i++) 111 { 112 if (!decoded[i].opcode->can_bundle) 113 { 114 /* Instructions that cannot be bundled are padded out with nops, 115 rather than fnops. Displaying them is always clutter. */ 116 padding_mnemonic = TILEPRO_OPC_NOP; 117 break; 118 } 119 } 120 121 for (i = 0; i < num_instructions; i++) 122 { 123 const struct tilepro_opcode *opcode = decoded[i].opcode; 124 const char *name; 125 int j; 126 127 /* Do not print out fnops, unless everything is an fnop, in 128 which case we will print out just the last one. */ 129 if (opcode->mnemonic == padding_mnemonic 130 && (num_printed > 0 || i + 1 < num_instructions)) 131 continue; 132 133 if (num_printed > 0) 134 info->fprintf_func (info->stream, " ; "); 135 ++num_printed; 136 137 name = opcode->name; 138 if (name == NULL) 139 name = "<invalid>"; 140 info->fprintf_func (info->stream, "%s", name); 141 142 for (j = 0; j < opcode->num_operands; j++) 143 { 144 int num; 145 const struct tilepro_operand *op; 146 const char *spr_name; 147 148 if (j > 0) 149 info->fprintf_func (info->stream, ","); 150 info->fprintf_func (info->stream, " "); 151 152 num = decoded[i].operand_values[j]; 153 154 op = decoded[i].operands[j]; 155 switch (op->type) 156 { 157 case TILEPRO_OP_TYPE_REGISTER: 158 info->fprintf_func (info->stream, "%s", 159 tilepro_register_names[num]); 160 break; 161 162 case TILEPRO_OP_TYPE_SPR: 163 spr_name = get_tilepro_spr_name(num); 164 if (spr_name != NULL) 165 info->fprintf_func (info->stream, "%s", spr_name); 166 else 167 info->fprintf_func (info->stream, "%d", num); 168 break; 169 170 case TILEPRO_OP_TYPE_IMMEDIATE: 171 { 172 bfd_vma addr = 0; 173 int found_addr = 0; 174 int addr_piece; 175 176 switch (opcode->mnemonic) 177 { 178 case TILEPRO_OPC_ADDLI: 179 if (contains_insn (TILEPRO_OPC_AULI, 180 decoded[i].operand_values[1], 181 TREG_ZERO, 182 memaddr - TILEPRO_BUNDLE_SIZE_IN_BYTES, 183 &addr_piece, 184 info)) 185 { 186 addr = num + (addr_piece << 16); 187 found_addr = 1; 188 } 189 break; 190 191 case TILEPRO_OPC_AULI: 192 if (contains_insn (TILEPRO_OPC_MOVELI, 193 decoded[i].operand_values[1], 194 -1, 195 memaddr - TILEPRO_BUNDLE_SIZE_IN_BYTES, 196 &addr_piece, 197 info)) 198 { 199 addr = (num << 16) + addr_piece; 200 found_addr = 1; 201 } 202 break; 203 204 default: 205 /* Operand does not look like a constructed address. */ 206 break; 207 } 208 209 info->fprintf_func (info->stream, "%d", num); 210 211 if (found_addr) 212 { 213 info->fprintf_func (info->stream, " /* "); 214 info->print_address_func (addr, info); 215 info->fprintf_func (info->stream, " */"); 216 } 217 } 218 break; 219 220 case TILEPRO_OP_TYPE_ADDRESS: 221 info->print_address_func ((bfd_vma)(unsigned int) num, info); 222 break; 223 224 default: 225 abort (); 226 } 227 } 228 } 229 info->fprintf_func (info->stream, " }"); 230 231 return TILEPRO_BUNDLE_SIZE_IN_BYTES; 232 } 233