Home | History | Annotate | Line # | Download | only in opcodes
      1      1.1  christos /* C-SKY disassembler.
      2  1.1.1.4  christos    Copyright (C) 1988-2025 Free Software Foundation, Inc.
      3      1.1  christos    Contributed by C-SKY Microsystems and Mentor Graphics.
      4      1.1  christos 
      5      1.1  christos    This file is part of the GNU opcodes library.
      6      1.1  christos 
      7      1.1  christos    This library is free software; you can redistribute it and/or modify
      8      1.1  christos    it under the terms of the GNU General Public License as published by
      9      1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     10      1.1  christos    any later version.
     11      1.1  christos 
     12      1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     13      1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14      1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15      1.1  christos    License for more details.
     16      1.1  christos 
     17      1.1  christos    You should have received a copy of the GNU General Public License
     18      1.1  christos    along with this program; if not, write to the Free Software
     19      1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20      1.1  christos    MA 02110-1301, USA.  */
     21      1.1  christos 
     22      1.1  christos #include "sysdep.h"
     23      1.1  christos #include "config.h"
     24      1.1  christos #include <stdio.h>
     25  1.1.1.2  christos #include <stdint.h>
     26  1.1.1.2  christos #include <elf/csky.h>
     27      1.1  christos #include "disassemble.h"
     28      1.1  christos #include "elf-bfd.h"
     29      1.1  christos #include "opcode/csky.h"
     30      1.1  christos #include "libiberty.h"
     31      1.1  christos #include "csky-opc.h"
     32      1.1  christos #include "floatformat.h"
     33      1.1  christos 
     34      1.1  christos #define CSKY_INST_TYPE unsigned long
     35      1.1  christos #define HAS_SUB_OPERAND (unsigned int)0xffffffff
     36  1.1.1.2  christos #define CSKY_DEFAULT_ISA 0xffffffff
     37      1.1  christos 
     38      1.1  christos enum sym_type
     39      1.1  christos {
     40      1.1  christos   CUR_TEXT,
     41      1.1  christos   CUR_DATA
     42      1.1  christos };
     43      1.1  christos 
     44      1.1  christos struct csky_dis_info
     45      1.1  christos {
     46      1.1  christos   /* Mem to disassemble.  */
     47      1.1  christos   bfd_vma mem;
     48      1.1  christos   /* Disassemble info.  */
     49      1.1  christos   disassemble_info *info;
     50      1.1  christos   /* Opcode information.  */
     51      1.1  christos   struct csky_opcode_info const *opinfo;
     52  1.1.1.2  christos   uint64_t isa;
     53      1.1  christos   /* The value of operand to show.  */
     54      1.1  christos   int value;
     55      1.1  christos   /* Whether to look up/print a symbol name.  */
     56      1.1  christos   int need_output_symbol;
     57      1.1  christos } dis_info;
     58      1.1  christos 
     59      1.1  christos 
     60      1.1  christos enum sym_type last_type;
     61      1.1  christos int last_map_sym = 1;
     62      1.1  christos bfd_vma last_map_addr = 0;
     63  1.1.1.2  christos int using_abi = 0;
     64      1.1  christos 
     65      1.1  christos /* Only for objdump tool.  */
     66      1.1  christos #define INIT_MACH_FLAG  0xffffffff
     67      1.1  christos #define BINARY_MACH_FLAG 0x0
     68      1.1  christos 
     69      1.1  christos static unsigned int mach_flag = INIT_MACH_FLAG;
     70      1.1  christos 
     71      1.1  christos static void
     72      1.1  christos print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
     73      1.1  christos 		 struct disassemble_info *info,
     74      1.1  christos 		 long given)
     75      1.1  christos {
     76      1.1  christos   switch (info->bytes_per_chunk)
     77      1.1  christos     {
     78      1.1  christos     case 1:
     79      1.1  christos       info->fprintf_func (info->stream, ".byte\t0x%02lx", given);
     80      1.1  christos       break;
     81      1.1  christos     case 2:
     82      1.1  christos       info->fprintf_func (info->stream, ".short\t0x%04lx", given);
     83      1.1  christos       break;
     84      1.1  christos     case 4:
     85      1.1  christos       info->fprintf_func (info->stream, ".long\t0x%08lx", given);
     86      1.1  christos       break;
     87      1.1  christos     default:
     88      1.1  christos       abort ();
     89      1.1  christos     }
     90      1.1  christos }
     91      1.1  christos 
     92      1.1  christos static int
     93      1.1  christos get_sym_code_type (struct disassemble_info *info,
     94      1.1  christos 		   int n,
     95      1.1  christos 		   enum sym_type *sym_type)
     96      1.1  christos {
     97      1.1  christos   const char *name;
     98      1.1  christos   name = bfd_asymbol_name (info->symtab[n]);
     99      1.1  christos   if (name[0] == '$' && (name[1] == 't' || name[1] == 'd')
    100      1.1  christos       && (name[2] == 0 || name[2] == '.'))
    101      1.1  christos     {
    102      1.1  christos       *sym_type = ((name[1] == 't') ? CUR_TEXT : CUR_DATA);
    103  1.1.1.2  christos       return true;
    104      1.1  christos     }
    105  1.1.1.2  christos   return false;
    106      1.1  christos }
    107      1.1  christos 
    108      1.1  christos static int
    109      1.1  christos csky_get_operand_mask (struct operand const *oprnd)
    110      1.1  christos {
    111      1.1  christos   int mask = 0;
    112      1.1  christos   if (oprnd->mask == HAS_SUB_OPERAND)
    113      1.1  christos     {
    114      1.1  christos       struct soperand *sop = (struct soperand *)oprnd;
    115      1.1  christos       mask |= csky_get_operand_mask (&sop->subs[0]);
    116      1.1  christos       mask |= csky_get_operand_mask (&sop->subs[1]);
    117      1.1  christos       return mask;
    118      1.1  christos     }
    119      1.1  christos   return oprnd->mask;
    120      1.1  christos }
    121      1.1  christos 
    122      1.1  christos static int
    123      1.1  christos csky_get_mask (struct csky_opcode_info const *pinfo)
    124      1.1  christos {
    125      1.1  christos   int i = 0;
    126      1.1  christos   int mask = 0;
    127      1.1  christos   /* List type.  */
    128      1.1  christos   if (pinfo->operand_num == -1)
    129      1.1  christos     mask |= csky_get_operand_mask (&pinfo->oprnd.oprnds[i]);
    130      1.1  christos   else
    131      1.1  christos     for (; i < pinfo->operand_num; i++)
    132      1.1  christos       mask |= csky_get_operand_mask (&pinfo->oprnd.oprnds[i]);
    133      1.1  christos 
    134      1.1  christos   mask = ~mask;
    135      1.1  christos   return mask;
    136      1.1  christos }
    137      1.1  christos 
    138      1.1  christos static unsigned int
    139      1.1  christos csky_chars_to_number (unsigned char * buf, int n)
    140      1.1  christos {
    141      1.1  christos   int i;
    142      1.1  christos   unsigned int val = 0;
    143      1.1  christos 
    144      1.1  christos   if (dis_info.info->endian == BFD_ENDIAN_BIG)
    145      1.1  christos     for (i = 0; i < n; i++)
    146      1.1  christos       val = val << 8 | buf[i];
    147      1.1  christos   else
    148      1.1  christos     for (i = n - 1; i >= 0; i--)
    149      1.1  christos       val = val << 8 | buf[i];
    150      1.1  christos   return val;
    151      1.1  christos }
    152      1.1  christos 
    153      1.1  christos static struct csky_opcode const *g_opcodeP;
    154      1.1  christos 
    155      1.1  christos static struct csky_opcode const *
    156      1.1  christos csky_find_inst_info (struct csky_opcode_info const **pinfo,
    157      1.1  christos 		     CSKY_INST_TYPE inst, int length)
    158      1.1  christos {
    159      1.1  christos   int i;
    160      1.1  christos   unsigned int mask;
    161      1.1  christos   struct csky_opcode const *p;
    162      1.1  christos 
    163      1.1  christos   p = g_opcodeP;
    164      1.1  christos   while (p->mnemonic)
    165      1.1  christos     {
    166  1.1.1.2  christos 	if (!(p->isa_flag16 & dis_info.isa)
    167  1.1.1.2  christos 	      && !(p->isa_flag32 & dis_info.isa))
    168  1.1.1.2  christos 	{
    169  1.1.1.2  christos 	  p++;
    170  1.1.1.2  christos 	  continue;
    171  1.1.1.2  christos 	}
    172  1.1.1.2  christos 
    173      1.1  christos       /* Get the opcode mask.  */
    174      1.1  christos       for (i = 0; i < OP_TABLE_NUM; i++)
    175      1.1  christos 	if (length == 2)
    176      1.1  christos 	  {
    177      1.1  christos 	    mask =  csky_get_mask (&p->op16[i]);
    178      1.1  christos 	    if (mask != 0 && (inst & mask) == p->op16[i].opcode)
    179      1.1  christos 	      {
    180      1.1  christos 		*pinfo = &p->op16[i];
    181      1.1  christos 		g_opcodeP = p;
    182      1.1  christos 		return p;
    183      1.1  christos 	      }
    184      1.1  christos 	  }
    185      1.1  christos 	else if (length == 4)
    186      1.1  christos 	  {
    187      1.1  christos 	    mask =  csky_get_mask (&p->op32[i]);
    188      1.1  christos 	    if (mask != 0
    189      1.1  christos 		&& ((unsigned long)(inst & mask)
    190      1.1  christos 		    == (unsigned long)p->op32[i].opcode))
    191      1.1  christos 	      {
    192      1.1  christos 		*pinfo = &p->op32[i];
    193      1.1  christos 		g_opcodeP = p;
    194      1.1  christos 		return p;
    195      1.1  christos 	      }
    196      1.1  christos 	  }
    197      1.1  christos       p++;
    198      1.1  christos     }
    199      1.1  christos 
    200      1.1  christos   return NULL;
    201      1.1  christos }
    202      1.1  christos 
    203  1.1.1.2  christos static bool
    204      1.1  christos is_extern_symbol (struct disassemble_info *info, int addr)
    205      1.1  christos {
    206      1.1  christos   unsigned int rel_count = 0;
    207      1.1  christos 
    208      1.1  christos   if (info->section == NULL)
    209      1.1  christos     return 0;
    210      1.1  christos   if ((info->section->flags & SEC_RELOC) != 0)	/* Fit .o file.  */
    211      1.1  christos     {
    212      1.1  christos       struct reloc_cache_entry *pt = info->section->relocation;
    213      1.1  christos       for (; rel_count < info->section->reloc_count; rel_count++, pt++)
    214      1.1  christos 	if ((long unsigned int)addr == pt->address)
    215  1.1.1.2  christos 	  return true;
    216  1.1.1.2  christos       return false;
    217      1.1  christos     }
    218  1.1.1.2  christos   return false;
    219      1.1  christos }
    220      1.1  christos 
    221      1.1  christos 
    222      1.1  christos /* Suppress printing of mapping symbols emitted by the assembler to mark
    223      1.1  christos    the beginning of code and data sequences.  */
    224      1.1  christos 
    225  1.1.1.2  christos bool
    226      1.1  christos csky_symbol_is_valid (asymbol *sym,
    227      1.1  christos 		      struct disassemble_info *info ATTRIBUTE_UNUSED)
    228      1.1  christos {
    229      1.1  christos   const char *name;
    230      1.1  christos 
    231      1.1  christos   if (sym == NULL)
    232  1.1.1.2  christos     return false;
    233      1.1  christos   name = bfd_asymbol_name (sym);
    234      1.1  christos   return name && *name != '$';
    235      1.1  christos }
    236      1.1  christos 
    237      1.1  christos disassembler_ftype
    238      1.1  christos csky_get_disassembler (bfd *abfd)
    239      1.1  christos {
    240  1.1.1.2  christos   obj_attribute *attr;
    241  1.1.1.2  christos   const char *sec_name = NULL;
    242  1.1.1.2  christos   if (!abfd || bfd_get_flavour (abfd) != bfd_target_elf_flavour)
    243  1.1.1.2  christos     dis_info.isa = CSKY_DEFAULT_ISA;
    244  1.1.1.2  christos   else
    245  1.1.1.2  christos     {
    246  1.1.1.2  christos       mach_flag = elf_elfheader (abfd)->e_flags;
    247  1.1.1.2  christos 
    248  1.1.1.2  christos       sec_name = get_elf_backend_data (abfd)->obj_attrs_section;
    249  1.1.1.2  christos       /* Skip any input that hasn't attribute section.
    250  1.1.1.2  christos          This enables to link object files without attribute section with
    251  1.1.1.2  christos          any others.  */
    252  1.1.1.2  christos       if (bfd_get_section_by_name (abfd, sec_name) != NULL)
    253  1.1.1.2  christos         {
    254  1.1.1.2  christos           attr = elf_known_obj_attributes_proc (abfd);
    255  1.1.1.2  christos           dis_info.isa = attr[Tag_CSKY_ISA_EXT_FLAGS].i;
    256  1.1.1.2  christos           dis_info.isa <<= 32;
    257  1.1.1.2  christos           dis_info.isa |= attr[Tag_CSKY_ISA_FLAGS].i;
    258  1.1.1.2  christos         }
    259  1.1.1.2  christos       else
    260  1.1.1.2  christos         dis_info.isa = CSKY_DEFAULT_ISA;
    261  1.1.1.2  christos     }
    262  1.1.1.2  christos 
    263  1.1.1.2  christos    return print_insn_csky;
    264  1.1.1.2  christos }
    265  1.1.1.2  christos 
    266  1.1.1.2  christos /* Parse the string of disassembler options.  */
    267  1.1.1.2  christos static void
    268  1.1.1.2  christos parse_csky_dis_options (const char *opts_in)
    269  1.1.1.2  christos {
    270  1.1.1.2  christos   char *opts = xstrdup (opts_in);
    271  1.1.1.2  christos   char *opt = opts;
    272  1.1.1.2  christos   char *opt_end = opts;
    273  1.1.1.2  christos 
    274  1.1.1.2  christos   for (; opt_end != NULL; opt = opt_end + 1)
    275  1.1.1.2  christos     {
    276  1.1.1.2  christos       if ((opt_end = strchr (opt, ',')) != NULL)
    277  1.1.1.2  christos 	*opt_end = 0;
    278  1.1.1.2  christos       if (strcmp (opt, "abi-names") == 0)
    279  1.1.1.2  christos 	using_abi = 1;
    280  1.1.1.2  christos       else
    281  1.1.1.2  christos 	fprintf (stderr,
    282  1.1.1.2  christos 		 "unrecognized disassembler option: %s", opt);
    283  1.1.1.2  christos     }
    284  1.1.1.2  christos }
    285  1.1.1.2  christos 
    286  1.1.1.2  christos /* Get general register name.  */
    287  1.1.1.2  christos static const char *
    288  1.1.1.2  christos get_gr_name (int regno)
    289  1.1.1.2  christos {
    290  1.1.1.2  christos   return csky_get_general_reg_name (mach_flag, regno, using_abi);
    291  1.1.1.2  christos }
    292  1.1.1.2  christos 
    293  1.1.1.2  christos /* Get control register name.  */
    294  1.1.1.2  christos static const char *
    295  1.1.1.2  christos get_cr_name (unsigned int regno, int bank)
    296  1.1.1.2  christos {
    297  1.1.1.2  christos   return csky_get_control_reg_name (mach_flag, bank, regno, using_abi);
    298      1.1  christos }
    299      1.1  christos 
    300      1.1  christos static int
    301      1.1  christos csky_output_operand (char *str, struct operand const *oprnd,
    302      1.1  christos 		     CSKY_INST_TYPE inst, int reloc ATTRIBUTE_UNUSED)
    303      1.1  christos {
    304      1.1  christos   int ret = 0;;
    305      1.1  christos   int bit = 0;
    306      1.1  christos   int result = 0;
    307      1.1  christos   bfd_vma value;
    308      1.1  christos   int mask = oprnd->mask;
    309      1.1  christos   int max = 0;
    310      1.1  christos   char buf[128];
    311      1.1  christos 
    312      1.1  christos   /* Get operand value with mask.  */
    313      1.1  christos   value = inst & mask;
    314      1.1  christos   for (; mask; mask >>= 1, value >>=1)
    315      1.1  christos     if (mask & 0x1)
    316      1.1  christos       {
    317      1.1  christos 	result |= ((value & 0x1) << bit);
    318      1.1  christos 	max |= (1 << bit);
    319      1.1  christos 	bit++;
    320      1.1  christos       }
    321      1.1  christos   value = result;
    322      1.1  christos 
    323      1.1  christos   /* Here is general instructions that have no reloc.  */
    324      1.1  christos   switch (oprnd->type)
    325      1.1  christos     {
    326      1.1  christos     case OPRND_TYPE_CTRLREG:
    327  1.1.1.2  christos 	if (IS_CSKY_V1(mach_flag) && ((value & 0x1f) == 0x1f))
    328  1.1.1.2  christos 	  return -1;
    329  1.1.1.2  christos 	strcat (str, get_cr_name((value & 0x1f), (value >> 5)));
    330  1.1.1.2  christos 	break;
    331      1.1  christos     case OPRND_TYPE_DUMMY_REG:
    332      1.1  christos       mask = dis_info.opinfo->oprnd.oprnds[0].mask;
    333      1.1  christos       value = inst & mask;
    334      1.1  christos       for (; mask; mask >>= 1, value >>=1)
    335      1.1  christos 	if (mask & 0x1)
    336      1.1  christos 	  {
    337      1.1  christos 	    result |= ((value & 0x1) << bit);
    338      1.1  christos 	    bit++;
    339      1.1  christos 	  }
    340      1.1  christos       value = result;
    341  1.1.1.2  christos       strcat (str, get_gr_name (value));
    342      1.1  christos       break;
    343      1.1  christos     case OPRND_TYPE_GREG0_7:
    344      1.1  christos     case OPRND_TYPE_GREG0_15:
    345      1.1  christos     case OPRND_TYPE_GREG16_31:
    346      1.1  christos     case OPRND_TYPE_REGnsplr:
    347      1.1  christos     case OPRND_TYPE_AREG:
    348  1.1.1.2  christos       strcat (str, get_gr_name (value));
    349      1.1  christos       break;
    350      1.1  christos     case OPRND_TYPE_CPREG:
    351  1.1.1.2  christos       sprintf (buf, "cpr%d", (int)value);
    352  1.1.1.2  christos       strcat (str, buf);
    353      1.1  christos       break;
    354      1.1  christos     case OPRND_TYPE_FREG:
    355      1.1  christos       sprintf (buf, "fr%d", (int)value);
    356      1.1  christos       strcat (str, buf);
    357      1.1  christos       break;
    358      1.1  christos     case OPRND_TYPE_VREG:
    359  1.1.1.2  christos       dis_info.value = value;
    360      1.1  christos       sprintf (buf, "vr%d", (int)value);
    361      1.1  christos       strcat (str, buf);
    362      1.1  christos       break;
    363      1.1  christos     case OPRND_TYPE_CPCREG:
    364  1.1.1.2  christos       sprintf (buf, "cpcr%d", (int)value);
    365  1.1.1.2  christos       strcat (str, buf);
    366      1.1  christos       break;
    367      1.1  christos     case OPRND_TYPE_CPIDX:
    368  1.1.1.2  christos       sprintf (buf, "cp%d", (int)value);
    369  1.1.1.2  christos       strcat (str, buf);
    370      1.1  christos       break;
    371      1.1  christos     case OPRND_TYPE_IMM2b_JMPIX:
    372      1.1  christos       value = (value + 2) << 3;
    373      1.1  christos       sprintf (buf, "%d", (int)value);
    374      1.1  christos       strcat (str, buf);
    375      1.1  christos       break;
    376      1.1  christos     case OPRND_TYPE_IMM_LDST:
    377      1.1  christos     case OPRND_TYPE_IMM_FLDST:
    378      1.1  christos       value <<= oprnd->shift;
    379      1.1  christos       sprintf (buf, "0x%x", (unsigned int)value);
    380      1.1  christos       strcat (str, buf);
    381      1.1  christos       break;
    382      1.1  christos     case OPRND_TYPE_IMM7b_LS2:
    383      1.1  christos     case OPRND_TYPE_IMM8b_LS2:
    384      1.1  christos       sprintf (buf, "%d", (int)(value << 2));
    385      1.1  christos       strcat (str, buf);
    386      1.1  christos       ret = 0;
    387      1.1  christos       break;
    388      1.1  christos     case OPRND_TYPE_IMM5b_BMASKI:
    389      1.1  christos       if ((value != 0) && (value > 31 || value < 8))
    390      1.1  christos 	{
    391      1.1  christos 	  ret = -1;
    392      1.1  christos 	  break;
    393      1.1  christos 	}
    394      1.1  christos       sprintf (buf, "%d", (int)value);
    395      1.1  christos       strcat (str, buf);
    396      1.1  christos       ret = 0;
    397      1.1  christos       break;
    398      1.1  christos     case OPRND_TYPE_IMM5b_1_31:
    399      1.1  christos       if (value > 31 || value < 1)
    400      1.1  christos 	{
    401      1.1  christos 	  ret = -1;
    402      1.1  christos 	  break;
    403      1.1  christos 	}
    404      1.1  christos       sprintf (buf, "%d", (int)value);
    405      1.1  christos       strcat (str, buf);
    406      1.1  christos       ret = 0;
    407      1.1  christos       break;
    408      1.1  christos     case OPRND_TYPE_IMM5b_7_31:
    409      1.1  christos       if (value > 31 || value < 7)
    410      1.1  christos 	{
    411      1.1  christos 	  ret = -1;
    412      1.1  christos 	  break;
    413      1.1  christos 	}
    414      1.1  christos       sprintf (buf, "%d", (int)value);
    415      1.1  christos       strcat (str, buf);
    416      1.1  christos       ret = 0;
    417      1.1  christos       break;
    418  1.1.1.2  christos     case OPRND_TYPE_IMM5b_VSH:
    419  1.1.1.2  christos       {
    420  1.1.1.2  christos 	char num[128];
    421  1.1.1.2  christos 	value = ((value & 0x1) << 4) | (value >> 1);
    422  1.1.1.2  christos 	sprintf (num, "%d", (int)value);
    423  1.1.1.2  christos 	strcat (str, num);
    424  1.1.1.2  christos 	ret = 0;
    425  1.1.1.2  christos 	break;
    426  1.1.1.2  christos       }
    427      1.1  christos     case OPRND_TYPE_MSB2SIZE:
    428      1.1  christos     case OPRND_TYPE_LSB2SIZE:
    429      1.1  christos       {
    430      1.1  christos 	static int size;
    431      1.1  christos 	if (oprnd->type == OPRND_TYPE_MSB2SIZE)
    432      1.1  christos 	  size = value;
    433      1.1  christos 	else
    434      1.1  christos 	  {
    435      1.1  christos 	    str[strlen (str) - 2] = '\0';
    436      1.1  christos 	    sprintf (buf, "%d, %d", (int)(size + value), (int)value);
    437      1.1  christos 	    strcat (str, buf);
    438      1.1  christos 	  }
    439      1.1  christos 	break;
    440      1.1  christos       }
    441      1.1  christos     case OPRND_TYPE_IMM1b:
    442      1.1  christos     case OPRND_TYPE_IMM2b:
    443      1.1  christos     case OPRND_TYPE_IMM4b:
    444      1.1  christos     case OPRND_TYPE_IMM5b:
    445  1.1.1.2  christos     case OPRND_TYPE_IMM5b_LS:
    446      1.1  christos     case OPRND_TYPE_IMM7b:
    447      1.1  christos     case OPRND_TYPE_IMM8b:
    448      1.1  christos     case OPRND_TYPE_IMM12b:
    449      1.1  christos     case OPRND_TYPE_IMM15b:
    450      1.1  christos     case OPRND_TYPE_IMM16b:
    451      1.1  christos     case OPRND_TYPE_IMM16b_MOVIH:
    452      1.1  christos     case OPRND_TYPE_IMM16b_ORI:
    453      1.1  christos       sprintf (buf, "%d", (int)value);
    454      1.1  christos       strcat (str, buf);
    455      1.1  christos       ret = 0;
    456      1.1  christos       break;
    457      1.1  christos     case OPRND_TYPE_OFF8b:
    458      1.1  christos     case OPRND_TYPE_OFF16b:
    459      1.1  christos       {
    460      1.1  christos 	unsigned char ibytes[4];
    461      1.1  christos 	int shift = oprnd->shift;
    462      1.1  christos 	int status;
    463      1.1  christos 	unsigned int mem_val;
    464      1.1  christos 
    465      1.1  christos 	dis_info.info->stop_vma = 0;
    466      1.1  christos 
    467      1.1  christos 	value = ((dis_info.mem + (value << shift)
    468      1.1  christos 		  + ((IS_CSKY_V1 (mach_flag)) ? 2 : 0))
    469      1.1  christos 		 & 0xfffffffc);
    470      1.1  christos 	status = dis_info.info->read_memory_func (value, ibytes, 4,
    471      1.1  christos 						  dis_info.info);
    472      1.1  christos 	if (status != 0)
    473      1.1  christos 	  {
    474      1.1  christos 	    dis_info.info->memory_error_func (status, dis_info.mem,
    475      1.1  christos 					      dis_info.info);
    476      1.1  christos 	    return -1;
    477      1.1  christos 	  }
    478      1.1  christos 	mem_val = csky_chars_to_number (ibytes, 4);
    479      1.1  christos 	/* Remove [] around literal value to match ABI syntax.  */
    480      1.1  christos 	sprintf (buf, "0x%X", mem_val);
    481      1.1  christos 	strcat (str, buf);
    482      1.1  christos 	/* For jmpi/jsri, we'll try to get a symbol for the target.  */
    483      1.1  christos 	if (dis_info.info->print_address_func && mem_val != 0)
    484      1.1  christos 	  {
    485      1.1  christos 	    dis_info.value = mem_val;
    486      1.1  christos 	    dis_info.need_output_symbol = 1;
    487      1.1  christos 	  }
    488      1.1  christos 	else
    489      1.1  christos 	  {
    490      1.1  christos 	    sprintf (buf, "\t// from address pool at 0x%x",
    491      1.1  christos 		     (unsigned int)value);
    492      1.1  christos 	    strcat (str, buf);
    493      1.1  christos 	  }
    494      1.1  christos 	break;
    495      1.1  christos       }
    496      1.1  christos     case OPRND_TYPE_BLOOP_OFF4b:
    497      1.1  christos     case OPRND_TYPE_BLOOP_OFF12b:
    498      1.1  christos     case OPRND_TYPE_OFF11b:
    499      1.1  christos     case OPRND_TYPE_OFF16b_LSL1:
    500      1.1  christos     case OPRND_TYPE_IMM_OFF18b:
    501      1.1  christos     case OPRND_TYPE_OFF26b:
    502      1.1  christos       {
    503      1.1  christos 	int shift = oprnd->shift;
    504      1.1  christos 	if (value & ((max >> 1) + 1))
    505      1.1  christos 	  value |= ~max;
    506      1.1  christos 	if (is_extern_symbol (dis_info.info, dis_info.mem))
    507      1.1  christos 	  value = 0;
    508      1.1  christos 	else if (IS_CSKY_V1 (mach_flag))
    509      1.1  christos 	  value = dis_info.mem + 2 + (value << shift);
    510      1.1  christos 	else
    511      1.1  christos 	  value = dis_info.mem + (value << shift);
    512      1.1  christos 	dis_info.need_output_symbol = 1;
    513      1.1  christos 	dis_info.value= value;
    514      1.1  christos 	sprintf (buf, "0x%x", (unsigned int)value);
    515      1.1  christos 	strcat (str, buf);
    516      1.1  christos 	break;
    517      1.1  christos       }
    518      1.1  christos     case OPRND_TYPE_CONSTANT:
    519      1.1  christos     case OPRND_TYPE_FCONSTANT:
    520      1.1  christos       {
    521      1.1  christos 	int shift = oprnd->shift;
    522  1.1.1.3  christos 	bfd_byte ibytes[8];
    523      1.1  christos 	int status;
    524      1.1  christos 	bfd_vma addr;
    525      1.1  christos 	int nbytes;
    526      1.1  christos 
    527      1.1  christos 	dis_info.info->stop_vma = 0;
    528      1.1  christos 	value <<= shift;
    529      1.1  christos 
    530      1.1  christos 	if (IS_CSKY_V1 (mach_flag))
    531      1.1  christos 	  addr = (dis_info.mem + 2 + value) & 0xfffffffc;
    532      1.1  christos 	else
    533      1.1  christos 	  addr = (dis_info.mem + value) & 0xfffffffc;
    534      1.1  christos 
    535      1.1  christos 	if (oprnd->type == OPRND_TYPE_FCONSTANT
    536      1.1  christos 	    && dis_info.opinfo->opcode != CSKYV2_INST_FLRW)
    537      1.1  christos 	  nbytes = 8;
    538      1.1  christos 	else
    539      1.1  christos 	  nbytes = 4;
    540      1.1  christos 
    541  1.1.1.3  christos 	status = dis_info.info->read_memory_func (addr, ibytes,
    542      1.1  christos 						  nbytes, dis_info.info);
    543      1.1  christos 	if (status != 0)
    544      1.1  christos 	  /* Address out of bounds.  -> lrw rx, [pc, 0ffset]. */
    545      1.1  christos 	  sprintf (buf, "[pc, %d]\t// from address pool at %x", (int)value,
    546      1.1  christos 		   (unsigned int)addr);
    547  1.1.1.3  christos 	else if (oprnd->type == OPRND_TYPE_FCONSTANT)
    548      1.1  christos 	  {
    549      1.1  christos 	    double f;
    550      1.1  christos 
    551      1.1  christos 	    if (dis_info.opinfo->opcode == CSKYV2_INST_FLRW)
    552      1.1  christos 	      /* flrws.  */
    553      1.1  christos 	      floatformat_to_double ((dis_info.info->endian == BFD_ENDIAN_BIG
    554      1.1  christos 				      ? &floatformat_ieee_single_big
    555      1.1  christos 				      : &floatformat_ieee_single_little),
    556      1.1  christos 				     ibytes, &f);
    557      1.1  christos 	    else
    558      1.1  christos 	      floatformat_to_double ((dis_info.info->endian == BFD_ENDIAN_BIG
    559      1.1  christos 				      ? &floatformat_ieee_double_big
    560      1.1  christos 				      : &floatformat_ieee_double_little),
    561      1.1  christos 				     ibytes, &f);
    562  1.1.1.2  christos 	    sprintf (buf, "%.7g", f);
    563      1.1  christos 	  }
    564      1.1  christos 	else
    565      1.1  christos 	  {
    566  1.1.1.3  christos 	    dis_info.value = addr;
    567      1.1  christos 	    dis_info.need_output_symbol = 1;
    568  1.1.1.3  christos 	    value = csky_chars_to_number (ibytes, 4);
    569  1.1.1.3  christos 	    sprintf (buf, "0x%x", (unsigned int) value);
    570      1.1  christos 	  }
    571      1.1  christos 
    572      1.1  christos 	strcat (str, buf);
    573      1.1  christos 	break;
    574      1.1  christos       }
    575      1.1  christos     case OPRND_TYPE_ELRW_CONSTANT:
    576      1.1  christos       {
    577      1.1  christos 	int shift = oprnd->shift;
    578      1.1  christos 	char ibytes[4];
    579      1.1  christos 	int status;
    580      1.1  christos 	bfd_vma addr;
    581      1.1  christos 	dis_info.info->stop_vma = 0;
    582      1.1  christos 
    583      1.1  christos 	value = 0x80 + ((~value) & 0x7f);
    584      1.1  christos 
    585      1.1  christos 	value = value << shift;
    586      1.1  christos 	addr = (dis_info.mem + value) & 0xfffffffc;
    587      1.1  christos 
    588      1.1  christos 	status = dis_info.info->read_memory_func (addr, (bfd_byte *)ibytes,
    589      1.1  christos 						  4, dis_info.info);
    590      1.1  christos 	if (status != 0)
    591      1.1  christos 	  /* Address out of bounds.  -> lrw rx, [pc, 0ffset]. */
    592      1.1  christos 	  sprintf (buf, "[pc, %d]\t// from address pool at %x", (int) value,
    593      1.1  christos 		   (unsigned int)addr);
    594      1.1  christos 	else
    595      1.1  christos 	  {
    596      1.1  christos 	    dis_info.value = addr;
    597      1.1  christos 	    value = csky_chars_to_number ((unsigned char *)ibytes, 4);
    598      1.1  christos 	    dis_info.need_output_symbol = 1;
    599      1.1  christos 	    sprintf (buf, "0x%x", (unsigned int)value);
    600      1.1  christos 	  }
    601      1.1  christos 
    602      1.1  christos 	strcat (str, buf);
    603      1.1  christos 	break;
    604      1.1  christos       }
    605      1.1  christos     case OPRND_TYPE_SFLOAT:
    606      1.1  christos     case OPRND_TYPE_DFLOAT:
    607      1.1  christos       {
    608      1.1  christos 	/* This is for fmovis/fmovid, which have an internal 13-bit
    609      1.1  christos 	   encoding that they convert to single/double precision
    610      1.1  christos 	   (respectively).  We'll convert the 13-bit encoding to an IEEE
    611      1.1  christos 	   double and then to host double format to print it.
    612      1.1  christos 	   Sign bit: bit 20.
    613      1.1  christos 	   4-bit exponent: bits 19:16, biased by 11.
    614      1.1  christos 	   8-bit mantissa: split between 24:21 and 7:4.  */
    615      1.1  christos 	uint64_t imm4;
    616      1.1  christos 	uint64_t imm8;
    617      1.1  christos 	uint64_t dbnum;
    618      1.1  christos 	unsigned char valbytes[8];
    619      1.1  christos 	double fvalue;
    620      1.1  christos 
    621      1.1  christos 	imm4 = ((inst >> 16) & 0xf);
    622      1.1  christos 	imm4 = (uint64_t)(1023 - (imm4 - 11)) << 52;
    623      1.1  christos 
    624      1.1  christos 	imm8 = (uint64_t)((inst >> 4) & 0xf) << 44;
    625      1.1  christos 	imm8 |= (uint64_t)((inst >> 21) & 0xf) << 48;
    626      1.1  christos 
    627      1.1  christos 	dbnum = (uint64_t)((inst >> 20) & 1) << 63;
    628      1.1  christos 	dbnum |= imm4 | imm8;
    629      1.1  christos 
    630      1.1  christos 	/* Do this a byte at a time so we don't have to
    631      1.1  christos 	   worry about the host's endianness.  */
    632      1.1  christos 	valbytes[0] = dbnum & 0xff;
    633      1.1  christos 	valbytes[1] = (dbnum >> 8) & 0xff;
    634      1.1  christos 	valbytes[2] = (dbnum >> 16) & 0xff;
    635      1.1  christos 	valbytes[3] = (dbnum >> 24) & 0xff;
    636      1.1  christos 	valbytes[4] = (dbnum >> 32) & 0xff;
    637      1.1  christos 	valbytes[5] = (dbnum >> 40) & 0xff;
    638      1.1  christos 	valbytes[6] = (dbnum >> 48) & 0xff;
    639      1.1  christos 	valbytes[7] = (dbnum >> 56) & 0xff;
    640      1.1  christos 
    641      1.1  christos 	floatformat_to_double (&floatformat_ieee_double_little, valbytes,
    642      1.1  christos 			       &fvalue);
    643      1.1  christos 
    644  1.1.1.2  christos 	sprintf (buf, "%.7g", fvalue);
    645  1.1.1.2  christos 	strcat (str, buf);
    646  1.1.1.2  christos 	break;
    647  1.1.1.2  christos       }
    648  1.1.1.2  christos     case OPRND_TYPE_HFLOAT_FMOVI:
    649  1.1.1.2  christos     case OPRND_TYPE_SFLOAT_FMOVI:
    650  1.1.1.2  christos       {
    651  1.1.1.2  christos 	int imm4;
    652  1.1.1.2  christos 	int imm8;
    653  1.1.1.2  christos 	imm4 = ((inst >> 16) & 0xf);
    654  1.1.1.2  christos 	imm4 = (138 - imm4) << 23;
    655  1.1.1.2  christos 
    656  1.1.1.2  christos 	imm8 = ((inst >> 8) & 0x3);
    657  1.1.1.2  christos 	imm8 |= (((inst >> 20) & 0x3f) << 2);
    658  1.1.1.2  christos 	imm8 <<= 15;
    659  1.1.1.2  christos 
    660  1.1.1.2  christos 	value = ((inst >> 5) & 1) << 31;
    661  1.1.1.2  christos 	value |= imm4 | imm8;
    662  1.1.1.2  christos 
    663  1.1.1.2  christos 	imm4 = 138 - (imm4 >> 23);
    664  1.1.1.2  christos 	imm8 >>= 15;
    665  1.1.1.2  christos 	if ((inst >> 5) & 1)
    666  1.1.1.2  christos 	  {
    667  1.1.1.2  christos 	    imm8 = 0 - imm8;
    668  1.1.1.2  christos 	  }
    669  1.1.1.2  christos 
    670  1.1.1.2  christos 	float f = 0;
    671  1.1.1.2  christos 	memcpy (&f, &value, sizeof (float));
    672  1.1.1.2  christos 	sprintf (buf, "%.7g\t// imm9:%4d, imm4:%2d", f, imm8, imm4);
    673      1.1  christos 	strcat (str, buf);
    674  1.1.1.2  christos 
    675  1.1.1.2  christos 	break;
    676  1.1.1.2  christos       }
    677  1.1.1.2  christos 
    678  1.1.1.2  christos     case OPRND_TYPE_DFLOAT_FMOVI:
    679  1.1.1.2  christos       {
    680  1.1.1.2  christos 	uint64_t imm4;
    681  1.1.1.2  christos 	uint64_t imm8;
    682  1.1.1.2  christos 	uint64_t dvalue;
    683  1.1.1.2  christos 	imm4 = ((inst >> 16) & 0xf);
    684  1.1.1.2  christos 	imm4 = (1034 - imm4) << 52;
    685  1.1.1.2  christos 
    686  1.1.1.2  christos 	imm8 = ((inst >> 8) & 0x3);
    687  1.1.1.2  christos 	imm8 |= (((inst >> 20) & 0x3f) << 2);
    688  1.1.1.2  christos 	imm8 <<= 44;
    689  1.1.1.2  christos 
    690  1.1.1.2  christos 	dvalue = (((uint64_t)inst >> 5) & 1) << 63;
    691  1.1.1.2  christos 	dvalue |= imm4 | imm8;
    692  1.1.1.2  christos 
    693  1.1.1.2  christos 	imm4 = 1034 - (imm4 >> 52);
    694  1.1.1.2  christos 	imm8 >>= 44;
    695  1.1.1.2  christos 	if (inst >> 5)
    696  1.1.1.2  christos 	  {
    697  1.1.1.2  christos 	    imm8 = 0 - imm8;
    698  1.1.1.2  christos 	  }
    699  1.1.1.2  christos 	double d = 0;
    700  1.1.1.2  christos 	memcpy (&d, &dvalue, sizeof (double));
    701  1.1.1.2  christos 	sprintf (buf, "%.7g\t// imm9:%4ld, imm4:%2ld", d, (long) imm8, (long) imm4);
    702  1.1.1.2  christos 	strcat (str, buf);
    703  1.1.1.2  christos 
    704      1.1  christos 	break;
    705      1.1  christos       }
    706      1.1  christos     case OPRND_TYPE_LABEL_WITH_BRACKET:
    707      1.1  christos       sprintf (buf, "[0x%x]", (unsigned int)value);
    708      1.1  christos       strcat (str, buf);
    709      1.1  christos       strcat (str, "\t// the offset is based on .data");
    710      1.1  christos       break;
    711      1.1  christos     case OPRND_TYPE_OIMM3b:
    712      1.1  christos     case OPRND_TYPE_OIMM4b:
    713      1.1  christos     case OPRND_TYPE_OIMM5b:
    714      1.1  christos     case OPRND_TYPE_OIMM5b_IDLY:
    715      1.1  christos     case OPRND_TYPE_OIMM8b:
    716      1.1  christos     case OPRND_TYPE_OIMM12b:
    717      1.1  christos     case OPRND_TYPE_OIMM16b:
    718      1.1  christos     case OPRND_TYPE_OIMM18b:
    719      1.1  christos       value += 1;
    720      1.1  christos       sprintf (buf, "%d", (int)value);
    721      1.1  christos       strcat (str, buf);
    722      1.1  christos       break;
    723      1.1  christos     case OPRND_TYPE_OIMM5b_BMASKI:
    724      1.1  christos       if (value > 32 || value < 16)
    725      1.1  christos 	{
    726      1.1  christos 	  ret = -1;
    727      1.1  christos 	  break;
    728      1.1  christos 	}
    729      1.1  christos       sprintf (buf, "%d", (int)(value + 1));
    730      1.1  christos       strcat (str, buf);
    731      1.1  christos       ret = 0;
    732      1.1  christos       break;
    733      1.1  christos     case OPRND_TYPE_FREGLIST_DASH:
    734      1.1  christos       if (IS_CSKY_V2 (mach_flag))
    735      1.1  christos 	{
    736  1.1.1.2  christos 	  int vrx = 0;
    737  1.1.1.2  christos 	  int vry = 0;
    738  1.1.1.2  christos 	  if (dis_info.isa & CSKY_ISA_FLOAT_7E60
    739  1.1.1.2  christos 	      && (strstr (str, "fstm") != NULL
    740  1.1.1.2  christos 		  || strstr (str, "fldm") != NULL))
    741  1.1.1.2  christos 	    {
    742  1.1.1.2  christos 	      vrx = value & 0x1f;
    743  1.1.1.2  christos 	      vry = vrx + (value >> 5);
    744  1.1.1.2  christos 	    }
    745  1.1.1.2  christos 	  else
    746  1.1.1.2  christos 	    {
    747  1.1.1.2  christos 	      vrx = value & 0xf;
    748  1.1.1.2  christos 	      vry = vrx + (value >> 4);
    749  1.1.1.2  christos 	    }
    750      1.1  christos 	  sprintf (buf, "fr%d-fr%d", vrx, vry);
    751      1.1  christos 	  strcat (str, buf);
    752      1.1  christos 	}
    753      1.1  christos       break;
    754      1.1  christos     case OPRND_TYPE_REGLIST_DASH:
    755      1.1  christos       if (IS_CSKY_V1 (mach_flag))
    756      1.1  christos 	{
    757  1.1.1.2  christos 	  sprintf (buf, "%s-r15", get_gr_name (value));
    758  1.1.1.2  christos 	  strcat (str, buf);
    759      1.1  christos 	}
    760      1.1  christos       else
    761      1.1  christos 	{
    762  1.1.1.2  christos 	  if ((value & 0x1f) + (value >> 5) > 31)
    763  1.1.1.2  christos 	    {
    764  1.1.1.2  christos 	      ret = -1;
    765  1.1.1.2  christos 	      break;
    766  1.1.1.2  christos 	    }
    767  1.1.1.2  christos 	  strcat (str, get_gr_name ((value >> 5)));
    768      1.1  christos 	  strcat (str, "-");
    769  1.1.1.2  christos 	  strcat (str, get_gr_name ((value & 0x1f) + (value >> 5)));
    770      1.1  christos 	}
    771      1.1  christos       break;
    772      1.1  christos     case OPRND_TYPE_PSR_BITS_LIST:
    773      1.1  christos       {
    774      1.1  christos 	struct psrbit const *bits;
    775  1.1.1.2  christos 	int first_oprnd = true;
    776      1.1  christos 	int i = 0;
    777      1.1  christos 	if (IS_CSKY_V1 (mach_flag))
    778      1.1  christos 	  {
    779      1.1  christos 	    if (value == 0)
    780      1.1  christos 	      {
    781      1.1  christos 		strcat (str, "af");
    782      1.1  christos 		break;
    783      1.1  christos 	      }
    784      1.1  christos 	    bits = cskyv1_psr_bits;
    785      1.1  christos 	  }
    786      1.1  christos 	else
    787      1.1  christos 	  bits = cskyv2_psr_bits;
    788      1.1  christos 	while (value != 0 && bits[i].name != NULL)
    789      1.1  christos 	    {
    790      1.1  christos 	      if (value & bits[i].value)
    791      1.1  christos 		{
    792      1.1  christos 		  if (!first_oprnd)
    793      1.1  christos 		    strcat (str, ", ");
    794      1.1  christos 		  strcat (str, bits[i].name);
    795      1.1  christos 		  value &= ~bits[i].value;
    796  1.1.1.2  christos 		  first_oprnd = false;
    797      1.1  christos 		}
    798      1.1  christos 	      i++;
    799      1.1  christos 	    }
    800      1.1  christos 	break;
    801      1.1  christos       }
    802      1.1  christos     case OPRND_TYPE_REGbsp:
    803      1.1  christos       if (IS_CSKY_V1 (mach_flag))
    804  1.1.1.2  christos 	sprintf(buf, "(%s)", get_gr_name (0));
    805      1.1  christos       else
    806  1.1.1.2  christos 	sprintf(buf, "(%s)", get_gr_name (14));
    807  1.1.1.2  christos       strcat (str, buf);
    808      1.1  christos       break;
    809      1.1  christos     case OPRND_TYPE_REGsp:
    810      1.1  christos       if (IS_CSKY_V1 (mach_flag))
    811  1.1.1.2  christos 	strcat (str, get_gr_name (0));
    812      1.1  christos       else
    813  1.1.1.2  christos 	strcat (str, get_gr_name (14));
    814      1.1  christos       break;
    815      1.1  christos     case OPRND_TYPE_REGnr4_r7:
    816      1.1  christos     case OPRND_TYPE_AREG_WITH_BRACKET:
    817  1.1.1.2  christos       strcat (str, "(");
    818  1.1.1.2  christos       strcat (str, get_gr_name (value));
    819  1.1.1.2  christos       strcat (str, ")");
    820      1.1  christos       break;
    821      1.1  christos     case OPRND_TYPE_AREG_WITH_LSHIFT:
    822  1.1.1.2  christos       strcat (str, get_gr_name (value >> 5));
    823      1.1  christos       strcat (str, " << ");
    824      1.1  christos       if ((value & 0x1f) == 0x1)
    825      1.1  christos 	strcat (str, "0");
    826      1.1  christos       else if ((value & 0x1f) == 0x2)
    827      1.1  christos 	strcat (str, "1");
    828      1.1  christos       else if ((value & 0x1f) == 0x4)
    829      1.1  christos 	strcat (str, "2");
    830      1.1  christos       else if ((value & 0x1f) == 0x8)
    831      1.1  christos 	strcat (str, "3");
    832      1.1  christos       break;
    833      1.1  christos     case OPRND_TYPE_AREG_WITH_LSHIFT_FPU:
    834  1.1.1.2  christos       strcat (str, get_gr_name (value >> 2));
    835      1.1  christos       strcat (str, " << ");
    836      1.1  christos       if ((value & 0x3) == 0x0)
    837      1.1  christos 	strcat (str, "0");
    838      1.1  christos       else if ((value & 0x3) == 0x1)
    839      1.1  christos 	strcat (str, "1");
    840      1.1  christos       else if ((value & 0x3) == 0x2)
    841      1.1  christos 	strcat (str, "2");
    842      1.1  christos       else if ((value & 0x3) == 0x3)
    843      1.1  christos 	strcat (str, "3");
    844      1.1  christos       break;
    845  1.1.1.2  christos     case OPRND_TYPE_VREG_WITH_INDEX:
    846      1.1  christos       {
    847      1.1  christos 	unsigned freg_val = value & 0xf;
    848      1.1  christos 	unsigned index_val = (value >> 4) & 0xf;
    849      1.1  christos 	sprintf (buf, "vr%d[%d]", freg_val, index_val);
    850      1.1  christos 	strcat(str, buf);
    851      1.1  christos 	break;
    852      1.1  christos       }
    853  1.1.1.2  christos     case OPRND_TYPE_FREG_WITH_INDEX:
    854  1.1.1.2  christos       {
    855  1.1.1.2  christos 	unsigned freg_val = value & 0xf;
    856  1.1.1.2  christos 	unsigned index_val = (value >> 4) & 0xf;
    857  1.1.1.2  christos 	sprintf (buf, "fr%d[%d]", freg_val, index_val);
    858  1.1.1.2  christos 	strcat(str, buf);
    859  1.1.1.2  christos 	break;
    860  1.1.1.2  christos       }
    861      1.1  christos     case OPRND_TYPE_REGr4_r7:
    862      1.1  christos       if (IS_CSKY_V1 (mach_flag))
    863  1.1.1.2  christos 	{
    864  1.1.1.2  christos 	  sprintf (buf, "%s-%s", get_gr_name (4), get_gr_name (7));
    865  1.1.1.2  christos 	  strcat (str, buf);
    866  1.1.1.2  christos 	}
    867      1.1  christos       break;
    868      1.1  christos     case OPRND_TYPE_CONST1:
    869      1.1  christos       strcat (str, "1");
    870      1.1  christos       break;
    871      1.1  christos     case OPRND_TYPE_REG_r1a:
    872      1.1  christos     case OPRND_TYPE_REG_r1b:
    873  1.1.1.2  christos       strcat (str, get_gr_name (1));
    874      1.1  christos       break;
    875      1.1  christos     case OPRND_TYPE_REG_r28:
    876  1.1.1.2  christos       strcat (str, get_gr_name (28));
    877      1.1  christos       break;
    878      1.1  christos     case OPRND_TYPE_REGLIST_DASH_COMMA:
    879      1.1  christos       /* 16-bit reglist.  */
    880      1.1  christos       if (value & 0xf)
    881      1.1  christos 	{
    882  1.1.1.2  christos 	  strcat (str, get_gr_name (4));
    883      1.1  christos 	  if ((value & 0xf) > 1)
    884      1.1  christos 	    {
    885      1.1  christos 	      strcat (str, "-");
    886  1.1.1.2  christos 	      strcat (str, get_gr_name ((value & 0xf) + 3));
    887      1.1  christos 	    }
    888      1.1  christos 	  if (value & ~0xf)
    889      1.1  christos 	    strcat (str, ", ");
    890      1.1  christos 	}
    891      1.1  christos       if (value & 0x10)
    892      1.1  christos 	{
    893      1.1  christos 	  /* r15.  */
    894  1.1.1.2  christos 	  strcat (str, get_gr_name (15));
    895      1.1  christos 	  if (value & ~0x1f)
    896      1.1  christos 	    strcat (str, ", ");
    897      1.1  christos 	}
    898      1.1  christos       if (dis_info.opinfo->oprnd.oprnds[0].mask != OPRND_MASK_0_4)
    899      1.1  christos 	{
    900      1.1  christos 	  /* 32bits reglist.  */
    901      1.1  christos 	  value >>= 5;
    902      1.1  christos 	  if (value & 0x3)
    903      1.1  christos 	    {
    904  1.1.1.2  christos 	      strcat (str, get_gr_name (16));
    905      1.1  christos 	      if ((value & 0x7) > 1)
    906      1.1  christos 		{
    907      1.1  christos 		  strcat (str, "-");
    908  1.1.1.2  christos 		  strcat (str, get_gr_name ((value & 0x7) + 15));
    909      1.1  christos 		}
    910      1.1  christos 	      if (value & ~0x7)
    911      1.1  christos 		strcat (str, ", ");
    912      1.1  christos 	      }
    913      1.1  christos 	  if (value & 0x8)
    914      1.1  christos 	    /* r15.  */
    915  1.1.1.2  christos 	    strcat (str, get_gr_name (28));
    916      1.1  christos 	}
    917      1.1  christos       break;
    918      1.1  christos     case OPRND_TYPE_UNCOND10b:
    919      1.1  christos     case OPRND_TYPE_UNCOND16b:
    920      1.1  christos     case OPRND_TYPE_COND10b:
    921      1.1  christos     case OPRND_TYPE_COND16b:
    922      1.1  christos       {
    923      1.1  christos 	int shift = oprnd->shift;
    924      1.1  christos 
    925      1.1  christos 	if (value & ((max >> 1) + 1))
    926      1.1  christos 	  value |= ~max;
    927      1.1  christos 	if (is_extern_symbol (dis_info.info, dis_info.mem))
    928      1.1  christos 	  value = 0;
    929      1.1  christos 	else
    930      1.1  christos 	  value = dis_info.mem + (value << shift);
    931      1.1  christos 	sprintf (buf, "0x%x", (unsigned int)value);
    932      1.1  christos 	strcat (str, buf);
    933      1.1  christos 	dis_info.need_output_symbol = 1;
    934      1.1  christos 	dis_info.value = value;
    935      1.1  christos       }
    936      1.1  christos       break;
    937      1.1  christos 
    938      1.1  christos     default:
    939      1.1  christos       ret = -1;
    940      1.1  christos       break;
    941      1.1  christos     }
    942      1.1  christos   return ret;
    943      1.1  christos }
    944      1.1  christos 
    945      1.1  christos static int
    946      1.1  christos csky_print_operand (char *str, struct operand const *oprnd,
    947      1.1  christos 		    CSKY_INST_TYPE inst, int reloc)
    948      1.1  christos {
    949      1.1  christos   int ret = -1;
    950      1.1  christos   char *lc = "";
    951      1.1  christos   char *rc = "";
    952      1.1  christos   if (oprnd->mask == HAS_SUB_OPERAND)
    953      1.1  christos     {
    954      1.1  christos       struct soperand *sop = (struct soperand *)oprnd;
    955      1.1  christos       if (oprnd->type == OPRND_TYPE_BRACKET)
    956      1.1  christos 	{
    957      1.1  christos 	  lc = "(";
    958      1.1  christos 	  rc = ")";
    959      1.1  christos 	}
    960      1.1  christos       else if (oprnd->type == OPRND_TYPE_ABRACKET)
    961      1.1  christos 	{
    962      1.1  christos 	  lc = "<";
    963      1.1  christos 	  rc = ">";
    964      1.1  christos 	}
    965      1.1  christos       strcat (str, lc);
    966      1.1  christos       ret = csky_print_operand (str, &sop->subs[0], inst, reloc);
    967      1.1  christos       if (ret)
    968      1.1  christos 	return ret;
    969      1.1  christos       strcat (str, ", ");
    970      1.1  christos       ret = csky_print_operand (str, &sop->subs[1], inst, reloc);
    971      1.1  christos       strcat (str, rc);
    972      1.1  christos       return ret;
    973      1.1  christos     }
    974      1.1  christos   return csky_output_operand (str, oprnd, inst, reloc);
    975      1.1  christos }
    976      1.1  christos 
    977      1.1  christos static int
    978      1.1  christos csky_print_operands (char *str, struct csky_opcode_info const *pinfo,
    979      1.1  christos 		     struct disassemble_info *info, CSKY_INST_TYPE inst,
    980      1.1  christos 		     int reloc)
    981      1.1  christos {
    982      1.1  christos   int i = 0;
    983      1.1  christos   int ret = 0;
    984      1.1  christos   if (pinfo->operand_num)
    985      1.1  christos     strcat (str, "      \t");
    986      1.1  christos   if (pinfo->operand_num == -1)
    987      1.1  christos     {
    988      1.1  christos       ret = csky_print_operand (str, &pinfo->oprnd.oprnds[i], inst, reloc);
    989      1.1  christos       if (ret)
    990      1.1  christos 	return ret;
    991      1.1  christos     }
    992      1.1  christos   else
    993      1.1  christos     for (; i < pinfo->operand_num; i++)
    994      1.1  christos       {
    995      1.1  christos 	if (i != 0)
    996      1.1  christos 	  strcat (str, ", ");
    997      1.1  christos 	ret = csky_print_operand (str, &pinfo->oprnd.oprnds[i], inst, reloc);
    998      1.1  christos 	if (ret)
    999      1.1  christos 	  return ret;
   1000      1.1  christos       }
   1001      1.1  christos   info->fprintf_func (info->stream, "%s", str);
   1002      1.1  christos   if (dis_info.need_output_symbol)
   1003      1.1  christos     {
   1004      1.1  christos       info->fprintf_func (info->stream, "\t// ");
   1005      1.1  christos       info->print_address_func (dis_info.value, dis_info.info);
   1006      1.1  christos     }
   1007      1.1  christos   return 0;
   1008      1.1  christos }
   1009      1.1  christos 
   1010      1.1  christos static void
   1011      1.1  christos number_to_chars_littleendian (char *buf, CSKY_INST_TYPE val, int n)
   1012      1.1  christos {
   1013      1.1  christos   if (n <= 0)
   1014      1.1  christos     abort ();
   1015      1.1  christos   while (n--)
   1016      1.1  christos     {
   1017      1.1  christos       *buf++ = val & 0xff;
   1018      1.1  christos       val >>= 8;
   1019      1.1  christos     }
   1020      1.1  christos }
   1021      1.1  christos 
   1022      1.1  christos #define CSKY_READ_DATA()                                        \
   1023      1.1  christos {                                                               \
   1024      1.1  christos   status = info->read_memory_func (memaddr, buf, 2, info);      \
   1025      1.1  christos   if (status)                                                   \
   1026      1.1  christos     {                                                           \
   1027      1.1  christos       info->memory_error_func (status, memaddr, info);          \
   1028      1.1  christos       return -1;                                                \
   1029      1.1  christos     }                                                           \
   1030      1.1  christos   if (info->endian == BFD_ENDIAN_BIG)                           \
   1031      1.1  christos     inst |= (buf[0] << 8) | buf[1];                             \
   1032      1.1  christos   else if (info->endian == BFD_ENDIAN_LITTLE)                   \
   1033      1.1  christos     inst |= (buf[1] << 8) | buf[0];                             \
   1034      1.1  christos   else                                                          \
   1035      1.1  christos     abort();                                                    \
   1036      1.1  christos   info->bytes_per_chunk += 2;                                   \
   1037      1.1  christos   memaddr += 2;                                                 \
   1038      1.1  christos }
   1039      1.1  christos 
   1040      1.1  christos int
   1041      1.1  christos print_insn_csky (bfd_vma memaddr, struct disassemble_info *info)
   1042      1.1  christos {
   1043      1.1  christos   unsigned char buf[4];
   1044      1.1  christos   CSKY_INST_TYPE inst = 0;
   1045      1.1  christos   int status;
   1046      1.1  christos   char str[256];
   1047  1.1.1.2  christos   unsigned long given;
   1048  1.1.1.2  christos   int is_data = false;
   1049      1.1  christos   void (*printer) (bfd_vma, struct disassemble_info *, long);
   1050      1.1  christos   unsigned int  size = 4;
   1051      1.1  christos 
   1052      1.1  christos   memset (str, 0, sizeof (str));
   1053      1.1  christos   info->bytes_per_chunk = 0;
   1054      1.1  christos   info->bytes_per_chunk = 0;
   1055      1.1  christos   dis_info.mem = memaddr;
   1056      1.1  christos   dis_info.info = info;
   1057      1.1  christos   dis_info.need_output_symbol = 0;
   1058  1.1.1.2  christos 
   1059  1.1.1.2  christos   if (info->disassembler_options)
   1060  1.1.1.2  christos     {
   1061  1.1.1.2  christos       parse_csky_dis_options (info->disassembler_options);
   1062  1.1.1.2  christos       info->disassembler_options = NULL;
   1063  1.1.1.2  christos     }
   1064  1.1.1.2  christos 
   1065      1.1  christos   if (mach_flag != INIT_MACH_FLAG && mach_flag != BINARY_MACH_FLAG)
   1066      1.1  christos     info->mach = mach_flag;
   1067      1.1  christos   else if (mach_flag == INIT_MACH_FLAG)
   1068  1.1.1.2  christos     {
   1069  1.1.1.2  christos       mach_flag = info->mach;
   1070  1.1.1.2  christos       dis_info.isa = CSKY_DEFAULT_ISA;
   1071  1.1.1.2  christos     }
   1072      1.1  christos 
   1073      1.1  christos   if (mach_flag == BINARY_MACH_FLAG && info->endian == BFD_ENDIAN_UNKNOWN)
   1074  1.1.1.2  christos     {
   1075  1.1.1.2  christos       info->endian = BFD_ENDIAN_LITTLE;
   1076  1.1.1.2  christos       dis_info.isa = CSKY_DEFAULT_ISA;
   1077  1.1.1.2  christos     }
   1078      1.1  christos 
   1079      1.1  christos   /* First check the full symtab for a mapping symbol, even if there
   1080      1.1  christos      are no usable non-mapping symbols for this address.  */
   1081      1.1  christos   if (info->symtab_size != 0
   1082      1.1  christos       && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour)
   1083      1.1  christos     {
   1084      1.1  christos       bfd_vma addr;
   1085      1.1  christos       int n;
   1086      1.1  christos       int last_sym = -1;
   1087      1.1  christos       enum sym_type type = CUR_TEXT;
   1088      1.1  christos 
   1089      1.1  christos       if (memaddr <= last_map_addr)
   1090      1.1  christos 	last_map_sym = -1;
   1091      1.1  christos       /* Start scanning at the start of the function, or wherever
   1092      1.1  christos 	 we finished last time.  */
   1093      1.1  christos       n = 0;
   1094      1.1  christos       if (n < last_map_sym)
   1095      1.1  christos 	n = last_map_sym;
   1096      1.1  christos 
   1097      1.1  christos       /* Scan up to the location being disassembled.  */
   1098      1.1  christos       for (; n < info->symtab_size; n++)
   1099      1.1  christos 	{
   1100      1.1  christos 	  addr = bfd_asymbol_value (info->symtab[n]);
   1101      1.1  christos 	  if (addr > memaddr)
   1102      1.1  christos 	    break;
   1103      1.1  christos 	  if ((info->section == NULL
   1104      1.1  christos 	       || info->section == info->symtab[n]->section)
   1105      1.1  christos 	      && get_sym_code_type (info, n, &type))
   1106      1.1  christos 	    last_sym = n;
   1107      1.1  christos 	}
   1108      1.1  christos       last_map_sym = last_sym;
   1109      1.1  christos       last_type = type;
   1110      1.1  christos       is_data = (last_type == CUR_DATA);
   1111      1.1  christos       if (is_data)
   1112      1.1  christos 	{
   1113      1.1  christos 	  size = 4 - ( memaddr & 3);
   1114      1.1  christos 	  for (n = last_sym + 1; n < info->symtab_size; n++)
   1115      1.1  christos 	    {
   1116      1.1  christos 	      addr = bfd_asymbol_value (info->symtab[n]);
   1117      1.1  christos 	      if (addr > memaddr)
   1118      1.1  christos 		{
   1119      1.1  christos 		  if (addr - memaddr < size)
   1120      1.1  christos 		    size = addr - memaddr;
   1121      1.1  christos 		  break;
   1122      1.1  christos 		}
   1123      1.1  christos 	    }
   1124      1.1  christos 	  /* If the next symbol is after three bytes, we need to
   1125      1.1  christos 	     print only part of the data, so that we can use either
   1126      1.1  christos 	     .byte or .short.  */
   1127      1.1  christos 	  if (size == 3)
   1128      1.1  christos 	    size = (memaddr & 1) ? 1 : 2;
   1129      1.1  christos 	}
   1130      1.1  christos     }
   1131      1.1  christos   info->bytes_per_line = 4;
   1132      1.1  christos 
   1133      1.1  christos   if (is_data)
   1134      1.1  christos     {
   1135      1.1  christos       int i;
   1136      1.1  christos 
   1137      1.1  christos       /* Size was already set above.  */
   1138      1.1  christos       info->bytes_per_chunk = size;
   1139      1.1  christos       printer = print_insn_data;
   1140      1.1  christos 
   1141      1.1  christos       status = info->read_memory_func (memaddr, (bfd_byte *) buf, size, info);
   1142      1.1  christos       given = 0;
   1143      1.1  christos       if (info->endian == BFD_ENDIAN_LITTLE)
   1144      1.1  christos 	for (i = size - 1; i >= 0; i--)
   1145      1.1  christos 	  given = buf[i] | (given << 8);
   1146      1.1  christos       else
   1147      1.1  christos 	for (i = 0; i < (int) size; i++)
   1148      1.1  christos 	  given = buf[i] | (given << 8);
   1149      1.1  christos 
   1150      1.1  christos       printer (memaddr, info, given);
   1151      1.1  christos       return info->bytes_per_chunk;
   1152      1.1  christos     }
   1153      1.1  christos 
   1154      1.1  christos   /* Handle instructions.  */
   1155      1.1  christos   CSKY_READ_DATA();
   1156      1.1  christos   if ((inst & 0xc000) == 0xc000 && IS_CSKY_V2 (mach_flag))
   1157      1.1  christos     {
   1158      1.1  christos       /* It's a 32-bit instruction.  */
   1159      1.1  christos       inst <<= 16;
   1160      1.1  christos       CSKY_READ_DATA();
   1161      1.1  christos       if (info->buffer && (info->endian == BFD_ENDIAN_LITTLE))
   1162      1.1  christos 	{
   1163      1.1  christos 	  char* src = (char *)(info->buffer
   1164      1.1  christos 			       + ((memaddr - 4 - info->buffer_vma)
   1165      1.1  christos 				  * info->octets_per_byte));
   1166      1.1  christos 	  if (info->endian == BFD_ENDIAN_LITTLE)
   1167      1.1  christos 	    number_to_chars_littleendian (src, inst, 4);
   1168      1.1  christos 	}
   1169      1.1  christos     }
   1170      1.1  christos 
   1171      1.1  christos   if (IS_CSKY_V1 (mach_flag))
   1172      1.1  christos     g_opcodeP = csky_v1_opcodes;
   1173      1.1  christos   else
   1174      1.1  christos     g_opcodeP = csky_v2_opcodes;
   1175      1.1  christos 
   1176      1.1  christos   do
   1177      1.1  christos     {
   1178      1.1  christos       struct csky_opcode const *op;
   1179      1.1  christos       struct csky_opcode_info const *pinfo = NULL;
   1180      1.1  christos       int reloc;
   1181      1.1  christos 
   1182      1.1  christos       memset (str, 0, sizeof (str));
   1183      1.1  christos       op = csky_find_inst_info (&pinfo, inst, info->bytes_per_chunk);
   1184      1.1  christos       if (!op)
   1185      1.1  christos 	{
   1186      1.1  christos 	  if (IS_CSKY_V1 (mach_flag))
   1187      1.1  christos 	    info->fprintf_func (info->stream, ".short: 0x%04x",
   1188      1.1  christos 				(unsigned short)inst);
   1189      1.1  christos 	  else
   1190      1.1  christos 	    info->fprintf_func (info->stream, ".long: 0x%08x",
   1191      1.1  christos 				(unsigned int)inst);
   1192      1.1  christos 	  return info->bytes_per_chunk;
   1193      1.1  christos 	}
   1194      1.1  christos 
   1195      1.1  christos       if (info->bytes_per_chunk == 2)
   1196      1.1  christos 	reloc = op->reloc16;
   1197      1.1  christos       else
   1198      1.1  christos 	reloc = op->reloc32;
   1199      1.1  christos       dis_info.opinfo = pinfo;
   1200      1.1  christos       strcat (str, op->mnemonic);
   1201      1.1  christos 
   1202      1.1  christos       if (csky_print_operands (str, pinfo, info, inst, reloc))
   1203      1.1  christos 	g_opcodeP++;
   1204      1.1  christos       else
   1205      1.1  christos 	break;
   1206      1.1  christos     } while (1);
   1207      1.1  christos 
   1208      1.1  christos   return info->bytes_per_chunk;
   1209      1.1  christos }
   1210