Home | History | Annotate | Download | only in opcodes
      1 /* tilegx-dis.c.  Disassembly routines for the TILE-Gx architecture.
      2    Copyright (C) 2011-2016 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