1230025Sed/* tilepro-dis.c. Disassembly routines for the TILEPro architecture. 2230025Sed Copyright (C) 2011-2022 Free Software Foundation, Inc. 3230025Sed 4230025Sed This file is part of the GNU opcodes library. 5230025Sed 6230025Sed This program is free software; you can redistribute it and/or modify 7230025Sed it under the terms of the GNU General Public License as published by 8230025Sed the Free Software Foundation; either version 3 of the License, or 9230025Sed (at your option) any later version. 10230025Sed 11230025Sed This program is distributed in the hope that it will be useful, 12230025Sed but WITHOUT ANY WARRANTY; without even the implied warranty of 13230025Sed MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14230025Sed GNU General Public License for more details. 15230025Sed 16230025Sed You should have received a copy of the GNU General Public License 17230025Sed along with this program; if not, write to the Free Software 18230025Sed Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19230025Sed MA 02110-1301, USA. */ 20230025Sed 21230025Sed#include "sysdep.h" 22230025Sed#include <stddef.h> 23230025Sed#include <assert.h> 24230025Sed#include "bfd.h" 25230025Sed#include "elf/tilepro.h" 26230025Sed#include "elf-bfd.h" 27230025Sed#include "disassemble.h" 28230025Sed#include "opcode/tilepro.h" 29230025Sed 30230025Sed 31230025Sed#define TREG_ZERO 63 32230025Sed 33230025Sedstatic int 34230025Sedcontains_insn (tilepro_mnemonic expected_mnemonic, 35230025Sed int expected_first_operand, 36230025Sed int expected_second_operand, 37230025Sed bfd_vma memaddr, 38230025Sed int *last_operand_ret, 39230025Sed disassemble_info *info) 40230025Sed{ 41230025Sed struct tilepro_decoded_instruction 42230025Sed decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE]; 43230025Sed bfd_byte opbuf[TILEPRO_BUNDLE_SIZE_IN_BYTES]; 44230025Sed int i, num_instructions; 45230025Sed 46230025Sed if ((*info->read_memory_func) (memaddr, opbuf, 47230025Sed TILEPRO_BUNDLE_SIZE_IN_BYTES, info) != 0) 48230025Sed /* If we cannot even read the memory, it obviously does not have the 49230025Sed instruction for which we are looking. */ 50235389Smarius return 0; 51230025Sed 52230025Sed /* Parse the instructions in the bundle. */ 53230025Sed num_instructions = parse_insn_tilepro (bfd_getl64 (opbuf), memaddr, decoded); 54235389Smarius 55235389Smarius for (i = 0; i < num_instructions; i++) 56230025Sed { 57230025Sed const struct tilepro_opcode *opcode = decoded[i].opcode; 58230025Sed 59230025Sed if (opcode->mnemonic != expected_mnemonic) 60230025Sed continue; 61230025Sed 62230025Sed if (expected_first_operand != -1 63230025Sed && decoded[i].operand_values[0] != expected_first_operand) 64230025Sed continue; 65230025Sed 66230025Sed if (expected_second_operand != -1 67230025Sed && decoded[i].operand_values[1] != expected_second_operand) 68230025Sed continue; 69230025Sed 70230025Sed *last_operand_ret = decoded[i].operand_values[opcode->num_operands - 1]; 71230025Sed return 1; 72230025Sed } 73230025Sed 74230025Sed /* No match. */ 75230025Sed return 0; 76230025Sed} 77230025Sed 78230025Sed 79230025Sedint 80230025Sedprint_insn_tilepro (bfd_vma memaddr, disassemble_info *info) 81230025Sed{ 82230025Sed struct tilepro_decoded_instruction 83230025Sed decoded[TILEPRO_MAX_INSTRUCTIONS_PER_BUNDLE]; 84230025Sed bfd_byte opbuf[TILEPRO_BUNDLE_SIZE_IN_BYTES]; 85230025Sed int status, i, num_instructions, num_printed; 86230025Sed tilepro_mnemonic padding_mnemonic; 87230025Sed 88230025Sed status = (*info->read_memory_func) (memaddr, opbuf, 89230025Sed TILEPRO_BUNDLE_SIZE_IN_BYTES, info); 90230025Sed if (status != 0) 91230025Sed { 92230025Sed (*info->memory_error_func) (status, memaddr, info); 93230025Sed return -1; 94230025Sed } 95230025Sed 96230025Sed info->bytes_per_line = TILEPRO_BUNDLE_SIZE_IN_BYTES; 97230025Sed info->bytes_per_chunk = TILEPRO_BUNDLE_SIZE_IN_BYTES; 98230025Sed info->octets_per_byte = 1; 99230025Sed info->display_endian = BFD_ENDIAN_LITTLE; 100230025Sed 101230025Sed /* Parse the instructions in the bundle. */ 102230025Sed num_instructions = parse_insn_tilepro (bfd_getl64 (opbuf), memaddr, decoded); 103230025Sed 104230025Sed /* Print the instructions in the bundle. */ 105230025Sed info->fprintf_func (info->stream, "{ "); 106230025Sed num_printed = 0; 107230025Sed 108230025Sed /* Determine which nop opcode is used for padding and should be skipped. */ 109230025Sed padding_mnemonic = TILEPRO_OPC_FNOP; 110230025Sed for (i = 0; i < num_instructions; i++) 111230025Sed { 112230025Sed if (!decoded[i].opcode->can_bundle) 113230025Sed { 114230025Sed /* Instructions that cannot be bundled are padded out with nops, 115230025Sed rather than fnops. Displaying them is always clutter. */ 116230025Sed padding_mnemonic = TILEPRO_OPC_NOP; 117230025Sed break; 118230025Sed } 119230025Sed } 120230025Sed 121230025Sed for (i = 0; i < num_instructions; i++) 122230025Sed { 123230025Sed const struct tilepro_opcode *opcode = decoded[i].opcode; 124230025Sed const char *name; 125230025Sed int j; 126230025Sed 127230025Sed /* Do not print out fnops, unless everything is an fnop, in 128230025Sed which case we will print out just the last one. */ 129235389Smarius if (opcode->mnemonic == padding_mnemonic 130235389Smarius && (num_printed > 0 || i + 1 < num_instructions)) 131230025Sed continue; 132230025Sed 133230025Sed if (num_printed > 0) 134230025Sed info->fprintf_func (info->stream, " ; "); 135230025Sed ++num_printed; 136230025Sed 137230025Sed name = opcode->name; 138230025Sed if (name == NULL) 139230025Sed name = "<invalid>"; 140230025Sed info->fprintf_func (info->stream, "%s", name); 141230025Sed 142230025Sed for (j = 0; j < opcode->num_operands; j++) 143230025Sed { 144230025Sed int num; 145230025Sed const struct tilepro_operand *op; 146230025Sed const char *spr_name; 147235389Smarius 148235389Smarius if (j > 0) 149230025Sed info->fprintf_func (info->stream, ","); 150230025Sed info->fprintf_func (info->stream, " "); 151230025Sed 152230025Sed num = decoded[i].operand_values[j]; 153230025Sed 154230025Sed op = decoded[i].operands[j]; 155230025Sed switch (op->type) 156230025Sed { 157230025Sed case TILEPRO_OP_TYPE_REGISTER: 158230025Sed info->fprintf_func (info->stream, "%s", 159230025Sed tilepro_register_names[num]); 160230025Sed break; 161230025Sed 162230025Sed case TILEPRO_OP_TYPE_SPR: 163230025Sed spr_name = get_tilepro_spr_name(num); 164230025Sed if (spr_name != NULL) 165230025Sed info->fprintf_func (info->stream, "%s", spr_name); 166230025Sed else 167230025Sed info->fprintf_func (info->stream, "%d", num); 168230025Sed break; 169230025Sed 170230025Sed case TILEPRO_OP_TYPE_IMMEDIATE: 171230025Sed { 172230025Sed bfd_vma addr = 0; 173230025Sed int found_addr = 0; 174230025Sed int addr_piece; 175230025Sed 176230025Sed switch (opcode->mnemonic) 177230025Sed { 178230025Sed case TILEPRO_OPC_ADDLI: 179230025Sed if (contains_insn (TILEPRO_OPC_AULI, 180230025Sed decoded[i].operand_values[1], 181230025Sed TREG_ZERO, 182230025Sed memaddr - TILEPRO_BUNDLE_SIZE_IN_BYTES, 183230025Sed &addr_piece, 184230025Sed info)) 185230025Sed { 186230025Sed addr = num + (addr_piece << 16); 187230025Sed found_addr = 1; 188230025Sed } 189230025Sed break; 190230025Sed 191230025Sed case TILEPRO_OPC_AULI: 192230025Sed if (contains_insn (TILEPRO_OPC_MOVELI, 193230025Sed decoded[i].operand_values[1], 194230025Sed -1, 195230025Sed memaddr - TILEPRO_BUNDLE_SIZE_IN_BYTES, 196230025Sed &addr_piece, 197230025Sed info)) 198230025Sed { 199230025Sed addr = (num << 16) + addr_piece; 200230025Sed found_addr = 1; 201230025Sed } 202230025Sed break; 203230025Sed 204230025Sed default: 205230025Sed /* Operand does not look like a constructed address. */ 206230025Sed break; 207230025Sed } 208230025Sed 209230025Sed info->fprintf_func (info->stream, "%d", num); 210230025Sed 211230025Sed if (found_addr) 212230025Sed { 213230025Sed info->fprintf_func (info->stream, " /* "); 214230025Sed info->print_address_func (addr, info); 215230025Sed info->fprintf_func (info->stream, " */"); 216230025Sed } 217230025Sed } 218230025Sed break; 219230025Sed 220230025Sed case TILEPRO_OP_TYPE_ADDRESS: 221230025Sed info->print_address_func ((bfd_vma)(unsigned int) num, info); 222230025Sed break; 223230025Sed 224230025Sed default: 225230025Sed abort (); 226230025Sed } 227230025Sed } 228230025Sed } 229230025Sed info->fprintf_func (info->stream, " }"); 230230025Sed 231230025Sed return TILEPRO_BUNDLE_SIZE_IN_BYTES; 232230025Sed} 233230025Sed