(root)/
binutils-2.41/
opcodes/
tilepro-dis.c
       1  /* tilepro-dis.c.  Disassembly routines for the TILEPro architecture.
       2     Copyright (C) 2011-2023 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 "disassemble.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  }