public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] CSKY: Add objdump option -M abi-names.
@ 2020-09-17  6:30 Cooper Qu
  2020-09-23 15:50 ` Lifang Xia
  2020-09-24 14:14 ` [PUSHED] " Andrew Burgess
  0 siblings, 2 replies; 5+ messages in thread
From: Cooper Qu @ 2020-09-17  6:30 UTC (permalink / raw)
  To: binutils, lifang_xia; +Cc: Cooper Qu

Add option parser for disassembler, and refine the codes of
parse register operand and disassemble register operand.
While strengthen the operands legality check of some instructions.

Co-Authored-By: Lifang Xia <lifang_xia@c-sky.com>

gas/
	* config/tc-csky.c (parse_type_ctrlreg): Use function
	csky_get_control_regno to operand.
	(csky_get_reg_val): Likewise.
	(is_reg_sp_with_bracket): Use function csky_get_reg_val
	to parse operand.
	(is_reg_sp): Refine.
	(is_oimm_within_range): Fix, report error when operand
	is not constant.
	(parse_type_cpreg): Refine.
	(parse_type_cpcreg): Refine.
	(get_operand_value): Add handle of OPRND_TYPE_IMM5b_LS.
	(md_assemble): Fix no error reporting somtimes when
	operands number are not fit.
	(csky_addc64): Refine.
	(csky_subc64): Refine.
	(csky_or64): Refine.
	(v1_work_fpu_fo): Refine.
	(v1_work_fpu_read): Refine.
	(v1_work_fpu_writed): Refine.
	(v1_work_fpu_readd): Refine.
	(v2_work_addc): New function, strengthen the operands legality
	check of addc.
	* gas/testsuite/gas/csky/all.d : Use register number format when
	disassemble register name by default.
	* gas/testsuite/gas/csky/cskyv2_all.d : Likewise.
	* gas/testsuite/gas/csky/trust.d: Likewise.
	* gas/testsuite/gas/csky/cskyv2_ck860.d : Fix.
	* gas/testsuite/gas/csky/trust.s : Fix.

opcodes/
	* csky-dis.c (using_abi): New.
	(parse_csky_dis_options): New function.
	(get_gr_name): New function.
	(get_cr_name): New function.
	(csky_output_operand): Use get_gr_name and get_cr_name to
	disassemble and add handle of OPRND_TYPE_IMM5b_LS.
	(print_insn_csky): Parse disassembler options.
	* opcodes/csky-opc.h (OPRND_TYPE_IMM5b_LS): New enum.
	(GENARAL_REG_BANK): Define.
	(REG_SUPPORT_ALL): Define.
	(REG_SUPPORT_ALL): New.
	(ASH): Define.
	(REG_SUPPORT_A): Define.
	(REG_SUPPORT_B): Define.
	(REG_SUPPORT_C): Define.
	(REG_SUPPORT_D): Define.
	(REG_SUPPORT_E): Define.
	(csky_abiv1_general_regs): New.
	(csky_abiv1_control_regs): New.
	(csky_abiv2_general_regs): New.
	(csky_abiv2_control_regs): New.
	(get_register_name): New function.
	(get_register_number): New function.
	(csky_get_general_reg_name): New function.
	(csky_get_general_regno): New function.
	(csky_get_control_reg_name): New function.
	(csky_get_control_regno): New function.
	(csky_v2_opcodes): Prefer two oprerans format for bclri and
	bseti, strengthen the operands legality check of addc, zext
	and sext.

---
 gas/config/tc-csky.c                | 641 ++++++++++++----------------
 gas/testsuite/gas/csky/all.d        |   2 +-
 gas/testsuite/gas/csky/cskyv2_all.d |  36 +-
 gas/testsuite/gas/csky/cskyv2_all.s |  24 +-
 gas/testsuite/gas/csky/trust.d      |   9 +-
 gas/testsuite/gas/csky/trust.s      |   1 -
 opcodes/csky-dis.c                  | 148 ++++---
 opcodes/csky-opc.h                  | 529 ++++++++++++++++++-----
 8 files changed, 794 insertions(+), 596 deletions(-)

diff --git a/gas/config/tc-csky.c b/gas/config/tc-csky.c
index 808dca1e52c..60d5aa1f53b 100644
--- a/gas/config/tc-csky.c
+++ b/gas/config/tc-csky.c
@@ -174,6 +174,7 @@ bfd_boolean float_work_fmovi (void);
 bfd_boolean dsp_work_bloop (void);
 bfd_boolean float_work_fpuv3_fmovi (void);
 bfd_boolean float_work_fpuv3_fstore (void);
+bfd_boolean v2_work_addc (void);
 
 /* csky-opc.h must be included after workers are declared.  */
 #include "opcodes/csky-opc.h"
@@ -2508,133 +2509,101 @@ static bfd_boolean
 parse_type_ctrlreg (char** oper)
 {
   int i = -1;
-  int len = 0;
+  int group = 0;
+  int crx;
+  int sel;
+  char *s = *oper;
+  expressionS e;
 
   if (TOLOWER (*(*oper + 0)) == 'c'
       && TOLOWER (*(*oper + 1)) == 'r'
       && ISDIGIT (*(*oper + 2)))
     {
       /* The control registers are named crxx.  */
-      i = *(*oper + 2) - 0x30;
-      i = ISDIGIT (*(*oper + 3)) ? (*(*oper + 3) - 0x30) + 10 * i : i;
-      len = ISDIGIT (*(*oper + 3)) ? 4 : 3;
-      *oper += len;
-    }
-  else if (!(TOLOWER (*(*oper + 0)) == 'c'
-	     && TOLOWER (*(*oper + 1)) == 'r'))
-    {
-      /* The control registers are aliased.  */
-      struct csky_reg *reg = &csky_ctrl_regs[0];
-      while (reg->name)
-	{
-	  if (memcmp (*oper, reg->name, strlen (reg->name)) == 0
-	      && (!reg->flag || (isa_flag & reg->flag)))
-	    {
-	      i = reg->index;
-	      len = strlen (reg->name);
-	      *oper += len;
-	      break;
-	    }
-	  reg++;
+      s = *oper+2;
+      s = parse_exp (s, &e);
+      if (e.X_op == O_constant)
+        {
+	  i = e.X_add_number;
+	  *oper = s;
 	}
     }
 
   if (IS_CSKY_V2 (mach_flag))
     {
-      char *s = *oper;
-      int crx;
-      int sel;
+
+      s = *oper;
       if (i != -1)
 	{
 	  crx = i;
-	  sel = 0;
+	  sel = group;
 	}
-      else
+      else if (TOLOWER (*(*oper + 0)) == 'c'
+	       && TOLOWER (*(*oper + 1)) == 'r')
 	{
-	  if (s[0] == 'c' && s[1] == 'r')
+	  s += 2;
+	  if (*s != '<')
 	    {
-	      s += 2;
-	      if (*s == '<')
-		{
-		  s++;
-		  if (s[0] == '3' && s[1] >= '0' && s[1] <= '1')
-		    {
-		      crx = 30 + s[1] - '0';
-		      s += 2;
-		    }
-		  else if (s[0] == '2' && s[1] >= '0' && s[1] <= '9')
-		    {
-		      crx = 20 + s[1] - '0';
-		      s += 2;
-		    }
-		  else if (s[0] == '1' && s[1] >= '0' && s[1] <= '9')
-		    {
-		      crx = 10 + s[1] - '0';
-		      s += 2;
-		    }
-		  else if (s[0] >= '0' && s[0] <= '9')
-		    {
-		      crx = s[0] - '0';
-		      s += 1;
-		    }
-		  else
-		    {
-		      SET_ERROR_STRING (ERROR_REG_OVER_RANGE, "control");
-		      return FALSE;
-		    }
-		  if (*s == ',')
-		    s++;
-		  else
-		    {
-		      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, NULL);
-		      return FALSE;
-		    }
-		  char *pS = s;
-		  while (*pS != '>' && !is_end_of_line[(unsigned char) *pS])
-		    pS++;
-		  if (*pS == '>')
-		      *pS = '\0';
-		  else
-		    {
-		      /* Error. Missing '>'.  */
-		      SET_ERROR_STRING (ERROR_MISSING_RANGLE_BRACKETS, NULL);
-		      return FALSE;
-		    }
-		  expressionS e;
-		  s = parse_exp (s, &e);
-		  if (e.X_op == O_constant
-		      && e.X_add_number >= 0
-		      && e.X_add_number <= 31)
-		    {
-		      *oper = s;
-		      sel = e.X_add_number;
-		    }
-		  else
-		    return FALSE;
-		}
-	      else
-		{
-		  /* Error. Missing '<'.  */
-		  SET_ERROR_STRING (ERROR_MISSING_LANGLE_BRACKETS, NULL);
-		  return FALSE;
-		}
+	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
+	      return FALSE;
 	    }
-	  else
+	  s++;
+	  crx = strtol(s, &s, 10);
+	  if (crx < 0 || crx > 31 || *s != ',')
+	    {
+	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
+	      return FALSE;
+	    }
+	  s++;
+	  sel = strtol(s, &s, 10);
+	  if (sel < 0 || sel > 31 || *s != '>')
 	    {
-	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, NULL);
+	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
+	      return FALSE;
+	    }
+	  s++;
+	}
+      else
+	{
+	  crx = csky_get_control_regno (mach_flag & CSKY_ARCH_MASK,
+			  s, &s, &sel);
+	  if (crx < 0)
+	    {
+	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
 	      return FALSE;
 	    }
 	}
 	i = (sel << 5) | crx;
     }
+  else if (i == -1)
+    {
+      i = csky_get_control_regno (mach_flag & CSKY_ARCH_MASK,
+				  s, &s, &sel);
+      if (i < 0)
+	{
+	  SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
+	  return FALSE;
+	}
+    }
+  *oper = s;
   csky_insn.val[csky_insn.idx++] = i;
   return TRUE;
 }
 
+static int
+csky_get_reg_val (char *str, int *len)
+{
+  int regno = 0;
+  char *s = str;
+  regno = csky_get_general_regno (mach_flag & CSKY_ARCH_MASK, str, &s);
+  *len = (s - str);
+  return regno;
+}
+
 static bfd_boolean
 is_reg_sp_with_bracket (char **oper)
 {
-  const char **regs;
+  int reg;
   int sp_idx;
   int len;
 
@@ -2646,40 +2615,30 @@ is_reg_sp_with_bracket (char **oper)
   if (**oper != '(')
       return FALSE;
   *oper += 1;
-  regs = csky_general_reg;
-  len = strlen (regs[sp_idx]);
-  if (memcmp (*oper, regs[sp_idx], len) == 0)
+  reg = csky_get_reg_val (*oper, &len);
+  *oper += len;
+  if (reg == sp_idx)
     {
-      *oper += len;
       if (**oper != ')')
-	return FALSE;
+        {
+          SET_ERROR_STRING (ERROR_UNDEFINE,
+			    "Operand format is error. '(sp)' expected");
+          return FALSE;
+        }
       *oper += 1;
       csky_insn.val[csky_insn.idx++] = sp_idx;
       return TRUE;
     }
-  else
-    {
-      if (IS_CSKY_V1 (mach_flag))
-	regs = cskyv1_general_alias_reg;
-      else
-	regs = cskyv2_general_alias_reg;
-      len = strlen (regs[sp_idx]);
-      if (memcmp (*oper, regs[sp_idx], len) == 0)
-	{
-	  *oper += len;
-	  if (**oper != ')')
-	    return FALSE;
-	  *oper += 1;
-	  return TRUE;
-	}
-    }
+
+  SET_ERROR_STRING (ERROR_UNDEFINE,
+		    "Operand format is error. '(sp)' expected");
   return FALSE;
 }
 
 static bfd_boolean
 is_reg_sp (char **oper)
 {
-  const char **regs;
+  char sp_name[16];
   int sp_idx;
   int len;
   if (IS_CSKY_V1 (mach_flag))
@@ -2687,183 +2646,23 @@ is_reg_sp (char **oper)
   else
     sp_idx = 14;
 
-  regs = csky_general_reg;
-  len = strlen (regs[sp_idx]);
-  if (memcmp (*oper, regs[sp_idx], len) == 0)
+  /* ABI names: "sp". */
+  if (memcmp (*oper, "sp", 2) == 0)
     {
-      *oper += len;
+      *oper += 2;
       csky_insn.val[csky_insn.idx++] = sp_idx;
       return TRUE;
     }
-  else
-    {
-      if (IS_CSKY_V1 (mach_flag))
-	regs = cskyv1_general_alias_reg;
-      else
-	regs = cskyv2_general_alias_reg;
-      len = strlen (regs[sp_idx]);
-      if (memcmp (*oper, regs[sp_idx], len) == 0)
-	{
-	  *oper += len;
-	  csky_insn.val[csky_insn.idx++] = sp_idx;
-	  return TRUE;
-	}
-    }
-  return FALSE;
-}
-
-static int
-csky_get_reg_val (char *str, int *len)
-{
-  long reg = 0;
-  if (TOLOWER (str[0]) == 'r' && ISDIGIT (str[1]))
-    {
-      if (ISDIGIT (str[1]) && ISDIGIT (str[2]))
-	{
-	  reg = (str[1] - '0') * 10 + str[2] - '0';
-	  *len = 3;
-	}
-      else if (ISDIGIT (str[1]))
-	{
-	  reg = str[1] - '0';
-	  *len = 2;
-	}
-      else
-	return -1;
-    }
-  else if (TOLOWER (str[0]) == 's' && TOLOWER (str[1]) == 'p'
-	   && !ISDIGIT (str[2]))
-    {
-      /* sp.  */
-      if (IS_CSKY_V1 (mach_flag))
-	reg = 0;
-      else
-	reg = 14;
-      *len = 2;
-    }
-  else if (TOLOWER (str[0]) == 'g' && TOLOWER (str[1]) == 'b'
-	   && !ISDIGIT (str[2]))
-    {
-      /* gb.  */
-      if (IS_CSKY_V1 (mach_flag))
-	reg = 14;
-      else
-	reg = 28;
-      *len = 2;
-    }
-  else if (TOLOWER (str[0]) == 'l' && TOLOWER (str[1]) == 'r'
-	   && !ISDIGIT (str[2]))
-    {
-      /* lr.  */
-      reg = 15;
-      *len = 2;
-    }
-  else if (TOLOWER (str[0]) == 't' && TOLOWER (str[1]) == 'l'
-	   && TOLOWER (str[2]) == 's' && !ISDIGIT (str[3]))
-    {
-      /* tls.  */
-      if (IS_CSKY_V2 (mach_flag))
-	reg = 31;
-      else
-	return -1;
-      *len = 3;
-    }
-  else if (TOLOWER (str[0]) == 's' && TOLOWER (str[1]) == 'v'
-	   && TOLOWER (str[2]) == 'b' && TOLOWER (str[3]) == 'r')
-    {
-      if (IS_CSKY_V2 (mach_flag))
-	reg = 30;
-      else
-	return -1;
-      *len = 4;
-    }
-  else if (TOLOWER (str[0]) == 'a')
-    {
-      if (ISDIGIT (str[1]) && !ISDIGIT (str[2]))
-	{
-	  if (IS_CSKY_V1 (mach_flag) && (str[1] - '0') <= 5)
-	    /* a0 - a5.  */
-	    reg = 2 + str[1] - '0';
-	  else if (IS_CSKY_V2 (mach_flag) && (str[1] - '0') <= 3)
-	    /* a0 - a3.  */
-	    reg = str[1] - '0';
-	  else
-	    return -1;
-	  *len = 2;
-	}
-    }
-  else if (TOLOWER (str[0]) == 't')
-    {
-      if (IS_CSKY_V2 (mach_flag))
-	{
-	  reg = atoi (str + 1);
-	  if (reg > 9)
-	    return -1;
-
-	  if (reg > 1)
-	    /* t2 - t9.  */
-	    reg = reg + 16;
-	  else
-	    /* t0 - t1.  */
-	    reg = reg + 12;
-	  *len = 2;
-	}
-    }
-  else if (TOLOWER (str[0]) == 'l')
-    {
-      if (str[1] < '0' || str[1] > '9')
-	return -1;
-      if (IS_CSKY_V2 (mach_flag))
-	{
-	  reg = atoi (str + 1);
-	  if (reg > 9)
-	    return -1;
-	  if (reg > 7)
-	    /* l8 - l9.  */
-	    reg = reg + 8;
-	  else
-	    /* l0 - l7.  */
-	    reg = reg + 4;
-	}
-      else
-	{
-	  reg = atoi (str + 1);
-	  if (reg > 5)
-	    return -1;
-	  /* l0 - l6 -> r8 - r13.  */
-	  reg = reg + 8;
-	}
-      *len = 2;
-    }
-  else
-    return -1;
 
-  /* Is register available?  */
-  if (IS_CSKY_ARCH_801 (mach_flag))
-    {
-      /* CK801 register range is r0-r8 & r13-r15.  */
-      if ((reg > 8 && reg < 13) || reg > 15)
-	{
-	  SET_ERROR_STRING (ERROR_REG_OVER_RANGE, reg);
-	  return -1;
-	}
-    }
-  else if (IS_CSKY_ARCH_802 (mach_flag))
-    {
-      /* CK802 register range is r0-r15 & r23-r25 & r30.  */
-      if ((reg > 15 && reg < 23) || (reg > 25 && reg != 30))
-	{
-	  SET_ERROR_STRING (ERROR_REG_OVER_RANGE, reg);
-	  return -1;
-	}
-    }
-  else if (reg > 31 || reg < 0)
+  len = sprintf (sp_name, "r%d", sp_idx);
+  if (memcmp (*oper, sp_name, len) == 0)
     {
-      SET_ERROR_STRING (ERROR_REG_OVER_RANGE, reg);
-      return -1;
+      *oper += len;
+      csky_insn.val[csky_insn.idx++] = sp_idx;
+      return TRUE;
     }
 
-  return reg;
+  return FALSE;
 }
 
 static int
@@ -3168,7 +2967,6 @@ is_imm_within_range (char **oper, int min, int max)
 	e.X_add_number |= 0x80000000;
       csky_insn.val[csky_insn.idx++] = e.X_add_number;
     }
-
   else
     SET_ERROR_STRING(ERROR_IMM_ILLEGAL, NULL);
 
@@ -3217,6 +3015,8 @@ is_oimm_within_range (char **oper, int min, int max)
 	}
       csky_insn.val[csky_insn.idx++] = e.X_add_number - 1;
     }
+  else
+    SET_ERROR_STRING (ERROR_IMM_ILLEGAL, NULL);
 
   return ret;
 }
@@ -3291,43 +3091,51 @@ parse_type_cpidx (char** oper)
 static bfd_boolean
 parse_type_cpreg (char** oper)
 {
-  const char **regs = csky_cp_reg;
-  int i;
-  int len;
+  expressionS e;
 
-  for (i = 0; i < (int)(sizeof (csky_cp_reg) / sizeof (char *)); i++)
+  if (strncasecmp (*oper, "cpr", 3) != 0)
     {
-      len = strlen (regs[i]);
-      if (memcmp (*oper, regs[i], len) == 0 && !ISDIGIT (*(*oper + len)))
-	{
-	  *oper += len;
-	  csky_insn.val[csky_insn.idx++] = i;
-	  return TRUE;
-	}
+      SET_ERROR_STRING(ERROR_CPREG_ILLEGAL, *oper);
+      return FALSE;
     }
-  SET_ERROR_STRING (ERROR_CPREG_ILLEGAL, *oper);
-  return FALSE;
+
+  *oper += 3;
+
+  *oper = parse_exp (*oper, &e);
+  if (e.X_op != O_constant)
+    {
+      SET_ERROR_STRING(ERROR_CPREG_ILLEGAL, *oper);
+      return FALSE;
+    }
+
+  csky_insn.val[csky_insn.idx++] = e.X_add_number;
+
+  return TRUE;
 }
 
 static bfd_boolean
 parse_type_cpcreg (char** oper)
 {
-  const char **regs;
-  int i;
-  int len;
-  regs = csky_cp_creg;
-  for (i = 0; i < (int)(sizeof (csky_cp_creg) / sizeof (char *)); i++)
+  expressionS e;
+
+  if (strncasecmp (*oper, "cpcr", 4) != 0)
     {
-      len = strlen (regs[i]);
-      if (memcmp (*oper, regs[i], len) == 0 && !ISDIGIT (*(*oper + len)))
-	{
-	  *oper += len;
-	  csky_insn.val[csky_insn.idx++] = i;
-	  return TRUE;
-	}
+      SET_ERROR_STRING(ERROR_CPREG_ILLEGAL, *oper);
+      return FALSE;
     }
-  SET_ERROR_STRING (ERROR_CPREG_ILLEGAL, *oper);
-  return FALSE;
+
+  *oper += 4;
+
+  *oper = parse_exp (*oper, &e);
+  if (e.X_op != O_constant)
+    {
+      SET_ERROR_STRING(ERROR_CPREG_ILLEGAL, *oper);
+      return FALSE;
+    }
+
+  csky_insn.val[csky_insn.idx++] = e.X_add_number;
+
+  return TRUE;
 }
 
 static bfd_boolean
@@ -3830,6 +3638,10 @@ get_operand_value (struct csky_opcode_info *op,
 	else
 	  return FALSE;
 
+    case OPRND_TYPE_IMM5b_LS:
+      return is_imm_within_range (oper,
+				  0,
+				  csky_insn.val[csky_insn.idx - 1]);
     case OPRND_TYPE_IMM5b_RORI:
       {
 	unsigned max_shift = IS_CSKY_V1 (mach_flag) ? 31 : 32;
@@ -4769,6 +4581,7 @@ md_assemble (char *str)
 		       (void *)error_state.arg1, (void *)error_state.arg1);
       return;
     }
+  error_state.err_num = ERROR_NONE;
 
   /* if this insn has work in opcode table, then do it.  */
   if (csky_insn.opcode->work != NULL)
@@ -6195,21 +6008,26 @@ csky_addc64 (void)
   int reg1;
   int reg2;
   int reg3;
+  char reg1_name[16] = {0};
+  char reg3_name[16] = {0};
 
   if (!get_macro_reg_vals (&reg1, &reg2, &reg3))
     return;
-  csky_macro_md_assemble ("cmplt",
-			  csky_general_reg[reg1],
-			  csky_general_reg[reg1],
-			  NULL);
-  csky_macro_md_assemble ("addc",
-			  csky_general_reg[reg1 + (target_big_endian ? 1 : 0)],
-			  csky_general_reg[reg3 + (target_big_endian ? 1 : 0)],
-			  NULL);
-  csky_macro_md_assemble ("addc",
-			  csky_general_reg[reg1 + (target_big_endian ? 0 : 1)],
-			  csky_general_reg[reg3 + (target_big_endian ? 0 : 1)],
-			  NULL);
+
+  sprintf (reg1_name, "r%d", reg1);
+  csky_macro_md_assemble ("cmplt", reg1_name, reg1_name, NULL);
+  if (error_state.err_num != ERROR_NONE)
+    return;
+
+  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 1 : 0));
+  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 1 : 0));
+  csky_macro_md_assemble ("addc", reg1_name, reg3_name, NULL);
+  if (error_state.err_num != ERROR_NONE)
+    return;
+
+  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 0 : 1));
+  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 0 : 1));
+  csky_macro_md_assemble ("addc", reg1_name, reg3_name, NULL);
   return;
 }
 
@@ -6221,21 +6039,26 @@ csky_subc64 (void)
   int reg1;
   int reg2;
   int reg3;
+  char reg1_name[16] = {0};
+  char reg3_name[16] = {0};
 
   if (!get_macro_reg_vals (&reg1, &reg2, &reg3))
     return;
-  csky_macro_md_assemble ("cmphs",
-			  csky_general_reg[reg1],
-			  csky_general_reg[reg1],
-			  NULL);
-  csky_macro_md_assemble ("subc",
-			  csky_general_reg[reg1 + (target_big_endian ? 1 : 0)],
-			  csky_general_reg[reg3 + (target_big_endian ? 1 : 0)],
-			  NULL);
-  csky_macro_md_assemble ("subc",
-			  csky_general_reg[reg1 + (target_big_endian ? 0 : 1)],
-			  csky_general_reg[reg3 + (target_big_endian ? 0 : 1)],
-			  NULL);
+
+  sprintf (reg1_name, "r%d", reg1);
+  csky_macro_md_assemble ("cmphs", reg1_name, reg1_name, NULL);
+  if (error_state.err_num != ERROR_NONE)
+    return;
+
+  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 1 : 0));
+  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 1 : 0));
+  csky_macro_md_assemble ("subc", reg1_name, reg3_name, NULL);
+  if (error_state.err_num != ERROR_NONE)
+    return;
+
+  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 0 : 1));
+  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 0 : 1));
+  csky_macro_md_assemble ("subc", reg1_name, reg3_name, NULL);
   return;
 }
 
@@ -6247,17 +6070,20 @@ csky_or64 (void)
   int reg1;
   int reg2;
   int reg3;
+  char reg1_name[16] = {0};
+  char reg3_name[16] = {0};
 
   if (!get_macro_reg_vals (&reg1, &reg2, &reg3))
     return;
-  csky_macro_md_assemble ("or",
-			  csky_general_reg[reg1 + (target_big_endian ? 1 : 0)],
-			  csky_general_reg[reg3 + (target_big_endian ? 1 : 0)],
-			  NULL);
-  csky_macro_md_assemble ("or",
-			  csky_general_reg[reg1 + (target_big_endian ? 0 : 1)],
-			  csky_general_reg[reg3 + (target_big_endian ? 0 : 1)],
-			  NULL);
+  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 1 : 0));
+  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 1 : 0));
+  csky_macro_md_assemble ("or", reg1_name, reg3_name, NULL);
+
+  if (error_state.err_num != ERROR_NONE)
+    return;
+  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 0 : 1));
+  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 0 : 1));
+  csky_macro_md_assemble ("or", reg1_name, reg3_name, NULL);
   return;
 }
 
