|  | /* tilegx-dis.c.  Disassembly routines for the TILE-Gx architecture. | 
|  | Copyright (C) 2011-2025 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 <stddef.h> | 
|  | #include <assert.h> | 
|  | #include "bfd.h" | 
|  | #include "elf/tilegx.h" | 
|  | #include "elf-bfd.h" | 
|  | #include "disassemble.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; | 
|  | } |