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