@@ -6269,17 +6095,21 @@ csky_xor64 (void)
   int reg1;
   int reg2;
   int reg3;
+  char reg1_name[16] = {0};
+  char reg3_name[16] = {0};
 
   if (!get_macro_reg_vals (&reg1, &reg2, &reg3))
     return;
-  csky_macro_md_assemble ("xor",
-			  csky_general_reg[reg1 + (target_big_endian ? 1 : 0)],
-			  csky_general_reg[reg3 + (target_big_endian ? 1 : 0)],
-			  NULL);
-  csky_macro_md_assemble ("xor",
-			  csky_general_reg[reg1 + (target_big_endian ? 0 : 1)],
-			  csky_general_reg[reg3 + (target_big_endian ? 0 : 1)],
-			  NULL);
+
+  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 1 : 0));
+  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 1 : 0));
+  csky_macro_md_assemble ("xor", reg1_name, reg3_name, NULL);
+  if (error_state.err_num != ERROR_NONE)
+    return;
+
+  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 0 : 1));
+  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 0 : 1));
+  csky_macro_md_assemble ("xor", reg1_name, reg3_name, NULL);
   return;
 }
 
@@ -6463,11 +6293,10 @@ v1_work_fpu_fo (void)
   inst = csky_insn.inst;
 
   /* Now get greg and inst, we can write instruction to floating unit.  */
-  sprintf (buff, "lrw %s,0x%x", csky_general_reg[greg], inst);
+  sprintf (buff, "lrw r%d,0x%x", greg, inst);
   md_assemble (buff);
-  sprintf (buff, "cpwir %s", csky_general_reg[greg]);
+  sprintf (buff, "cpwir r%d", greg);
   md_assemble (buff);
-
   return FALSE;
 }
 
@@ -6496,9 +6325,9 @@ v1_work_fpu_fo_fc (void)
   inst = csky_insn.inst;
 
   /* Now get greg and inst, we can write instruction to floating unit.  */
-  sprintf (buff, "lrw %s,0x%x", csky_general_reg[greg], inst);
+  sprintf (buff, "lrw r%d,0x%x", greg, inst);
   md_assemble (buff);
-  sprintf (buff, "cpwir %s", csky_general_reg[greg]);
+  sprintf (buff, "cpwir r%d", greg);
   md_assemble (buff);
   sprintf (buff, "cprc");
   md_assemble (buff);
@@ -6517,7 +6346,7 @@ v1_work_fpu_write (void)
   freg = csky_insn.val[1];
 
   /* Now get greg and freg, we can write instruction to floating unit.  */
-  sprintf (buff, "cpwgr %s,%s", csky_general_reg[greg], csky_cp_reg[freg]);
+  sprintf (buff, "cpwgr r%d,cpr%d", greg, freg);
   md_assemble (buff);
 
   return FALSE;
@@ -6533,7 +6362,7 @@ v1_work_fpu_read (void)
   greg = csky_insn.val[0];
   freg = csky_insn.val[1];
   /* Now get greg and freg, we can write instruction to floating unit.  */
-  sprintf (buff, "cprgr %s,%s", csky_general_reg[greg], csky_cp_reg[freg]);
+  sprintf (buff, "cprgr r%d,cpr%d", greg, freg);
   md_assemble (buff);
 
   return FALSE;
@@ -6556,20 +6385,15 @@ v1_work_fpu_writed (void)
     }
   /* Now get greg and freg, we can write instruction to floating unit.  */
   if (target_big_endian)
-    sprintf (buff, "cpwgr %s,%s",
-	     csky_general_reg[greg + 1], csky_cp_reg[freg]);
+    sprintf (buff, "cpwgr r%d,cpr%d", greg + 1, freg);
   else
-    sprintf (buff, "cpwgr %s,%s",
-	     csky_general_reg[greg], csky_cp_reg[freg]);
+    sprintf (buff, "cpwgr r%d,cpr%d", greg, freg);
   md_assemble (buff);
   if (target_big_endian)
-    sprintf (buff, "cpwgr %s,%s",
-	     csky_general_reg[greg], csky_cp_reg[freg + 1]);
+    sprintf (buff, "cpwgr r%d,cpr%d", greg, freg + 1);
   else
-    sprintf (buff, "cpwgr %s,%s",
-	     csky_general_reg[greg + 1], csky_cp_reg[freg + 1]);
+    sprintf (buff, "cpwgr r%d,cpr%d", greg+1, freg + 1);
   md_assemble (buff);
-
   return FALSE;
 }
 
@@ -6590,18 +6414,14 @@ v1_work_fpu_readd (void)
     }
   /* Now get greg and freg, we can write instruction to floating unit.  */
   if (target_big_endian)
-    sprintf (buff, "cprgr %s,%s",
-	     csky_general_reg[greg + 1], csky_cp_reg[freg]);
+    sprintf (buff, "cprgr r%d,cpr%d", greg+1, freg);
   else
-    sprintf (buff, "cprgr %s,%s",
-	     csky_general_reg[greg], csky_cp_reg[freg]);
+    sprintf (buff, "cprgr r%d,cpr%d", greg, freg);
   md_assemble (buff);
   if (target_big_endian)
-    sprintf (buff, "cprgr %s,%s",
-	     csky_general_reg[greg], csky_cp_reg[freg + 1]);
+    sprintf (buff, "cprgr r%d,cpr%d", greg, freg + 1);
   else
-    sprintf (buff, "cprgr %s,%s",
-	     csky_general_reg[greg + 1], csky_cp_reg[freg + 1]);
+    sprintf (buff, "cprgr r%d,cpr%d", greg+1, freg + 1);
   md_assemble (buff);
 
   return FALSE;
@@ -7677,6 +7497,69 @@ float_work_fpuv3_fstore(void)
   return TRUE;
 }
 
+bfd_boolean
+v2_work_addc (void)
+{
+  int reg1;
+  int reg2;
+  int reg3 = 0;
+  int is_16_bit = 0;
+
+  reg1 = csky_insn.val[0];
+  reg2 = csky_insn.val[1];
+  if (csky_insn.number == 2)
+    {
+      if (reg1 > 15 || reg2 > 15)
+	{
+	  is_16_bit = 0;
+	  reg3 = reg1;
+	}
+      else
+	is_16_bit = 1;
+    }
+  else
+    {
+      reg3 = csky_insn.val[2];
+      if (reg1 > 15 || reg2 > 15 || reg3 > 15)
+	is_16_bit = 0;
+      else if (reg1 == reg2 || reg1 == reg3)
+	{
+	  is_16_bit = 1;
+	  reg2 = (reg1 == reg2) ? reg3 : reg2;
+	}
+      else
+	is_16_bit = 0;
+    }
+
+  if (is_16_bit
+      && csky_insn.flag_force != INSN_OPCODE32F)
+    {
+      csky_insn.isize = 2;
+      csky_insn.inst = csky_insn.opcode->op16[0].opcode
+	| (reg1 << 6) | (reg2 << 2);
+    }
+  else if (csky_insn.flag_force != INSN_OPCODE16F)
+    {
+      csky_insn.isize = 4;
+      csky_insn.inst = csky_insn.opcode->op32[0].opcode
+	| (reg1 << 0) | (reg2 << 16) | (reg3 << 21);
+    }
+  else
+    {
+      SET_ERROR_INTEGER (ERROR_REG_OVER_RANGE, reg1 > 15 ? reg1 : reg2);
+      csky_show_error (ERROR_REG_OVER_RANGE, 0, 0, NULL);
+    }
+
+  /* Generate relax or reloc if necessary.  */
+  csky_generate_frags ();
+  /* Write inst to frag.  */
+  csky_write_insn (csky_insn.output,
+		   csky_insn.inst,
+		   csky_insn.isize);
+
+  return TRUE;
+}
+
 /* The following are for assembler directive handling.  */
 
 /* Helper function to adjust constant pool counts when we emit a
diff --git a/gas/testsuite/gas/csky/all.d b/gas/testsuite/gas/csky/all.d
index 606bcc0d3c6..af9acb50da8 100644
--- a/gas/testsuite/gas/csky/all.d
+++ b/gas/testsuite/gas/csky/all.d
@@ -20,7 +20,7 @@ Disassembly of section \.text:
 \s*[0-9a-f]*:\s*0032\s*mvcv\s*r2
 \s*[0-9a-f]*:\s*0042\s*ldq\s*r4-r7, \(r2\)
 \s*[0-9a-f]*:\s*0052\s*stq\s*r4-r7, \(r2\)
-\s*[0-9a-f]*:\s*0061\s*ldm\s*r1-r15, \(sp\)
+\s*[0-9a-f]*:\s*0061\s*ldm\s*r1-r15, \(r0\)
 \s*[0-9a-f]*:\s*0082\s*dect\s*r2, r2, 1
 \s*[0-9a-f]*:\s*0092\s*decf\s*r2, r2, 1
 \s*[0-9a-f]*:\s*00a2\s*inct\s*r2, r2, 1
diff --git a/gas/testsuite/gas/csky/cskyv2_all.d b/gas/testsuite/gas/csky/cskyv2_all.d
index bb688ec97d4..bb104a7bc09 100644
--- a/gas/testsuite/gas/csky/cskyv2_all.d
+++ b/gas/testsuite/gas/csky/cskyv2_all.d
@@ -14,10 +14,10 @@ Disassembly of section \.text:
 \s*[0-9a-f]*:\s*c6824848\s*lsri\s*r8,\s*r2,\s*20
 \s*[0-9a-f]*:\s*5227\s*asri\s*r1,\s*r2,\s*7
 \s*[0-9a-f]*:\s*6049\s*addc\s*r1,\s*r2
-\s*[0-9a-f]*:\s*c4310051\s*addc\s*r17,\s*r17,\s*r1
+\s*[0-9a-f]*:\s*c6210051\s*addc\s*r17,\s*r1,\s*r17
 \s*[0-9a-f]*:\s*c4620041\s*addc\s*r1,\s*r2,\s*r3
 \s*[0-9a-f]*:\s*6049\s*addc\s*r1,\s*r2
-\s*[0-9a-f]*:\s*c6210041\s*addc\s*r1,\s*r1,\s*r17
+\s*[0-9a-f]*:\s*c4310041\s*addc\s*r1,\s*r17,\s*r1
 \s*[0-9a-f]*:\s*c7d20052\s*addc\s*r18,\s*r18,\s*r30
 \s*[0-9a-f]*:\s*604b\s*subc\s*r1,\s*r2
 \s*[0-9a-f]*:\s*c4310111\s*subc\s*r17,\s*r17,\s*r1
@@ -67,23 +67,23 @@ Disassembly of section \.text:
 \s*[0-9a-f]*:\s*c4419421\s*mulsw\s*r1,\s*r1,\s*r2
 \s*[0-9a-f]*:\s*8344\s*ld.b\s*r2,\s*\(r3,\s*0x4\)
 \s*[0-9a-f]*:\s*8b42\s*ld.h\s*r2,\s*\(r3,\s*0x4\)
-\s*[0-9a-f]*:\s*9841\s*ld.w\s*r2,\s*\(sp,\s*0x4\)
+\s*[0-9a-f]*:\s*9841\s*ld.w\s*r2,\s*\(r14,\s*0x4\)
 \s*[0-9a-f]*:\s*a344\s*st.b\s*r2,\s*\(r3,\s*0x4\)
 \s*[0-9a-f]*:\s*ab42\s*st.h\s*r2,\s*\(r3,\s*0x4\)
-\s*[0-9a-f]*:\s*b841\s*st.w\s*r2,\s*\(sp,\s*0x4\)
+\s*[0-9a-f]*:\s*b841\s*st.w\s*r2,\s*\(r14,\s*0x4\)
 \s*[0-9a-f]*:\s*d9030004\s*ld.b\s*r8,\s*\(r3,\s*0x4\)
 \s*[0-9a-f]*:\s*d8481002\s*ld.h\s*r2,\s*\(r8,\s*0x4\)
-\s*[0-9a-f]*:\s*9841\s*ld.w\s*r2,\s*\(sp,\s*0x4\)
+\s*[0-9a-f]*:\s*9841\s*ld.w\s*r2,\s*\(r14,\s*0x4\)
 \s*[0-9a-f]*:\s*dc480004\s*st.b\s*r2,\s*\(r8,\s*0x4\)
 \s*[0-9a-f]*:\s*dc481002\s*st.h\s*r2,\s*\(r8,\s*0x4\)
-\s*[0-9a-f]*:\s*dd0e2001\s*st.w\s*r8,\s*\(sp,\s*0x4\)
+\s*[0-9a-f]*:\s*dd0e2001\s*st.w\s*r8,\s*\(r14,\s*0x4\)
 \s*[0-9a-f]*:\s*d8434003\s*ld.bs\s*r2,\s*\(r3,\s*0x3\)
 \s*[0-9a-f]*:\s*d8433001\s*ld.d\s*r2,\s*\(r3,\s*0x4\)
 \s*[0-9a-f]*:\s*dc433001\s*st.d\s*r2,\s*\(r3,\s*0x4\)
 \s*[0-9a-f]*:\s*dc437001\s*stex.w\s*r2,\s*\(r3,\s*0x4\)
 \s*[0-9a-f]*:\s*d8437001\s*ldex.w\s*r2,\s*\(r3,\s*0x4\)
-\s*[0-9a-f]*:\s*140c\s*addi\s*sp,\s*sp,\s*48
-\s*[0-9a-f]*:\s*1b01\s*addi\s*r3,\s*sp,\s*4
+\s*[0-9a-f]*:\s*140c\s*addi\s*r14,\s*r14,\s*48
+\s*[0-9a-f]*:\s*1b01\s*addi\s*r3,\s*r14,\s*4
 \s*[0-9a-f]*:\s*2113\s*addi\s*r1,\s*20
 \s*[0-9a-f]*:\s*2113\s*addi\s*r1,\s*20
 \s*[0-9a-f]*:\s*e6b50013\s*addi\s*r21,\s*r21,\s*20
@@ -92,16 +92,16 @@ Disassembly of section \.text:
 \s*[0-9a-f]*:\s*e5040000\s*addi\s*r8,\s*r4,\s*1
 \s*[0-9a-f]*:\s*e4240008\s*addi\s*r1,\s*r4,\s*9
 \s*[0-9a-f]*:\s*cc3c0008\s*addi\s*r1,\s*r28,\s*9
-\s*[0-9a-f]*:\s*e46e0000\s*addi\s*r3,\s*sp,\s*1
-\s*[0-9a-f]*:\s*e46e03ff\s*addi\s*r3,\s*sp,\s*1024
-\s*[0-9a-f]*:\s*e5ce0032\s*addi\s*sp,\s*sp,\s*51
-\s*[0-9a-f]*:\s*e5ce01ff\s*addi\s*sp,\s*sp,\s*512
+\s*[0-9a-f]*:\s*e46e0000\s*addi\s*r3,\s*r14,\s*1
+\s*[0-9a-f]*:\s*e46e03ff\s*addi\s*r3,\s*r14,\s*1024
+\s*[0-9a-f]*:\s*e5ce0032\s*addi\s*r14,\s*r14,\s*51
+\s*[0-9a-f]*:\s*e5ce01ff\s*addi\s*r14,\s*r14,\s*512
 \s*[0-9a-f]*:\s*2113\s*addi\s*r1,\s*20
 \s*[0-9a-f]*:\s*5c42\s*addi\s*r2,\s*r4,\s*1
 \s*[0-9a-f]*:\s*e4440000\s*addi\s*r2,\s*r4,\s*1
-\s*[0-9a-f]*:\s*e46e03ff\s*addi\s*r3,\s*sp,\s*1024
-\s*[0-9a-f]*:\s*e5ce0032\s*addi\s*sp,\s*sp,\s*51
-\s*[0-9a-f]*:\s*142c\s*subi\s*sp,\s*sp,\s*48
+\s*[0-9a-f]*:\s*e46e03ff\s*addi\s*r3,\s*r14,\s*1024
+\s*[0-9a-f]*:\s*e5ce0032\s*addi\s*r14,\s*r14,\s*51
+\s*[0-9a-f]*:\s*142c\s*subi\s*r14,\s*r14,\s*48
 \s*[0-9a-f]*:\s*2913\s*subi\s*r1,\s*20
 \s*[0-9a-f]*:\s*2913\s*subi\s*r1,\s*20
 \s*[0-9a-f]*:\s*e6b51013\s*subi\s*r21,\s*r21,\s*20
@@ -110,12 +110,12 @@ Disassembly of section \.text:
 \s*[0-9a-f]*:\s*e5041000\s*subi\s*r8,\s*r4,\s*1
 \s*[0-9a-f]*:\s*e4241008\s*subi\s*r1,\s*r4,\s*9
 \s*[0-9a-f]*:\s*e43c1008\s*subi\s*r1,\s*r28,\s*9
-\s*[0-9a-f]*:\s*e5ce1032\s*subi\s*sp,\s*sp,\s*51
-\s*[0-9a-f]*:\s*e5ce11ff\s*subi\s*sp,\s*sp,\s*512
+\s*[0-9a-f]*:\s*e5ce1032\s*subi\s*r14,\s*r14,\s*51
+\s*[0-9a-f]*:\s*e5ce11ff\s*subi\s*r14,\s*r14,\s*512
 \s*[0-9a-f]*:\s*2913\s*subi\s*r1,\s*20
 \s*[0-9a-f]*:\s*5c43\s*subi\s*r2,\s*r4,\s*1
 \s*[0-9a-f]*:\s*e4441000\s*subi\s*r2,\s*r4,\s*1
-\s*[0-9a-f]*:\s*e5ce1032\s*subi\s*sp,\s*sp,\s*51
+\s*[0-9a-f]*:\s*e5ce1032\s*subi\s*r14,\s*r14,\s*51
 \s*[0-9a-f]*:\s*60c2\s*subu\s*r3,\s*r0
 \s*[0-9a-f]*:\s*6202\s*subu\s*r8,\s*r0
 \s*[0-9a-f]*:\s*c4030089\s*subu\s*r9,\s*r3,\s*r0
diff --git a/gas/testsuite/gas/csky/cskyv2_all.s b/gas/testsuite/gas/csky/cskyv2_all.s
index 6e6902e077b..6db5b202bfb 100644
--- a/gas/testsuite/gas/csky/cskyv2_all.s
+++ b/gas/testsuite/gas/csky/cskyv2_all.s
@@ -76,8 +76,8 @@ all:
    st.d    r2, (r3, 4)
    stex.w   r2, (r3, 4)
    ldex.w   r2, (r3, 4)
-   addi    sp,  sp, 0x30
-   addi    r3,  sp, 0x4
+   addi    r14,  r14, 0x30
+   addi    r3,  r14, 0x4
    addi    r1,  20
    addi    r1,  r1, 20
    addi    r21, 20
@@ -86,16 +86,16 @@ all:
    addi    r8,  r4, 1
    addi    r1,  r4, 9
    addi    r1,  r28, 9
-   addi    r3,  sp, 0x1
-   addi    r3,  sp, 0x400
-   addi    sp,  sp, 0x33
-   addi    sp,  sp, 0x200
+   addi    r3,  r14, 0x1
+   addi    r3,  r14, 0x400
+   addi    r14,  r14, 0x33
+   addi    r14,  r14, 0x200
    addi16  r1,  20
    addi16  r2,  r4, 1
    addi32  r2,  r4, 1
-   addi32  r3,  sp, 0x400
-   addi32  sp,  sp, 0x33
-   subi    sp,  sp, 0x30
+   addi32  r3,  r14, 0x400
+   addi32  r14,  r14, 0x33
+   subi    r14,  r14, 0x30
    subi    r1,  20
    subi    r1,  r1, 20
    subi    r21, 20
@@ -104,12 +104,12 @@ all:
    subi    r8,  r4, 1
    subi    r1,  r4, 9
    subi    r1,  r28, 9
-   subi    sp,  sp, 0x33
-   subi    sp,  sp, 0x200
+   subi    r14,  r14, 0x33
+   subi    r14,  r14, 0x200
    subi16  r1,  20
    subi16  r2,  r4, 1
    subi32  r2,  r4, 1
-   subi32  sp,  sp, 0x33
+   subi32  r14,  r14, 0x33
    sub     r3, r0
    sub     r8, r0
    sub     r9, r3, r0
diff --git a/gas/testsuite/gas/csky/trust.d b/gas/testsuite/gas/csky/trust.d
index 1a87b4d472b..adaa21cd77c 100644
--- a/gas/testsuite/gas/csky/trust.d
+++ b/gas/testsuite/gas/csky/trust.d
@@ -7,11 +7,10 @@
 Disassembly of section \.text:
 #...
 \s*[0-9a-f]*:\s*c0003c20\s*wsc
-\s*[0-9a-f]*:\s*c0006024\s*mfcr\s*r4,\s*cr<0,\s*0>
-\s*[0-9a-f]*:\s*c0156024\s*mfcr\s*r4,\s*cr<21,\s*0>
-\s*[0-9a-f]*:\s*c004642b\s*mtcr\s*r4,\s*cr<11,\s*0>
-\s*[0-9a-f]*:\s*c0046428\s*mtcr\s*r4,\s*cr<8,\s*0>
-\s*[0-9a-f]*:\s*c0096024\s*mfcr\s*r4,\s*cr<9,\s*0>
+\s*[0-9a-f]*:\s*c0006024\s*mfcr\s*r4,\s*cr<0,\s+0>
+\s*[0-9a-f]*:\s*c004642b\s*mtcr\s*r4,\s*cr<11,\s+0>
+\s*[0-9a-f]*:\s*c0646428\s*mtcr\s*r4,\s*cr<8,\s+3>
+\s*[0-9a-f]*:\s*c0696024\s*mfcr\s*r4,\s*cr<9,\s+3>
 \s*[0-9a-f]*:\s*c2007420\s*psrset\s*sie
 \s*[0-9a-f]*:\s*c2007020\s*psrclr\s*sie
 #...
diff --git a/gas/testsuite/gas/csky/trust.s b/gas/testsuite/gas/csky/trust.s
index 781dc8cbb84..862fa5bc94a 100644
--- a/gas/testsuite/gas/csky/trust.s
+++ b/gas/testsuite/gas/csky/trust.s
@@ -1,7 +1,6 @@
 TRUST:
      wsc
      mfcr r4, psr
-     mfcr r4, rid
      mtcr r4, gcr
      mtcr r4, sedcr
      mfcr r4, sepcr
diff --git a/opcodes/csky-dis.c b/opcodes/csky-dis.c
index ba0f4605f54..169368ac4be 100644
--- a/opcodes/csky-dis.c
+++ b/opcodes/csky-dis.c
@@ -60,6 +60,7 @@ struct csky_dis_info
 enum sym_type last_type;
 int last_map_sym = 1;
 bfd_vma last_map_addr = 0;
+int using_abi = 0;
 
 /* Only for objdump tool.  */
 #define INIT_MACH_FLAG  0xffffffff
@@ -260,6 +261,40 @@ csky_get_disassembler (bfd *abfd)
    return print_insn_csky;
 }
 
+/* Parse the string of disassembler options.  */
+static void
+parse_csky_dis_options (const char *opts_in)
+{
+  char *opts = xstrdup (opts_in);
+  char *opt = opts;
+  char *opt_end = opts;
+
+  for (; opt_end != NULL; opt = opt_end + 1)
+    {
+      if ((opt_end = strchr (opt, ',')) != NULL)
+	*opt_end = 0;
+      if (strcmp (opt, "abi-names") == 0)
+	using_abi = 1;
+      else
+	fprintf (stderr,
+		 "unrecognized disassembler option: %s", opt);
+    }
+}
+
+/* Get general register name.  */
+static const char *
+get_gr_name (int regno)
+{
+  return csky_get_general_reg_name (mach_flag & CSKY_ABI_MASK, regno, using_abi);
+}
+
+/* Get control register name.  */
+static const char *
+get_cr_name (unsigned int regno, int bank)
+{
+  return csky_get_control_reg_name (mach_flag & CSKY_ABI_MASK, bank, regno, using_abi);
+}
+
 static int
 csky_output_operand (char *str, struct operand const *oprnd,
 		     CSKY_INST_TYPE inst, int reloc ATTRIBUTE_UNUSED)
