[PATCH] CSKY: Add objdump option -M abi-names.

Lifang Xia lifang_xia@c-sky.com
Wed Sep 23 15:50:35 GMT 2020


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


More information about the Binutils mailing list