Home | History | Annotate | Download | only in opcodes
      1 /* Disassemble SH64 instructions.
      2    Copyright (C) 2000-2014 Free Software Foundation, Inc.
      3 
      4    This file is part of the GNU opcodes library.
      5 
      6    This library 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, or (at your option)
      9    any later version.
     10 
     11    It is distributed in the hope that it will be useful, but WITHOUT
     12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     14    License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this file; see the file COPYING.  If not, write to the
     18    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
     19    MA 02110-1301, USA.  */
     20 
     21 #include "sysdep.h"
     22 #include <stdio.h>
     23 #include "dis-asm.h"
     24 #include "sh64-opc.h"
     25 #include "libiberty.h"
     26 /* We need to refer to the ELF header structure.  */
     27 #include "elf-bfd.h"
     28 #include "elf/sh.h"
     29 #include "elf32-sh64.h"
     30 
     31 #define ELF_MODE32_CODE_LABEL_P(SYM) \
     32  (((elf_symbol_type *) (SYM))->internal_elf_sym.st_other & STO_SH5_ISA32)
     33 
     34 #define SAVED_MOVI_R(INFO) \
     35  (((struct sh64_disassemble_info *) ((INFO)->private_data))->address_reg)
     36 
     37 #define SAVED_MOVI_IMM(INFO) \
     38  (((struct sh64_disassemble_info *) ((INFO)->private_data))->built_address)
     39 
     40 struct sh64_disassemble_info
     41  {
     42    /* When we see a MOVI, we save the register and the value, and merge a
     43       subsequent SHORI and display the address, if there is one.  */
     44    unsigned int address_reg;
     45    bfd_signed_vma built_address;
     46 
     47    /* This is the range decriptor for the current address.  It is kept
     48       around for the next call.  */
     49    sh64_elf_crange crange;
     50  };
     51 
     52 /* Each item in the table is a mask to indicate which bits to be set
     53    to determine an instruction's operator.
     54    The index is as same as the instruction in the opcode table.
     55    Note that some archs have this as a field in the opcode table.  */
     56 static unsigned long *shmedia_opcode_mask_table;
     57 
     58 /* Initialize the SH64 opcode mask table for each instruction in SHmedia
     59    mode.  */
     60 
     61 static void
     62 initialize_shmedia_opcode_mask_table (void)
     63 {
     64   int n_opc;
     65   int n;
     66 
     67   /* Calculate number of opcodes.  */
     68   for (n_opc = 0; shmedia_table[n_opc].name != NULL; n_opc++)
     69     ;
     70 
     71   shmedia_opcode_mask_table
     72     = xmalloc (sizeof (shmedia_opcode_mask_table[0]) * n_opc);
     73 
     74   for (n = 0; n < n_opc; n++)
     75     {
     76       int i;
     77 
     78       unsigned long mask = 0;
     79 
     80       for (i = 0; shmedia_table[n].arg[i] != A_NONE; i++)
     81 	{
     82 	  int offset = shmedia_table[n].nibbles[i];
     83 	  int length;
     84 
     85 	  switch (shmedia_table[n].arg[i])
     86 	    {
     87 	    case A_GREG_M:
     88 	    case A_GREG_N:
     89 	    case A_GREG_D:
     90 	    case A_CREG_K:
     91 	    case A_CREG_J:
     92 	    case A_FREG_G:
     93 	    case A_FREG_H:
     94 	    case A_FREG_F:
     95 	    case A_DREG_G:
     96 	    case A_DREG_H:
     97 	    case A_DREG_F:
     98 	    case A_FMREG_G:
     99 	    case A_FMREG_H:
    100 	    case A_FMREG_F:
    101 	    case A_FPREG_G:
    102 	    case A_FPREG_H:
    103 	    case A_FPREG_F:
    104 	    case A_FVREG_G:
    105 	    case A_FVREG_H:
    106 	    case A_FVREG_F:
    107 	    case A_REUSE_PREV:
    108 	      length = 6;
    109 	      break;
    110 
    111 	    case A_TREG_A:
    112 	    case A_TREG_B:
    113 	      length = 3;
    114 	      break;
    115 
    116 	    case A_IMMM:
    117 	      abort ();
    118 	      break;
    119 
    120 	    case A_IMMU5:
    121 	      length = 5;
    122 	      break;
    123 
    124 	    case A_IMMS6:
    125 	    case A_IMMU6:
    126 	    case A_IMMS6BY32:
    127 	      length = 6;
    128 	      break;
    129 
    130 	    case A_IMMS10:
    131 	    case A_IMMS10BY1:
    132 	    case A_IMMS10BY2:
    133 	    case A_IMMS10BY4:
    134 	    case A_IMMS10BY8:
    135 	      length = 10;
    136 	      break;
    137 
    138 	    case A_IMMU16:
    139 	    case A_IMMS16:
    140 	    case A_PCIMMS16BY4:
    141 	    case A_PCIMMS16BY4_PT:
    142 	      length = 16;
    143 	      break;
    144 
    145 	    default:
    146 	      abort ();
    147 	      length = 0;
    148 	      break;
    149 	    }
    150 
    151 	  if (length != 0)
    152 	    mask |= (0xffffffff >> (32 - length)) << offset;
    153 	}
    154       shmedia_opcode_mask_table[n] = 0xffffffff & ~mask;
    155     }
    156 }
    157 
    158 /* Get a predefined control-register-name, or return NULL.  */
    159 
    160 static const char *
    161 creg_name (int cregno)
    162 {
    163   const shmedia_creg_info *cregp;
    164 
    165   /* If control register usage is common enough, change this to search a
    166      hash-table.  */
    167   for (cregp = shmedia_creg_table; cregp->name != NULL; cregp++)
    168     if (cregp->cregno == cregno)
    169       return cregp->name;
    170 
    171   return NULL;
    172 }
    173 
    174 /* Main function to disassemble SHmedia instructions.  */
    175 
    176 static int
    177 print_insn_shmedia (bfd_vma memaddr, struct disassemble_info *info)
    178 {
    179   fprintf_ftype fprintf_fn = info->fprintf_func;
    180   void *stream = info->stream;
    181   unsigned char insn[4];
    182   unsigned long instruction;
    183   int status;
    184   int n;
    185   const shmedia_opcode_info *op;
    186   int i;
    187   unsigned int r = 0;
    188   long imm = 0;
    189   bfd_vma disp_pc_addr;
    190 
    191   status = info->read_memory_func (memaddr, insn, 4, info);
    192 
    193   /* If we can't read four bytes, something is wrong.  Display any data we
    194      can get as .byte:s.  */
    195   if (status != 0)
    196     {
    197       for (i = 0; i < 3; i++)
    198 	{
    199 	  status = info->read_memory_func (memaddr + i, insn, 1, info);
    200 	  if (status != 0)
    201 	    break;
    202 	  (*fprintf_fn) (stream, "%s0x%02x",
    203 			 i == 0 ? ".byte " : ", ",
    204 			 insn[0]);
    205 	}
    206 
    207       return i ? i : -1;
    208     }
    209 
    210   /* Rearrange the bytes to make up an instruction.  */
    211   if (info->endian == BFD_ENDIAN_LITTLE)
    212     instruction = bfd_getl32 (insn);
    213   else
    214     instruction = bfd_getb32 (insn);
    215 
    216   /* FIXME: Searching could be implemented using a hash on relevant
    217      fields.  */
    218   for (n = 0, op = shmedia_table;
    219        op->name != NULL
    220        && ((instruction & shmedia_opcode_mask_table[n]) != op->opcode_base);
    221        n++, op++)
    222     ;
    223 
    224   /* FIXME: We should also check register number constraints.  */
    225   if (op->name == NULL)
    226     {
    227       fprintf_fn (stream, ".long 0x%08lx", instruction);
    228       return 4;
    229     }
    230 
    231   fprintf_fn (stream, "%s\t", op->name);
    232 
    233   for (i = 0; i < 3 && op->arg[i] != A_NONE; i++)
    234     {
    235       unsigned long temp = instruction >> op->nibbles[i];
    236       int by_number = 0;
    237 
    238       if (i > 0 && op->arg[i] != A_REUSE_PREV)
    239 	fprintf_fn (stream, ",");
    240 
    241       switch (op->arg[i])
    242 	{
    243 	case A_REUSE_PREV:
    244 	  continue;
    245 
    246 	case A_GREG_M:
    247 	case A_GREG_N:
    248 	case A_GREG_D:
    249 	  r = temp & 0x3f;
    250 	  fprintf_fn (stream, "r%d", r);
    251 	  break;
    252 
    253 	case A_FVREG_F:
    254 	case A_FVREG_G:
    255 	case A_FVREG_H:
    256 	  r = temp & 0x3f;
    257 	  fprintf_fn (stream, "fv%d", r);
    258 	  break;
    259 
    260 	case A_FPREG_F:
    261 	case A_FPREG_G:
    262 	case A_FPREG_H:
    263 	  r = temp & 0x3f;
    264 	  fprintf_fn (stream, "fp%d", r);
    265 	  break;
    266 
    267 	case A_FMREG_F:
    268 	case A_FMREG_G:
    269 	case A_FMREG_H:
    270 	  r = temp & 0x3f;
    271 	  fprintf_fn (stream, "mtrx%d", r);
    272 	  break;
    273 
    274 	case A_CREG_K:
    275 	case A_CREG_J:
    276 	  {
    277 	    const char *name;
    278 
    279 	    r = temp & 0x3f;
    280 
    281 	    name = creg_name (r);
    282 
    283 	    if (name != NULL)
    284 	      fprintf_fn (stream, "%s", name);
    285 	    else
    286 	      fprintf_fn (stream, "cr%d", r);
    287 	  }
    288 	  break;
    289 
    290 	case A_FREG_G:
    291 	case A_FREG_H:
    292 	case A_FREG_F:
    293 	  r = temp & 0x3f;
    294 	  fprintf_fn (stream, "fr%d", r);
    295 	  break;
    296 
    297 	case A_DREG_G:
    298 	case A_DREG_H:
    299 	case A_DREG_F:
    300 	  r = temp & 0x3f;
    301 	  fprintf_fn (stream, "dr%d", r);
    302 	  break;
    303 
    304 	case A_TREG_A:
    305 	case A_TREG_B:
    306 	  r = temp & 0x7;
    307 	  fprintf_fn (stream, "tr%d", r);
    308 	  break;
    309 
    310 	  /* A signed 6-bit number.  */
    311 	case A_IMMS6:
    312 	  imm = temp & 0x3f;
    313 	  if (imm & (unsigned long) 0x20)
    314 	    imm |= ~(unsigned long) 0x3f;
    315 	  fprintf_fn (stream, "%ld", imm);
    316 	  break;
    317 
    318 	  /* A signed 6-bit number, multiplied by 32 when used.  */
    319 	case A_IMMS6BY32:
    320 	  imm = temp & 0x3f;
    321 	  if (imm & (unsigned long) 0x20)
    322 	    imm |= ~(unsigned long) 0x3f;
    323 	  fprintf_fn (stream, "%ld", imm * 32);
    324 	  break;
    325 
    326 	  /* A signed 10-bit number, multiplied by 8 when used.  */
    327 	case A_IMMS10BY8:
    328 	  by_number++;
    329 	  /* Fall through.  */
    330 
    331 	  /* A signed 10-bit number, multiplied by 4 when used.  */
    332 	case A_IMMS10BY4:
    333 	  by_number++;
    334 	  /* Fall through.  */
    335 
    336 	  /* A signed 10-bit number, multiplied by 2 when used.  */
    337 	case A_IMMS10BY2:
    338 	  by_number++;
    339 	  /* Fall through.  */
    340 
    341 	  /* A signed 10-bit number.  */
    342 	case A_IMMS10:
    343 	case A_IMMS10BY1:
    344 	  imm = temp & 0x3ff;
    345 	  if (imm & (unsigned long) 0x200)
    346 	    imm |= ~(unsigned long) 0x3ff;
    347 	  imm <<= by_number;
    348 	  fprintf_fn (stream, "%ld", imm);
    349 	  break;
    350 
    351 	  /* A signed 16-bit number.  */
    352 	case A_IMMS16:
    353 	  imm = temp & 0xffff;
    354 	  if (imm & (unsigned long) 0x8000)
    355 	    imm |= ~((unsigned long) 0xffff);
    356 	  fprintf_fn (stream, "%ld", imm);
    357 	  break;
    358 
    359 	  /* A PC-relative signed 16-bit number, multiplied by 4 when
    360 	     used.  */
    361 	case A_PCIMMS16BY4:
    362 	  imm = temp & 0xffff;	/* 16 bits */
    363 	  if (imm & (unsigned long) 0x8000)
    364 	    imm |= ~(unsigned long) 0xffff;
    365 	  imm <<= 2;
    366 	  disp_pc_addr = (bfd_vma) imm + memaddr;
    367 	  (*info->print_address_func) (disp_pc_addr, info);
    368 	  break;
    369 
    370 	  /* An unsigned 5-bit number.  */
    371 	case A_IMMU5:
    372 	  imm = temp & 0x1f;
    373 	  fprintf_fn (stream, "%ld", imm);
    374 	  break;
    375 
    376 	  /* An unsigned 6-bit number.  */
    377 	case A_IMMU6:
    378 	  imm = temp & 0x3f;
    379 	  fprintf_fn (stream, "%ld", imm);
    380 	  break;
    381 
    382 	  /* An unsigned 16-bit number.  */
    383 	case A_IMMU16:
    384 	  imm = temp & 0xffff;
    385 	  fprintf_fn (stream, "%ld", imm);
    386 	  break;
    387 
    388 	default:
    389 	  abort ();
    390 	  break;
    391 	}
    392     }
    393 
    394   /* FIXME: Looks like 32-bit values only are handled.
    395      FIXME: PC-relative numbers aren't handled correctly.  */
    396   if (op->opcode_base == (unsigned long) SHMEDIA_SHORI_OPC
    397       && SAVED_MOVI_R (info) == r)
    398     {
    399       asection *section = info->section;
    400 
    401       /* Most callers do not set the section field correctly yet.  Revert
    402 	 to getting the section from symbols, if any. */
    403       if (section == NULL
    404 	  && info->symbols != NULL
    405 	  && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
    406 	  && ! bfd_is_und_section (bfd_get_section (info->symbols[0]))
    407 	  && ! bfd_is_abs_section (bfd_get_section (info->symbols[0])))
    408 	section = bfd_get_section (info->symbols[0]);
    409 
    410       /* Only guess addresses when the contents of this section is fully
    411 	 relocated.  Otherwise, the value will be zero or perhaps even
    412 	 bogus.  */
    413       if (section == NULL
    414 	  || section->owner == NULL
    415 	  || elf_elfheader (section->owner)->e_type == ET_EXEC)
    416 	{
    417 	  bfd_signed_vma shori_addr;
    418 
    419 	  shori_addr = SAVED_MOVI_IMM (info) << 16;
    420 	  shori_addr |= imm;
    421 
    422 	  fprintf_fn (stream, "\t! 0x");
    423 	  (*info->print_address_func) (shori_addr, info);
    424 	}
    425     }
    426 
    427   if (op->opcode_base == SHMEDIA_MOVI_OPC)
    428     {
    429       SAVED_MOVI_IMM (info) = imm;
    430       SAVED_MOVI_R (info) = r;
    431     }
    432   else
    433     {
    434       SAVED_MOVI_IMM (info) = 0;
    435       SAVED_MOVI_R (info) = 255;
    436     }
    437 
    438   return 4;
    439 }
    440 
    441 /* Check the type of contents about to be disassembled.  This is like
    442    sh64_get_contents_type (which may be called from here), except that it
    443    takes the same arguments as print_insn_* and does what can be done if
    444    no section is available.  */
    445 
    446 static enum sh64_elf_cr_type
    447 sh64_get_contents_type_disasm (bfd_vma memaddr, struct disassemble_info *info)
    448 {
    449   struct sh64_disassemble_info *sh64_infop = info->private_data;
    450 
    451   /* Perhaps we have a region from a previous probe and it still counts
    452      for this address?  */
    453   if (sh64_infop->crange.cr_type != CRT_NONE
    454       && memaddr >= sh64_infop->crange.cr_addr
    455       && memaddr < sh64_infop->crange.cr_addr + sh64_infop->crange.cr_size)
    456     return sh64_infop->crange.cr_type;
    457 
    458   /* If we have a section, try and use it.  */
    459   if (info->section
    460       && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour)
    461     {
    462       enum sh64_elf_cr_type cr_type
    463 	= sh64_get_contents_type (info->section, memaddr,
    464 				  &sh64_infop->crange);
    465 
    466       if (cr_type != CRT_NONE)
    467 	return cr_type;
    468     }
    469 
    470   /* If we have symbols, we can try and get at a section from *that*.  */
    471   if (info->symbols != NULL
    472       && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
    473       && ! bfd_is_und_section (bfd_get_section (info->symbols[0]))
    474       && ! bfd_is_abs_section (bfd_get_section (info->symbols[0])))
    475     {
    476       enum sh64_elf_cr_type cr_type
    477 	= sh64_get_contents_type (bfd_get_section (info->symbols[0]),
    478 				  memaddr, &sh64_infop->crange);
    479 
    480       if (cr_type != CRT_NONE)
    481 	return cr_type;
    482     }
    483 
    484   /* We can make a reasonable guess based on the st_other field of a
    485      symbol; for a BranchTarget this is marked as STO_SH5_ISA32 and then
    486      it's most probably code there.  */
    487   if (info->symbols
    488       && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
    489       && elf_symbol_from (bfd_asymbol_bfd (info->symbols[0]),
    490 			  info->symbols[0])->internal_elf_sym.st_other
    491       == STO_SH5_ISA32)
    492     return CRT_SH5_ISA32;
    493 
    494   /* If all else fails, guess this is code and guess on the low bit set.  */
    495   return (memaddr & 1) == 1 ? CRT_SH5_ISA32 : CRT_SH5_ISA16;
    496 }
    497 
    498 /* Initialize static and dynamic disassembly state.  */
    499 
    500 static bfd_boolean
    501 init_sh64_disasm_info (struct disassemble_info *info)
    502 {
    503   struct sh64_disassemble_info *sh64_infop
    504     = calloc (sizeof (*sh64_infop), 1);
    505 
    506   if (sh64_infop == NULL)
    507     return FALSE;
    508 
    509   info->private_data = sh64_infop;
    510 
    511   SAVED_MOVI_IMM (info) = 0;
    512   SAVED_MOVI_R (info) = 255;
    513 
    514   if (shmedia_opcode_mask_table == NULL)
    515     initialize_shmedia_opcode_mask_table ();
    516 
    517   return TRUE;
    518 }
    519 
    520 /* Main entry to disassemble SHmedia instructions, given an endian set in
    521    INFO.  Note that the simulator uses this as the main entry and does not
    522    use any of the functions further below.  */
    523 
    524 int
    525 print_insn_sh64x_media (bfd_vma memaddr, struct disassemble_info *info)
    526 {
    527   if (info->private_data == NULL && ! init_sh64_disasm_info (info))
    528     return -1;
    529 
    530   /* Make reasonable output.  */
    531   info->bytes_per_line = 4;
    532   info->bytes_per_chunk = 4;
    533 
    534   return print_insn_shmedia (memaddr, info);
    535 }
    536 
    537 /* Main entry to disassemble SHmedia insns.
    538    If we see an SHcompact instruction, return -2.  */
    539 
    540 int
    541 print_insn_sh64 (bfd_vma memaddr, struct disassemble_info *info)
    542 {
    543   enum bfd_endian endian = info->endian;
    544   enum sh64_elf_cr_type cr_type;
    545 
    546   if (info->private_data == NULL && ! init_sh64_disasm_info (info))
    547     return -1;
    548 
    549   cr_type = sh64_get_contents_type_disasm (memaddr, info);
    550   if (cr_type != CRT_SH5_ISA16)
    551     {
    552       int length = 4 - (memaddr % 4);
    553       info->display_endian = endian;
    554 
    555       /* If we got an uneven address to indicate SHmedia, adjust it.  */
    556       if (cr_type == CRT_SH5_ISA32 && length == 3)
    557 	memaddr--, length = 4;
    558 
    559       /* Only disassemble on four-byte boundaries.  Addresses that are not
    560 	 a multiple of four can happen after a data region.  */
    561       if (cr_type == CRT_SH5_ISA32 && length == 4)
    562 	return print_insn_sh64x_media (memaddr, info);
    563 
    564       /* We get CRT_DATA *only* for data regions in a mixed-contents
    565 	 section.  For sections with data only, we get indication of one
    566 	 of the ISA:s.  You may think that we shouldn't disassemble
    567 	 section with only data if we can figure that out.  However, the
    568 	 disassembly function is by default not called for data-only
    569 	 sections, so if the user explicitly specified disassembly of a
    570 	 data section, that's what we should do.  */
    571       if (cr_type == CRT_DATA || length != 4)
    572 	{
    573 	  int status;
    574 	  unsigned char data[4];
    575 	  struct sh64_disassemble_info *sh64_infop = info->private_data;
    576 
    577 	  if (length == 4
    578 	      && sh64_infop->crange.cr_type != CRT_NONE
    579 	      && memaddr >= sh64_infop->crange.cr_addr
    580 	      && memaddr < (sh64_infop->crange.cr_addr
    581 			    + sh64_infop->crange.cr_size))
    582 	    length
    583 	      = (sh64_infop->crange.cr_addr
    584 		 + sh64_infop->crange.cr_size - memaddr);
    585 
    586 	  status
    587 	    = (*info->read_memory_func) (memaddr, data,
    588 					 length >= 4 ? 4 : length, info);
    589 
    590 	  if (status == 0 && length >= 4)
    591 	    {
    592 	      (*info->fprintf_func) (info->stream, ".long 0x%08lx",
    593 				     endian == BFD_ENDIAN_BIG
    594 				     ? (long) (bfd_getb32 (data))
    595 				     : (long) (bfd_getl32 (data)));
    596 	      return 4;
    597 	    }
    598 	  else
    599 	    {
    600 	      int i;
    601 
    602 	      for (i = 0; i < length; i++)
    603 		{
    604 		  status = info->read_memory_func (memaddr + i, data, 1, info);
    605 		  if (status != 0)
    606 		    break;
    607 		  (*info->fprintf_func) (info->stream, "%s0x%02x",
    608 					 i == 0 ? ".byte " : ", ",
    609 					 data[0]);
    610 		}
    611 
    612 	      return i ? i : -1;
    613 	    }
    614 	}
    615     }
    616 
    617   /* SH1 .. SH4 instruction, let caller handle it.  */
    618   return -2;
    619 }
    620