@@ -287,30 +322,10 @@ csky_output_operand (char *str, struct operand const *oprnd,
   switch (oprnd->type)
     {
     case OPRND_TYPE_CTRLREG:
-      if (IS_CSKY_V1 (mach_flag))
-	{
-	  /* In V1 only cr0-cr12 have alias names.  */
-	  if (value <= 12)
-	    strcat (str, csky_ctrl_regs[value].name);
-	  /* Others using crn(n > 12).  */
-	  else if (value <= 30)
-	    {
-	      sprintf (buf, "cr%d", (int)value);
-	      strcat (str, buf);
-	    }
-	  else
-	    return -1;
-	}
-      else
-	{
-	  int sel;
-	  int crx;
-	  sel = value >> 5;
-	  crx = value & 0x1f;
-	  sprintf (buf, "cr<%d, %d>", crx, sel);
-	  strcat (str, buf);
-	}
-      break;
+	if (IS_CSKY_V1(mach_flag) && ((value & 0x1f) == 0x1f))
+	  return -1;
+	strcat (str, get_cr_name((value & 0x1f), (value >> 5)));
+	break;
     case OPRND_TYPE_DUMMY_REG:
       mask = dis_info.opinfo->oprnd.oprnds[0].mask;
       value = inst & mask;
@@ -321,21 +336,18 @@ csky_output_operand (char *str, struct operand const *oprnd,
 	    bit++;
 	  }
       value = result;
-      strcat (str, csky_general_reg[value]);
+      strcat (str, get_gr_name (value));
       break;
     case OPRND_TYPE_GREG0_7:
     case OPRND_TYPE_GREG0_15:
     case OPRND_TYPE_GREG16_31:
     case OPRND_TYPE_REGnsplr:
     case OPRND_TYPE_AREG:
-      if (IS_CSKY_V2 (mach_flag) && value == 14)
-	strcat (str, "sp");
-      else
-	strcat (str, csky_general_reg[value]);
-      dis_info.value = value;
+      strcat (str, get_gr_name (value));
       break;
     case OPRND_TYPE_CPREG:
-      strcat (str, csky_cp_reg[value]);
+      sprintf (buf, "cpr%d", (int)value);
+      strcat (str, buf);
       break;
     case OPRND_TYPE_FREG:
       sprintf (buf, "fr%d", (int)value);
@@ -347,10 +359,12 @@ csky_output_operand (char *str, struct operand const *oprnd,
       strcat (str, buf);
       break;
     case OPRND_TYPE_CPCREG:
-      strcat (str, csky_cp_creg[value]);
+      sprintf (buf, "cpcr%d", (int)value);
+      strcat (str, buf);
       break;
     case OPRND_TYPE_CPIDX:
-      strcat (str, csky_cp_idx[value]);
+      sprintf (buf, "cp%d", (int)value);
+      strcat (str, buf);
       break;
     case OPRND_TYPE_IMM2b_JMPIX:
       value = (value + 2) << 3;
@@ -417,6 +431,7 @@ csky_output_operand (char *str, struct operand const *oprnd,
     case OPRND_TYPE_IMM2b:
     case OPRND_TYPE_IMM4b:
     case OPRND_TYPE_IMM5b:
+    case OPRND_TYPE_IMM5b_LS:
     case OPRND_TYPE_IMM7b:
     case OPRND_TYPE_IMM8b:
     case OPRND_TYPE_IMM12b:
@@ -732,14 +747,19 @@ csky_output_operand (char *str, struct operand const *oprnd,
     case OPRND_TYPE_REGLIST_DASH:
       if (IS_CSKY_V1 (mach_flag))
 	{
-	  strcat (str, csky_general_reg[value]);
-	  strcat (str, "-r15");
+	  sprintf (buf, "%s-r15", get_gr_name (value));
+	  strcat (str, buf);
 	}
       else
 	{
-	  strcat (str, csky_general_reg[value >> 5]);
+	  if ((value & 0x1f) + (value >> 5) > 31)
+	    {
+	      ret = -1;
+	      break;
+	    }
+	  strcat (str, get_gr_name ((value >> 5)));
 	  strcat (str, "-");
-	  strcat (str, csky_general_reg[(value & 0x1f) + (value >> 5)]);
+	  strcat (str, get_gr_name ((value & 0x1f) + (value >> 5)));
 	}
       break;
     case OPRND_TYPE_PSR_BITS_LIST:
@@ -774,33 +794,25 @@ csky_output_operand (char *str, struct operand const *oprnd,
       }
     case OPRND_TYPE_REGbsp:
       if (IS_CSKY_V1 (mach_flag))
-	strcat (str, "(sp)");
+	sprintf(buf, "(%s)", get_gr_name (0));
       else
-	strcat (str, "(sp)");
+	sprintf(buf, "(%s)", get_gr_name (14));
+      strcat (str, buf);
       break;
     case OPRND_TYPE_REGsp:
       if (IS_CSKY_V1 (mach_flag))
-	strcat (str, "sp");
+	strcat (str, get_gr_name (0));
       else
-	strcat (str, "sp");
+	strcat (str, get_gr_name (14));
       break;
     case OPRND_TYPE_REGnr4_r7:
     case OPRND_TYPE_AREG_WITH_BRACKET:
-      if (IS_CSKY_V1 (mach_flag) && (value < 4 || value > 7))
-	{
-	  strcat (str, "(");
-	  strcat (str, csky_general_reg[value]);
-	  strcat (str, ")");
-	}
-      else
-	{
-	  strcat (str, "(");
-	  strcat (str, csky_general_reg[value]);
-	  strcat (str, ")");
-	}
+      strcat (str, "(");
+      strcat (str, get_gr_name (value));
+      strcat (str, ")");
       break;
     case OPRND_TYPE_AREG_WITH_LSHIFT:
-      strcat (str, csky_general_reg[value >> 5]);
+      strcat (str, get_gr_name (value >> 5));
       strcat (str, " << ");
       if ((value & 0x1f) == 0x1)
 	strcat (str, "0");
@@ -812,7 +824,7 @@ csky_output_operand (char *str, struct operand const *oprnd,
 	strcat (str, "3");
       break;
     case OPRND_TYPE_AREG_WITH_LSHIFT_FPU:
-      strcat (str, csky_general_reg[value >> 2]);
+      strcat (str, get_gr_name (value >> 2));
       strcat (str, " << ");
       if ((value & 0x3) == 0x0)
 	strcat (str, "0");
@@ -833,27 +845,28 @@ csky_output_operand (char *str, struct operand const *oprnd,
       }
     case OPRND_TYPE_REGr4_r7:
       if (IS_CSKY_V1 (mach_flag))
-	strcat (str, "r4-r7");
+	sprintf (buf, "%s-%s", get_gr_name (4), get_gr_name (7));
+	strcat (str, buf);
       break;
     case OPRND_TYPE_CONST1:
       strcat (str, "1");
       break;
     case OPRND_TYPE_REG_r1a:
     case OPRND_TYPE_REG_r1b:
-      strcat (str, "r1");
+      strcat (str, get_gr_name (1));
       break;
     case OPRND_TYPE_REG_r28:
-      strcat (str, "r28");
+      strcat (str, get_gr_name (28));
       break;
     case OPRND_TYPE_REGLIST_DASH_COMMA:
       /* 16-bit reglist.  */
       if (value & 0xf)
 	{
-	  strcat (str, "r4");
+	  strcat (str, get_gr_name (4));
 	  if ((value & 0xf) > 1)
 	    {
 	      strcat (str, "-");
-	      strcat (str, csky_general_reg[(value & 0xf) + 3]);
+	      strcat (str, get_gr_name ((value & 0xf) + 3));
 	    }
 	  if (value & ~0xf)
 	    strcat (str, ", ");
@@ -861,7 +874,7 @@ csky_output_operand (char *str, struct operand const *oprnd,
       if (value & 0x10)
 	{
 	  /* r15.  */
-	  strcat (str, "r15");
+	  strcat (str, get_gr_name (15));
 	  if (value & ~0x1f)
 	    strcat (str, ", ");
 	}
@@ -871,18 +884,18 @@ csky_output_operand (char *str, struct operand const *oprnd,
 	  value >>= 5;
 	  if (value & 0x3)
 	    {
-	      strcat (str, "r16");
+	      strcat (str, get_gr_name (16));
 	      if ((value & 0x7) > 1)
 		{
 		  strcat (str, "-");
-		  strcat (str, csky_general_reg[(value & 0xf) + 15]);
+		  strcat (str, get_gr_name ((value & 0x7) + 15));
 		}
 	      if (value & ~0x7)
 		strcat (str, ", ");
 	      }
 	  if (value & 0x8)
 	    /* r15.  */
-	    strcat (str, "r28");
+	    strcat (str, get_gr_name (28));
 	}
       break;
     case OPRND_TYPE_UNCOND10b:
@@ -1025,6 +1038,13 @@ print_insn_csky (bfd_vma memaddr, struct disassemble_info *info)
   dis_info.mem = memaddr;
   dis_info.info = info;
   dis_info.need_output_symbol = 0;
+
+  if (info->disassembler_options)
+    {
+      parse_csky_dis_options (info->disassembler_options);
+      info->disassembler_options = NULL;
+    }
+
   if (mach_flag != INIT_MACH_FLAG && mach_flag != BINARY_MACH_FLAG)
     info->mach = mach_flag;
   else if (mach_flag == INIT_MACH_FLAG)
diff --git a/opcodes/csky-opc.h b/opcodes/csky-opc.h
index a1c67e971b8..8cd0d1e2a2d 100644
--- a/opcodes/csky-opc.h
+++ b/opcodes/csky-opc.h
@@ -20,6 +20,7 @@
    02110-1301, USA.  */
 
 #include "opcode/csky.h"
+#include "safe-ctype.h"
 
 #define OP_TABLE_NUM    2
 #define MAX_OPRND_NUM   5
@@ -128,6 +129,8 @@ enum operand_type
   /* OPRND_TYPE_IMM5b_a_b means: Immediate in (a, b).  */
   OPRND_TYPE_IMM5b_1_31,
   OPRND_TYPE_IMM5b_7_31,
+  /* OPRND_TYPE_IMM5b_LS means: Imm <= prev Imm.  */
+  OPRND_TYPE_IMM5b_LS,
   /* Operand type for rori and rotri.  */
   OPRND_TYPE_IMM5b_RORI,
   OPRND_TYPE_IMM5b_POWER,
@@ -624,128 +627,421 @@ struct csky_opcode
 #define V1_REG_SP              0
 #define V1_REG_LR             15
 
-struct csky_reg
+struct psrbit
 {
+  int value;
+  int isa;
   const char *name;
-  int  index;
-  int  flag;
 };
 
-const char *csky_general_reg[] =
+const struct psrbit cskyv1_psr_bits[] =
 {
-  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
-  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
-  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
-  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
-  NULL,
+  {1,    0, "ie"},
+  {2,    0, "fe"},
+  {4,    0, "ee"},
+  {8,    0, "af"},
+  {0, 0, NULL},
 };
 
-/* TODO: optimize.  */
-const char *cskyv2_general_alias_reg[] =
+const struct psrbit cskyv2_psr_bits[] =
 {
-  "a0", "a1", "a2", "a3", "l0", "l1", "l2", "l3",
-  "l4", "l5", "l6", "l7", "t0", "t1", "sp", "lr",
-  "l8", "l9", "t2", "t3", "t4", "t5", "t6", "t7",
-  "t8", "t9", "r26", "r27", "rdb", "gb", "r30", "r31",
-  NULL,
+  {8, 0, "ee"},
+  {4, 0, "ie"},
+  {2, 0, "fe"},
+  {1, 0, "af"},
+  {0x10, CSKY_ISA_TRUST, "sie"},
+  {0, 0, NULL},
 };
 
-/* TODO: optimize.  */
-const char *cskyv1_general_alias_reg[] =
+#define GENARAL_REG_BANK      0x80000000
+#define REG_SUPPORT_ALL 0xffffffff
+
+/* CSKY register description.  */
+struct csky_reg_def
 {
-  "sp", "r1", "a0", "a1", "a2", "a3", "a4", "a5",
-  "fp", "l0", "l1", "l2", "l3", "l4", "gb", "lr",
-  NULL,
+  /* The group number for control registers,
+     and set the bank of genaral registers to a special number.  */
+  int bank;
+  int regno;
+  /* The name displayed by serial number.  */
+  const char *name;
+  /* The name displayed by ABI infomation,
+     used when objdump add option -Mabi-names.  */
+  const char *abi_name;
+  /* The flags indicate which arches support the register.  */
+  int arch_flag;
+  /* Some registers depend on special features.  */
+  char *features;
 };
 
-/* TODO: optimize.  */
-const char *csky_fpu_reg[] =
+/* Arch flag.  */
+#define ASH(a) (1 << CSKY_ARCH_##a)
+
+/* All arches exclued 801.  */
+#define REG_SUPPORT_A   (REG_SUPPORT_ALL & ~ASH(801))
+
+/* All arches exclued 801 and 802.  */
+#define REG_SUPPORT_B   (REG_SUPPORT_ALL & ~(ASH(801) | ASH(802)))
+
+/* All arches exclued 801, 802, 803, 805.*/
+#define REG_SUPPORT_C   (REG_SUPPORT_ALL & ~(ASH(801)			\
+		       	| ASH(802) | ASH(803) | ASH(805)))
+
+/* All arches exclued 801, 802, 803, 805, 807, 810.  */
+#define REG_SUPPORT_D   (REG_SUPPORT_C & ~(ASH(807) | ASH(810)))
+
+/* All arches exclued 807, 810, 860.  */
+#define REG_SUPPORT_E   (REG_SUPPORT_ALL & ~(ASH(807) | ASH(810) |	\
+		       	ASH(860)))
+
+/* C-SKY V1 general registers table.  */
+static struct csky_reg_def csky_abiv1_general_regs[] = 
 {
-  "fr0",  "fr1",  "fr2",  "fr3",  "fr4",  "fr5",  "fr6",  "fr7",
-  "fr8",  "fr9",  "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
-  "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
-  "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",
-  NULL,
+#define DECLARE_REG(regno, abi_name, support)		\
+  {GENARAL_REG_BANK, regno, "r"#regno, abi_name, support, NULL}
+
+  DECLARE_REG (0, "sp", REG_SUPPORT_ALL),
+  DECLARE_REG (1, NULL, REG_SUPPORT_ALL),
+  DECLARE_REG (2, "a0", REG_SUPPORT_ALL),
+  DECLARE_REG (3, "a1", REG_SUPPORT_ALL),
+  DECLARE_REG (4, "a2", REG_SUPPORT_ALL),
+  DECLARE_REG (5, "a3", REG_SUPPORT_ALL),
+  DECLARE_REG (6, "a4", REG_SUPPORT_ALL),
+  DECLARE_REG (7, "a5", REG_SUPPORT_ALL),
+  DECLARE_REG (8, "fp", REG_SUPPORT_ALL),
+  DECLARE_REG (8, "l0", REG_SUPPORT_ALL),
+  DECLARE_REG (9, "l1", REG_SUPPORT_ALL),
+  DECLARE_REG (10, "l2", REG_SUPPORT_ALL),
+  DECLARE_REG (11, "l3", REG_SUPPORT_ALL),
+  DECLARE_REG (12, "l4", REG_SUPPORT_ALL),
+  DECLARE_REG (13, "l5", REG_SUPPORT_ALL),
+  DECLARE_REG (14, "gb", REG_SUPPORT_ALL),
+  DECLARE_REG (15, "lr", REG_SUPPORT_ALL),
+#undef DECLARE_REG
+  {-1, -1, NULL, NULL, 0, NULL},
 };
 
-/* Control Registers.  */
-struct csky_reg csky_ctrl_regs[] =
+/* C-SKY V1 control registers table.  */
+static struct csky_reg_def csky_abiv1_control_regs[] = 
 {
-  {"psr", 0, 0},  {"vbr", 1, 0},    {"epsr", 2, 0},  {"fpsr", 3, 0},
-  {"epc", 4, 0},  {"fpc", 5, 0},    {"ss0", 6, 0},   {"ss1", 7, 0},
-  {"ss2", 8, 0},  {"ss3", 9, 0},    {"ss4", 10, 0},  {"gcr", 11, 0},
-  {"gsr", 12, 0}, {"cpuidr", 13, 0}, {"dcsr", 14, 0}, {"cwr", 15, 0},
-  {"cfr", 16, 0}, {"ccr", 17, 0},   {"capr", 19, 0}, {"pacr", 20, 0},
-  {"rid", 21, 0}, {"sedcr", 8, CSKY_ISA_TRUST}, {"sepcr", 9, CSKY_ISA_TRUST},
-  {NULL, 0, 0}
+#define DECLARE_REG(regno, abi_name, support)		\
+  {0, regno, "cr"#regno, abi_name, support, NULL}
+
+  DECLARE_REG (0, "psr", REG_SUPPORT_ALL),
+  DECLARE_REG (1, "vbr", REG_SUPPORT_ALL),
+  DECLARE_REG (2, "epsr", REG_SUPPORT_ALL),
+  DECLARE_REG (3, "fpsr", REG_SUPPORT_ALL),
+  DECLARE_REG (4, "epc", REG_SUPPORT_ALL),
+  DECLARE_REG (5, "fpc", REG_SUPPORT_ALL),
+  DECLARE_REG (6, "ss0", REG_SUPPORT_ALL),
+  DECLARE_REG (7, "ss1", REG_SUPPORT_ALL),
+  DECLARE_REG (8, "ss2", REG_SUPPORT_ALL),
+  DECLARE_REG (9, "ss3", REG_SUPPORT_ALL),
+  DECLARE_REG (10, "ss4", REG_SUPPORT_ALL),
+  DECLARE_REG (11, "gcr", REG_SUPPORT_ALL),
+  DECLARE_REG (12, "gsr", REG_SUPPORT_ALL),
+  DECLARE_REG (13, "cpid", REG_SUPPORT_ALL),
+  DECLARE_REG (14, "dcsr", REG_SUPPORT_ALL),
+  DECLARE_REG (15, "cwr", REG_SUPPORT_ALL),
+  DECLARE_REG (16, NULL, REG_SUPPORT_ALL),
+  DECLARE_REG (17, "cfr", REG_SUPPORT_ALL),
+  DECLARE_REG (18, "ccr", REG_SUPPORT_ALL),
+  DECLARE_REG (19, "capr", REG_SUPPORT_ALL),
+  DECLARE_REG (20, "pacr", REG_SUPPORT_ALL),
+  DECLARE_REG (21, "prsr", REG_SUPPORT_ALL),
+  DECLARE_REG (22, "mir", REG_SUPPORT_ALL),
+  DECLARE_REG (23, "mrr", REG_SUPPORT_ALL),
+  DECLARE_REG (24, "mel0", REG_SUPPORT_ALL),
+  DECLARE_REG (25, "mel1", REG_SUPPORT_ALL),
+  DECLARE_REG (26, "meh", REG_SUPPORT_ALL),
+  DECLARE_REG (27, "mcr", REG_SUPPORT_ALL),
+  DECLARE_REG (28, "mpr", REG_SUPPORT_ALL),
+  DECLARE_REG (29, "mwr", REG_SUPPORT_ALL),
+  DECLARE_REG (30, "mcir", REG_SUPPORT_ALL),
+#undef DECLARE_REG
+  {-1, -1, NULL, NULL, 0, NULL},
 };
 
-const char *csky_cp_idx[] =
+/* C-SKY V2 general registers table.  */
+static struct csky_reg_def csky_abiv2_general_regs[] = 
 {
-  "cp0", "cp1", "cp2", "cp3", "cp4", "cp5", "cp6", "cp7",
-  "cp8", "cp9", "cp10", "cp11", "cp12", "cp13", "cp14", "cp15",
-  "cp16", "cp17", "cp18", "cp19", "cp20",
-  NULL,
+#ifdef DECLARE_REG
+#undef DECLARE_REG
+#endif
+#define DECLARE_REG(regno, abi_name, support)		\
+  {GENARAL_REG_BANK, regno, "r"#regno, abi_name, support, NULL}
+
+  DECLARE_REG (0, "a0", REG_SUPPORT_ALL),
+  DECLARE_REG (1, "a1", REG_SUPPORT_ALL),
+  DECLARE_REG (2, "a2", REG_SUPPORT_ALL),
+  DECLARE_REG (3, "a3", REG_SUPPORT_ALL),
+  DECLARE_REG (4, "l0", REG_SUPPORT_ALL),
+  DECLARE_REG (5, "l1", REG_SUPPORT_ALL),
+  DECLARE_REG (6, "l2", REG_SUPPORT_ALL),
+  DECLARE_REG (7, "l3", REG_SUPPORT_ALL),
+  DECLARE_REG (8, "l4", REG_SUPPORT_ALL),
+  DECLARE_REG (9, "l5", REG_SUPPORT_A),
+  DECLARE_REG (10, "l6", REG_SUPPORT_A),
+  DECLARE_REG (11, "l7", REG_SUPPORT_A),
+  DECLARE_REG (12, "t0", REG_SUPPORT_A),
+  DECLARE_REG (13, "t1", REG_SUPPORT_ALL),
+  DECLARE_REG (14, "sp", REG_SUPPORT_ALL),
+  DECLARE_REG (15, "lr", REG_SUPPORT_ALL),
+  DECLARE_REG (16, "l8", REG_SUPPORT_B),
+  DECLARE_REG (17, "l9", REG_SUPPORT_B),
+  DECLARE_REG (18, "t2", REG_SUPPORT_B),
+  DECLARE_REG (19, "t3", REG_SUPPORT_B),
+  DECLARE_REG (20, "t4", REG_SUPPORT_B),
+  DECLARE_REG (21, "t5", REG_SUPPORT_B),
+  DECLARE_REG (22, "t6", REG_SUPPORT_B),
+  DECLARE_REG (23, "t7", REG_SUPPORT_B),
+  DECLARE_REG (24, "t8", REG_SUPPORT_B),
+  DECLARE_REG (25, "t9", REG_SUPPORT_B),
+  DECLARE_REG (26, NULL, REG_SUPPORT_B),
+  DECLARE_REG (27, NULL, REG_SUPPORT_B),
+  DECLARE_REG (28, "gb", REG_SUPPORT_B),
+  DECLARE_REG (28, "rgb", REG_SUPPORT_B),
+  DECLARE_REG (28, "rdb", REG_SUPPORT_B),
+  DECLARE_REG (29, "tb", REG_SUPPORT_B),
+  DECLARE_REG (29, "rtb", REG_SUPPORT_B),
+  DECLARE_REG (30, "svbr", REG_SUPPORT_A),
+  DECLARE_REG (31, "tls", REG_SUPPORT_B),
+
+  /* The followings JAVA/BCTM's features.  */
+  DECLARE_REG (23, "fp", REG_SUPPORT_ALL),
+  DECLARE_REG (24, "top", REG_SUPPORT_ALL),
+  DECLARE_REG (25, "bsp", REG_SUPPORT_ALL),
+
+  {-1, -1, NULL, NULL, 0, NULL},
 };
 
-const char *csky_cp_reg[] =
+/* C-SKY V2 control registers table.  */
+static struct csky_reg_def csky_abiv2_control_regs[] = 
 {
-  "cpr0",  "cpr1",  "cpr2",  "cpr3",  "cpr4",  "cpr5",  "cpr6",  "cpr7",
-  "cpr8",  "cpr9",  "cpr10", "cpr11", "cpr12", "cpr13", "cpr14", "cpr15",
-  "cpr16", "cpr17", "cpr18", "cpr19", "cpr20", "cpr21", "cpr22", "cpr23",
-  "cpr24", "cpr25", "cpr26", "cpr27", "cpr28", "cpr29", "cpr30", "cpr31",
-  "cpr32", "cpr33", "cpr34", "cpr35", "cpr36", "cpr37", "cpr38", "cpr39",
-  "cpr40", "cpr41", "cpr42", "cpr43", "cpr44", "cpr45", "cpr46", "cpr47",
-  "cpr48", "cpr49", "cpr50", "cpr51", "cpr52", "cpr53", "cpr54", "cpr55",
-  "cpr56", "cpr57", "cpr58", "cpr59", "cpr60", "cpr61", "cpr62", "cpr63",
-  NULL,
+
+#ifdef DECLARE_REG
+#undef DECLARE_REG
+#endif
+  /* Bank0.  */
+#define DECLARE_REG(regno, abi_name)		\
+  {0, regno, "cr<"#regno", 0>", abi_name, REG_SUPPORT_ALL, NULL}
+  DECLARE_REG (0, "psr"),
+  DECLARE_REG (1, "vbr"),
+  DECLARE_REG (2, "epsr"),
+  DECLARE_REG (3, "fpsr"),
+  DECLARE_REG (4, "epc"),
+  DECLARE_REG (5, "fpc"),
+  DECLARE_REG (6, "ss0"),
+  DECLARE_REG (7, "ss1"),
+  DECLARE_REG (8, "ss2"),
+  DECLARE_REG (9, "ss3"),
+  DECLARE_REG (10, "ss4"),
+  DECLARE_REG (11, "gcr"),
+  DECLARE_REG (12, "gsr"),
+  DECLARE_REG (13, "cpid"),
+  DECLARE_REG (14, "dcsr"),
+  DECLARE_REG (15, NULL),
+  DECLARE_REG (16, NULL),
+  DECLARE_REG (17, "cfr"),
+  DECLARE_REG (18, "ccr"),
+  DECLARE_REG (19, "capr"),
+  DECLARE_REG (20, "pacr"),
+  DECLARE_REG (21, "prsr"),
+  DECLARE_REG (22, "cir"),
+  DECLARE_REG (23, "ccr2"),
+  DECLARE_REG (24, NULL),
+  DECLARE_REG (25, "cer2"),
+  DECLARE_REG (26, NULL),
+  DECLARE_REG (27, NULL),
+  DECLARE_REG (28, "rvbr"),
+  DECLARE_REG (29, "rmr"),
+  DECLARE_REG (30, "mpid"),
+
+#undef DECLARE_REG
+#define DECLARE_REG(regno, abi_name, support)		\
+  {0, regno, "cr<"#regno", 0>", abi_name, support, NULL}
+  DECLARE_REG (31, "chr", REG_SUPPORT_E),
+  DECLARE_REG (31, "hint", REG_SUPPORT_C),
+
+  /* Bank1.  */
+#undef DECLARE_REG
+#define DECLARE_REG(regno, abi_name)		\
+  {1, regno, "cr<"#regno", 1>", abi_name, REG_SUPPORT_ALL, NULL}
+
+  DECLARE_REG (14, "usp"),
+  DECLARE_REG (26, "cindex"),
+  DECLARE_REG (27, "cdata0"),
+  DECLARE_REG (28, "cdata1"),
+  DECLARE_REG (29, "cdata2"),
+  DECLARE_REG (30, "cdata3"),
+  DECLARE_REG (31, "cins"),
+
+  /* Bank2.  */
+#undef DECLARE_REG
+#define DECLARE_REG(regno, abi_name)		\
+  {2, regno, "cr<"#regno", 2>", abi_name, REG_SUPPORT_ALL, NULL}
+
+  DECLARE_REG (0, "fid"),
+  DECLARE_REG (1, "fcr"),
+  DECLARE_REG (2, "fesr"),
+
+  /* Bank3.  */
+#undef DECLARE_REG
+#define DECLARE_REG(regno, abi_name)		\
+  {3, regno, "cr<"#regno", 3>", abi_name, REG_SUPPORT_ALL, NULL}
+  DECLARE_REG (8, "dcr"),
+  DECLARE_REG (8, "sedcr"),
+  DECLARE_REG (9, "pcr"),
+  DECLARE_REG (9, "sepcr"),
+
+  /* Bank15.  */
+#undef DECLARE_REG
+#define DECLARE_REG(regno, abi_name)		\
+  {15, regno, "cr<"#regno", 15>", abi_name, REG_SUPPORT_ALL, NULL}
+
+  DECLARE_REG (0, "mir"),
+  DECLARE_REG (2, "mel0"),
+  DECLARE_REG (3, "mel1"),
+  DECLARE_REG (4, "meh"),
+  DECLARE_REG (6, "mpr"),
+  DECLARE_REG (8, "mcir"),
+  DECLARE_REG (28, "mpgd0"),
+  DECLARE_REG (29, "mpgd"),
+  DECLARE_REG (29, "mpgd1"),
+  DECLARE_REG (30, "msa0"),
+  DECLARE_REG (31, "msa1"),
+#undef DECLARE_REG
+  {-1, -1, NULL, NULL, 0, NULL},
 };
 
-const char *csky_cp_creg[] =
+/* Get register name according to giving parameters,
+   IS_ABI controls whether is ABI name or not.  */
+static inline const char *
+get_register_name (struct csky_reg_def *reg_table,
+		   int arch, int bank, int regno, int is_abi)
 {
-  "cpcr0",  "cpcr1",  "cpcr2",  "cpcr3",
-  "cpcr4",  "cpcr5",  "cpcr6",  "cpcr7",
-  "cpcr8",  "cpcr9",  "cpcr10", "cpcr11",
-  "cpcr12", "cpcr13", "cpcr14", "cpcr15",
-  "cpcr16", "cpcr17", "cpcr18", "cpcr19",
-  "cpcr20", "cpcr21", "cpcr22", "cpcr23",
-  "cpcr24", "cpcr25", "cpcr26", "cpcr27",
-  "cpcr28", "cpcr29", "cpcr30", "cpcr31",
-  "cpcr32", "cpcr33", "cpcr34", "cpcr35",
-  "cpcr36", "cpcr37", "cpcr38", "cpcr39",
-  "cpcr40", "cpcr41", "cpcr42", "cpcr43",
-  "cpcr44", "cpcr45", "cpcr46", "cpcr47",
-  "cpcr48", "cpcr49", "cpcr50", "cpcr51",
-  "cpcr52", "cpcr53", "cpcr54", "cpcr55",
-  "cpcr56", "cpcr57", "cpcr58", "cpcr59",
-  "cpcr60", "cpcr61", "cpcr62", "cpcr63",
-  NULL,
-};
+  static char regname[64] = {0};
+  unsigned int i = 0;
+  while (reg_table[i].name != NULL)
+    {
+      if (reg_table[i].bank == bank
+	  && reg_table[i].regno == regno
+	  && (reg_table[i].arch_flag & (1 << arch)))
+	{
+	  if (is_abi && reg_table[i].abi_name)
+	    return reg_table[i].abi_name;
+	  else
+	    return reg_table[i].name;
+	}
+      i++;
+    }
 
-struct psrbit
+  if (bank & 0x80000000)
+    return "unkown register";
+
+  sprintf (regname, "cr<%d, %d>", regno, bank);
+
+  return regname;
+}
+
+/* Get register number according to giving parameters.
+   If not found, return -1.  */
+static inline int
+get_register_number (struct csky_reg_def *reg_table,
+		     int arch, char *s, char **end, int *bank)
 {
-  int value;
-  int isa;
-  const char *name;
-};
-const struct psrbit cskyv1_psr_bits[] =
+  unsigned int i = 0;
+  int len = 0;
+  while (reg_table[i].name != NULL)
+    {
+      len = strlen (reg_table[i].name);
+      if ((strncasecmp (reg_table[i].name, s, len) == 0)
+	  && !(ISDIGIT (s[len]))
+	  && (reg_table[i].arch_flag & (1 << arch)))
+	{
+	  *end = s + len;
+	  *bank = reg_table[i].bank;
+	  return reg_table[i].regno;
+	}
+
+      if (reg_table[i].abi_name == NULL)
+	{
+	  i++;
+	  continue;
+	}
+
+      len = strlen (reg_table[i].abi_name);
+      if ((strncasecmp (reg_table[i].abi_name, s, len) == 0)
+	  && !(ISALNUM (s[len]))
+	  && (reg_table[i].arch_flag & (1 << arch)))
+	{
+	  *end = s + len;
+	  *bank = reg_table[i].bank;
+	  return reg_table[i].regno;
+	}
+      i++;
+    }
+  return -1;
+}
+
+/* Return general register's name.  */
+static inline const char *
+csky_get_general_reg_name (int arch, int regno, int is_abi)
 {
-  {1,    0, "ie"},
-  {2,    0, "fe"},
-  {4,    0, "ee"},
-  {8,    0, "af"},
-  {0, 0, NULL},
-};
-const struct psrbit cskyv2_psr_bits[] =
+  struct csky_reg_def *reg_table;
+
+  if (IS_CSKY_ARCH_V1(arch))
+    reg_table = csky_abiv1_general_regs;
+  else
+    reg_table = csky_abiv2_general_regs;
+
+  return get_register_name (reg_table, arch,
+			    GENARAL_REG_BANK, regno, is_abi);
+}
+
+/* Return general register's number.  */
+static inline int
+csky_get_general_regno(int arch, char *s, char **end)
 {
-  {8, 0, "ee"},
-  {4, 0, "ie"},
-  {2, 0, "fe"},
-  {1, 0, "af"},
-  {0x10, CSKY_ISA_TRUST, "sie"},
-  {0, 0, NULL},
-};
+  struct csky_reg_def *reg_table;
+  int bank = 0;
 
+  if (IS_CSKY_ARCH_V1(arch))
+    reg_table = csky_abiv1_general_regs;
+  else
+    reg_table = csky_abiv2_general_regs;
+
+  return get_register_number (reg_table, arch, s, end, &bank);
+}
+
+/* Return control register's name.  */
+static inline const char *
+csky_get_control_reg_name (int arch, int bank, int regno, int is_abi)
+{
+  struct csky_reg_def *reg_table;
+
+  if (IS_CSKY_ARCH_V1(arch))
+    reg_table = csky_abiv1_control_regs;
+  else
+    reg_table = csky_abiv2_control_regs;
+
+  return get_register_name (reg_table, arch, bank,
+			    regno, is_abi);
+}
+
+/* Return control register's number.  */
+static inline int
+csky_get_control_regno(int arch, char *s, char **end, int *bank)
+{
+  struct csky_reg_def *reg_table;
+
+  if (IS_CSKY_ARCH_V1(arch))
+    reg_table = csky_abiv1_control_regs;
+  else
+    reg_table = csky_abiv2_control_regs;
+
+  return get_register_number (reg_table, arch, s, end, bank);
+}
 
 /* C-SKY V1 opcodes.  */
 const struct csky_opcode csky_v1_opcodes[] =
@@ -3620,12 +3916,12 @@ const struct csky_opcode csky_v2_opcodes[] =
 #undef _TRANSFER
 #define _TRANSFER   0
     DOP16_DOP32 ("bclri",
-		 OPCODE_INFO3 (0x3880,
+    		 OPCODE_INFO2 (0x3880,
 			       (8_10, GREG0_7, OPRND_SHIFT_0_BIT),
-			       (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT),
 			       (0_4, IMM5b, OPRND_SHIFT_0_BIT)),
-		 OPCODE_INFO2 (0x3880,
+		 OPCODE_INFO3 (0x3880,
 			       (8_10, GREG0_7, OPRND_SHIFT_0_BIT),
+			       (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT),
 			       (0_4, IMM5b, OPRND_SHIFT_0_BIT)),
 		 CSKYV2_ISA_E1,
 		 OPCODE_INFO3 (0xc4002820,
@@ -3637,12 +3933,12 @@ const struct csky_opcode csky_v2_opcodes[] =
 			       (21_25, IMM5b, OPRND_SHIFT_0_BIT)),
 		 CSKYV2_ISA_1E2),
     DOP16_DOP32 ("bseti",
-		 OPCODE_INFO3 (0x38a0,
+    		 OPCODE_INFO2 (0x38a0,
 			       (8_10, GREG0_7, OPRND_SHIFT_0_BIT),
-			       (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT),
 			       (0_4, IMM5b, OPRND_SHIFT_0_BIT)),
-		 OPCODE_INFO2 (0x38a0,
+		 OPCODE_INFO3 (0x38a0,
 			       (8_10, GREG0_7, OPRND_SHIFT_0_BIT),
+			       (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT),
 			       (0_4, IMM5b, OPRND_SHIFT_0_BIT)),
 		 CSKYV2_ISA_E1,
 		 OPCODE_INFO3 (0xc4002840,
@@ -3707,23 +4003,24 @@ const struct csky_opcode csky_v2_opcodes[] =
 			     (16_20, AREG, OPRND_SHIFT_0_BIT),
 			     (21_25, IMM5b, OPRND_SHIFT_0_BIT)),
 	       CSKYV2_ISA_1E2),
-    DOP16_DOP32 ("addc",
-		 OPCODE_INFO2 (0x6001,
-			       (6_9, GREG0_15, OPRND_SHIFT_0_BIT),
-			       (2_5, GREG0_15, OPRND_SHIFT_0_BIT)),
-		 OPCODE_INFO3 (0x6001,
-			       (6_9, GREG0_15, OPRND_SHIFT_0_BIT),
-			       (2_5, 2IN1_DUMMY, OPRND_SHIFT_0_BIT),
-			       (2_5, 2IN1_DUMMY, OPRND_SHIFT_0_BIT)),
-		 CSKYV2_ISA_E1,
-		 OPCODE_INFO3 (0xc4000040,
-			       (0_4, AREG, OPRND_SHIFT_0_BIT),
-			       (16_20, AREG, OPRND_SHIFT_0_BIT),
-			       (21_25, AREG, OPRND_SHIFT_0_BIT)),
-		 OPCODE_INFO2 (0xc4000040,
-			       (0_4or16_20, DUP_AREG, OPRND_SHIFT_0_BIT),
-			       (21_25, AREG, OPRND_SHIFT_0_BIT)),
-		 CSKYV2_ISA_1E2),
+    DOP16_DOP32_WITH_WORK ("addc",
+			   OPCODE_INFO2 (0x6001,
+					 (6_9, GREG0_15, OPRND_SHIFT_0_BIT),
+					 (2_5, GREG0_15, OPRND_SHIFT_0_BIT)),
+			   OPCODE_INFO3 (0x6001,
+					 (6_9, GREG0_15, OPRND_SHIFT_0_BIT),
+					 (2_5, GREG0_15, OPRND_SHIFT_0_BIT),
+					 (2_5, GREG0_15, OPRND_SHIFT_0_BIT)),
+			   CSKYV2_ISA_E1,
+			   OPCODE_INFO3 (0xc4000040,
+					 (0_4, AREG, OPRND_SHIFT_0_BIT),
+					 (16_20, AREG, OPRND_SHIFT_0_BIT),
+					 (21_25, AREG, OPRND_SHIFT_0_BIT)),
+			   OPCODE_INFO2 (0xc4000040,
+					 (0_4or16_20, AREG, OPRND_SHIFT_0_BIT),
+					 (21_25, AREG, OPRND_SHIFT_0_BIT)),
+			   CSKYV2_ISA_1E2,
+			   v2_work_addc),
     DOP16_DOP32 ("subc",
 		 OPCODE_INFO2 (0x6003,
 			       (6_9, GREG0_15, OPRND_SHIFT_0_BIT),
@@ -4015,14 +4312,14 @@ const struct csky_opcode csky_v2_opcodes[] =
 			(0_4, AREG, OPRND_SHIFT_0_BIT),
 			(16_20, AREG, OPRND_SHIFT_0_BIT),
 			(5_9, IMM5b, OPRND_SHIFT_0_BIT),
-			(21_25, IMM5b, OPRND_SHIFT_0_BIT)),
+			(21_25, IMM5b_LS, OPRND_SHIFT_0_BIT)),
 	  CSKYV2_ISA_2E3),
     OP32 ("sext",
 	  OPCODE_INFO4 (0xc4005800,
 			(0_4, AREG, OPRND_SHIFT_0_BIT),
 			(16_20, AREG, OPRND_SHIFT_0_BIT),
 			(5_9, IMM5b, OPRND_SHIFT_0_BIT),
-			(21_25, IMM5b, OPRND_SHIFT_0_BIT)),
+			(21_25, IMM5b_LS, OPRND_SHIFT_0_BIT)),
 	  CSKYV2_ISA_2E3),
 #undef _TRANSFER
 #define _TRANSFER   2
-- 
2.26.2


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] CSKY: Add objdump option -M abi-names.
  2020-09-17  6:30 [PATCH] CSKY: Add objdump option -M abi-names Cooper Qu
@ 2020-09-23 15:50 ` Lifang Xia
  2020-09-25 13:18   ` Alan Modra
  2020-09-24 14:14 ` [PUSHED] " Andrew Burgess
  1 sibling, 1 reply; 5+ messages in thread
From: Lifang Xia @ 2020-09-23 15:50 UTC (permalink / raw)
  To: Cooper Qu, binutils

Hi Cooper,

Merged.

Best Regards
Lifang Xia


On 2020/9/17 14:30, Cooper Qu wrote:
> Add option parser for disassembler, and refine the codes of
> parse register operand and disassemble register operand.
> While strengthen the operands legality check of some instructions.
>
> Co-Authored-By: Lifang Xia <lifang_xia@c-sky.com>
>
> gas/
> 	* config/tc-csky.c (parse_type_ctrlreg): Use function
> 	csky_get_control_regno to operand.
> 	(csky_get_reg_val): Likewise.
> 	(is_reg_sp_with_bracket): Use function csky_get_reg_val
> 	to parse operand.
> 	(is_reg_sp): Refine.
> 	(is_oimm_within_range): Fix, report error when operand
> 	is not constant.
> 	(parse_type_cpreg): Refine.
> 	(parse_type_cpcreg): Refine.
> 	(get_operand_value): Add handle of OPRND_TYPE_IMM5b_LS.
> 	(md_assemble): Fix no error reporting somtimes when
> 	operands number are not fit.
> 	(csky_addc64): Refine.
> 	(csky_subc64): Refine.
> 	(csky_or64): Refine.
> 	(v1_work_fpu_fo): Refine.
> 	(v1_work_fpu_read): Refine.
> 	(v1_work_fpu_writed): Refine.
> 	(v1_work_fpu_readd): Refine.
> 	(v2_work_addc): New function, strengthen the operands legality
> 	check of addc.
> 	* gas/testsuite/gas/csky/all.d : Use register number format when
> 	disassemble register name by default.
> 	* gas/testsuite/gas/csky/cskyv2_all.d : Likewise.
> 	* gas/testsuite/gas/csky/trust.d: Likewise.
> 	* gas/testsuite/gas/csky/cskyv2_ck860.d : Fix.
> 	* gas/testsuite/gas/csky/trust.s : Fix.
>
> opcodes/
> 	* csky-dis.c (using_abi): New.
> 	(parse_csky_dis_options): New function.
> 	(get_gr_name): New function.
> 	(get_cr_name): New function.
> 	(csky_output_operand): Use get_gr_name and get_cr_name to
> 	disassemble and add handle of OPRND_TYPE_IMM5b_LS.
> 	(print_insn_csky): Parse disassembler options.
> 	* opcodes/csky-opc.h (OPRND_TYPE_IMM5b_LS): New enum.
> 	(GENARAL_REG_BANK): Define.
> 	(REG_SUPPORT_ALL): Define.
> 	(REG_SUPPORT_ALL): New.
> 	(ASH): Define.
> 	(REG_SUPPORT_A): Define.
> 	(REG_SUPPORT_B): Define.
> 	(REG_SUPPORT_C): Define.
> 	(REG_SUPPORT_D): Define.
> 	(REG_SUPPORT_E): Define.
> 	(csky_abiv1_general_regs): New.
> 	(csky_abiv1_control_regs): New.
> 	(csky_abiv2_general_regs): New.
> 	(csky_abiv2_control_regs): New.
> 	(get_register_name): New function.
> 	(get_register_number): New function.
> 	(csky_get_general_reg_name): New function.
> 	(csky_get_general_regno): New function.
> 	(csky_get_control_reg_name): New function.
> 	(csky_get_control_regno): New function.
> 	(csky_v2_opcodes): Prefer two oprerans format for bclri and
> 	bseti, strengthen the operands legality check of addc, zext
> 	and sext.
>
> ---
>   gas/config/tc-csky.c                | 641 ++++++++++++----------------
>   gas/testsuite/gas/csky/all.d        |   2 +-
>   gas/testsuite/gas/csky/cskyv2_all.d |  36 +-
>   gas/testsuite/gas/csky/cskyv2_all.s |  24 +-
>   gas/testsuite/gas/csky/trust.d      |   9 +-
>   gas/testsuite/gas/csky/trust.s      |   1 -
>   opcodes/csky-dis.c                  | 148 ++++---
>   opcodes/csky-opc.h                  | 529 ++++++++++++++++++-----
>   8 files changed, 794 insertions(+), 596 deletions(-)
>
> diff --git a/gas/config/tc-csky.c b/gas/config/tc-csky.c
> index 808dca1e52c..60d5aa1f53b 100644
> --- a/gas/config/tc-csky.c
> +++ b/gas/config/tc-csky.c
> @@ -174,6 +174,7 @@ bfd_boolean float_work_fmovi (void);
>   bfd_boolean dsp_work_bloop (void);
>   bfd_boolean float_work_fpuv3_fmovi (void);
>   bfd_boolean float_work_fpuv3_fstore (void);
> +bfd_boolean v2_work_addc (void);
>   
>   /* csky-opc.h must be included after workers are declared.  */
>   #include "opcodes/csky-opc.h"
> @@ -2508,133 +2509,101 @@ static bfd_boolean
>   parse_type_ctrlreg (char** oper)
>   {
>     int i = -1;
> -  int len = 0;
> +  int group = 0;
> +  int crx;
> +  int sel;
> +  char *s = *oper;
> +  expressionS e;
>   
>     if (TOLOWER (*(*oper + 0)) == 'c'
>         && TOLOWER (*(*oper + 1)) == 'r'
>         && ISDIGIT (*(*oper + 2)))
>       {
>         /* The control registers are named crxx.  */
> -      i = *(*oper + 2) - 0x30;
> -      i = ISDIGIT (*(*oper + 3)) ? (*(*oper + 3) - 0x30) + 10 * i : i;
> -      len = ISDIGIT (*(*oper + 3)) ? 4 : 3;
> -      *oper += len;
> -    }
> -  else if (!(TOLOWER (*(*oper + 0)) == 'c'
> -	     && TOLOWER (*(*oper + 1)) == 'r'))
> -    {
> -      /* The control registers are aliased.  */
> -      struct csky_reg *reg = &csky_ctrl_regs[0];
> -      while (reg->name)
> -	{
> -	  if (memcmp (*oper, reg->name, strlen (reg->name)) == 0
> -	      && (!reg->flag || (isa_flag & reg->flag)))
> -	    {
> -	      i = reg->index;
> -	      len = strlen (reg->name);
> -	      *oper += len;
> -	      break;
> -	    }
> -	  reg++;
> +      s = *oper+2;
> +      s = parse_exp (s, &e);
> +      if (e.X_op == O_constant)
> +        {
> +	  i = e.X_add_number;
> +	  *oper = s;
>   	}
>       }
>   
>     if (IS_CSKY_V2 (mach_flag))
>       {
> -      char *s = *oper;
> -      int crx;
> -      int sel;
> +
> +      s = *oper;
>         if (i != -1)
>   	{
>   	  crx = i;
> -	  sel = 0;
> +	  sel = group;
>   	}
> -      else
> +      else if (TOLOWER (*(*oper + 0)) == 'c'
> +	       && TOLOWER (*(*oper + 1)) == 'r')
>   	{
> -	  if (s[0] == 'c' && s[1] == 'r')
> +	  s += 2;
> +	  if (*s != '<')
>   	    {
> -	      s += 2;
> -	      if (*s == '<')
> -		{
> -		  s++;
> -		  if (s[0] == '3' && s[1] >= '0' && s[1] <= '1')
> -		    {
> -		      crx = 30 + s[1] - '0';
> -		      s += 2;
> -		    }
> -		  else if (s[0] == '2' && s[1] >= '0' && s[1] <= '9')
> -		    {
> -		      crx = 20 + s[1] - '0';
> -		      s += 2;
> -		    }
> -		  else if (s[0] == '1' && s[1] >= '0' && s[1] <= '9')
> -		    {
> -		      crx = 10 + s[1] - '0';
> -		      s += 2;
> -		    }
> -		  else if (s[0] >= '0' && s[0] <= '9')
> -		    {
> -		      crx = s[0] - '0';
> -		      s += 1;
> -		    }
> -		  else
> -		    {
> -		      SET_ERROR_STRING (ERROR_REG_OVER_RANGE, "control");
> -		      return FALSE;
> -		    }
> -		  if (*s == ',')
> -		    s++;
> -		  else
> -		    {
> -		      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, NULL);
> -		      return FALSE;
> -		    }
> -		  char *pS = s;
> -		  while (*pS != '>' && !is_end_of_line[(unsigned char) *pS])
> -		    pS++;
> -		  if (*pS == '>')
> -		      *pS = '\0';
> -		  else
> -		    {
> -		      /* Error. Missing '>'.  */
> -		      SET_ERROR_STRING (ERROR_MISSING_RANGLE_BRACKETS, NULL);
> -		      return FALSE;
> -		    }
> -		  expressionS e;
> -		  s = parse_exp (s, &e);
> -		  if (e.X_op == O_constant
> -		      && e.X_add_number >= 0
> -		      && e.X_add_number <= 31)
> -		    {
> -		      *oper = s;
> -		      sel = e.X_add_number;
> -		    }
> -		  else
> -		    return FALSE;
> -		}
> -	      else
> -		{
> -		  /* Error. Missing '<'.  */
> -		  SET_ERROR_STRING (ERROR_MISSING_LANGLE_BRACKETS, NULL);
> -		  return FALSE;
> -		}
> +	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
> +	      return FALSE;
>   	    }
> -	  else
> +	  s++;
> +	  crx = strtol(s, &s, 10);
> +	  if (crx < 0 || crx > 31 || *s != ',')
> +	    {
> +	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
> +	      return FALSE;
> +	    }
> +	  s++;
> +	  sel = strtol(s, &s, 10);
> +	  if (sel < 0 || sel > 31 || *s != '>')
>   	    {
> -	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, NULL);
> +	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
> +	      return FALSE;
> +	    }
> +	  s++;
> +	}
> +      else
> +	{
> +	  crx = csky_get_control_regno (mach_flag & CSKY_ARCH_MASK,
> +			  s, &s, &sel);
> +	  if (crx < 0)
> +	    {
> +	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
>   	      return FALSE;
>   	    }
>   	}
>   	i = (sel << 5) | crx;
>       }
> +  else if (i == -1)
> +    {
> +      i = csky_get_control_regno (mach_flag & CSKY_ARCH_MASK,
> +				  s, &s, &sel);
> +      if (i < 0)
> +	{
> +	  SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
> +	  return FALSE;
> +	}
> +    }
> +  *oper = s;
>     csky_insn.val[csky_insn.idx++] = i;
>     return TRUE;
>   }
>   
> +static int
> +csky_get_reg_val (char *str, int *len)
> +{
> +  int regno = 0;
> +  char *s = str;
> +  regno = csky_get_general_regno (mach_flag & CSKY_ARCH_MASK, str, &s);
> +  *len = (s - str);
> +  return regno;
> +}
> +
>   static bfd_boolean
>   is_reg_sp_with_bracket (char **oper)
>   {
> -  const char **regs;
> +  int reg;
>     int sp_idx;
>     int len;
>   
> @@ -2646,40 +2615,30 @@ is_reg_sp_with_bracket (char **oper)
>     if (**oper != '(')
>         return FALSE;
>     *oper += 1;
> -  regs = csky_general_reg;
> -  len = strlen (regs[sp_idx]);
> -  if (memcmp (*oper, regs[sp_idx], len) == 0)
> +  reg = csky_get_reg_val (*oper, &len);
> +  *oper += len;
> +  if (reg == sp_idx)
>       {
> -      *oper += len;
>         if (**oper != ')')
> -	return FALSE;
> +        {
> +          SET_ERROR_STRING (ERROR_UNDEFINE,
> +			    "Operand format is error. '(sp)' expected");
> +          return FALSE;
> +        }
>         *oper += 1;
>         csky_insn.val[csky_insn.idx++] = sp_idx;
>         return TRUE;
>       }
> -  else
> -    {
> -      if (IS_CSKY_V1 (mach_flag))
> -	regs = cskyv1_general_alias_reg;
> -      else
> -	regs = cskyv2_general_alias_reg;
> -      len = strlen (regs[sp_idx]);
> -      if (memcmp (*oper, regs[sp_idx], len) == 0)
> -	{
> -	  *oper += len;
> -	  if (**oper != ')')
> -	    return FALSE;
> -	  *oper += 1;
> -	  return TRUE;
> -	}
> -    }
> +
> +  SET_ERROR_STRING (ERROR_UNDEFINE,
> +		    "Operand format is error. '(sp)' expected");
>     return FALSE;
>   }
>   
>   static bfd_boolean
>   is_reg_sp (char **oper)
>   {
> -  const char **regs;
> +  char sp_name[16];
>     int sp_idx;
>     int len;
>     if (IS_CSKY_V1 (mach_flag))
> @@ -2687,183 +2646,23 @@ is_reg_sp (char **oper)
>     else
>       sp_idx = 14;
>   
> -  regs = csky_general_reg;
> -  len = strlen (regs[sp_idx]);
> -  if (memcmp (*oper, regs[sp_idx], len) == 0)
> +  /* ABI names: "sp". */
> +  if (memcmp (*oper, "sp", 2) == 0)
>       {
> -      *oper += len;
> +      *oper += 2;
>         csky_insn.val[csky_insn.idx++] = sp_idx;
>         return TRUE;
>       }
> -  else
> -    {
> -      if (IS_CSKY_V1 (mach_flag))
> -	regs = cskyv1_general_alias_reg;
> -      else
> -	regs = cskyv2_general_alias_reg;
> -      len = strlen (regs[sp_idx]);
> -      if (memcmp (*oper, regs[sp_idx], len) == 0)
> -	{
> -	  *oper += len;
> -	  csky_insn.val[csky_insn.idx++] = sp_idx;
> -	  return TRUE;
> -	}
> -    }
> -  return FALSE;
> -}
> -
> -static int
> -csky_get_reg_val (char *str, int *len)
> -{
> -  long reg = 0;
> -  if (TOLOWER (str[0]) == 'r' && ISDIGIT (str[1]))
> -    {
> -      if (ISDIGIT (str[1]) && ISDIGIT (str[2]))
> -	{
> -	  reg = (str[1] - '0') * 10 + str[2] - '0';
> -	  *len = 3;
> -	}
> -      else if (ISDIGIT (str[1]))
> -	{
> -	  reg = str[1] - '0';
> -	  *len = 2;
> -	}
> -      else
> -	return -1;
> -    }
> -  else if (TOLOWER (str[0]) == 's' && TOLOWER (str[1]) == 'p'
> -	   && !ISDIGIT (str[2]))
> -    {
> -      /* sp.  */
> -      if (IS_CSKY_V1 (mach_flag))
> -	reg = 0;
> -      else
> -	reg = 14;
> -      *len = 2;
> -    }
> -  else if (TOLOWER (str[0]) == 'g' && TOLOWER (str[1]) == 'b'
> -	   && !ISDIGIT (str[2]))
> -    {
> -      /* gb.  */
> -      if (IS_CSKY_V1 (mach_flag))
> -	reg = 14;
> -      else
> -	reg = 28;
> -      *len = 2;
> -    }
> -  else if (TOLOWER (str[0]) == 'l' && TOLOWER (str[1]) == 'r'
> -	   && !ISDIGIT (str[2]))
> -    {
> -      /* lr.  */
> -      reg = 15;
> -      *len = 2;
> -    }
> -  else if (TOLOWER (str[0]) == 't' && TOLOWER (str[1]) == 'l'
> -	   && TOLOWER (str[2]) == 's' && !ISDIGIT (str[3]))
> -    {
> -      /* tls.  */
> -      if (IS_CSKY_V2 (mach_flag))
> -	reg = 31;
> -      else
> -	return -1;
> -      *len = 3;
> -    }
> -  else if (TOLOWER (str[0]) == 's' && TOLOWER (str[1]) == 'v'
> -	   && TOLOWER (str[2]) == 'b' && TOLOWER (str[3]) == 'r')
> -    {
> -      if (IS_CSKY_V2 (mach_flag))
> -	reg = 30;
> -      else
> -	return -1;
> -      *len = 4;
> -    }
> -  else if (TOLOWER (str[0]) == 'a')
> -    {
> -      if (ISDIGIT (str[1]) && !ISDIGIT (str[2]))
> -	{
> -	  if (IS_CSKY_V1 (mach_flag) && (str[1] - '0') <= 5)
> -	    /* a0 - a5.  */
> -	    reg = 2 + str[1] - '0';
> -	  else if (IS_CSKY_V2 (mach_flag) && (str[1] - '0') <= 3)
> -	    /* a0 - a3.  */
> -	    reg = str[1] - '0';
> -	  else
> -	    return -1;
> -	  *len = 2;
> -	}
> -    }
> -  else if (TOLOWER (str[0]) == 't')
> -    {
> -      if (IS_CSKY_V2 (mach_flag))
> -	{
> -	  reg = atoi (str + 1);
> -	  if (reg > 9)
> -	    return -1;
> -
> -	  if (reg > 1)
> -	    /* t2 - t9.  */
> -	    reg = reg + 16;
> -	  else
> -	    /* t0 - t1.  */
> -	    reg = reg + 12;
> -	  *len = 2;
> -	}
> -    }
> -  else if (TOLOWER (str[0]) == 'l')
> -    {
> -      if (str[1] < '0' || str[1] > '9')
> -	return -1;
> -      if (IS_CSKY_V2 (mach_flag))
> -	{
> -	  reg = atoi (str + 1);
> -	  if (reg > 9)
> -	    return -1;
> -	  if (reg > 7)
> -	    /* l8 - l9.  */
> -	    reg = reg + 8;
> -	  else
> -	    /* l0 - l7.  */
> -	    reg = reg + 4;
> -	}
> -      else
> -	{
> -	  reg = atoi (str + 1);
> -	  if (reg > 5)
> -	    return -1;
> -	  /* l0 - l6 -> r8 - r13.  */
> -	  reg = reg + 8;
> -	}
> -      *len = 2;
> -    }
> -  else
> -    return -1;
>   
> -  /* Is register available?  */
> -  if (IS_CSKY_ARCH_801 (mach_flag))
> -    {
> -      /* CK801 register range is r0-r8 & r13-r15.  */
> -      if ((reg > 8 && reg < 13) || reg > 15)
> -	{
> -	  SET_ERROR_STRING (ERROR_REG_OVER_RANGE, reg);
> -	  return -1;
> -	}
> -    }
> -  else if (IS_CSKY_ARCH_802 (mach_flag))
> -    {
> -      /* CK802 register range is r0-r15 & r23-r25 & r30.  */
> -      if ((reg > 15 && reg < 23) || (reg > 25 && reg != 30))
> -	{
> -	  SET_ERROR_STRING (ERROR_REG_OVER_RANGE, reg);
> -	  return -1;
> -	}
> -    }
> -  else if (reg > 31 || reg < 0)
> +  len = sprintf (sp_name, "r%d", sp_idx);
> +  if (memcmp (*oper, sp_name, len) == 0)
>       {
> -      SET_ERROR_STRING (ERROR_REG_OVER_RANGE, reg);
> -      return -1;
> +      *oper += len;
> +      csky_insn.val[csky_insn.idx++] = sp_idx;
> +      return TRUE;
>       }
>   
> -  return reg;
> +  return FALSE;
>   }
>   
>   static int
> @@ -3168,7 +2967,6 @@ is_imm_within_range (char **oper, int min, int max)
>   	e.X_add_number |= 0x80000000;
>         csky_insn.val[csky_insn.idx++] = e.X_add_number;
>       }
> -
>     else
>       SET_ERROR_STRING(ERROR_IMM_ILLEGAL, NULL);
>   
> @@ -3217,6 +3015,8 @@ is_oimm_within_range (char **oper, int min, int max)
>   	}
>         csky_insn.val[csky_insn.idx++] = e.X_add_number - 1;
>       }
> +  else
> +    SET_ERROR_STRING (ERROR_IMM_ILLEGAL, NULL);
>   
>     return ret;
>   }
> @@ -3291,43 +3091,51 @@ parse_type_cpidx (char** oper)
>   static bfd_boolean
>   parse_type_cpreg (char** oper)
>   {
> -  const char **regs = csky_cp_reg;
> -  int i;
> -  int len;
> +  expressionS e;
>   
> -  for (i = 0; i < (int)(sizeof (csky_cp_reg) / sizeof (char *)); i++)
> +  if (strncasecmp (*oper, "cpr", 3) != 0)
>       {
> -      len = strlen (regs[i]);
> -      if (memcmp (*oper, regs[i], len) == 0 && !ISDIGIT (*(*oper + len)))
> -	{
> -	  *oper += len;
> -	  csky_insn.val[csky_insn.idx++] = i;
> -	  return TRUE;
> -	}
> +      SET_ERROR_STRING(ERROR_CPREG_ILLEGAL, *oper);
> +      return FALSE;
>       }
> -  SET_ERROR_STRING (ERROR_CPREG_ILLEGAL, *oper);
> -  return FALSE;
> +
> +  *oper += 3;
> +
> +  *oper = parse_exp (*oper, &e);
> +  if (e.X_op != O_constant)
> +    {
> +      SET_ERROR_STRING(ERROR_CPREG_ILLEGAL, *oper);
> +      return FALSE;
> +    }
> +
> +  csky_insn.val[csky_insn.idx++] = e.X_add_number;
> +
> +  return TRUE;
>   }
>   
>   static bfd_boolean
>   parse_type_cpcreg (char** oper)
>   {
> -  const char **regs;
> -  int i;
> -  int len;
> -  regs = csky_cp_creg;
> -  for (i = 0; i < (int)(sizeof (csky_cp_creg) / sizeof (char *)); i++)
> +  expressionS e;
> +
> +  if (strncasecmp (*oper, "cpcr", 4) != 0)
>       {
> -      len = strlen (regs[i]);
> -      if (memcmp (*oper, regs[i], len) == 0 && !ISDIGIT (*(*oper + len)))
> -	{
> -	  *oper += len;
> -	  csky_insn.val[csky_insn.idx++] = i;
> -	  return TRUE;
> -	}
> +      SET_ERROR_STRING(ERROR_CPREG_ILLEGAL, *oper);
> +      return FALSE;
>       }
> -  SET_ERROR_STRING (ERROR_CPREG_ILLEGAL, *oper);
> -  return FALSE;
> +
> +  *oper += 4;
> +
> +  *oper = parse_exp (*oper, &e);
> +  if (e.X_op != O_constant)
> +    {
> +      SET_ERROR_STRING(ERROR_CPREG_ILLEGAL, *oper);
> +      return FALSE;
> +    }
> +
> +  csky_insn.val[csky_insn.idx++] = e.X_add_number;
> +
> +  return TRUE;
>   }
>   
>   static bfd_boolean
> @@ -3830,6 +3638,10 @@ get_operand_value (struct csky_opcode_info *op,
>   	else
>   	  return FALSE;
>   
> +    case OPRND_TYPE_IMM5b_LS:
> +      return is_imm_within_range (oper,
> +				  0,
> +				  csky_insn.val[csky_insn.idx - 1]);
>       case OPRND_TYPE_IMM5b_RORI:
>         {
>   	unsigned max_shift = IS_CSKY_V1 (mach_flag) ? 31 : 32;
> @@ -4769,6 +4581,7 @@ md_assemble (char *str)
>   		       (void *)error_state.arg1, (void *)error_state.arg1);
>         return;
>       }
> +  error_state.err_num = ERROR_NONE;
>   
>     /* if this insn has work in opcode table, then do it.  */
>     if (csky_insn.opcode->work != NULL)
> @@ -6195,21 +6008,26 @@ csky_addc64 (void)
>     int reg1;
>     int reg2;
>     int reg3;
> +  char reg1_name[16] = {0};
> +  char reg3_name[16] = {0};
>   
>     if (!get_macro_reg_vals (&reg1, &reg2, &reg3))
>       return;
> -  csky_macro_md_assemble ("cmplt",
> -			  csky_general_reg[reg1],
> -			  csky_general_reg[reg1],
> -			  NULL);
> -  csky_macro_md_assemble ("addc",
> -			  csky_general_reg[reg1 + (target_big_endian ? 1 : 0)],
> -			  csky_general_reg[reg3 + (target_big_endian ? 1 : 0)],
> -			  NULL);
> -  csky_macro_md_assemble ("addc",
> -			  csky_general_reg[reg1 + (target_big_endian ? 0 : 1)],
> -			  csky_general_reg[reg3 + (target_big_endian ? 0 : 1)],
> -			  NULL);
> +
> +  sprintf (reg1_name, "r%d", reg1);
> +  csky_macro_md_assemble ("cmplt", reg1_name, reg1_name, NULL);
> +  if (error_state.err_num != ERROR_NONE)
> +    return;
> +
> +  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 1 : 0));
> +  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 1 : 0));
> +  csky_macro_md_assemble ("addc", reg1_name, reg3_name, NULL);
> +  if (error_state.err_num != ERROR_NONE)
> +    return;
> +
> +  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 0 : 1));
> +  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 0 : 1));
> +  csky_macro_md_assemble ("addc", reg1_name, reg3_name, NULL);
>     return;
>   }
>   
> @@ -6221,21 +6039,26 @@ csky_subc64 (void)
>     int reg1;
>     int reg2;
>     int reg3;
> +  char reg1_name[16] = {0};
> +  char reg3_name[16] = {0};
>   
>     if (!get_macro_reg_vals (&reg1, &reg2, &reg3))
>       return;
> -  csky_macro_md_assemble ("cmphs",
> -			  csky_general_reg[reg1],
> -			  csky_general_reg[reg1],
> -			  NULL);
> -  csky_macro_md_assemble ("subc",
> -			  csky_general_reg[reg1 + (target_big_endian ? 1 : 0)],
> -			  csky_general_reg[reg3 + (target_big_endian ? 1 : 0)],
> -			  NULL);
> -  csky_macro_md_assemble ("subc",
> -			  csky_general_reg[reg1 + (target_big_endian ? 0 : 1)],
> -			  csky_general_reg[reg3 + (target_big_endian ? 0 : 1)],
> -			  NULL);
> +
> +  sprintf (reg1_name, "r%d", reg1);
> +  csky_macro_md_assemble ("cmphs", reg1_name, reg1_name, NULL);
> +  if (error_state.err_num != ERROR_NONE)
> +    return;
> +
> +  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 1 : 0));
> +  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 1 : 0));
> +  csky_macro_md_assemble ("subc", reg1_name, reg3_name, NULL);
> +  if (error_state.err_num != ERROR_NONE)
> +    return;
> +
> +  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 0 : 1));
> +  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 0 : 1));
> +  csky_macro_md_assemble ("subc", reg1_name, reg3_name, NULL);
>     return;
>   }
>   
> @@ -6247,17 +6070,20 @@ csky_or64 (void)
>     int reg1;
>     int reg2;
>     int reg3;
> +  char reg1_name[16] = {0};
> +  char reg3_name[16] = {0};
>   
>     if (!get_macro_reg_vals (&reg1, &reg2, &reg3))
>       return;
> -  csky_macro_md_assemble ("or",
> -			  csky_general_reg[reg1 + (target_big_endian ? 1 : 0)],
> -			  csky_general_reg[reg3 + (target_big_endian ? 1 : 0)],
> -			  NULL);
> -  csky_macro_md_assemble ("or",
> -			  csky_general_reg[reg1 + (target_big_endian ? 0 : 1)],
> -			  csky_general_reg[reg3 + (target_big_endian ? 0 : 1)],
> -			  NULL);
> +  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 1 : 0));
> +  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 1 : 0));
> +  csky_macro_md_assemble ("or", reg1_name, reg3_name, NULL);
> +
> +  if (error_state.err_num != ERROR_NONE)
> +    return;
> +  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 0 : 1));
> +  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 0 : 1));
> +  csky_macro_md_assemble ("or", reg1_name, reg3_name, NULL);
>     return;
>   }
>   
> @@ -6269,17 +6095,21 @@ csky_xor64 (void)
>     int reg1;
>     int reg2;
>     int reg3;
> +  char reg1_name[16] = {0};
> +  char reg3_name[16] = {0};
>   
>     if (!get_macro_reg_vals (&reg1, &reg2, &reg3))
>       return;
> -  csky_macro_md_assemble ("xor",
> -			  csky_general_reg[reg1 + (target_big_endian ? 1 : 0)],
> -			  csky_general_reg[reg3 + (target_big_endian ? 1 : 0)],
> -			  NULL);
> -  csky_macro_md_assemble ("xor",
> -			  csky_general_reg[reg1 + (target_big_endian ? 0 : 1)],
> -			  csky_general_reg[reg3 + (target_big_endian ? 0 : 1)],
> -			  NULL);
> +
> +  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 1 : 0));
> +  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 1 : 0));
> +  csky_macro_md_assemble ("xor", reg1_name, reg3_name, NULL);
> +  if (error_state.err_num != ERROR_NONE)
> +    return;
> +
> +  sprintf (reg1_name, "r%d", reg1 + (target_big_endian ? 0 : 1));
> +  sprintf (reg3_name, "r%d", reg3 + (target_big_endian ? 0 : 1));
> +  csky_macro_md_assemble ("xor", reg1_name, reg3_name, NULL);
>     return;
>   }
>   
> @@ -6463,11 +6293,10 @@ v1_work_fpu_fo (void)
>     inst = csky_insn.inst;
>   
>     /* Now get greg and inst, we can write instruction to floating unit.  */
> -  sprintf (buff, "lrw %s,0x%x", csky_general_reg[greg], inst);
> +  sprintf (buff, "lrw r%d,0x%x", greg, inst);
>     md_assemble (buff);
> -  sprintf (buff, "cpwir %s", csky_general_reg[greg]);
> +  sprintf (buff, "cpwir r%d", greg);
>     md_assemble (buff);
> -
>     return FALSE;
>   }
>   
> @@ -6496,9 +6325,9 @@ v1_work_fpu_fo_fc (void)
>     inst = csky_insn.inst;
>   
>     /* Now get greg and inst, we can write instruction to floating unit.  */
> -  sprintf (buff, "lrw %s,0x%x", csky_general_reg[greg], inst);
> +  sprintf (buff, "lrw r%d,0x%x", greg, inst);
>     md_assemble (buff);
> -  sprintf (buff, "cpwir %s", csky_general_reg[greg]);
> +  sprintf (buff, "cpwir r%d", greg);
>     md_assemble (buff);
>     sprintf (buff, "cprc");
>     md_assemble (buff);
> @@ -6517,7 +6346,7 @@ v1_work_fpu_write (void)
>     freg = csky_insn.val[1];
>   
>     /* Now get greg and freg, we can write instruction to floating unit.  */
> -  sprintf (buff, "cpwgr %s,%s", csky_general_reg[greg], csky_cp_reg[freg]);
> +  sprintf (buff, "cpwgr r%d,cpr%d", greg, freg);
>     md_assemble (buff);
>   
>     return FALSE;
> @@ -6533,7 +6362,7 @@ v1_work_fpu_read (void)
>     greg = csky_insn.val[0];
>     freg = csky_insn.val[1];
>     /* Now get greg and freg, we can write instruction to floating unit.  */
> -  sprintf (buff, "cprgr %s,%s", csky_general_reg[greg], csky_cp_reg[freg]);
> +  sprintf (buff, "cprgr r%d,cpr%d", greg, freg);
>     md_assemble (buff);
>   
>     return FALSE;
> @@ -6556,20 +6385,15 @@ v1_work_fpu_writed (void)
>       }
>     /* Now get greg and freg, we can write instruction to floating unit.  */
>     if (target_big_endian)
> -    sprintf (buff, "cpwgr %s,%s",
> -	     csky_general_reg[greg + 1], csky_cp_reg[freg]);
> +    sprintf (buff, "cpwgr r%d,cpr%d", greg + 1, freg);
>     else
> -    sprintf (buff, "cpwgr %s,%s",
> -	     csky_general_reg[greg], csky_cp_reg[freg]);
> +    sprintf (buff, "cpwgr r%d,cpr%d", greg, freg);
>     md_assemble (buff);
>     if (target_big_endian)
> -    sprintf (buff, "cpwgr %s,%s",
> -	     csky_general_reg[greg], csky_cp_reg[freg + 1]);
> +    sprintf (buff, "cpwgr r%d,cpr%d", greg, freg + 1);
>     else
> -    sprintf (buff, "cpwgr %s,%s",
> -	     csky_general_reg[greg + 1], csky_cp_reg[freg + 1]);
> +    sprintf (buff, "cpwgr r%d,cpr%d", greg+1, freg + 1);
>     md_assemble (buff);
> -
>     return FALSE;
>   }
>   
> @@ -6590,18 +6414,14 @@ v1_work_fpu_readd (void)
>       }
>     /* Now get greg and freg, we can write instruction to floating unit.  */
>     if (target_big_endian)
> -    sprintf (buff, "cprgr %s,%s",
> -	     csky_general_reg[greg + 1], csky_cp_reg[freg]);
> +    sprintf (buff, "cprgr r%d,cpr%d", greg+1, freg);
>     else
> -    sprintf (buff, "cprgr %s,%s",
> -	     csky_general_reg[greg], csky_cp_reg[freg]);
> +    sprintf (buff, "cprgr r%d,cpr%d", greg, freg);
>     md_assemble (buff);
>     if (target_big_endian)
> -    sprintf (buff, "cprgr %s,%s",
> -	     csky_general_reg[greg], csky_cp_reg[freg + 1]);
> +    sprintf (buff, "cprgr r%d,cpr%d", greg, freg + 1);
>     else
> -    sprintf (buff, "cprgr %s,%s",
> -	     csky_general_reg[greg + 1], csky_cp_reg[freg + 1]);
> +    sprintf (buff, "cprgr r%d,cpr%d", greg+1, freg + 1);
>     md_assemble (buff);
>   
>     return FALSE;
> @@ -7677,6 +7497,69 @@ float_work_fpuv3_fstore(void)
>     return TRUE;
>   }
>   
> +bfd_boolean
> +v2_work_addc (void)
> +{
> +  int reg1;
> +  int reg2;
> +  int reg3 = 0;
> +  int is_16_bit = 0;
> +
> +  reg1 = csky_insn.val[0];
> +  reg2 = csky_insn.val[1];
> +  if (csky_insn.number == 2)
> +    {
> +      if (reg1 > 15 || reg2 > 15)
> +	{
> +	  is_16_bit = 0;
> +	  reg3 = reg1;
> +	}
> +      else
> +	is_16_bit = 1;
> +    }
> +  else
> +    {
> +      reg3 = csky_insn.val[2];
> +      if (reg1 > 15 || reg2 > 15 || reg3 > 15)
> +	is_16_bit = 0;
> +      else if (reg1 == reg2 || reg1 == reg3)
> +	{
> +	  is_16_bit = 1;
> +	  reg2 = (reg1 == reg2) ? reg3 : reg2;
> +	}
> +      else
> +	is_16_bit = 0;
> +    }
> +
> +  if (is_16_bit
> +      && csky_insn.flag_force != INSN_OPCODE32F)
> +    {
> +      csky_insn.isize = 2;
> +      csky_insn.inst = csky_insn.opcode->op16[0].opcode
> +	| (reg1 << 6) | (reg2 << 2);
> +    }
> +  else if (csky_insn.flag_force != INSN_OPCODE16F)
> +    {
> +      csky_insn.isize = 4;
> +      csky_insn.inst = csky_insn.opcode->op32[0].opcode
> +	| (reg1 << 0) | (reg2 << 16) | (reg3 << 21);
> +    }
> +  else
> +    {
> +      SET_ERROR_INTEGER (ERROR_REG_OVER_RANGE, reg1 > 15 ? reg1 : reg2);
> +      csky_show_error (ERROR_REG_OVER_RANGE, 0, 0, NULL);
> +    }
> +
> +  /* Generate relax or reloc if necessary.  */
> +  csky_generate_frags ();
> +  /* Write inst to frag.  */
> +  csky_write_insn (csky_insn.output,
> +		   csky_insn.inst,
> +		   csky_insn.isize);
> +
> +  return TRUE;
> +}
> +
>   /* The following are for assembler directive handling.  */
>   
>   /* Helper function to adjust constant pool counts when we emit a
> diff --git a/gas/testsuite/gas/csky/all.d b/gas/testsuite/gas/csky/all.d
> index 606bcc0d3c6..af9acb50da8 100644
> --- a/gas/testsuite/gas/csky/all.d
> +++ b/gas/testsuite/gas/csky/all.d
> @@ -20,7 +20,7 @@ Disassembly of section \.text:
>   \s*[0-9a-f]*:\s*0032\s*mvcv\s*r2
>   \s*[0-9a-f]*:\s*0042\s*ldq\s*r4-r7, \(r2\)
>   \s*[0-9a-f]*:\s*0052\s*stq\s*r4-r7, \(r2\)
> -\s*[0-9a-f]*:\s*0061\s*ldm\s*r1-r15, \(sp\)
> +\s*[0-9a-f]*:\s*0061\s*ldm\s*r1-r15, \(r0\)
>   \s*[0-9a-f]*:\s*0082\s*dect\s*r2, r2, 1
>   \s*[0-9a-f]*:\s*0092\s*decf\s*r2, r2, 1
>   \s*[0-9a-f]*:\s*00a2\s*inct\s*r2, r2, 1
> diff --git a/gas/testsuite/gas/csky/cskyv2_all.d b/gas/testsuite/gas/csky/cskyv2_all.d
> index bb688ec97d4..bb104a7bc09 100644
> --- a/gas/testsuite/gas/csky/cskyv2_all.d
> +++ b/gas/testsuite/gas/csky/cskyv2_all.d
> @@ -14,10 +14,10 @@ Disassembly of section \.text:
>   \s*[0-9a-f]*:\s*c6824848\s*lsri\s*r8,\s*r2,\s*20
>   \s*[0-9a-f]*:\s*5227\s*asri\s*r1,\s*r2,\s*7
>   \s*[0-9a-f]*:\s*6049\s*addc\s*r1,\s*r2
> -\s*[0-9a-f]*:\s*c4310051\s*addc\s*r17,\s*r17,\s*r1
> +\s*[0-9a-f]*:\s*c6210051\s*addc\s*r17,\s*r1,\s*r17
>   \s*[0-9a-f]*:\s*c4620041\s*addc\s*r1,\s*r2,\s*r3
>   \s*[0-9a-f]*:\s*6049\s*addc\s*r1,\s*r2
> -\s*[0-9a-f]*:\s*c6210041\s*addc\s*r1,\s*r1,\s*r17
> +\s*[0-9a-f]*:\s*c4310041\s*addc\s*r1,\s*r17,\s*r1
>   \s*[0-9a-f]*:\s*c7d20052\s*addc\s*r18,\s*r18,\s*r30
>   \s*[0-9a-f]*:\s*604b\s*subc\s*r1,\s*r2
>   \s*[0-9a-f]*:\s*c4310111\s*subc\s*r17,\s*r17,\s*r1
> @@ -67,23 +67,23 @@ Disassembly of section \.text:
>   \s*[0-9a-f]*:\s*c4419421\s*mulsw\s*r1,\s*r1,\s*r2
>   \s*[0-9a-f]*:\s*8344\s*ld.b\s*r2,\s*\(r3,\s*0x4\)
>   \s*[0-9a-f]*:\s*8b42\s*ld.h\s*r2,\s*\(r3,\s*0x4\)
> -\s*[0-9a-f]*:\s*9841\s*ld.w\s*r2,\s*\(sp,\s*0x4\)
> +\s*[0-9a-f]*:\s*9841\s*ld.w\s*r2,\s*\(r14,\s*0x4\)
>   \s*[0-9a-f]*:\s*a344\s*st.b\s*r2,\s*\(r3,\s*0x4\)
>   \s*[0-9a-f]*:\s*ab42\s*st.h\s*r2,\s*\(r3,\s*0x4\)
> -\s*[0-9a-f]*:\s*b841\s*st.w\s*r2,\s*\(sp,\s*0x4\)
> +\s*[0-9a-f]*:\s*b841\s*st.w\s*r2,\s*\(r14,\s*0x4\)
>   \s*[0-9a-f]*:\s*d9030004\s*ld.b\s*r8,\s*\(r3,\s*0x4\)
>   \s*[0-9a-f]*:\s*d8481002\s*ld.h\s*r2,\s*\(r8,\s*0x4\)
> -\s*[0-9a-f]*:\s*9841\s*ld.w\s*r2,\s*\(sp,\s*0x4\)
> +\s*[0-9a-f]*:\s*9841\s*ld.w\s*r2,\s*\(r14,\s*0x4\)
>   \s*[0-9a-f]*:\s*dc480004\s*st.b\s*r2,\s*\(r8,\s*0x4\)
>   \s*[0-9a-f]*:\s*dc481002\s*st.h\s*r2,\s*\(r8,\s*0x4\)
> -\s*[0-9a-f]*:\s*dd0e2001\s*st.w\s*r8,\s*\(sp,\s*0x4\)
> +\s*[0-9a-f]*:\s*dd0e2001\s*st.w\s*r8,\s*\(r14,\s*0x4\)
>   \s*[0-9a-f]*:\s*d8434003\s*ld.bs\s*r2,\s*\(r3,\s*0x3\)
>   \s*[0-9a-f]*:\s*d8433001\s*ld.d\s*r2,\s*\(r3,\s*0x4\)
>   \s*[0-9a-f]*:\s*dc433001\s*st.d\s*r2,\s*\(r3,\s*0x4\)
>   \s*[0-9a-f]*:\s*dc437001\s*stex.w\s*r2,\s*\(r3,\s*0x4\)
>   \s*[0-9a-f]*:\s*d8437001\s*ldex.w\s*r2,\s*\(r3,\s*0x4\)
> -\s*[0-9a-f]*:\s*140c\s*addi\s*sp,\s*sp,\s*48
> -\s*[0-9a-f]*:\s*1b01\s*addi\s*r3,\s*sp,\s*4
> +\s*[0-9a-f]*:\s*140c\s*addi\s*r14,\s*r14,\s*48
> +\s*[0-9a-f]*:\s*1b01\s*addi\s*r3,\s*r14,\s*4
>   \s*[0-9a-f]*:\s*2113\s*addi\s*r1,\s*20
>   \s*[0-9a-f]*:\s*2113\s*addi\s*r1,\s*20
>   \s*[0-9a-f]*:\s*e6b50013\s*addi\s*r21,\s*r21,\s*20
> @@ -92,16 +92,16 @@ Disassembly of section \.text:
>   \s*[0-9a-f]*:\s*e5040000\s*addi\s*r8,\s*r4,\s*1
>   \s*[0-9a-f]*:\s*e4240008\s*addi\s*r1,\s*r4,\s*9
>   \s*[0-9a-f]*:\s*cc3c0008\s*addi\s*r1,\s*r28,\s*9
> -\s*[0-9a-f]*:\s*e46e0000\s*addi\s*r3,\s*sp,\s*1
> -\s*[0-9a-f]*:\s*e46e03ff\s*addi\s*r3,\s*sp,\s*1024
> -\s*[0-9a-f]*:\s*e5ce0032\s*addi\s*sp,\s*sp,\s*51
> -\s*[0-9a-f]*:\s*e5ce01ff\s*addi\s*sp,\s*sp,\s*512
> +\s*[0-9a-f]*:\s*e46e0000\s*addi\s*r3,\s*r14,\s*1
> +\s*[0-9a-f]*:\s*e46e03ff\s*addi\s*r3,\s*r14,\s*1024
> +\s*[0-9a-f]*:\s*e5ce0032\s*addi\s*r14,\s*r14,\s*51
> +\s*[0-9a-f]*:\s*e5ce01ff\s*addi\s*r14,\s*r14,\s*512
>   \s*[0-9a-f]*:\s*2113\s*addi\s*r1,\s*20
>   \s*[0-9a-f]*:\s*5c42\s*addi\s*r2,\s*r4,\s*1
>   \s*[0-9a-f]*:\s*e4440000\s*addi\s*r2,\s*r4,\s*1
> -\s*[0-9a-f]*:\s*e46e03ff\s*addi\s*r3,\s*sp,\s*1024
> -\s*[0-9a-f]*:\s*e5ce0032\s*addi\s*sp,\s*sp,\s*51
> -\s*[0-9a-f]*:\s*142c\s*subi\s*sp,\s*sp,\s*48
> +\s*[0-9a-f]*:\s*e46e03ff\s*addi\s*r3,\s*r14,\s*1024
> +\s*[0-9a-f]*:\s*e5ce0032\s*addi\s*r14,\s*r14,\s*51
> +\s*[0-9a-f]*:\s*142c\s*subi\s*r14,\s*r14,\s*48
>   \s*[0-9a-f]*:\s*2913\s*subi\s*r1,\s*20
>   \s*[0-9a-f]*:\s*2913\s*subi\s*r1,\s*20
>   \s*[0-9a-f]*:\s*e6b51013\s*subi\s*r21,\s*r21,\s*20
> @@ -110,12 +110,12 @@ Disassembly of section \.text:
>   \s*[0-9a-f]*:\s*e5041000\s*subi\s*r8,\s*r4,\s*1
>   \s*[0-9a-f]*:\s*e4241008\s*subi\s*r1,\s*r4,\s*9
>   \s*[0-9a-f]*:\s*e43c1008\s*subi\s*r1,\s*r28,\s*9
> -\s*[0-9a-f]*:\s*e5ce1032\s*subi\s*sp,\s*sp,\s*51
> -\s*[0-9a-f]*:\s*e5ce11ff\s*subi\s*sp,\s*sp,\s*512
> +\s*[0-9a-f]*:\s*e5ce1032\s*subi\s*r14,\s*r14,\s*51
> +\s*[0-9a-f]*:\s*e5ce11ff\s*subi\s*r14,\s*r14,\s*512
>   \s*[0-9a-f]*:\s*2913\s*subi\s*r1,\s*20
>   \s*[0-9a-f]*:\s*5c43\s*subi\s*r2,\s*r4,\s*1
>   \s*[0-9a-f]*:\s*e4441000\s*subi\s*r2,\s*r4,\s*1
> -\s*[0-9a-f]*:\s*e5ce1032\s*subi\s*sp,\s*sp,\s*51
> +\s*[0-9a-f]*:\s*e5ce1032\s*subi\s*r14,\s*r14,\s*51
>   \s*[0-9a-f]*:\s*60c2\s*subu\s*r3,\s*r0
>   \s*[0-9a-f]*:\s*6202\s*subu\s*r8,\s*r0
>   \s*[0-9a-f]*:\s*c4030089\s*subu\s*r9,\s*r3,\s*r0
> diff --git a/gas/testsuite/gas/csky/cskyv2_all.s b/gas/testsuite/gas/csky/cskyv2_all.s
> index 6e6902e077b..6db5b202bfb 100644
> --- a/gas/testsuite/gas/csky/cskyv2_all.s
> +++ b/gas/testsuite/gas/csky/cskyv2_all.s
> @@ -76,8 +76,8 @@ all:
>      st.d    r2, (r3, 4)
>      stex.w   r2, (r3, 4)
>      ldex.w   r2, (r3, 4)
> -   addi    sp,  sp, 0x30
> -   addi    r3,  sp, 0x4
> +   addi    r14,  r14, 0x30
> +   addi    r3,  r14, 0x4
>      addi    r1,  20
>      addi    r1,  r1, 20
>      addi    r21, 20
> @@ -86,16 +86,16 @@ all:
>      addi    r8,  r4, 1
>      addi    r1,  r4, 9
>      addi    r1,  r28, 9
> -   addi    r3,  sp, 0x1
> -   addi    r3,  sp, 0x400
> -   addi    sp,  sp, 0x33
> -   addi    sp,  sp, 0x200
> +   addi    r3,  r14, 0x1
> +   addi    r3,  r14, 0x400
> +   addi    r14,  r14, 0x33
> +   addi    r14,  r14, 0x200
>      addi16  r1,  20
>      addi16  r2,  r4, 1
>      addi32  r2,  r4, 1
> -   addi32  r3,  sp, 0x400
> -   addi32  sp,  sp, 0x33
> -   subi    sp,  sp, 0x30
> +   addi32  r3,  r14, 0x400
> +   addi32  r14,  r14, 0x33
> +   subi    r14,  r14, 0x30
>      subi    r1,  20
>      subi    r1,  r1, 20
>      subi    r21, 20
> @@ -104,12 +104,12 @@ all:
>      subi    r8,  r4, 1
>      subi    r1,  r4, 9
>      subi    r1,  r28, 9
> -   subi    sp,  sp, 0x33
> -   subi    sp,  sp, 0x200
> +   subi    r14,  r14, 0x33
> +   subi    r14,  r14, 0x200
>      subi16  r1,  20
>      subi16  r2,  r4, 1
>      subi32  r2,  r4, 1
> -   subi32  sp,  sp, 0x33
> +   subi32  r14,  r14, 0x33
>      sub     r3, r0
>      sub     r8, r0
>      sub     r9, r3, r0
> diff --git a/gas/testsuite/gas/csky/trust.d b/gas/testsuite/gas/csky/trust.d
> index 1a87b4d472b..adaa21cd77c 100644
> --- a/gas/testsuite/gas/csky/trust.d
> +++ b/gas/testsuite/gas/csky/trust.d
> @@ -7,11 +7,10 @@
>   Disassembly of section \.text:
>   #...
>   \s*[0-9a-f]*:\s*c0003c20\s*wsc
> -\s*[0-9a-f]*:\s*c0006024\s*mfcr\s*r4,\s*cr<0,\s*0>
> -\s*[0-9a-f]*:\s*c0156024\s*mfcr\s*r4,\s*cr<21,\s*0>
> -\s*[0-9a-f]*:\s*c004642b\s*mtcr\s*r4,\s*cr<11,\s*0>
> -\s*[0-9a-f]*:\s*c0046428\s*mtcr\s*r4,\s*cr<8,\s*0>
> -\s*[0-9a-f]*:\s*c0096024\s*mfcr\s*r4,\s*cr<9,\s*0>
> +\s*[0-9a-f]*:\s*c0006024\s*mfcr\s*r4,\s*cr<0,\s+0>
> +\s*[0-9a-f]*:\s*c004642b\s*mtcr\s*r4,\s*cr<11,\s+0>
> +\s*[0-9a-f]*:\s*c0646428\s*mtcr\s*r4,\s*cr<8,\s+3>
> +\s*[0-9a-f]*:\s*c0696024\s*mfcr\s*r4,\s*cr<9,\s+3>
>   \s*[0-9a-f]*:\s*c2007420\s*psrset\s*sie
>   \s*[0-9a-f]*:\s*c2007020\s*psrclr\s*sie
>   #...
> diff --git a/gas/testsuite/gas/csky/trust.s b/gas/testsuite/gas/csky/trust.s
> index 781dc8cbb84..862fa5bc94a 100644
> --- a/gas/testsuite/gas/csky/trust.s
> +++ b/gas/testsuite/gas/csky/trust.s
> @@ -1,7 +1,6 @@
>   TRUST:
>        wsc
>        mfcr r4, psr
> -     mfcr r4, rid
>        mtcr r4, gcr
>        mtcr r4, sedcr
>        mfcr r4, sepcr
> diff --git a/opcodes/csky-dis.c b/opcodes/csky-dis.c
> index ba0f4605f54..169368ac4be 100644
> --- a/opcodes/csky-dis.c
> +++ b/opcodes/csky-dis.c
> @@ -60,6 +60,7 @@ struct csky_dis_info
>   enum sym_type last_type;
>   int last_map_sym = 1;
>   bfd_vma last_map_addr = 0;
> +int using_abi = 0;
>   
>   /* Only for objdump tool.  */
>   #define INIT_MACH_FLAG  0xffffffff
> @@ -260,6 +261,40 @@ csky_get_disassembler (bfd *abfd)
>      return print_insn_csky;
>   }
>   
> +/* Parse the string of disassembler options.  */
> +static void
> +parse_csky_dis_options (const char *opts_in)
> +{
> +  char *opts = xstrdup (opts_in);
> +  char *opt = opts;
> +  char *opt_end = opts;
> +
> +  for (; opt_end != NULL; opt = opt_end + 1)
> +    {
> +      if ((opt_end = strchr (opt, ',')) != NULL)
> +	*opt_end = 0;
> +      if (strcmp (opt, "abi-names") == 0)
> +	using_abi = 1;
> +      else
> +	fprintf (stderr,
> +		 "unrecognized disassembler option: %s", opt);
> +    }
> +}
> +
> +/* Get general register name.  */
> +static const char *
> +get_gr_name (int regno)
> +{
> +  return csky_get_general_reg_name (mach_flag & CSKY_ABI_MASK, regno, using_abi);
> +}
> +
> +/* Get control register name.  */
> +static const char *
> +get_cr_name (unsigned int regno, int bank)
> +{
> +  return csky_get_control_reg_name (mach_flag & CSKY_ABI_MASK, bank, regno, using_abi);
> +}
> +
>   static int
>   csky_output_operand (char *str, struct operand const *oprnd,
>   		     CSKY_INST_TYPE inst, int reloc ATTRIBUTE_UNUSED)
> @@ -287,30 +322,10 @@ csky_output_operand (char *str, struct operand const *oprnd,
>     switch (oprnd->type)
>       {
>       case OPRND_TYPE_CTRLREG:
> -      if (IS_CSKY_V1 (mach_flag))
> -	{
> -	  /* In V1 only cr0-cr12 have alias names.  */
> -	  if (value <= 12)
> -	    strcat (str, csky_ctrl_regs[value].name);
> -	  /* Others using crn(n > 12).  */
> -	  else if (value <= 30)
> -	    {
> -	      sprintf (buf, "cr%d", (int)value);
> -	      strcat (str, buf);
> -	    }
> -	  else
> -	    return -1;
> -	}
> -      else
> -	{
> -	  int sel;
> -	  int crx;
> -	  sel = value >> 5;
> -	  crx = value & 0x1f;
> -	  sprintf (buf, "cr<%d, %d>", crx, sel);
> -	  strcat (str, buf);
> -	}
> -      break;
> +	if (IS_CSKY_V1(mach_flag) && ((value & 0x1f) == 0x1f))
> +	  return -1;
> +	strcat (str, get_cr_name((value & 0x1f), (value >> 5)));
> +	break;
>       case OPRND_TYPE_DUMMY_REG:
>         mask = dis_info.opinfo->oprnd.oprnds[0].mask;
>         value = inst & mask;
> @@ -321,21 +336,18 @@ csky_output_operand (char *str, struct operand const *oprnd,
>   	    bit++;
>   	  }
>         value = result;
> -      strcat (str, csky_general_reg[value]);
> +      strcat (str, get_gr_name (value));
>         break;
>       case OPRND_TYPE_GREG0_7:
>       case OPRND_TYPE_GREG0_15:
>       case OPRND_TYPE_GREG16_31:
>       case OPRND_TYPE_REGnsplr:
>       case OPRND_TYPE_AREG:
> -      if (IS_CSKY_V2 (mach_flag) && value == 14)
> -	strcat (str, "sp");
> -      else
> -	strcat (str, csky_general_reg[value]);
> -      dis_info.value = value;
> +      strcat (str, get_gr_name (value));
>         break;
>       case OPRND_TYPE_CPREG:
> -      strcat (str, csky_cp_reg[value]);
> +      sprintf (buf, "cpr%d", (int)value);
> +      strcat (str, buf);
>         break;
>       case OPRND_TYPE_FREG:
>         sprintf (buf, "fr%d", (int)value);
> @@ -347,10 +359,12 @@ csky_output_operand (char *str, struct operand const *oprnd,
>         strcat (str, buf);
>         break;
>       case OPRND_TYPE_CPCREG:
> -      strcat (str, csky_cp_creg[value]);
> +      sprintf (buf, "cpcr%d", (int)value);
> +      strcat (str, buf);
>         break;
>       case OPRND_TYPE_CPIDX:
> -      strcat (str, csky_cp_idx[value]);
> +      sprintf (buf, "cp%d", (int)value);
> +      strcat (str, buf);
>         break;
>       case OPRND_TYPE_IMM2b_JMPIX:
>         value = (value + 2) << 3;
> @@ -417,6 +431,7 @@ csky_output_operand (char *str, struct operand const *oprnd,
>       case OPRND_TYPE_IMM2b:
>       case OPRND_TYPE_IMM4b:
>       case OPRND_TYPE_IMM5b:
> +    case OPRND_TYPE_IMM5b_LS:
>       case OPRND_TYPE_IMM7b:
>       case OPRND_TYPE_IMM8b:
>       case OPRND_TYPE_IMM12b:
> @@ -732,14 +747,19 @@ csky_output_operand (char *str, struct operand const *oprnd,
>       case OPRND_TYPE_REGLIST_DASH:
>         if (IS_CSKY_V1 (mach_flag))
>   	{
> -	  strcat (str, csky_general_reg[value]);
> -	  strcat (str, "-r15");
> +	  sprintf (buf, "%s-r15", get_gr_name (value));
> +	  strcat (str, buf);
>   	}
>         else
>   	{
> -	  strcat (str, csky_general_reg[value >> 5]);
> +	  if ((value & 0x1f) + (value >> 5) > 31)
> +	    {
> +	      ret = -1;
> +	      break;
> +	    }
> +	  strcat (str, get_gr_name ((value >> 5)));
>   	  strcat (str, "-");
> -	  strcat (str, csky_general_reg[(value & 0x1f) + (value >> 5)]);
> +	  strcat (str, get_gr_name ((value & 0x1f) + (value >> 5)));
>   	}
>         break;
>       case OPRND_TYPE_PSR_BITS_LIST:
> @@ -774,33 +794,25 @@ csky_output_operand (char *str, struct operand const *oprnd,
>         }
>       case OPRND_TYPE_REGbsp:
>         if (IS_CSKY_V1 (mach_flag))
> -	strcat (str, "(sp)");
> +	sprintf(buf, "(%s)", get_gr_name (0));
>         else
> -	strcat (str, "(sp)");
> +	sprintf(buf, "(%s)", get_gr_name (14));
> +      strcat (str, buf);
>         break;
>       case OPRND_TYPE_REGsp:
>         if (IS_CSKY_V1 (mach_flag))
> -	strcat (str, "sp");
> +	strcat (str, get_gr_name (0));
>         else
> -	strcat (str, "sp");
> +	strcat (str, get_gr_name (14));
>         break;
>       case OPRND_TYPE_REGnr4_r7:
>       case OPRND_TYPE_AREG_WITH_BRACKET:
> -      if (IS_CSKY_V1 (mach_flag) && (value < 4 || value > 7))
> -	{
> -	  strcat (str, "(");
> -	  strcat (str, csky_general_reg[value]);
> -	  strcat (str, ")");
> -	}
> -      else
> -	{
> -	  strcat (str, "(");
> -	  strcat (str, csky_general_reg[value]);
> -	  strcat (str, ")");
> -	}
> +      strcat (str, "(");
> +      strcat (str, get_gr_name (value));
> +      strcat (str, ")");
>         break;
>       case OPRND_TYPE_AREG_WITH_LSHIFT:
> -      strcat (str, csky_general_reg[value >> 5]);
> +      strcat (str, get_gr_name (value >> 5));
>         strcat (str, " << ");
>         if ((value & 0x1f) == 0x1)
>   	strcat (str, "0");
> @@ -812,7 +824,7 @@ csky_output_operand (char *str, struct operand const *oprnd,
>   	strcat (str, "3");
>         break;
>       case OPRND_TYPE_AREG_WITH_LSHIFT_FPU:
> -      strcat (str, csky_general_reg[value >> 2]);
> +      strcat (str, get_gr_name (value >> 2));
>         strcat (str, " << ");
>         if ((value & 0x3) == 0x0)
>   	strcat (str, "0");
> @@ -833,27 +845,28 @@ csky_output_operand (char *str, struct operand const *oprnd,
>         }
>       case OPRND_TYPE_REGr4_r7:
>         if (IS_CSKY_V1 (mach_flag))
> -	strcat (str, "r4-r7");
> +	sprintf (buf, "%s-%s", get_gr_name (4), get_gr_name (7));
> +	strcat (str, buf);
>         break;
>       case OPRND_TYPE_CONST1:
>         strcat (str, "1");
>         break;
>       case OPRND_TYPE_REG_r1a:
>       case OPRND_TYPE_REG_r1b:
> -      strcat (str, "r1");
> +      strcat (str, get_gr_name (1));
>         break;
>       case OPRND_TYPE_REG_r28:
> -      strcat (str, "r28");
> +      strcat (str, get_gr_name (28));
>         break;
>       case OPRND_TYPE_REGLIST_DASH_COMMA:
>         /* 16-bit reglist.  */
>         if (value & 0xf)
>   	{
> -	  strcat (str, "r4");
> +	  strcat (str, get_gr_name (4));
>   	  if ((value & 0xf) > 1)
>   	    {
>   	      strcat (str, "-");
> -	      strcat (str, csky_general_reg[(value & 0xf) + 3]);
> +	      strcat (str, get_gr_name ((value & 0xf) + 3));
>   	    }
>   	  if (value & ~0xf)
>   	    strcat (str, ", ");
> @@ -861,7 +874,7 @@ csky_output_operand (char *str, struct operand const *oprnd,
>         if (value & 0x10)
>   	{
>   	  /* r15.  */
> -	  strcat (str, "r15");
> +	  strcat (str, get_gr_name (15));
>   	  if (value & ~0x1f)
>   	    strcat (str, ", ");
>   	}
> @@ -871,18 +884,18 @@ csky_output_operand (char *str, struct operand const *oprnd,
>   	  value >>= 5;
>   	  if (value & 0x3)
>   	    {
> -	      strcat (str, "r16");
> +	      strcat (str, get_gr_name (16));
>   	      if ((value & 0x7) > 1)
>   		{
>   		  strcat (str, "-");
> -		  strcat (str, csky_general_reg[(value & 0xf) + 15]);
> +		  strcat (str, get_gr_name ((value & 0x7) + 15));
>   		}
>   	      if (value & ~0x7)
>   		strcat (str, ", ");
>   	      }
>   	  if (value & 0x8)
>   	    /* r15.  */
> -	    strcat (str, "r28");
> +	    strcat (str, get_gr_name (28));
>   	}
>         break;
>       case OPRND_TYPE_UNCOND10b:
> @@ -1025,6 +1038,13 @@ print_insn_csky (bfd_vma memaddr, struct disassemble_info *info)
>     dis_info.mem = memaddr;
>     dis_info.info = info;
>     dis_info.need_output_symbol = 0;
> +
> +  if (info->disassembler_options)
> +    {
> +      parse_csky_dis_options (info->disassembler_options);
> +      info->disassembler_options = NULL;
> +    }
> +
>     if (mach_flag != INIT_MACH_FLAG && mach_flag != BINARY_MACH_FLAG)
>       info->mach = mach_flag;
>     else if (mach_flag == INIT_MACH_FLAG)
> diff --git a/opcodes/csky-opc.h b/opcodes/csky-opc.h
> index a1c67e971b8..8cd0d1e2a2d 100644
> --- a/opcodes/csky-opc.h
> +++ b/opcodes/csky-opc.h
> @@ -20,6 +20,7 @@
>      02110-1301, USA.  */
>   
>   #include "opcode/csky.h"
> +#include "safe-ctype.h"
>   
>   #define OP_TABLE_NUM    2
>   #define MAX_OPRND_NUM   5
> @@ -128,6 +129,8 @@ enum operand_type
>     /* OPRND_TYPE_IMM5b_a_b means: Immediate in (a, b).  */
>     OPRND_TYPE_IMM5b_1_31,
>     OPRND_TYPE_IMM5b_7_31,
> +  /* OPRND_TYPE_IMM5b_LS means: Imm <= prev Imm.  */
> +  OPRND_TYPE_IMM5b_LS,
>     /* Operand type for rori and rotri.  */
>     OPRND_TYPE_IMM5b_RORI,
>     OPRND_TYPE_IMM5b_POWER,
> @@ -624,128 +627,421 @@ struct csky_opcode
>   #define V1_REG_SP              0
>   #define V1_REG_LR             15
>   
> -struct csky_reg
> +struct psrbit
>   {
> +  int value;
> +  int isa;
>     const char *name;
> -  int  index;
> -  int  flag;
>   };
>   
> -const char *csky_general_reg[] =
> +const struct psrbit cskyv1_psr_bits[] =
>   {
> -  "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
> -  "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
> -  "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
> -  "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
> -  NULL,
> +  {1,    0, "ie"},
> +  {2,    0, "fe"},
> +  {4,    0, "ee"},
> +  {8,    0, "af"},
> +  {0, 0, NULL},
>   };
>   
> -/* TODO: optimize.  */
> -const char *cskyv2_general_alias_reg[] =
> +const struct psrbit cskyv2_psr_bits[] =
>   {
> -  "a0", "a1", "a2", "a3", "l0", "l1", "l2", "l3",
> -  "l4", "l5", "l6", "l7", "t0", "t1", "sp", "lr",
> -  "l8", "l9", "t2", "t3", "t4", "t5", "t6", "t7",
> -  "t8", "t9", "r26", "r27", "rdb", "gb", "r30", "r31",
> -  NULL,
> +  {8, 0, "ee"},
> +  {4, 0, "ie"},
> +  {2, 0, "fe"},
> +  {1, 0, "af"},
> +  {0x10, CSKY_ISA_TRUST, "sie"},
> +  {0, 0, NULL},
>   };
>   
> -/* TODO: optimize.  */
> -const char *cskyv1_general_alias_reg[] =
> +#define GENARAL_REG_BANK      0x80000000
> +#define REG_SUPPORT_ALL 0xffffffff
> +
> +/* CSKY register description.  */
> +struct csky_reg_def
>   {
> -  "sp", "r1", "a0", "a1", "a2", "a3", "a4", "a5",
> -  "fp", "l0", "l1", "l2", "l3", "l4", "gb", "lr",
> -  NULL,
> +  /* The group number for control registers,
> +     and set the bank of genaral registers to a special number.  */
> +  int bank;
> +  int regno;
> +  /* The name displayed by serial number.  */
> +  const char *name;
> +  /* The name displayed by ABI infomation,
> +     used when objdump add option -Mabi-names.  */
> +  const char *abi_name;
> +  /* The flags indicate which arches support the register.  */
> +  int arch_flag;
> +  /* Some registers depend on special features.  */
> +  char *features;
>   };
>   
> -/* TODO: optimize.  */
> -const char *csky_fpu_reg[] =
> +/* Arch flag.  */
> +#define ASH(a) (1 << CSKY_ARCH_##a)
> +
> +/* All arches exclued 801.  */
> +#define REG_SUPPORT_A   (REG_SUPPORT_ALL & ~ASH(801))
> +
> +/* All arches exclued 801 and 802.  */
> +#define REG_SUPPORT_B   (REG_SUPPORT_ALL & ~(ASH(801) | ASH(802)))
> +
> +/* All arches exclued 801, 802, 803, 805.*/
> +#define REG_SUPPORT_C   (REG_SUPPORT_ALL & ~(ASH(801)			\
> +		       	| ASH(802) | ASH(803) | ASH(805)))
> +
> +/* All arches exclued 801, 802, 803, 805, 807, 810.  */
> +#define REG_SUPPORT_D   (REG_SUPPORT_C & ~(ASH(807) | ASH(810)))
> +
> +/* All arches exclued 807, 810, 860.  */
> +#define REG_SUPPORT_E   (REG_SUPPORT_ALL & ~(ASH(807) | ASH(810) |	\
> +		       	ASH(860)))
> +
> +/* C-SKY V1 general registers table.  */
> +static struct csky_reg_def csky_abiv1_general_regs[] =
>   {
> -  "fr0",  "fr1",  "fr2",  "fr3",  "fr4",  "fr5",  "fr6",  "fr7",
> -  "fr8",  "fr9",  "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
> -  "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
> -  "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31",
> -  NULL,
> +#define DECLARE_REG(regno, abi_name, support)		\
> +  {GENARAL_REG_BANK, regno, "r"#regno, abi_name, support, NULL}
> +
> +  DECLARE_REG (0, "sp", REG_SUPPORT_ALL),
> +  DECLARE_REG (1, NULL, REG_SUPPORT_ALL),
> +  DECLARE_REG (2, "a0", REG_SUPPORT_ALL),
> +  DECLARE_REG (3, "a1", REG_SUPPORT_ALL),
> +  DECLARE_REG (4, "a2", REG_SUPPORT_ALL),
> +  DECLARE_REG (5, "a3", REG_SUPPORT_ALL),
> +  DECLARE_REG (6, "a4", REG_SUPPORT_ALL),
> +  DECLARE_REG (7, "a5", REG_SUPPORT_ALL),
> +  DECLARE_REG (8, "fp", REG_SUPPORT_ALL),
> +  DECLARE_REG (8, "l0", REG_SUPPORT_ALL),
> +  DECLARE_REG (9, "l1", REG_SUPPORT_ALL),
> +  DECLARE_REG (10, "l2", REG_SUPPORT_ALL),
> +  DECLARE_REG (11, "l3", REG_SUPPORT_ALL),
> +  DECLARE_REG (12, "l4", REG_SUPPORT_ALL),
> +  DECLARE_REG (13, "l5", REG_SUPPORT_ALL),
> +  DECLARE_REG (14, "gb", REG_SUPPORT_ALL),
> +  DECLARE_REG (15, "lr", REG_SUPPORT_ALL),
> +#undef DECLARE_REG
> +  {-1, -1, NULL, NULL, 0, NULL},
>   };
>   
> -/* Control Registers.  */
> -struct csky_reg csky_ctrl_regs[] =
> +/* C-SKY V1 control registers table.  */
> +static struct csky_reg_def csky_abiv1_control_regs[] =
>   {
> -  {"psr", 0, 0},  {"vbr", 1, 0},    {"epsr", 2, 0},  {"fpsr", 3, 0},
> -  {"epc", 4, 0},  {"fpc", 5, 0},    {"ss0", 6, 0},   {"ss1", 7, 0},
> -  {"ss2", 8, 0},  {"ss3", 9, 0},    {"ss4", 10, 0},  {"gcr", 11, 0},
> -  {"gsr", 12, 0}, {"cpuidr", 13, 0}, {"dcsr", 14, 0}, {"cwr", 15, 0},
> -  {"cfr", 16, 0}, {"ccr", 17, 0},   {"capr", 19, 0}, {"pacr", 20, 0},
> -  {"rid", 21, 0}, {"sedcr", 8, CSKY_ISA_TRUST}, {"sepcr", 9, CSKY_ISA_TRUST},
> -  {NULL, 0, 0}
> +#define DECLARE_REG(regno, abi_name, support)		\
> +  {0, regno, "cr"#regno, abi_name, support, NULL}
> +
> +  DECLARE_REG (0, "psr", REG_SUPPORT_ALL),
> +  DECLARE_REG (1, "vbr", REG_SUPPORT_ALL),
> +  DECLARE_REG (2, "epsr", REG_SUPPORT_ALL),
> +  DECLARE_REG (3, "fpsr", REG_SUPPORT_ALL),
> +  DECLARE_REG (4, "epc", REG_SUPPORT_ALL),
> +  DECLARE_REG (5, "fpc", REG_SUPPORT_ALL),
> +  DECLARE_REG (6, "ss0", REG_SUPPORT_ALL),
> +  DECLARE_REG (7, "ss1", REG_SUPPORT_ALL),
> +  DECLARE_REG (8, "ss2", REG_SUPPORT_ALL),
> +  DECLARE_REG (9, "ss3", REG_SUPPORT_ALL),
> +  DECLARE_REG (10, "ss4", REG_SUPPORT_ALL),
> +  DECLARE_REG (11, "gcr", REG_SUPPORT_ALL),
> +  DECLARE_REG (12, "gsr", REG_SUPPORT_ALL),
> +  DECLARE_REG (13, "cpid", REG_SUPPORT_ALL),
> +  DECLARE_REG (14, "dcsr", REG_SUPPORT_ALL),
> +  DECLARE_REG (15, "cwr", REG_SUPPORT_ALL),
> +  DECLARE_REG (16, NULL, REG_SUPPORT_ALL),
> +  DECLARE_REG (17, "cfr", REG_SUPPORT_ALL),
> +  DECLARE_REG (18, "ccr", REG_SUPPORT_ALL),
> +  DECLARE_REG (19, "capr", REG_SUPPORT_ALL),
> +  DECLARE_REG (20, "pacr", REG_SUPPORT_ALL),
> +  DECLARE_REG (21, "prsr", REG_SUPPORT_ALL),
> +  DECLARE_REG (22, "mir", REG_SUPPORT_ALL),
> +  DECLARE_REG (23, "mrr", REG_SUPPORT_ALL),
> +  DECLARE_REG (24, "mel0", REG_SUPPORT_ALL),
> +  DECLARE_REG (25, "mel1", REG_SUPPORT_ALL),
> +  DECLARE_REG (26, "meh", REG_SUPPORT_ALL),
> +  DECLARE_REG (27, "mcr", REG_SUPPORT_ALL),
> +  DECLARE_REG (28, "mpr", REG_SUPPORT_ALL),
> +  DECLARE_REG (29, "mwr", REG_SUPPORT_ALL),
> +  DECLARE_REG (30, "mcir", REG_SUPPORT_ALL),
> +#undef DECLARE_REG
> +  {-1, -1, NULL, NULL, 0, NULL},
>   };
>   
> -const char *csky_cp_idx[] =
> +/* C-SKY V2 general registers table.  */
> +static struct csky_reg_def csky_abiv2_general_regs[] =
>   {
> -  "cp0", "cp1", "cp2", "cp3", "cp4", "cp5", "cp6", "cp7",
> -  "cp8", "cp9", "cp10", "cp11", "cp12", "cp13", "cp14", "cp15",
> -  "cp16", "cp17", "cp18", "cp19", "cp20",
> -  NULL,
> +#ifdef DECLARE_REG
> +#undef DECLARE_REG
> +#endif
> +#define DECLARE_REG(regno, abi_name, support)		\
> +  {GENARAL_REG_BANK, regno, "r"#regno, abi_name, support, NULL}
> +
> +  DECLARE_REG (0, "a0", REG_SUPPORT_ALL),
> +  DECLARE_REG (1, "a1", REG_SUPPORT_ALL),
> +  DECLARE_REG (2, "a2", REG_SUPPORT_ALL),
> +  DECLARE_REG (3, "a3", REG_SUPPORT_ALL),
> +  DECLARE_REG (4, "l0", REG_SUPPORT_ALL),
> +  DECLARE_REG (5, "l1", REG_SUPPORT_ALL),
> +  DECLARE_REG (6, "l2", REG_SUPPORT_ALL),
> +  DECLARE_REG (7, "l3", REG_SUPPORT_ALL),
> +  DECLARE_REG (8, "l4", REG_SUPPORT_ALL),
> +  DECLARE_REG (9, "l5", REG_SUPPORT_A),
> +  DECLARE_REG (10, "l6", REG_SUPPORT_A),
> +  DECLARE_REG (11, "l7", REG_SUPPORT_A),
> +  DECLARE_REG (12, "t0", REG_SUPPORT_A),
> +  DECLARE_REG (13, "t1", REG_SUPPORT_ALL),
> +  DECLARE_REG (14, "sp", REG_SUPPORT_ALL),
> +  DECLARE_REG (15, "lr", REG_SUPPORT_ALL),
> +  DECLARE_REG (16, "l8", REG_SUPPORT_B),
> +  DECLARE_REG (17, "l9", REG_SUPPORT_B),
> +  DECLARE_REG (18, "t2", REG_SUPPORT_B),
> +  DECLARE_REG (19, "t3", REG_SUPPORT_B),
> +  DECLARE_REG (20, "t4", REG_SUPPORT_B),
> +  DECLARE_REG (21, "t5", REG_SUPPORT_B),
> +  DECLARE_REG (22, "t6", REG_SUPPORT_B),
> +  DECLARE_REG (23, "t7", REG_SUPPORT_B),
> +  DECLARE_REG (24, "t8", REG_SUPPORT_B),
> +  DECLARE_REG (25, "t9", REG_SUPPORT_B),
> +  DECLARE_REG (26, NULL, REG_SUPPORT_B),
> +  DECLARE_REG (27, NULL, REG_SUPPORT_B),
> +  DECLARE_REG (28, "gb", REG_SUPPORT_B),
> +  DECLARE_REG (28, "rgb", REG_SUPPORT_B),
> +  DECLARE_REG (28, "rdb", REG_SUPPORT_B),
> +  DECLARE_REG (29, "tb", REG_SUPPORT_B),
> +  DECLARE_REG (29, "rtb", REG_SUPPORT_B),
> +  DECLARE_REG (30, "svbr", REG_SUPPORT_A),
> +  DECLARE_REG (31, "tls", REG_SUPPORT_B),
> +
> +  /* The followings JAVA/BCTM's features.  */
> +  DECLARE_REG (23, "fp", REG_SUPPORT_ALL),
> +  DECLARE_REG (24, "top", REG_SUPPORT_ALL),
> +  DECLARE_REG (25, "bsp", REG_SUPPORT_ALL),
> +
> +  {-1, -1, NULL, NULL, 0, NULL},
>   };
>   
> -const char *csky_cp_reg[] =
> +/* C-SKY V2 control registers table.  */
> +static struct csky_reg_def csky_abiv2_control_regs[] =
>   {
> -  "cpr0",  "cpr1",  "cpr2",  "cpr3",  "cpr4",  "cpr5",  "cpr6",  "cpr7",
> -  "cpr8",  "cpr9",  "cpr10", "cpr11", "cpr12", "cpr13", "cpr14", "cpr15",
> -  "cpr16", "cpr17", "cpr18", "cpr19", "cpr20", "cpr21", "cpr22", "cpr23",
> -  "cpr24", "cpr25", "cpr26", "cpr27", "cpr28", "cpr29", "cpr30", "cpr31",
> -  "cpr32", "cpr33", "cpr34", "cpr35", "cpr36", "cpr37", "cpr38", "cpr39",
> -  "cpr40", "cpr41", "cpr42", "cpr43", "cpr44", "cpr45", "cpr46", "cpr47",
> -  "cpr48", "cpr49", "cpr50", "cpr51", "cpr52", "cpr53", "cpr54", "cpr55",
> -  "cpr56", "cpr57", "cpr58", "cpr59", "cpr60", "cpr61", "cpr62", "cpr63",
> -  NULL,
> +
> +#ifdef DECLARE_REG
> +#undef DECLARE_REG
> +#endif
> +  /* Bank0.  */
> +#define DECLARE_REG(regno, abi_name)		\
> +  {0, regno, "cr<"#regno", 0>", abi_name, REG_SUPPORT_ALL, NULL}
> +  DECLARE_REG (0, "psr"),
> +  DECLARE_REG (1, "vbr"),
> +  DECLARE_REG (2, "epsr"),
> +  DECLARE_REG (3, "fpsr"),
> +  DECLARE_REG (4, "epc"),
> +  DECLARE_REG (5, "fpc"),
> +  DECLARE_REG (6, "ss0"),
> +  DECLARE_REG (7, "ss1"),
> +  DECLARE_REG (8, "ss2"),
> +  DECLARE_REG (9, "ss3"),
> +  DECLARE_REG (10, "ss4"),
> +  DECLARE_REG (11, "gcr"),
> +  DECLARE_REG (12, "gsr"),
> +  DECLARE_REG (13, "cpid"),
> +  DECLARE_REG (14, "dcsr"),
> +  DECLARE_REG (15, NULL),
> +  DECLARE_REG (16, NULL),
> +  DECLARE_REG (17, "cfr"),
> +  DECLARE_REG (18, "ccr"),
> +  DECLARE_REG (19, "capr"),
> +  DECLARE_REG (20, "pacr"),
> +  DECLARE_REG (21, "prsr"),
> +  DECLARE_REG (22, "cir"),
> +  DECLARE_REG (23, "ccr2"),
> +  DECLARE_REG (24, NULL),
> +  DECLARE_REG (25, "cer2"),
> +  DECLARE_REG (26, NULL),
> +  DECLARE_REG (27, NULL),
> +  DECLARE_REG (28, "rvbr"),
> +  DECLARE_REG (29, "rmr"),
> +  DECLARE_REG (30, "mpid"),
> +
> +#undef DECLARE_REG
> +#define DECLARE_REG(regno, abi_name, support)		\
> +  {0, regno, "cr<"#regno", 0>", abi_name, support, NULL}
> +  DECLARE_REG (31, "chr", REG_SUPPORT_E),
> +  DECLARE_REG (31, "hint", REG_SUPPORT_C),
> +
> +  /* Bank1.  */
> +#undef DECLARE_REG
> +#define DECLARE_REG(regno, abi_name)		\
> +  {1, regno, "cr<"#regno", 1>", abi_name, REG_SUPPORT_ALL, NULL}
> +
> +  DECLARE_REG (14, "usp"),
> +  DECLARE_REG (26, "cindex"),
> +  DECLARE_REG (27, "cdata0"),
> +  DECLARE_REG (28, "cdata1"),
> +  DECLARE_REG (29, "cdata2"),
> +  DECLARE_REG (30, "cdata3"),
> +  DECLARE_REG (31, "cins"),
> +
> +  /* Bank2.  */
> +#undef DECLARE_REG
> +#define DECLARE_REG(regno, abi_name)		\
> +  {2, regno, "cr<"#regno", 2>", abi_name, REG_SUPPORT_ALL, NULL}
> +
> +  DECLARE_REG (0, "fid"),
> +  DECLARE_REG (1, "fcr"),
> +  DECLARE_REG (2, "fesr"),
> +
> +  /* Bank3.  */
> +#undef DECLARE_REG
> +#define DECLARE_REG(regno, abi_name)		\
> +  {3, regno, "cr<"#regno", 3>", abi_name, REG_SUPPORT_ALL, NULL}
> +  DECLARE_REG (8, "dcr"),
> +  DECLARE_REG (8, "sedcr"),
> +  DECLARE_REG (9, "pcr"),
> +  DECLARE_REG (9, "sepcr"),
> +
> +  /* Bank15.  */
> +#undef DECLARE_REG
> +#define DECLARE_REG(regno, abi_name)		\
> +  {15, regno, "cr<"#regno", 15>", abi_name, REG_SUPPORT_ALL, NULL}
> +
> +  DECLARE_REG (0, "mir"),
> +  DECLARE_REG (2, "mel0"),
> +  DECLARE_REG (3, "mel1"),
> +  DECLARE_REG (4, "meh"),
> +  DECLARE_REG (6, "mpr"),
> +  DECLARE_REG (8, "mcir"),
> +  DECLARE_REG (28, "mpgd0"),
> +  DECLARE_REG (29, "mpgd"),
> +  DECLARE_REG (29, "mpgd1"),
> +  DECLARE_REG (30, "msa0"),
> +  DECLARE_REG (31, "msa1"),
> +#undef DECLARE_REG
> +  {-1, -1, NULL, NULL, 0, NULL},
>   };
>   
> -const char *csky_cp_creg[] =
> +/* Get register name according to giving parameters,
> +   IS_ABI controls whether is ABI name or not.  */
> +static inline const char *
> +get_register_name (struct csky_reg_def *reg_table,
> +		   int arch, int bank, int regno, int is_abi)
>   {
> -  "cpcr0",  "cpcr1",  "cpcr2",  "cpcr3",
> -  "cpcr4",  "cpcr5",  "cpcr6",  "cpcr7",
> -  "cpcr8",  "cpcr9",  "cpcr10", "cpcr11",
> -  "cpcr12", "cpcr13", "cpcr14", "cpcr15",
> -  "cpcr16", "cpcr17", "cpcr18", "cpcr19",
> -  "cpcr20", "cpcr21", "cpcr22", "cpcr23",
> -  "cpcr24", "cpcr25", "cpcr26", "cpcr27",
> -  "cpcr28", "cpcr29", "cpcr30", "cpcr31",
> -  "cpcr32", "cpcr33", "cpcr34", "cpcr35",
> -  "cpcr36", "cpcr37", "cpcr38", "cpcr39",
> -  "cpcr40", "cpcr41", "cpcr42", "cpcr43",
> -  "cpcr44", "cpcr45", "cpcr46", "cpcr47",
> -  "cpcr48", "cpcr49", "cpcr50", "cpcr51",
> -  "cpcr52", "cpcr53", "cpcr54", "cpcr55",
> -  "cpcr56", "cpcr57", "cpcr58", "cpcr59",
> -  "cpcr60", "cpcr61", "cpcr62", "cpcr63",
> -  NULL,
> -};
> +  static char regname[64] = {0};
> +  unsigned int i = 0;
> +  while (reg_table[i].name != NULL)
> +    {
> +      if (reg_table[i].bank == bank
> +	  && reg_table[i].regno == regno
> +	  && (reg_table[i].arch_flag & (1 << arch)))
> +	{
> +	  if (is_abi && reg_table[i].abi_name)
> +	    return reg_table[i].abi_name;
> +	  else
> +	    return reg_table[i].name;
> +	}
> +      i++;
> +    }
>   
> -struct psrbit
> +  if (bank & 0x80000000)
> +    return "unkown register";
> +
> +  sprintf (regname, "cr<%d, %d>", regno, bank);
> +
> +  return regname;
> +}
> +
> +/* Get register number according to giving parameters.
> +   If not found, return -1.  */
> +static inline int
> +get_register_number (struct csky_reg_def *reg_table,
> +		     int arch, char *s, char **end, int *bank)
>   {
> -  int value;
> -  int isa;
> -  const char *name;
> -};
> -const struct psrbit cskyv1_psr_bits[] =
> +  unsigned int i = 0;
> +  int len = 0;
> +  while (reg_table[i].name != NULL)
> +    {
> +      len = strlen (reg_table[i].name);
> +      if ((strncasecmp (reg_table[i].name, s, len) == 0)
> +	  && !(ISDIGIT (s[len]))
> +	  && (reg_table[i].arch_flag & (1 << arch)))
> +	{
> +	  *end = s + len;
> +	  *bank = reg_table[i].bank;
> +	  return reg_table[i].regno;
> +	}
> +
> +      if (reg_table[i].abi_name == NULL)
> +	{
> +	  i++;
> +	  continue;
> +	}
> +
> +      len = strlen (reg_table[i].abi_name);
> +      if ((strncasecmp (reg_table[i].abi_name, s, len) == 0)
> +	  && !(ISALNUM (s[len]))
> +	  && (reg_table[i].arch_flag & (1 << arch)))
> +	{
> +	  *end = s + len;
> +	  *bank = reg_table[i].bank;
> +	  return reg_table[i].regno;
> +	}
> +      i++;
> +    }
> +  return -1;
> +}
> +
> +/* Return general register's name.  */
> +static inline const char *
> +csky_get_general_reg_name (int arch, int regno, int is_abi)
>   {
> -  {1,    0, "ie"},
> -  {2,    0, "fe"},
> -  {4,    0, "ee"},
> -  {8,    0, "af"},
> -  {0, 0, NULL},
> -};
> -const struct psrbit cskyv2_psr_bits[] =
> +  struct csky_reg_def *reg_table;
> +
> +  if (IS_CSKY_ARCH_V1(arch))
> +    reg_table = csky_abiv1_general_regs;
> +  else
> +    reg_table = csky_abiv2_general_regs;
> +
> +  return get_register_name (reg_table, arch,
> +			    GENARAL_REG_BANK, regno, is_abi);
> +}
> +
> +/* Return general register's number.  */
> +static inline int
> +csky_get_general_regno(int arch, char *s, char **end)
>   {
> -  {8, 0, "ee"},
> -  {4, 0, "ie"},
> -  {2, 0, "fe"},
> -  {1, 0, "af"},
> -  {0x10, CSKY_ISA_TRUST, "sie"},
> -  {0, 0, NULL},
> -};
> +  struct csky_reg_def *reg_table;
> +  int bank = 0;
>   
> +  if (IS_CSKY_ARCH_V1(arch))
> +    reg_table = csky_abiv1_general_regs;
> +  else
> +    reg_table = csky_abiv2_general_regs;
> +
> +  return get_register_number (reg_table, arch, s, end, &bank);
> +}
> +
> +/* Return control register's name.  */
> +static inline const char *
> +csky_get_control_reg_name (int arch, int bank, int regno, int is_abi)
> +{
> +  struct csky_reg_def *reg_table;
> +
> +  if (IS_CSKY_ARCH_V1(arch))
> +    reg_table = csky_abiv1_control_regs;
> +  else
> +    reg_table = csky_abiv2_control_regs;
> +
> +  return get_register_name (reg_table, arch, bank,
> +			    regno, is_abi);
> +}
> +
> +/* Return control register's number.  */
> +static inline int
> +csky_get_control_regno(int arch, char *s, char **end, int *bank)
> +{
> +  struct csky_reg_def *reg_table;
> +
> +  if (IS_CSKY_ARCH_V1(arch))
> +    reg_table = csky_abiv1_control_regs;
> +  else
> +    reg_table = csky_abiv2_control_regs;
> +
> +  return get_register_number (reg_table, arch, s, end, bank);
> +}
>   
>   /* C-SKY V1 opcodes.  */
>   const struct csky_opcode csky_v1_opcodes[] =
> @@ -3620,12 +3916,12 @@ const struct csky_opcode csky_v2_opcodes[] =
>   #undef _TRANSFER
>   #define _TRANSFER   0
>       DOP16_DOP32 ("bclri",
> -		 OPCODE_INFO3 (0x3880,
> +    		 OPCODE_INFO2 (0x3880,
>   			       (8_10, GREG0_7, OPRND_SHIFT_0_BIT),
> -			       (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT),
>   			       (0_4, IMM5b, OPRND_SHIFT_0_BIT)),
> -		 OPCODE_INFO2 (0x3880,
> +		 OPCODE_INFO3 (0x3880,
>   			       (8_10, GREG0_7, OPRND_SHIFT_0_BIT),
> +			       (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT),
>   			       (0_4, IMM5b, OPRND_SHIFT_0_BIT)),
>   		 CSKYV2_ISA_E1,
>   		 OPCODE_INFO3 (0xc4002820,
> @@ -3637,12 +3933,12 @@ const struct csky_opcode csky_v2_opcodes[] =
>   			       (21_25, IMM5b, OPRND_SHIFT_0_BIT)),
>   		 CSKYV2_ISA_1E2),
>       DOP16_DOP32 ("bseti",
> -		 OPCODE_INFO3 (0x38a0,
> +    		 OPCODE_INFO2 (0x38a0,
>   			       (8_10, GREG0_7, OPRND_SHIFT_0_BIT),
> -			       (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT),
>   			       (0_4, IMM5b, OPRND_SHIFT_0_BIT)),
> -		 OPCODE_INFO2 (0x38a0,
> +		 OPCODE_INFO3 (0x38a0,
>   			       (8_10, GREG0_7, OPRND_SHIFT_0_BIT),
> +			       (NONE, DUMMY_REG, OPRND_SHIFT_0_BIT),
>   			       (0_4, IMM5b, OPRND_SHIFT_0_BIT)),
>   		 CSKYV2_ISA_E1,
>   		 OPCODE_INFO3 (0xc4002840,
> @@ -3707,23 +4003,24 @@ const struct csky_opcode csky_v2_opcodes[] =
>   			     (16_20, AREG, OPRND_SHIFT_0_BIT),
>   			     (21_25, IMM5b, OPRND_SHIFT_0_BIT)),
>   	       CSKYV2_ISA_1E2),
> -    DOP16_DOP32 ("addc",
> -		 OPCODE_INFO2 (0x6001,
> -			       (6_9, GREG0_15, OPRND_SHIFT_0_BIT),
> -			       (2_5, GREG0_15, OPRND_SHIFT_0_BIT)),
> -		 OPCODE_INFO3 (0x6001,
> -			       (6_9, GREG0_15, OPRND_SHIFT_0_BIT),
> -			       (2_5, 2IN1_DUMMY, OPRND_SHIFT_0_BIT),
> -			       (2_5, 2IN1_DUMMY, OPRND_SHIFT_0_BIT)),
> -		 CSKYV2_ISA_E1,
> -		 OPCODE_INFO3 (0xc4000040,
> -			       (0_4, AREG, OPRND_SHIFT_0_BIT),
> -			       (16_20, AREG, OPRND_SHIFT_0_BIT),
> -			       (21_25, AREG, OPRND_SHIFT_0_BIT)),
> -		 OPCODE_INFO2 (0xc4000040,
> -			       (0_4or16_20, DUP_AREG, OPRND_SHIFT_0_BIT),
> -			       (21_25, AREG, OPRND_SHIFT_0_BIT)),
> -		 CSKYV2_ISA_1E2),
> +    DOP16_DOP32_WITH_WORK ("addc",
> +			   OPCODE_INFO2 (0x6001,
> +					 (6_9, GREG0_15, OPRND_SHIFT_0_BIT),
> +					 (2_5, GREG0_15, OPRND_SHIFT_0_BIT)),
> +			   OPCODE_INFO3 (0x6001,
> +					 (6_9, GREG0_15, OPRND_SHIFT_0_BIT),
> +					 (2_5, GREG0_15, OPRND_SHIFT_0_BIT),
> +					 (2_5, GREG0_15, OPRND_SHIFT_0_BIT)),
> +			   CSKYV2_ISA_E1,
> +			   OPCODE_INFO3 (0xc4000040,
> +					 (0_4, AREG, OPRND_SHIFT_0_BIT),
> +					 (16_20, AREG, OPRND_SHIFT_0_BIT),
> +					 (21_25, AREG, OPRND_SHIFT_0_BIT)),
> +			   OPCODE_INFO2 (0xc4000040,
> +					 (0_4or16_20, AREG, OPRND_SHIFT_0_BIT),
> +					 (21_25, AREG, OPRND_SHIFT_0_BIT)),
> +			   CSKYV2_ISA_1E2,
> +			   v2_work_addc),
>       DOP16_DOP32 ("subc",
>   		 OPCODE_INFO2 (0x6003,
>   			       (6_9, GREG0_15, OPRND_SHIFT_0_BIT),
> @@ -4015,14 +4312,14 @@ const struct csky_opcode csky_v2_opcodes[] =
>   			(0_4, AREG, OPRND_SHIFT_0_BIT),
>   			(16_20, AREG, OPRND_SHIFT_0_BIT),
>   			(5_9, IMM5b, OPRND_SHIFT_0_BIT),
> -			(21_25, IMM5b, OPRND_SHIFT_0_BIT)),
> +			(21_25, IMM5b_LS, OPRND_SHIFT_0_BIT)),
>   	  CSKYV2_ISA_2E3),
>       OP32 ("sext",
>   	  OPCODE_INFO4 (0xc4005800,
>   			(0_4, AREG, OPRND_SHIFT_0_BIT),
>   			(16_20, AREG, OPRND_SHIFT_0_BIT),
>   			(5_9, IMM5b, OPRND_SHIFT_0_BIT),
> -			(21_25, IMM5b, OPRND_SHIFT_0_BIT)),
> +			(21_25, IMM5b_LS, OPRND_SHIFT_0_BIT)),
>   	  CSKYV2_ISA_2E3),
>   #undef _TRANSFER
>   #define _TRANSFER   2

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PUSHED] Re: [PATCH] CSKY: Add objdump option -M abi-names.
  2020-09-17  6:30 [PATCH] CSKY: Add objdump option -M abi-names Cooper Qu
  2020-09-23 15:50 ` Lifang Xia
@ 2020-09-24 14:14 ` Andrew Burgess
  1 sibling, 0 replies; 5+ messages in thread
From: Andrew Burgess @ 2020-09-24 14:14 UTC (permalink / raw)
  To: Cooper Qu; +Cc: binutils, lifang_xia, Simon Marchi

I pushed the patch below under the "obvious" rule.

I inspected the code and concluded that either the strcat should be
included in the if body or the buf would be undefined, in which case
the original patch has other issues.

Thanks,
Andrew

---

commit 7b6addc226a004622a12c87d3292176dbc8da041
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Thu Sep 24 15:03:43 2020 +0100

    csky/opcodes: enclose if body in curly braces
    
    This commit:
    
      commit afdcafe89118cee761f9bf67ea1b1efc29311300
      Date:   Thu Sep 17 14:30:28 2020 +0800
    
          CSKY: Add objdump option -M abi-names.
    
    cases the build of GDB (configured with --enabled-targets=all) to fail
    with this error:
    
      libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I../../src/opcodes -I. -I../../src/opcodes -I../bfd -I../../src/opcodes/../include -I../../src/opcodes/../bfd -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Wstack-usage=262144 -Werror -O0 -g3 -D_GLIBCXX_DEBUG=1 -MT csky-dis.lo -MD -MP -MF .deps/csky-dis.Tpo -c ../../src/opcodes/csky-dis.c -o csky-dis.o
      ../../src/opcodes/csky-dis.c: In function ‘csky_output_operand’:
      ../../src/opcodes/csky-dis.c:849:7: error: this ‘if’ clause does not guard... [-Werror=misleading-indentation]
        849 |       if (IS_CSKY_V1 (mach_flag))
            |       ^~
      ../../src/opcodes/csky-dis.c:851:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the ‘if’
        851 |  strcat (str, buf);
            |  ^~~~~~
    
    this commit adds { ... } around the if body to resolve this issue.
    
    opcodes/ChangeLog:
    
            * csky-dis.c (csky_output_operand): Enclose body of if in curly
            braces.

diff --git a/opcodes/csky-dis.c b/opcodes/csky-dis.c
index 67fb4ee87ed..ce20f58c473 100644
--- a/opcodes/csky-dis.c
+++ b/opcodes/csky-dis.c
@@ -847,8 +847,10 @@ csky_output_operand (char *str, struct operand const *oprnd,
       }
     case OPRND_TYPE_REGr4_r7:
       if (IS_CSKY_V1 (mach_flag))
-	sprintf (buf, "%s-%s", get_gr_name (4), get_gr_name (7));
-	strcat (str, buf);
+	{
+	  sprintf (buf, "%s-%s", get_gr_name (4), get_gr_name (7));
+	  strcat (str, buf);
+	}
       break;
     case OPRND_TYPE_CONST1:
       strcat (str, "1");

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] CSKY: Add objdump option -M abi-names.
  2020-09-23 15:50 ` Lifang Xia
@ 2020-09-25 13:18   ` Alan Modra
  2020-09-25 16:45     ` Cooper Qu
  0 siblings, 1 reply; 5+ messages in thread
From: Alan Modra @ 2020-09-25 13:18 UTC (permalink / raw)
  To: Cooper Qu, Lifang Xia; +Cc: binutils

On Wed, Sep 23, 2020 at 11:50:35PM +0800, Lifang Xia wrote:
> On 2020/9/17 14:30, Cooper Qu wrote:
> > Add option parser for disassembler, and refine the codes of
> > parse register operand and disassemble register operand.
> > While strengthen the operands legality check of some instructions.
> >
> > Co-Authored-By: Lifang Xia <lifang_xia@c-sky.com>
> >
> > gas/
> > 	* config/tc-csky.c (parse_type_ctrlreg): Use function
> > 	csky_get_control_regno to operand.
> > 	(csky_get_reg_val): Likewise.
> > 	(is_reg_sp_with_bracket): Use function csky_get_reg_val
> > 	to parse operand.
> > 	(is_reg_sp): Refine.
> > 	(is_oimm_within_range): Fix, report error when operand
> > 	is not constant.
> > 	(parse_type_cpreg): Refine.
> > 	(parse_type_cpcreg): Refine.
> > 	(get_operand_value): Add handle of OPRND_TYPE_IMM5b_LS.
> > 	(md_assemble): Fix no error reporting somtimes when
> > 	operands number are not fit.
> > 	(csky_addc64): Refine.
> > 	(csky_subc64): Refine.
> > 	(csky_or64): Refine.
> > 	(v1_work_fpu_fo): Refine.
> > 	(v1_work_fpu_read): Refine.
> > 	(v1_work_fpu_writed): Refine.
> > 	(v1_work_fpu_readd): Refine.
> > 	(v2_work_addc): New function, strengthen the operands legality
> > 	check of addc.
> > 	* gas/testsuite/gas/csky/all.d : Use register number format when
> > 	disassemble register name by default.
> > 	* gas/testsuite/gas/csky/cskyv2_all.d : Likewise.
> > 	* gas/testsuite/gas/csky/trust.d: Likewise.
> > 	* gas/testsuite/gas/csky/cskyv2_ck860.d : Fix.
> > 	* gas/testsuite/gas/csky/trust.s : Fix.
> >
> > opcodes/
> > 	* csky-dis.c (using_abi): New.
> > 	(parse_csky_dis_options): New function.
> > 	(get_gr_name): New function.
> > 	(get_cr_name): New function.
> > 	(csky_output_operand): Use get_gr_name and get_cr_name to
> > 	disassemble and add handle of OPRND_TYPE_IMM5b_LS.
> > 	(print_insn_csky): Parse disassembler options.
> > 	* opcodes/csky-opc.h (OPRND_TYPE_IMM5b_LS): New enum.
> > 	(GENARAL_REG_BANK): Define.
> > 	(REG_SUPPORT_ALL): Define.
> > 	(REG_SUPPORT_ALL): New.
> > 	(ASH): Define.
> > 	(REG_SUPPORT_A): Define.
> > 	(REG_SUPPORT_B): Define.
> > 	(REG_SUPPORT_C): Define.
> > 	(REG_SUPPORT_D): Define.
> > 	(REG_SUPPORT_E): Define.
> > 	(csky_abiv1_general_regs): New.
> > 	(csky_abiv1_control_regs): New.
> > 	(csky_abiv2_general_regs): New.
> > 	(csky_abiv2_control_regs): New.
> > 	(get_register_name): New function.
> > 	(get_register_number): New function.
> > 	(csky_get_general_reg_name): New function.
> > 	(csky_get_general_regno): New function.
> > 	(csky_get_control_reg_name): New function.
> > 	(csky_get_control_regno): New function.
> > 	(csky_v2_opcodes): Prefer two oprerans format for bclri and
> > 	bseti, strengthen the operands legality check of addc, zext
> > 	and sext.

This patch results in ubsan errors, for example
opcodes/csky-opc.h:929 shift exponent 536870912 is too large

I took a look at what I think the code is trying to do, and came up
with the following fix.  Please check that this is correct.

opcodes/
	* csky-opc.h: Formatting.
	(GENERAL_REG_BANK): Correct spelling.  Update use throughout file.
	(get_register_name): Mask arch with CSKY_ARCH_MASK for shift,
	and shift 1u.
	(get_register_number): Likewise.
	* csky-dis.c (get_gr_name, get_cr_name): Don't mask mach_flag.
gas/
	* config/tc-csky.c (parse_type_ctrlreg): Don't mask mach_flag
	for csky_get_control_regno.
	(csky_get_reg_val): Likewise when calling csky_get_general_regno.

diff --git a/gas/config/tc-csky.c b/gas/config/tc-csky.c
index 60d5aa1f53..569fe2bc85 100644
--- a/gas/config/tc-csky.c
+++ b/gas/config/tc-csky.c
@@ -2565,8 +2565,7 @@ parse_type_ctrlreg (char** oper)
 	}
       else
 	{
-	  crx = csky_get_control_regno (mach_flag & CSKY_ARCH_MASK,
-			  s, &s, &sel);
+	  crx = csky_get_control_regno (mach_flag, s, &s, &sel);
 	  if (crx < 0)
 	    {
 	      SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
@@ -2577,8 +2576,7 @@ parse_type_ctrlreg (char** oper)
     }
   else if (i == -1)
     {
-      i = csky_get_control_regno (mach_flag & CSKY_ARCH_MASK,
-				  s, &s, &sel);
+      i = csky_get_control_regno (mach_flag, s, &s, &sel);
       if (i < 0)
 	{
 	  SET_ERROR_STRING (ERROR_CREG_ILLEGAL, s);
@@ -2595,7 +2593,7 @@ csky_get_reg_val (char *str, int *len)
 {
   int regno = 0;
   char *s = str;
-  regno = csky_get_general_regno (mach_flag & CSKY_ARCH_MASK, str, &s);
+  regno = csky_get_general_regno (mach_flag, str, &s);
   *len = (s - str);
   return regno;
 }
diff --git a/opcodes/csky-dis.c b/opcodes/csky-dis.c
index ce20f58c47..b31b685b90 100644
--- a/opcodes/csky-dis.c
+++ b/opcodes/csky-dis.c
@@ -287,14 +287,14 @@ parse_csky_dis_options (const char *opts_in)
 static const char *
 get_gr_name (int regno)
 {
-  return csky_get_general_reg_name (mach_flag & CSKY_ABI_MASK, regno, using_abi);
+  return csky_get_general_reg_name (mach_flag, regno, using_abi);
 }
 
 /* Get control register name.  */
 static const char *
 get_cr_name (unsigned int regno, int bank)
 {
-  return csky_get_control_reg_name (mach_flag & CSKY_ABI_MASK, bank, regno, using_abi);
+  return csky_get_control_reg_name (mach_flag, bank, regno, using_abi);
 }
 
 static int
diff --git a/opcodes/csky-opc.h b/opcodes/csky-opc.h
index 8cd0d1e2a2..199b891371 100644
--- a/opcodes/csky-opc.h
+++ b/opcodes/csky-opc.h
@@ -653,7 +653,7 @@ const struct psrbit cskyv2_psr_bits[] =
   {0, 0, NULL},
 };
 
-#define GENARAL_REG_BANK      0x80000000
+#define GENERAL_REG_BANK      0x80000000
 #define REG_SUPPORT_ALL 0xffffffff
 
 /* CSKY register description.  */
@@ -698,7 +698,7 @@ struct csky_reg_def
 static struct csky_reg_def csky_abiv1_general_regs[] = 
 {
 #define DECLARE_REG(regno, abi_name, support)		\
-  {GENARAL_REG_BANK, regno, "r"#regno, abi_name, support, NULL}
+  {GENERAL_REG_BANK, regno, "r"#regno, abi_name, support, NULL}
 
   DECLARE_REG (0, "sp", REG_SUPPORT_ALL),
   DECLARE_REG (1, NULL, REG_SUPPORT_ALL),
@@ -769,7 +769,7 @@ static struct csky_reg_def csky_abiv2_general_regs[] =
 #undef DECLARE_REG
 #endif
 #define DECLARE_REG(regno, abi_name, support)		\
-  {GENARAL_REG_BANK, regno, "r"#regno, abi_name, support, NULL}
+  {GENERAL_REG_BANK, regno, "r"#regno, abi_name, support, NULL}
 
   DECLARE_REG (0, "a0", REG_SUPPORT_ALL),
   DECLARE_REG (1, "a1", REG_SUPPORT_ALL),
@@ -926,7 +926,7 @@ get_register_name (struct csky_reg_def *reg_table,
     {
       if (reg_table[i].bank == bank
 	  && reg_table[i].regno == regno
-	  && (reg_table[i].arch_flag & (1 << arch)))
+	  && (reg_table[i].arch_flag & (1u << (arch & CSKY_ARCH_MASK))))
 	{
 	  if (is_abi && reg_table[i].abi_name)
 	    return reg_table[i].abi_name;
@@ -957,7 +957,7 @@ get_register_number (struct csky_reg_def *reg_table,
       len = strlen (reg_table[i].name);
       if ((strncasecmp (reg_table[i].name, s, len) == 0)
 	  && !(ISDIGIT (s[len]))
-	  && (reg_table[i].arch_flag & (1 << arch)))
+	  && (reg_table[i].arch_flag & (1u << (arch & CSKY_ARCH_MASK))))
 	{
 	  *end = s + len;
 	  *bank = reg_table[i].bank;
@@ -973,7 +973,7 @@ get_register_number (struct csky_reg_def *reg_table,
       len = strlen (reg_table[i].abi_name);
       if ((strncasecmp (reg_table[i].abi_name, s, len) == 0)
 	  && !(ISALNUM (s[len]))
-	  && (reg_table[i].arch_flag & (1 << arch)))
+	  && (reg_table[i].arch_flag & (1u << (arch & CSKY_ARCH_MASK))))
 	{
 	  *end = s + len;
 	  *bank = reg_table[i].bank;
@@ -990,23 +990,22 @@ csky_get_general_reg_name (int arch, int regno, int is_abi)
 {
   struct csky_reg_def *reg_table;
 
-  if (IS_CSKY_ARCH_V1(arch))
+  if (IS_CSKY_ARCH_V1 (arch))
     reg_table = csky_abiv1_general_regs;
   else
     reg_table = csky_abiv2_general_regs;
 
-  return get_register_name (reg_table, arch,
-			    GENARAL_REG_BANK, regno, is_abi);
+  return get_register_name (reg_table, arch, GENERAL_REG_BANK, regno, is_abi);
 }
 
 /* Return general register's number.  */
 static inline int
-csky_get_general_regno(int arch, char *s, char **end)
+csky_get_general_regno (int arch, char *s, char **end)
 {
   struct csky_reg_def *reg_table;
   int bank = 0;
 
-  if (IS_CSKY_ARCH_V1(arch))
+  if (IS_CSKY_ARCH_V1 (arch))
     reg_table = csky_abiv1_general_regs;
   else
     reg_table = csky_abiv2_general_regs;
@@ -1020,22 +1019,21 @@ csky_get_control_reg_name (int arch, int bank, int regno, int is_abi)
 {
   struct csky_reg_def *reg_table;
 
-  if (IS_CSKY_ARCH_V1(arch))
+  if (IS_CSKY_ARCH_V1 (arch))
     reg_table = csky_abiv1_control_regs;
   else
     reg_table = csky_abiv2_control_regs;
 
-  return get_register_name (reg_table, arch, bank,
-			    regno, is_abi);
+  return get_register_name (reg_table, arch, bank, regno, is_abi);
 }
 
 /* Return control register's number.  */
 static inline int
-csky_get_control_regno(int arch, char *s, char **end, int *bank)
+csky_get_control_regno (int arch, char *s, char **end, int *bank)
 {
   struct csky_reg_def *reg_table;
 
-  if (IS_CSKY_ARCH_V1(arch))
+  if (IS_CSKY_ARCH_V1 (arch))
     reg_table = csky_abiv1_control_regs;
   else
     reg_table = csky_abiv2_control_regs;


-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] CSKY: Add objdump option -M abi-names.
  2020-09-25 13:18   ` Alan Modra
@ 2020-09-25 16:45     ` Cooper Qu
  0 siblings, 0 replies; 5+ messages in thread
From: Cooper Qu @ 2020-09-25 16:45 UTC (permalink / raw)
  To: Alan Modra, Lifang Xia; +Cc: binutils

On 9/25/20 9:18 PM, Alan Modra wrote:

> On Wed, Sep 23, 2020 at 11:50:35PM +0800, Lifang Xia wrote:
>> On 2020/9/17 14:30, Cooper Qu wrote:
>>> Add option parser for disassembler, and refine the codes of
>>> parse register operand and disassemble register operand.
>>> While strengthen the operands legality check of some instructions.
>>>
>>> Co-Authored-By: Lifang Xia <lifang_xia@c-sky.com>
>>>
>>> gas/
>>> 	* config/tc-csky.c (parse_type_ctrlreg): Use function
>>> 	csky_get_control_regno to operand.
>>> 	(csky_get_reg_val): Likewise.
>>> 	(is_reg_sp_with_bracket): Use function csky_get_reg_val
>>> 	to parse operand.
>>> 	(is_reg_sp): Refine.
>>> 	(is_oimm_within_range): Fix, report error when operand
>>> 	is not constant.
>>> 	(parse_type_cpreg): Refine.
>>> 	(parse_type_cpcreg): Refine.
>>> 	(get_operand_value): Add handle of OPRND_TYPE_IMM5b_LS.
>>> 	(md_assemble): Fix no error reporting somtimes when
>>> 	operands number are not fit.
>>> 	(csky_addc64): Refine.
>>> 	(csky_subc64): Refine.
>>> 	(csky_or64): Refine.
>>> 	(v1_work_fpu_fo): Refine.
>>> 	(v1_work_fpu_read): Refine.
>>> 	(v1_work_fpu_writed): Refine.
>>> 	(v1_work_fpu_readd): Refine.
>>> 	(v2_work_addc): New function, strengthen the operands legality
>>> 	check of addc.
>>> 	* gas/testsuite/gas/csky/all.d : Use register number format when
>>> 	disassemble register name by default.
>>> 	* gas/testsuite/gas/csky/cskyv2_all.d : Likewise.
>>> 	* gas/testsuite/gas/csky/trust.d: Likewise.
>>> 	* gas/testsuite/gas/csky/cskyv2_ck860.d : Fix.
>>> 	* gas/testsuite/gas/csky/trust.s : Fix.
>>>
>>> opcodes/
>>> 	* csky-dis.c (using_abi): New.
>>> 	(parse_csky_dis_options): New function.
>>> 	(get_gr_name): New function.
>>> 	(get_cr_name): New function.
>>> 	(csky_output_operand): Use get_gr_name and get_cr_name to
>>> 	disassemble and add handle of OPRND_TYPE_IMM5b_LS.
>>> 	(print_insn_csky): Parse disassembler options.
>>> 	* opcodes/csky-opc.h (OPRND_TYPE_IMM5b_LS): New enum.
>>> 	(GENARAL_REG_BANK): Define.
>>> 	(REG_SUPPORT_ALL): Define.
>>> 	(REG_SUPPORT_ALL): New.
>>> 	(ASH): Define.
>>> 	(REG_SUPPORT_A): Define.
>>> 	(REG_SUPPORT_B): Define.
>>> 	(REG_SUPPORT_C): Define.
>>> 	(REG_SUPPORT_D): Define.
>>> 	(REG_SUPPORT_E): Define.
>>> 	(csky_abiv1_general_regs): New.
>>> 	(csky_abiv1_control_regs): New.
>>> 	(csky_abiv2_general_regs): New.
>>> 	(csky_abiv2_control_regs): New.
>>> 	(get_register_name): New function.
>>> 	(get_register_number): New function.
>>> 	(csky_get_general_reg_name): New function.
>>> 	(csky_get_general_regno): New function.
>>> 	(csky_get_control_reg_name): New function.
>>> 	(csky_get_control_regno): New function.
>>> 	(csky_v2_opcodes): Prefer two oprerans format for bclri and
>>> 	bseti, strengthen the operands legality check of addc, zext
>>> 	and sext.
> This patch results in ubsan errors, for example
> opcodes/csky-opc.h:929 shift exponent 536870912 is too large
>
> I took a look at what I think the code is trying to do, and came up
> with the following fix.  Please check that this is correct.
>
> opcodes/
> 	* csky-opc.h: Formatting.
> 	(GENERAL_REG_BANK): Correct spelling.  Update use throughout file.
> 	(get_register_name): Mask arch with CSKY_ARCH_MASK for shift,
> 	and shift 1u.
> 	(get_register_number): Likewise.
> 	* csky-dis.c (get_gr_name, get_cr_name): Don't mask mach_flag.
> gas/
> 	* config/tc-csky.c (parse_type_ctrlreg): Don't mask mach_flag
> 	for csky_get_control_regno.
> 	(csky_get_reg_val): Likewise when calling csky_get_general_regno.
>
Hi Alan,

The patch looks good and I have tested it, there is no problem. Thanks 
for fixing the bug and improving the code, these bugs will prompt me to 
write and test better next time.


Best Regards,

Cooper


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-09-25 16:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-17  6:30 [PATCH] CSKY: Add objdump option -M abi-names Cooper Qu
2020-09-23 15:50 ` Lifang Xia
2020-09-25 13:18   ` Alan Modra
2020-09-25 16:45     ` Cooper Qu
2020-09-24 14:14 ` [PUSHED] " Andrew Burgess

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).