PATCH [3/4] C-SKY port: assembler

Message ID 3d97e019-b75b-e84d-a8fb-202e791e4397@codesourcery.com
State Superseded
Headers show
Series
  • PATCH [3/4] C-SKY port: assembler
Related show

Commit Message

Sandra Loosemore May 24, 2018, 12:25 a.m.
This part of the C-SKY patch set includes the assembler pieces.

Both C-SKY variants have complex/irregular instruction sets with many 
different operand types that all need special parsing and error-checking 
code.  Particularly for V2, the same syntax may have multiple encodings 
which are selected based on register and constant ranges, etc; that's 
what the *_work functions are for.

BTW, the literal pool placement code (which is probably the most complex 
part of tc-csky.c) looked like it was copied from ARM, which might be a 
useful tidbit when reviewing that section.

-Sandra

Patch

commit 6976fc91cf923cbd29aa3c7a3a89349686c13954
Author: Sandra Loosemore <sandra@codesourcery.com>
Date:   Mon May 21 13:45:44 2018 -0700

    C-SKY port: assembler
    
    2018-05-21  Lifang Xia <lifang_xia@c-sky.com>
    	    Yunhai Shang  <yunhai_shang@c-sky.com>
    	    Wenmeng Zhang <wenmeng_zhang@c-sky.com>
    	    Wei Cheng <wei_cheng@c-sky.com>
    	    Linjie Yu <linjie_yu@c-sky.com>
    	    Sandra Loosemore <sandra@codesourcery.com>
    	    Chung-Lin Tang <cltang@codesourcery.com>
    
    	gas/
    	* Makefile.am (TARGET_CPU_CFILES): Add entry for C-SKY.
    	(TARGET_CPU_HFILES, TARGET_ENV_HFILES): Likewise.
    	* Makefile.in: Regenerated.
    	* config/tc-csky.c: New file.
    	* config/tc-csky.h: New file.
    	* config/te-csky_abiv1.h: New file.
    	* config/te-csky_abiv1_linux.h: New file.
    	* config/te-csky_abiv2.h: New file.
    	* config/te-csky_abiv2_linux.h: New file.
    	* configure.tgt: Add C-SKY.
    	* doc/Makefile.am (CPU_DOCS): Add entry for C-SKY.
    	* doc/Makefile.in: Regenerated.
    	* doc/all.texi: Set CSKY feature.
    	* doc/as.texinfo (Overview): Add C-SKY options.
    	(Machine Dependencies): Likewise.
    	* doc/c-csky.texi: New file.
    	* testsuite/gas/csky/*: New test cases.

diff --git a/gas/Makefile.am b/gas/Makefile.am
index ff46b0d..396c0fc 100644
--- a/gas/Makefile.am
+++ b/gas/Makefile.am
@@ -138,6 +138,7 @@  TARGET_CPU_CFILES = \
 	config/tc-cr16.c \
 	config/tc-cris.c \
 	config/tc-crx.c \
+	config/tc-csky.c \
 	config/tc-d10v.c \
 	config/tc-d30v.c \
 	config/tc-dlx.c \
@@ -212,6 +213,7 @@  TARGET_CPU_HFILES = \
 	config/tc-cr16.h \
 	config/tc-cris.h \
 	config/tc-crx.h \
+	config/tc-csky.h \
 	config/tc-d10v.h \
 	config/tc-d30v.h \
 	config/tc-dlx.h \
@@ -308,6 +310,10 @@  TARG_ENV_HFILES = \
 	config/te-armfbsdeabi.h \
 	config/te-armfbsdvfp.h \
 	config/te-armlinuxeabi.h \
+	config/te-csky_abiv1.h \
+	config/te-csky_abiv1_linux.h \
+	config/te-csky_abiv2.h \
+	config/te-csky_abiv2_linux.h \
 	config/te-freebsd.h \
 	config/te-generic.h \
 	config/te-gnu.h \
diff --git a/gas/Makefile.in b/gas/Makefile.in
index c127d36..2a075d1 100644
--- a/gas/Makefile.in
+++ b/gas/Makefile.in
@@ -434,6 +434,7 @@  TARGET_CPU_CFILES = \
 	config/tc-cr16.c \
 	config/tc-cris.c \
 	config/tc-crx.c \
+	config/tc-csky.c \
 	config/tc-d10v.c \
 	config/tc-d30v.c \
 	config/tc-dlx.c \
@@ -508,6 +509,7 @@  TARGET_CPU_HFILES = \
 	config/tc-cr16.h \
 	config/tc-cris.h \
 	config/tc-crx.h \
+	config/tc-csky.h \
 	config/tc-d10v.h \
 	config/tc-d30v.h \
 	config/tc-dlx.h \
@@ -604,6 +606,10 @@  TARG_ENV_HFILES = \
 	config/te-armfbsdeabi.h \
 	config/te-armfbsdvfp.h \
 	config/te-armlinuxeabi.h \
+	config/te-csky_abiv1.h \
+	config/te-csky_abiv1_linux.h \
+	config/te-csky_abiv2.h \
+	config/te-csky_abiv2_linux.h \
 	config/te-freebsd.h \
 	config/te-generic.h \
 	config/te-gnu.h \
@@ -856,6 +862,7 @@  distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-cr16.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-cris.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-crx.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-csky.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-d10v.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-d30v.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-dlx.Po@am__quote@
@@ -1069,6 +1076,20 @@  tc-crx.obj: config/tc-crx.c
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-crx.obj `if test -f 'config/tc-crx.c'; then $(CYGPATH_W) 'config/tc-crx.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-crx.c'; fi`
 
+tc-csky.o: config/tc-csky.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-csky.o -MD -MP -MF $(DEPDIR)/tc-csky.Tpo -c -o tc-csky.o `test -f 'config/tc-csky.c' || echo '$(srcdir)/'`config/tc-csky.c
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/tc-csky.Tpo $(DEPDIR)/tc-csky.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='config/tc-csky.c' object='tc-csky.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-csky.o `test -f 'config/tc-csky.c' || echo '$(srcdir)/'`config/tc-csky.c
+
+tc-csky.obj: config/tc-csky.c
+@am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-csky.obj -MD -MP -MF $(DEPDIR)/tc-csky.Tpo -c -o tc-csky.obj `if test -f 'config/tc-csky.c'; then $(CYGPATH_W) 'config/tc-csky.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-csky.c'; fi`
+@am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/tc-csky.Tpo $(DEPDIR)/tc-csky.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	source='config/tc-csky.c' object='tc-csky.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-csky.obj `if test -f 'config/tc-csky.c'; then $(CYGPATH_W) 'config/tc-csky.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-csky.c'; fi`
+
 tc-d10v.o: config/tc-d10v.c
 @am__fastdepCC_TRUE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-d10v.o -MD -MP -MF $(DEPDIR)/tc-d10v.Tpo -c -o tc-d10v.o `test -f 'config/tc-d10v.c' || echo '$(srcdir)/'`config/tc-d10v.c
 @am__fastdepCC_TRUE@	$(am__mv) $(DEPDIR)/tc-d10v.Tpo $(DEPDIR)/tc-d10v.Po
diff --git a/gas/config/tc-csky.c b/gas/config/tc-csky.c
new file mode 100644
index 0000000..743e94f
--- /dev/null
+++ b/gas/config/tc-csky.c
@@ -0,0 +1,7257 @@ 
+/* tc-csky.c -- Assembler for C-SKY
+   Copyright (C) 1989-2018 Free Software Foundation, Inc.
+   Created by Lifang Xia (lifang_xia@c-sky.com)
+   Contributed by C-SKY Microsystems and Mentor Graphics.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#include "as.h"
+#include <limits.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include "safe-ctype.h"
+#include "subsegs.h"
+#include "obstack.h"
+#include "libiberty.h"
+#include "struc-symbol.h"
+
+#ifdef OBJ_ELF
+#include "elf/csky.h"
+#include "dw2gencfi.h"
+#endif
+#include "tc-csky.h"
+#include "dwarf2dbg.h"
+
+#define BUILD_AS          1
+
+#define OPCODE_MAX_LEN    20
+#define HAS_SUB_OPERAND   0xfffffffful
+
+/* This value is just for lrw to distinguish "[]" label.  */
+#define NEED_OUTPUT_LITERAL           1
+
+#define IS_EXTERNAL_SYM(sym, sec)     (S_GET_SEGMENT (sym) != sec)
+#define IS_SUPPORT_OPCODE16(opcode)   (opcode->isa_flag16 | isa_flag)
+#define IS_SUPPORT_OPCODE32(opcode)   (opcode->isa_flag32 | isa_flag)
+
+
+#define KB                * 1024
+#define MB                KB * 1024
+#define GB                MB * 1024
+
+/* Define DSP version flags. For different CPU, the version of DSP
+   instructions may be different.  */
+#define CSKY_DSP_FLAG_V1          (1 << 0) /* Normal DSP instructions.  */
+#define CSKY_DSP_FLAG_V2          (1 << 1) /* CK803S enhanced DSP.  */
+
+/* Literal pool related macros.  */
+/* 1024 - 1 entry - 2 byte rounding.  */
+#define v1_SPANPANIC      (998)
+#define v1_SPANCLOSE      (900)
+#define v1_SPANEXIT       (600)
+#define v2_SPANPANIC      (1024 - 4)
+
+/* 1024 is flrw offset.
+   24 is the biggest size for single instruction.
+   for lrw16 (3+7, 512 bytes).  */
+#define v2_SPANCLOSE      (512 - 24)
+
+/* For lrw16, 112 average size for a function.  */
+#define v2_SPANEXIT       (512 - 112)
+
+/* For lrw16 (3+7, 512 bytes).  */
+#define v2_SPANCLOSE_ELRW (1016 - 24)
+
+/* For lrw16, 112 average size for a function.  */
+#define v2_SPANEXIT_ELRW  (1016 - 112)
+#define MAX_POOL_SIZE     (1024 / 4)
+#define POOL_END_LABEL    ".LE"
+#define POOL_START_LABEL  ".LS"
+
+/* Used in v1_relax_table.  */
+/* These are the two types of relaxable instruction.  */
+#define COND_JUMP         1
+#define UNCD_JUMP         2
+#define COND_JUMP_PIC     3
+#define UNCD_JUMP_PIC     4
+
+#define UNDEF_DISP        0
+#define DISP12            1
+#define DISP32            2
+#define UNDEF_WORD_DISP   3
+
+#define C12_LEN           2
+/* Allow for align: bt/jmpi/.long + align.  */
+#define C32_LEN           10
+/* Allow for align: bt/subi/stw/bsr/lrw/add/ld/addi/jmp/.long + align.  */
+#define C32_LEN_PIC       24
+#define U12_LEN           2
+/* Allow for align: jmpi/.long + align.  */
+#define U32_LEN           8
+/* Allow for align: subi/stw/bsr/lrw/add/ld/addi/jmp/.long + align.  */
+#define U32_LEN_PIC       22
+
+#define C(what,length)    (((what) << 2) + (length))
+#define UNCD_JUMP_S       (do_pic ? UNCD_JUMP_PIC : UNCD_JUMP)
+#define COND_JUMP_S       (do_pic ? COND_JUMP_PIC : COND_JUMP)
+#define U32_LEN_S         (do_pic ? U32_LEN_PIC  : U32_LEN)
+#define C32_LEN_S         (do_pic ? C32_LEN_PIC  : C32_LEN)
+
+/* Used in v2_relax_table.  */
+#define COND_DISP10_LEN   2   /* bt/bf_16.  */
+#define COND_DISP16_LEN   4   /* bt/bf_32.  */
+
+#define SCOND_DISP10_LEN   2   /* bt/bf_16, for CK801 only.  */
+#define SCOND_DISP16_LEN   6   /* !(bt/bf_16) + br_32.  */
+
+#define UNCD_DISP10_LEN   2   /* br_16.  */
+#define UNCD_DISP16_LEN   4   /* br_32.  */
+#define UNCD_DISP26_LEN   4   /* br32_old.  */
+
+#define JCOND_DISP10_LEN  2   /* bt/bf_16.  */
+#define JCOND_DISP16_LEN  4   /* bt/bf_32.  */
+#define JCOND_DISP32_LEN  12  /* !(bt/bf_16)/jmpi 32/.align 2/literal 4.  */
+#define JCOND_DISP26_LEN  8   /* bt/bf_32/br_32 old.  */
+
+#define JUNCD_DISP26_LEN  4   /* bt/bf_32 old.  */
+#define JUNCD_DISP10_LEN  2   /* br_16.  */
+#define JUNCD_DISP16_LEN  4   /* bt/bf_32.  */
+#define JUNCD_DISP32_LEN  10  /* jmpi_32/.align 2/literal 4/  CHANGED!.  */
+#define JCOMP_DISP26_LEN  8   /* bne_32/br_32 old.  */
+
+#define JCOMP_DISP16_LEN  4   /* bne_32 old.  */
+#define JCOMPZ_DISP16_LEN 4   /* bhlz_32.  */
+#define JCOMPZ_DISP32_LEN 14  /* bsz_32/jmpi 32/.align 2/literal 4.  */
+#define JCOMPZ_DISP26_LEN 8   /* bsz_32/br_32  old.  */
+#define JCOMP_DISP32_LEN  14  /* be_32/jmpi_32/.align 2/literal old.  */
+
+#define BSR_DISP10_LEN    2   /* bsr_16.  */
+#define BSR_DISP26_LEN    4   /* bsr_32.  */
+#define LRW_DISP7_LEN     2   /* lrw16.  */
+#define LRW_DISP16_LEN    4   /* lrw32.  */
+
+/* Declare worker functions.  */
+bfd_boolean v1_work_lrw (void);
+bfd_boolean v1_work_jbsr (void);
+bfd_boolean v1_work_fpu_fo (void);
+bfd_boolean v1_work_fpu_fo_fc (void);
+bfd_boolean v1_work_fpu_write (void);
+bfd_boolean v1_work_fpu_read (void);
+bfd_boolean v1_work_fpu_writed (void);
+bfd_boolean v1_work_fpu_readd (void);
+bfd_boolean v2_work_istack (void);
+bfd_boolean v2_work_btsti (void);
+bfd_boolean v2_work_addi (void);
+bfd_boolean v2_work_subi (void);
+bfd_boolean v2_work_add_sub (void);
+bfd_boolean v2_work_rotlc (void);
+bfd_boolean v2_work_bgeni (void);
+bfd_boolean v2_work_not (void);
+bfd_boolean v2_work_jbtf (void);
+bfd_boolean v2_work_jbr (void);
+bfd_boolean v2_work_lrw (void);
+bfd_boolean v2_work_lrsrsw (void);
+bfd_boolean v2_work_jbsr (void);
+bfd_boolean v2_work_jsri (void);
+bfd_boolean v2_work_movih (void);
+bfd_boolean v2_work_ori (void);
+bfd_boolean float_work_fmovi (void);
+bfd_boolean dsp_work_bloop (void);
+
+/* csky-opc.h must be included after workers are declared.  */
+#include "opcodes/csky-opc.h"
+#include "opcode/csky.h"
+
+enum
+{
+  RELAX_NONE = 0,
+  RELAX_OVERFLOW,
+
+  COND_DISP10 = 20,    /* bt/bf_16.  */
+  COND_DISP16,    /* bt/bf_32.  */
+
+  SCOND_DISP10,	   /* br_16 */
+  SCOND_DISP16,	   /* !(bt/bf_32) + br_32.  */
+
+  UNCD_DISP10,    /* br_16.  */
+  UNCD_DISP16,    /* br_32.  */
+
+  JCOND_DISP10,   /* bt/bf_16.  */
+  JCOND_DISP16,   /* bt/bf_32.  */
+  JCOND_DISP32,   /* !(bt/bf_32)/jmpi + literal.  */
+
+  JUNCD_DISP10,   /* br_16.  */
+  JUNCD_DISP16,   /* br_32.  */
+  JUNCD_DISP32,   /* jmpi + literal.  */
+
+  JCOMPZ_DISP16,  /* bez/bnez/bhz/blsz/blz/bhsz.  */
+  JCOMPZ_DISP32,  /* !(jbez/jbnez/jblsz/jblz/jbhsz) + jmpi + literal.  */
+
+  BSR_DISP26,     /* bsr_32.  */
+
+  LRW_DISP7,      /* lrw16.  */
+  LRW2_DISP8,     /* lrw16, -mno-bsr16,8 bit offset.  */
+  LRW_DISP16,     /* lrw32.  */
+};
+
+
+unsigned int mach_flag = 0;
+unsigned int arch_flag = 0;
+unsigned int other_flag = 0;
+unsigned int isa_flag = 0;
+unsigned int dsp_flag = 0;
+
+typedef struct stack_size_entry
+{
+  struct stack_size_entry *next;
+  symbolS *function;
+  unsigned int stack_size;
+} stack_size_entry;
+
+struct csky_arch_info
+{
+  const char *name;
+  unsigned int arch_flag;
+  unsigned int bfd_mach_flag;
+};
+
+struct csky_cpu_info
+{
+  const char *name;
+  unsigned int mach_flag;
+  unsigned int isa_flag;
+};
+
+typedef enum
+{
+  INSN_OPCODE,
+  INSN_OPCODE16F,
+  INSN_OPCODE32F,
+} inst_flag;
+
+/* Macro information.  */
+struct csky_macro_info
+{
+  const char *name;
+  /* How many operands : if operands == 5, all of 1,2,3,4 are ok.  */
+  long oprnd_num;
+  int isa_flag;
+  /* Do the work.  */
+  void (*handle_func)(void);
+};
+
+struct csky_insn_info
+{
+  /* Name of the opcode.  */
+  char *name;
+  /* Output instruction.  */
+  unsigned int inst;
+  /* Pointer for frag.  */
+  char *output;
+  /* End of instruction.  */
+  char *opcode_end;
+  /* Flag for INSN_OPCODE16F, INSN_OPCODE32F, INSN_OPCODE, INSN_MACRO.  */
+  inst_flag flag_force;
+  /* Operand number.  */
+  int number;
+  struct csky_opcode *opcode;
+  struct csky_macro_info *macro;
+  /* Insn size for check_literal.  */
+  unsigned int isize;
+  /* Max size of insn for relax frag_var.  */
+  unsigned int max;
+  /* Indicates which element is in csky_opcode_info op[] array.  */
+  int opcode_idx;
+  /* The value of each operand in instruction when layout.  */
+  int idx;
+  int val[MAX_OPRND_NUM];
+  struct relax_info
+    {
+      int max;
+      int var;
+      int subtype;
+    } relax;
+  /* The following are used for constant expressions.  */
+  uint64_t dbnum;
+  expressionS e1;
+  expressionS e2;
+};
+
+struct tls_addend {
+  fragS *frag;
+  offsetT offset;
+};
+
+/* Literal pool data structures.  */
+struct literal
+{
+  unsigned short  refcnt;
+  unsigned char   ispcrel;
+  unsigned char   unused;
+  bfd_reloc_code_real_type r_type;
+  expressionS     e;
+  struct tls_addend tls_addend;
+  unsigned char   isdouble;
+  uint64_t dbnum;
+};
+
+static void csky_idly (void);
+static void csky_rolc (void);
+static void csky_sxtrb (void);
+static void csky_movtf (void);
+static void csky_addc64 (void);
+static void csky_subc64 (void);
+static void csky_or64 (void);
+static void csky_xor64 (void);
+static void csky_neg (void);
+static void csky_rsubi (void);
+static void csky_arith (void);
+static void csky_decne (void);
+static void csky_lrw (void);
+
+static enum bfd_reloc_code_real insn_reloc;
+
+/* Assembler operand parse errors use these identifiers.  */
+
+enum error_number
+{
+  /* The following are errors.  */
+  ERROR_CREG_ILLEGAL = 0,
+  ERROR_REG_OVER_RANGE,
+  ERROR_GREG_ILLEGAL,
+  ERROR_802J_REG_OVER_RANGE,
+  ERROR_REG_FORMAT,
+  ERROR_REG_LIST,
+  ERROR_IMM_ILLEGAL,
+  ERROR_IMM_OVERFLOW,             /* 5  */
+  ERROR_IMM_POWER,
+  ERROR_JMPIX_OVER_RANGE,
+  ERROR_EXP_CREG,
+  ERROR_EXP_GREG,
+  ERROR_EXP_CONSTANT,
+  ERROR_EXP_EVEN_FREG,
+  ERROR_RELOC_ILLEGAL,
+  ERROR_MISSING_OPERAND,          /* 10  */
+  ERROR_MISSING_COMMA,
+  ERROR_MISSING_LBRACKET,
+  ERROR_MISSING_RBRACKET,
+  ERROR_MISSING_LSQUARE_BRACKETS,
+  ERROR_MISSING_RSQUARE_BRACKETS, /* 15  */
+  ERROR_MISSING_LANGLE_BRACKETS,
+  ERROR_MISSING_RANGLE_BRACKETS,
+  ERROR_OFFSET_UNALIGNED,
+  ERROR_BAD_END,
+  ERROR_UNDEFINE,
+  ERROR_CPREG_ILLEGAL,           /* 20  */
+  ERROR_OPCODE_PSRBIT,
+  ERROR_OPERANDS_ILLEGAL,
+  ERROR_OPERANDS_NUMBER,
+  ERROR_OPCODE_ILLEGAL,
+
+  /* The following are warnings.  */
+  WARNING_OPTIONS,
+  WARNING_IDLY,
+
+  /* Error and warning end.  */
+  ERROR_NONE,
+};
+
+/* Global error state.  ARG1 and ARG2 are opaque data interpreted
+   as appropriate for the error code.  */
+
+struct csky_error_state
+{
+  enum error_number err_num;
+  int opnum;
+  const void *arg1;
+  const void *arg2;
+} error_state;
+
+/* This macro is used to set error number and arg1 in the global state.  */
+
+#define SET_ERROR_NUMBER(err, msg)                      \
+  do {							\
+    if (error_state.err_num > err)			\
+      {							\
+	error_state.err_num = err;			\
+	error_state.arg1 = (void *)msg;			\
+      }							\
+  } while (0)
+
+
+/* Map error identifiers onto a format string, which will use
+   arg1 and arg2 from the global error state.  */
+struct csky_error_format_map
+{
+  enum error_number num;
+  const char *fmt;
+};
+
+static const struct csky_error_format_map err_formats[] =
+{
+  {ERROR_CREG_ILLEGAL, "Operand %d error: control register is illegal."},
+  {ERROR_REG_OVER_RANGE, "Operand %d error: r%d register is over range."},
+  {ERROR_GREG_ILLEGAL, "Operand %d error: general register is illegal."},
+  {ERROR_802J_REG_OVER_RANGE, "Operand %d register %s out of range (802j only has registers:0-15,23,24,25,30)"},
+  {ERROR_REG_FORMAT, "Operand %d error: %s."},
+  {ERROR_REG_LIST, "Register list format is illegal."},
+  {ERROR_IMM_ILLEGAL, "Operand %d is not an immediate."},
+  {ERROR_IMM_OVERFLOW, "Operand %d immediate is overflow."},
+  {ERROR_IMM_POWER, "immediate %d is not a power of two"},
+  {ERROR_JMPIX_OVER_RANGE, "The second operand must be 16/24/32/40"},
+  {ERROR_EXP_CREG, "Operand %d error: control register is expected."},
+  {ERROR_EXP_GREG, "Operand %d error: general register is expected."},
+  {ERROR_EXP_CONSTANT, "Operand %d error: constant is expected."},
+  {ERROR_EXP_EVEN_FREG, "Operand %d error: even float register is expected."},
+  {ERROR_RELOC_ILLEGAL, "@%s reloc is not supported"},
+  {ERROR_MISSING_OPERAND, "Operand %d is missing."},
+  {ERROR_MISSING_COMMA, "Missing ','"},
+  {ERROR_MISSING_LBRACKET, "Missing '('"},
+  {ERROR_MISSING_RBRACKET, "Missing ')'"},
+  {ERROR_MISSING_LSQUARE_BRACKETS, "Missing '['"},
+  {ERROR_MISSING_RSQUARE_BRACKETS, "Missing ']'"},
+  {ERROR_MISSING_LANGLE_BRACKETS, "Missing '<'"},
+  {ERROR_MISSING_RANGLE_BRACKETS, "Missing '>'"},
+  {ERROR_OFFSET_UNALIGNED, "Operand %d is unaligned. It must be %d aligned!"},
+  {ERROR_BAD_END, "Operands mismatch, it has a bad end: %s"},
+  {ERROR_UNDEFINE, NULL},
+  {ERROR_CPREG_ILLEGAL, "Operand %d illegal, expect a cpreg(cpr0-cpr63)."},
+  {ERROR_OPCODE_PSRBIT, "The operands must be 'ie'/'ee'/'fe'."},
+  {ERROR_OPERANDS_ILLEGAL, "Operands mismatch: %s."},
+  {ERROR_OPERANDS_NUMBER, "Operands number mismatch, %d operands expected."},
+  {ERROR_OPCODE_ILLEGAL, "The instruction is not recognized."},
+  {WARNING_OPTIONS, "Option %s is not support in %s."},
+  {WARNING_IDLY, "idly %d is encoded to: idly 4 "},
+  {ERROR_NONE, "There is no error."},
+};
+
+static int do_pic = 0;            /* for jbr/jbf/jbt relax jmpi reloc.  */
+static int do_pff = -1;           /* for insert two br ahead of literals.  */
+static int do_force2bsr = -1;     /* for jbsr->bsr.  */
+static int do_jsri2bsr = 1;       /* for jsri->bsr.  */
+static int do_nolrw = 0;          /* lrw to movih & ori, only for V2.  */
+static int do_long_jump = 0;      /* control if jbf,jbt,jbr relax to jmpi.  */
+static int do_extend_lrw = -1;    /* delete bsr16 in both two options,
+				     add btesti16, lrw offset +1 in -melrw.  */
+static int do_func_dump = 0;      /* dump literals after every function.  */
+static int do_br_dump = 1;        /* work for -mabr/-mno-abr, control the literals dump.  */
+static int do_intr_stack = -1;    /* control interrupt stack module, 801&802&803
+				     default on, 807&810, default off.  */
+
+#ifdef INCLUDE_BRANCH_STUB
+static int do_use_branchstub = -1;
+#else
+static int do_use_branchstub = 0;
+#endif
+
+/* These are only used for options parsing.  Values are bitmasks and are
+   OR'ed into the processor flag bits in md_begin.  */
+static int do_opt_mmp = 0;
+static int do_opt_mcp = 0;
+static int do_opt_mcache = 0;
+static int do_opt_msecurity = 0;
+static int do_opt_mhard_float = 0;
+static int do_opt_mtrust = 0;
+static int do_opt_mdsp = 0;
+static int do_opt_medsp = 0;
+static int do_opt_mvdsp = 0;
+
+const relax_typeS *md_relax_table = NULL;
+struct literal * literal_insn_offset;
+static struct literal litpool [MAX_POOL_SIZE];
+static struct literal litpool_tls [MAX_POOL_SIZE*4];
+static unsigned poolsize = 0;
+static unsigned poolnumber = 0;
+static unsigned long poolspan = 0;
+static unsigned  count_tls = 0;
+static unsigned int SPANPANIC;
+static unsigned int SPANCLOSE;
+static unsigned int SPANEXIT;
+
+static stack_size_entry *all_stack_size_data = NULL;
+static stack_size_entry **last_stack_size_data = &all_stack_size_data;
+
+/* Control by ".no_literal_dump N"
+ * 1 : don't dump literal pool between insn1 and insnN+1
+ * 0 : do nothing.  */
+static int do_noliteraldump = 0;
+
+/* Label for current pool.  */
+static symbolS * poolsym;
+static char poolname[8];
+
+static bfd_boolean mov_r1_before;
+static bfd_boolean mov_r1_after;
+
+const relax_typeS csky_relax_table [] =
+{
+  /* C-SKY V1 relax table.  */
+  {0, 0, 0, 0},                                   /* RELAX_NONE      */
+  {0, 0, 0, 0},                                   /* RELAX_OVERFLOW  */
+  {0, 0, 0, 0},
+  {0, 0, 0, 0},
+
+  /* COND_JUMP */
+  {    0,     0, 0,       0 },                     /* UNDEF_DISP */
+  { 2048, -2046, C12_LEN, C (COND_JUMP, DISP32) }, /* DISP12 */
+  {    0,     0, C32_LEN, 0 },                     /* DISP32 */
+  {    0,     0, C32_LEN, 0 },                     /* UNDEF_WORD_DISP */
+
+  /* UNCD_JUMP */
+  {    0,     0, 0,       0 },                     /* UNDEF_DISP */
+  { 2048, -2046, U12_LEN, C (UNCD_JUMP, DISP32) }, /* DISP12 */
+  {    0,     0, U32_LEN, 0 },                     /* DISP32 */
+  {    0,     0, U32_LEN, 0 },                     /* UNDEF_WORD_DISP */
+
+  /* COND_JUMP_PIC */
+  {    0,     0, 0,           0 },                     /* UNDEF_DISP */
+  { 2048, -2046, C12_LEN, C (COND_JUMP_PIC, DISP32) }, /* DISP12 */
+  {    0,     0, C32_LEN_PIC, 0 },                     /* DISP32 */
+  {    0,     0, C32_LEN_PIC, 0 },                     /* UNDEF_WORD_DISP */
+
+  /* UNCD_JUMP_PIC */
+  {    0,     0, 0,           0 },                     /* UNDEF_DISP */
+  { 2048, -2046, U12_LEN, C (UNCD_JUMP_PIC, DISP32) }, /* DISP12 */
+  {    0,     0, U32_LEN_PIC, 0 },                     /* DISP32 */
+  {    0,     0, U32_LEN_PIC, 0 },                     /* UNDEF_WORD_DISP */
+
+  /* C-SKY V2 relax table.  */
+  /* forward  backward      length          more     */
+  {  1 KB - 2,  -1 KB, COND_DISP10_LEN,   COND_DISP16    }, /* COND_DISP10 */
+  { 64 KB - 2, -64 KB, COND_DISP16_LEN,   RELAX_OVERFLOW }, /* COND_DISP16 */
+
+  {  1 KB - 2,  -1 KB, SCOND_DISP10_LEN,  SCOND_DISP16   }, /* SCOND_DISP10 */
+  { 64 KB - 2, -64 KB, SCOND_DISP16_LEN,  RELAX_OVERFLOW }, /* SCOND_DISP16 */
+
+  {  1 KB - 2,  -1 KB, UNCD_DISP10_LEN,   UNCD_DISP16    }, /* UNCD_DISP10 */
+  { 64 KB - 2, -64 KB, UNCD_DISP16_LEN,   RELAX_OVERFLOW }, /* UNCD_DISP16 */
+
+  {  1 KB - 2,  -1 KB, JCOND_DISP10_LEN,  JCOND_DISP16   }, /* JCOND_DISP10 */
+  { 64 KB - 2, -64 KB, JCOND_DISP16_LEN,  JCOND_DISP32   }, /* JCOND_DISP16 */
+  {         0,      0, JCOND_DISP32_LEN,  RELAX_NONE     }, /* JCOND_DISP32 */
+
+  {  1 KB - 2,  -1 KB, JUNCD_DISP10_LEN,  JUNCD_DISP16   }, /* JUNCD_DISP10 */
+  { 64 KB - 2, -64 KB, JUNCD_DISP16_LEN,  JUNCD_DISP32   }, /* JUNCD_DISP16 */
+  {         0,      0, JUNCD_DISP32_LEN,  RELAX_NONE     }, /* JUNCD_DISP32 */
+
+  { 64 KB - 2, -64 KB, JCOMPZ_DISP16_LEN, JCOMPZ_DISP32  }, /* JCOMPZ_DISP16 */
+  {         0,      0, JCOMPZ_DISP32_LEN, RELAX_NONE     }, /* JCOMPZ_DISP32 */
+
+  { 64 MB - 2, -64 MB, BSR_DISP26_LEN,    RELAX_OVERFLOW }, /* BSR_DISP26 */
+
+  {       508,      0, LRW_DISP7_LEN,     LRW_DISP16     }, /* LRW_DISP7 */
+  {      1016,      0, LRW_DISP7_LEN,     LRW_DISP16     }, /* LRW2_DISP8 */
+  {     64 KB,      0, LRW_DISP16_LEN,    RELAX_OVERFLOW }, /* LRW_DISP16 */
+
+};
+
+static void csky_write_insn (char *ptr, valueT use, int nbytes);
+void md_number_to_chars (char * buf, valueT val, int n);
+long md_pcrel_from_section (fixS * fixP, segT seg);
+
+/* C-SKY architecture table.  */
+const struct csky_arch_info csky_archs[] =
+{
+  {"ck510",  CSKY_ARCH_510,  bfd_mach_ck510},
+  {"ck610",  CSKY_ARCH_610,  bfd_mach_ck610},
+  {"ck801",  CSKY_ARCH_801,  bfd_mach_ck801},
+  {"ck802",  CSKY_ARCH_802,  bfd_mach_ck802},
+  {"ck803",  CSKY_ARCH_803,  bfd_mach_ck803},
+#define CSKY_ARCH_807_BASE    CSKY_ARCH_807 | CSKY_ARCH_DSP
+#define CSKY_ARCH_810_BASE    CSKY_ARCH_810 | CSKY_ARCH_DSP
+  {"ck807",  CSKY_ARCH_807_BASE,  bfd_mach_ck807},
+  {"ck810",  CSKY_ARCH_810_BASE,  bfd_mach_ck810},
+  {NULL, 0, 0}
+};
+
+/* C-SKY cpus table.  */
+const struct csky_cpu_info csky_cpus[] =
+{
+  /* CK510 series.  */
+#define CSKYV1_ISA_DSP   CSKY_ISA_DSP | CSKY_ISA_MAC_DSP
+  {"ck510",  CSKY_ARCH_510, CSKYV1_ISA_E1},
+  {"ck510e", CSKY_ARCH_510 | CSKY_ARCH_DSP, CSKYV1_ISA_E1 | CSKYV1_ISA_DSP},
+  {"ck520",  CSKY_ARCH_510 | CSKY_ARCH_MAC, CSKYV1_ISA_E1 | CSKY_ISA_MAC | CSKY_ISA_MAC_DSP},
+
+#define CSKY_ISA_610          CSKYV1_ISA_E1 | CSKY_ISA_CP
+  /* CK610 series.  */
+  {"ck610",  CSKY_ARCH_610, CSKY_ISA_610},
+  {"ck610e", CSKY_ARCH_610 | CSKY_ARCH_DSP, CSKY_ISA_610 | CSKYV1_ISA_DSP},
+  {"ck610f", CSKY_ARCH_610 | CSKY_ARCH_FLOAT, CSKY_ISA_610 | CSKY_ISA_FLOAT_E1},
+  {"ck610ef", CSKY_ARCH_610 | CSKY_ARCH_FLOAT | CSKY_ARCH_DSP, CSKY_ISA_610 | CSKY_ISA_FLOAT_E1 | CSKYV1_ISA_DSP},
+  {"ck610fe", CSKY_ARCH_610 | CSKY_ARCH_FLOAT | CSKY_ARCH_DSP, CSKY_ISA_610 | CSKY_ISA_FLOAT_E1 | CSKYV1_ISA_DSP},
+  {"ck620",  CSKY_ARCH_610 | CSKY_ARCH_MAC, CSKY_ISA_610 | CSKY_ISA_MAC | CSKY_ISA_MAC_DSP},
+
+  /* CK801 series.  */
+#define CSKY_ISA_801    CSKYV2_ISA_E1
+#define CSKYV2_ISA_DSP  (CSKY_ISA_DSP | CSKY_ISA_DSP_1E2)
+  {"ck801", CSKY_ARCH_801, CSKY_ISA_801},
+  {"ck801t", CSKY_ARCH_801, CSKY_ISA_801 | CSKY_ISA_TRUST},
+
+  /* CK802 series.  */
+#define CSKY_ISA_802    (CSKY_ISA_801 | CSKYV2_ISA_1E2 | CSKY_ISA_NVIC)
+  {"ck802", CSKY_ARCH_802, CSKY_ISA_802},
+  {"ck802j", CSKY_ARCH_802 | CSKY_ARCH_JAVA, CSKY_ISA_802 | CSKY_ISA_JAVA},
+  {"ck802t", CSKY_ARCH_802, CSKY_ISA_802 | CSKY_ISA_TRUST},
+
+  /* CK803 series.  */
+#define CSKY_ISA_803    (CSKY_ISA_802 | CSKYV2_ISA_2E3 | CSKY_ISA_MP)
+#define CSKY_ISA_803R1  (CSKY_ISA_803 | CSKYV2_ISA_3E3R1)
+#define CSKY_ISA_FLOAT_803 (CSKY_ISA_FLOAT_E1 | CSKY_ISA_FLOAT_1E3)
+  {"ck803", CSKY_ARCH_803, CSKY_ISA_803 },
+  {"ck803h", CSKY_ARCH_803, CSKY_ISA_803 },
+  {"ck803t", CSKY_ARCH_803, CSKY_ISA_803 | CSKY_ISA_TRUST},
+  {"ck803ht", CSKY_ARCH_803, CSKY_ISA_803 | CSKY_ISA_TRUST},
+  {"ck803f", CSKY_ARCH_803 | CSKY_ARCH_FLOAT, CSKY_ISA_803 | CSKY_ISA_FLOAT_803},
+  {"ck803fh", CSKY_ARCH_803 | CSKY_ARCH_FLOAT, CSKY_ISA_803 | CSKY_ISA_FLOAT_803},
+  {"ck803e", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803 | CSKYV2_ISA_DSP},
+  {"ck803eh", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803 | CSKYV2_ISA_DSP},
+  {"ck803et", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803 | CSKYV2_ISA_DSP | CSKY_ISA_TRUST},
+  {"ck803eht", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803 | CSKYV2_ISA_DSP | CSKY_ISA_TRUST},
+  {"ck803ef", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803 | CSKYV2_ISA_DSP | CSKY_ISA_FLOAT_803},
+  {"ck803efh", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803 | CSKYV2_ISA_DSP | CSKY_ISA_FLOAT_803},
+  {"ck803ft", CSKY_ARCH_803 | CSKY_ARCH_FLOAT, CSKY_ISA_803 | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
+  {"ck803eft", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803 | CSKYV2_ISA_DSP | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
+  {"ck803efht", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803 | CSKYV2_ISA_DSP | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
+  {"ck803r1", CSKY_ARCH_803, CSKY_ISA_803R1 },
+  {"ck803hr1", CSKY_ARCH_803, CSKY_ISA_803R1 },
+  {"ck803tr1", CSKY_ARCH_803, CSKY_ISA_803R1 | CSKY_ISA_TRUST},
+  {"ck803htr1", CSKY_ARCH_803, CSKY_ISA_803R1 | CSKY_ISA_TRUST},
+  {"ck803fr1", CSKY_ARCH_803 | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKY_ISA_FLOAT_803},
+  {"ck803fhr1", CSKY_ARCH_803 | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKY_ISA_FLOAT_803},
+  {"ck803er1", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803R1 | CSKY_ISA_DSP_ENHANCE},
+  {"ck803ehr1", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803R1 | CSKY_ISA_DSP_ENHANCE},
+  {"ck803etr1", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803R1 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_TRUST},
+  {"ck803ehtr1", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803R1 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_TRUST},
+  {"ck803efr1", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_FLOAT_803},
+  {"ck803efhr1", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_FLOAT_803},
+  {"ck803ftr1", CSKY_ARCH_803 | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
+  {"ck803eftr1", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
+  {"ck803ehftr1", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKY_ISA_DSP_ENHANCE | CSKY_ISA_FLOAT_803 | CSKY_ISA_TRUST},
+
+  {"ck803s", CSKY_ARCH_803, CSKY_ISA_803R1 },
+  {"ck803se", CSKY_ARCH_803 | CSKY_ARCH_DSP, CSKY_ISA_803R1 | CSKYV2_ISA_DSP},
+  {"ck803sj", CSKY_ARCH_803 | CSKY_ARCH_JAVA, CSKY_ISA_803R1 | CSKY_ISA_JAVA},
+  {"ck803sf", CSKY_ARCH_803 | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKY_ISA_FLOAT_803},
+  {"ck803sef", CSKY_ARCH_803 | CSKY_ARCH_DSP | CSKY_ARCH_FLOAT, CSKY_ISA_803R1 | CSKYV2_ISA_DSP | CSKY_ISA_FLOAT_803},
+  {"ck803st", CSKY_ARCH_803, CSKY_ISA_803R1 | CSKY_ISA_TRUST},
+
+  /* CK807 series.  */
+#define CSKY_ISA_807    (CSKY_ISA_803 | CSKYV2_ISA_3E7 | CSKY_ISA_DSP | CSKY_ISA_MP_1E2 | CSKY_ISA_CACHE)
+#define CSKY_ISA_FLOAT_807 (CSKY_ISA_FLOAT_803 | CSKY_ISA_FLOAT_3E4 | CSKY_ISA_FLOAT_1E2)
+  {"ck807e", CSKY_ARCH_807_BASE, CSKY_ISA_807 | CSKYV2_ISA_DSP},
+  {"ck807ef", CSKY_ARCH_807_BASE | CSKY_ARCH_FLOAT, CSKY_ISA_807 | CSKYV2_ISA_DSP | CSKY_ISA_FLOAT_807},
+  {"ck807", CSKY_ARCH_807_BASE, CSKY_ISA_807 | CSKYV2_ISA_DSP},
+  {"ck807f", CSKY_ARCH_807_BASE | CSKY_ARCH_FLOAT,  CSKY_ISA_807 | CSKYV2_ISA_DSP | CSKY_ISA_FLOAT_807},
+
+  /* CK810 series.  */
+#define CSKY_ISA_810    (CSKY_ISA_807 | CSKYV2_ISA_7E10)
+#define CSKY_ISA_FLOAT_810 (CSKY_ISA_FLOAT_E1 | CSKY_ISA_FLOAT_1E2)
+  {"ck810e", CSKY_ARCH_810_BASE, CSKY_ISA_810 | CSKYV2_ISA_DSP},
+  {"ck810et", CSKY_ARCH_810_BASE, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_TRUST},
+  {"ck810ef", CSKY_ARCH_810_BASE | CSKY_ARCH_FLOAT, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_FLOAT_810},
+  {"ck810eft", CSKY_ARCH_810_BASE | CSKY_ARCH_FLOAT, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_FLOAT_810 | CSKY_ISA_TRUST},
+  {"ck810", CSKY_ARCH_810_BASE, CSKY_ISA_810 | CSKYV2_ISA_DSP},
+  {"ck810v", CSKY_ARCH_810_BASE, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_VDSP},
+  {"ck810f", CSKY_ARCH_810_BASE | CSKY_ARCH_FLOAT, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_FLOAT_810},
+  {"ck810t", CSKY_ARCH_810_BASE, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_TRUST},
+  {"ck810tv", CSKY_ARCH_810_BASE, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_TRUST},
+  {"ck810ft", CSKY_ARCH_810_BASE | CSKY_ARCH_FLOAT, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_VDSP | CSKY_ISA_FLOAT_810 | CSKY_ISA_TRUST},
+  {"ck810ftv", CSKY_ARCH_810_BASE | CSKY_ARCH_FLOAT, CSKY_ISA_810 | CSKYV2_ISA_DSP | CSKY_ISA_VDSP | CSKY_ISA_FLOAT_810 | CSKY_ISA_TRUST},
+
+  {NULL, 0, 0, NULL}
+};
+
+int md_short_jump_size = 2;
+int md_long_jump_size = 4;
+
+/* This array holds the chars that always start a comment.  If the
+   pre-processor is disabled, these aren't very useful.  */
+const char comment_chars[] = "#";
+
+/* This array holds the chars that only start a comment at the beginning of
+   a line.  If the line seems to have the form '# 123 filename'
+   .line and .file directives will appear in the pre-processed output.  */
+/* Note that input_file.c hand checks for '#' at the beginning of the
+   first line of the input file.  This is because the compiler outputs
+   #NO_APP at the beginning of its output.  */
+/* Also note that comments like this one will always work.  */
+const char line_comment_chars[] = "#";
+
+const char line_separator_chars[] = ";";
+
+/* Chars that can be used to separate mant
+   from exp in floating point numbers.  */
+const char EXP_CHARS[] = "eE";
+
+/* Chars that mean this number is a floating point constant.
+   As in 0f12.456
+   or   0d1.2345e12  */
+
+const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
+
+const char *md_shortopts = "";
+
+struct option md_longopts[] = {
+#define OPTION_MARCH (OPTION_MD_BASE + 0)
+  {"march", required_argument, NULL, OPTION_MARCH},
+#define OPTION_MCPU (OPTION_MD_BASE + 1)
+  {"mcpu", required_argument, NULL, OPTION_MCPU},
+
+  /* Remaining options just set boolean flags.  */
+  {"EL", no_argument, &target_big_endian, 0},
+  {"mlittle-endian", no_argument, &target_big_endian, 0},
+  {"EB", no_argument, &target_big_endian, 1},
+  {"mbig-endian", no_argument, &target_big_endian, 1},
+  {"fpic", no_argument, &do_pic, 1},
+  {"pic", no_argument, &do_pic, 1},
+  {"mljump", no_argument, &do_long_jump, 1},
+  {"mno-ljump", no_argument, &do_long_jump, 0},
+  {"force2bsr", no_argument, &do_force2bsr, 1},
+  {"mforce2bsr", no_argument, &do_force2bsr, 1},
+  {"no-force2bsr", no_argument, &do_force2bsr, 0},
+  {"mno-force2bsr", no_argument, &do_force2bsr, 0},
+  {"jsri2bsr", no_argument, &do_jsri2bsr, 1},
+  {"mjsri2bsr", no_argument, &do_jsri2bsr, 1},
+  {"no-jsri2bsr", no_argument, &do_jsri2bsr, 0},
+  {"mno-jsri2bsr", no_argument, &do_jsri2bsr, 0},
+  {"mnolrw", no_argument, &do_nolrw, 1},
+  {"mno-lrw", no_argument, &do_nolrw, 1},
+  {"melrw", no_argument, &do_extend_lrw, 1},
+  {"mno-elrw", no_argument, &do_extend_lrw, 0},
+  {"mlaf", no_argument, &do_func_dump, 1},
+  {"mliterals-after-func", no_argument, &do_func_dump, 1},
+  {"mno-laf", no_argument, &do_func_dump, 0},
+  {"mno-literals-after-func", no_argument, &do_func_dump, 0},
+  {"mlabr", no_argument, &do_br_dump, 1},
+  {"mliterals-after-br", no_argument, &do_br_dump, 1},
+  {"mno-labr", no_argument, &do_br_dump, 0},
+  {"mnoliterals-after-br", no_argument, &do_br_dump, 0},
+  {"mistack", no_argument, &do_intr_stack, 1},
+  {"mno-istack", no_argument, &do_intr_stack, 0},
+#ifdef INCLUDE_BRANCH_STUB
+  {"mbranch-stub", no_argument, &do_use_branchstub, 1},
+  {"mno-branch-stub", no_argument, &do_use_branchstub, 0},
+#endif
+  {"mhard-float", no_argument, &do_opt_mhard_float, CSKY_ARCH_FLOAT},
+  {"mmp", no_argument, &do_opt_mmp, CSKY_ARCH_MP},
+  {"mcp", no_argument, &do_opt_mcp, CSKY_ARCH_CP},
+  {"mcache", no_argument, &do_opt_mcache, CSKY_ARCH_CACHE},
+  {"msecurity", no_argument, &do_opt_msecurity, CSKY_ARCH_MAC},
+  {"mtrust", no_argument, &do_opt_mtrust, CSKY_ISA_TRUST},
+  {"mdsp", no_argument, &do_opt_mdsp, CSKY_DSP_FLAG_V1},
+  {"medsp", no_argument, &do_opt_medsp, CSKY_DSP_FLAG_V2},
+  {"mvdsp", no_argument, &do_opt_mvdsp, CSKY_ISA_VDSP},
+};
+
+size_t md_longopts_size = sizeof (md_longopts);
+
+static struct csky_insn_info csky_insn;
+
+static struct hash_control *csky_opcodes_hash;
+static struct hash_control *csky_macros_hash;
+
+static struct csky_macro_info v1_macros_table[] =
+{
+  {"idly",   1, CSKYV1_ISA_E1, csky_idly},
+  {"rolc",   2, CSKYV1_ISA_E1, csky_rolc},
+  {"rotlc",  2, CSKYV1_ISA_E1, csky_rolc},
+  {"sxtrb0", 2, CSKYV1_ISA_E1, csky_sxtrb},
+  {"sxtrb1", 2, CSKYV1_ISA_E1, csky_sxtrb},
+  {"sxtrb2", 2, CSKYV1_ISA_E1, csky_sxtrb},
+  {"movtf",  3, CSKYV1_ISA_E1, csky_movtf},
+  {"addc64", 3, CSKYV1_ISA_E1, csky_addc64},
+  {"subc64", 3, CSKYV1_ISA_E1, csky_subc64},
+  {"or64",   3, CSKYV1_ISA_E1, csky_or64},
+  {"xor64",  3, CSKYV1_ISA_E1, csky_xor64},
+  {NULL,0,0,0}
+};
+
+static struct csky_macro_info v2_macros_table[] =
+{
+  {"neg",   1, CSKYV2_ISA_E1,  csky_neg},
+  {"rsubi", 2, CSKYV2_ISA_1E2, csky_rsubi},
+  {"incf",  1, CSKYV2_ISA_1E2, csky_arith},
+  {"inct",  1, CSKYV2_ISA_1E2, csky_arith},
+  {"decf",  1, CSKYV2_ISA_2E3, csky_arith},
+  {"decgt", 1, CSKYV2_ISA_2E3, csky_arith},
+  {"declt", 1, CSKYV2_ISA_2E3, csky_arith},
+  {"decne", 1, CSKYV2_ISA_1E2, csky_decne},
+  {"dect",  1, CSKYV2_ISA_1E2, csky_arith},
+  {"lslc",  1, CSKYV2_ISA_1E2, csky_arith},
+  {"lsrc",  1, CSKYV2_ISA_1E2, csky_arith},
+  {"xsr",   1, CSKYV2_ISA_1E2, csky_arith},
+  {NULL,0,0,0}
+};
+
+/* For option -mnolrw, replace lrw by movih & ori.  */
+static struct csky_macro_info v2_lrw_macro_opcode =
+  {"lrw", 2, CSKYV2_ISA_1E2, csky_lrw};
+
+/* This function is used to show errors or warnings.  */
+
+static void
+csky_show_error (enum error_number err, int idx, void *arg1, void *arg2)
+{
+  if (err == ERROR_NONE)
+    return;
+
+  switch (err)
+    {
+    case ERROR_REG_LIST:
+    case ERROR_OPCODE_PSRBIT:
+    case ERROR_OPCODE_ILLEGAL:
+    case ERROR_JMPIX_OVER_RANGE:
+    case ERROR_MISSING_COMMA:
+    case ERROR_MISSING_LBRACKET:
+    case ERROR_MISSING_RBRACKET:
+    case ERROR_MISSING_LSQUARE_BRACKETS:
+    case ERROR_MISSING_RSQUARE_BRACKETS:
+    case ERROR_MISSING_LANGLE_BRACKETS:
+    case ERROR_MISSING_RANGLE_BRACKETS:
+      /* Add NULL to fix warnings.  */
+      as_bad (err_formats[err].fmt, NULL);
+      break;
+    case ERROR_CREG_ILLEGAL:
+    case ERROR_GREG_ILLEGAL:
+    case ERROR_IMM_ILLEGAL:
+    case ERROR_IMM_OVERFLOW:
+    case ERROR_EXP_CREG:
+    case ERROR_EXP_GREG:
+    case ERROR_EXP_CONSTANT:
+    case ERROR_EXP_EVEN_FREG:
+    case ERROR_MISSING_OPERAND:
+    case ERROR_CPREG_ILLEGAL:
+      as_bad (err_formats[err].fmt, idx);
+      break;
+    case ERROR_OPERANDS_NUMBER:
+    case ERROR_IMM_POWER:
+      as_bad (err_formats[err].fmt, (long)arg1);
+      break;
+      
+    case ERROR_OFFSET_UNALIGNED:
+      as_bad (err_formats[err].fmt, idx, (long)arg1);
+      break;
+    case ERROR_RELOC_ILLEGAL:
+    case ERROR_BAD_END:
+    case ERROR_OPERANDS_ILLEGAL:
+      as_bad (err_formats[err].fmt, (char *)arg1);
+      break;
+    case ERROR_REG_OVER_RANGE:
+      as_bad (err_formats[err].fmt, idx, (long) arg1);
+      break;
+    case ERROR_802J_REG_OVER_RANGE:
+    case ERROR_REG_FORMAT:
+      as_bad (err_formats[err].fmt, idx, (char *)arg1);
+      break;
+    case ERROR_UNDEFINE:
+      /* Add NULL to fix warnings.  */
+      as_bad ((char *)arg1, NULL);
+      break;
+    case WARNING_IDLY:
+      as_warn (err_formats[err].fmt, (long)arg1);
+    case WARNING_OPTIONS:
+      as_warn (err_formats[err].fmt, (char *)arg1, (char *)arg2);
+    default:
+      break;
+    }
+}
+
+/* Handle errors in branch relaxation.  */
+static void
+csky_branch_report_error (const char* file, unsigned int line,
+			  symbolS* sym, offsetT val)
+{
+  as_bad_where (file ? file : _("unknown"),
+		line,
+		_("pcrel offset for branch to %s too far (0x%lx)"),
+		sym ? S_GET_NAME (sym) : _("<unknown>"),
+		(long) val);
+}
+
+/* Set appropriate flags for the cpu matching STR.  */
+
+static void
+parse_cpu (const char *str)
+{
+  int i = 0;
+
+  for (; csky_cpus[i].name != NULL; i++)
+    if (strcasecmp (str, csky_cpus[i].name) == 0)
+      {
+	mach_flag |= csky_cpus[i].mach_flag;
+	isa_flag = csky_cpus[i].isa_flag;
+	other_flag |= (csky_cpus[i].mach_flag & ~CSKY_ARCH_MASK);
+	return;
+      }
+  as_bad (_("unknown CPU '%s'"), str);
+}
+
+/* Set appropriate flags for the arch matching STR.  */
+static void
+parse_arch (const char *str)
+{
+  int i = 0;
+  for (; csky_archs[i].name != NULL; i++)
+    if (strcasecmp (str, csky_archs[i].name) == 0)
+      {
+	arch_flag |= csky_archs[i].arch_flag;
+	return;
+      }
+  as_bad (_("unknown architecture '%s'"), str);
+}
+
+
+/* Implement the TARGET_FORMAT macro.  */
+#ifdef OBJ_ELF
+const char *
+elf32_csky_target_format (void)
+{
+  return (target_big_endian
+	  ? "elf32-csky-big"
+	  : "elf32-csky-little");
+}
+#endif
+
+/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
+   for use in the a.out file, and stores them in the array pointed to by buf.
+   This knows about the endian-ness of the target machine and does
+   THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
+   2 (short) and 4 (long)  Floating numbers are put out as a series of
+   LITTLENUMS (shorts, here at least).  */
+
+void
+md_number_to_chars (char * buf, valueT val, int n)
+{
+  if (target_big_endian)
+    number_to_chars_bigendian (buf, val, n);
+  else
+    number_to_chars_littleendian (buf, val, n);
+}
+
+/* Get a log2(val).  */
+static int
+csky_log_2 (unsigned int val)
+{
+    int log = -1;
+    if ((val & (val - 1)) == 0)
+      for (; val; val >>= 1)
+	log ++;
+    else
+      csky_show_error (ERROR_IMM_POWER, 0, (void *)(long)val, NULL);
+    return log;
+}
+
+/* Output one instruction to the buffer at PTR.  */
+static void
+csky_write_insn (char *ptr, valueT use, int nbytes)
+{
+  if (nbytes == 2)
+    md_number_to_chars (ptr, use, nbytes);
+  else  /* 32-bit instruction.  */
+    {
+      /* Significant figures are in low bits.*/
+      md_number_to_chars (ptr, use >> 16, 2);
+      md_number_to_chars (ptr + 2, use & 0xFFFF, 2);
+    }
+}
+
+/* Read an NBYTES instruction from the buffer at PTR.  NBYTES should
+   be either 2 or 4.  This function is used in branch relaxation.  */
+static valueT
+csky_read_insn (char *ptr, int nbytes)
+{
+  unsigned char *uptr = (unsigned char *)ptr;
+  valueT v = 0;
+  int lo, hi;   /* hi/lo byte index in binary stream.  */
+
+  if (target_big_endian)
+    {
+      hi = 0;
+      lo = 1;
+    }
+  else
+    {
+      hi = 1;
+      lo = 0;
+    }
+  v = uptr[lo] | (uptr[hi] << 8);
+  if (nbytes == 4)
+    {
+      v <<= 16;
+      v |=  uptr[lo + 2] | (uptr[hi + 2] << 8);
+    }
+  return v;
+}
+
+/* Construct a label name into S from the 3-character prefix P and
+   number N formatted as a 4-digit hex number.  */
+static void
+make_internal_label (char *s, const char *p, int n)
+{
+  static const char hex[] = "0123456789ABCDEF";
+
+  s[0] = p[0];
+  s[1] = p[1];
+  s[2] = p[2];
+  s[3] = hex[(n >> 12) & 0xF];
+  s[4] = hex[(n >>  8) & 0xF];
+  s[5] = hex[(n >>  4) & 0xF];
+  s[6] = hex[(n)       & 0xF];
+  s[7] = 0;
+}
+
+/* md_operand is a no-op on C-SKY; we do everything elsewhere.  */
+void
+md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
+{
+  return;
+}
+
+/* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
+   Otherwise we have no need to default values of symbols.  */
+
+symbolS *
+md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
+{
+#ifdef OBJ_ELF
+  /* TODO:  */
+#endif
+  return NULL;
+}
+
+
+/* Use IEEE format for floating-point constants.  */
+const char *
+md_atof (int type, char *litP, int *sizeP)
+{
+  return ieee_md_atof (type, litP, sizeP, target_big_endian);
+}
+
+
+/* Print option help to FP.  */
+void
+md_show_usage (FILE *fp)
+{
+  int i, n;
+  const int margin = 48;
+
+  fprintf (fp, "\nC-SKY options:\n");
+
+  fprintf (fp, "\
+  -march=ARCH			select architecture ARCH:");
+  for (i = 0, n = margin; csky_archs[i].name != NULL; i++)
+    {
+      int l = strlen (csky_archs[i].name);
+      if (n + l >= margin)
+	{
+	  fprintf (fp, "\n\t\t\t\t");
+	  n = l;
+	}
+      else
+	{
+	  fprintf (fp, " ");
+	  n += l + 1;
+	}
+      fprintf (fp, "%s", csky_archs[i].name);
+    }
+  fprintf (fp, "\n");
+
+  fprintf (fp, "\
+  -mcpu=CPU			select processor CPU:");
+  for (i = 0, n = margin; csky_cpus[i].name != NULL; i++)
+    {
+      int l = strlen (csky_cpus[i].name);
+      if (n + l >= margin)
+	{
+	  fprintf (fp, "\n\t\t\t\t");
+	  n = l;
+	}
+      else
+	{
+	  fprintf (fp, " ");
+	  n += l + 1;
+	}
+      fprintf (fp, "%s", csky_cpus[i].name);
+    }
+  fprintf (fp, "\n");
+
+  fprintf (fp, "\
+  -EL  -mlittle-endian		generate little-endian output\n\
+  -EB  -mbig-endian		generate big-endian output\n\
+  -fpic  -pic			generate position-independent code\n");
+
+  fprintf (fp, "\
+  -mljump			transform jbf, jbt, jbr to jmpi (CK800 only)\n\
+  -mno-ljump\n");
+
+#ifdef INCLUDE_BRANCH_STUB
+  fprintf (fp, "\
+  -mbranch-stub			enable branch stubs for PC-relative calls\n\
+  -mno-branch-stub\n");
+#endif
+
+  fprintf (fp, "\
+  -force2bsr  -mforce2bsr	transform jbsr to bsr\n\
+  -no-force2bsr  -mno-force2bsr\n\
+  -jsri2bsr  -mjsri2bsr		transform jsri to bsr\n\
+  -no-jsri2bsr  -mno-jsri2bsr\n");
+
+  fprintf (fp, "\
+  -mnolrw  -mno-lrw		implement lrw as movih + ori\n\
+  -melrw			enable extended lrw (CK800 only)\n\
+  -mno-elrw\n");
+
+  fprintf (fp, "\
+  -mlaf  -mliterals-after-func	emit literals after each function\n\
+  -mno-laf  -mno-literals-after-func\n\
+  -mlabr  -mliterals-after-br	emit literals after branch instructions\n\
+  -mno-labr  -mnoliterals-after-br\n");
+
+  fprintf (fp, "\
+  -mistack			enable interrupt stack instructions\n\
+  -mno-istack\n");
+
+  fprintf (fp, "\
+  -mhard-float			enable hard float instructions\n\
+  -mmp				enable multiprocessor instructions\n\
+  -mcp				enable coprocessor instructions\n\
+  -mcache			enable cache prefetch instruction\n\
+  -msecurity			enable security instructions\n\
+  -mtrust			enable trust instructions\n\
+  -mdsp				enable DSP instructions\n\
+  -medsp			enable enhanced DSP instructions\n\
+  -mvdsp			enable vector DSP instructions\n");
+}
+
+
+/* Target-specific initialization and option handling.  */
+void
+md_begin (void)
+{
+  unsigned int bfd_mach_flag = 0;
+  struct csky_opcode const *opcode;
+  struct csky_macro_info const *macro;
+  struct csky_arch_info const *p_arch;
+  struct csky_cpu_info const *p_cpu;
+  unsigned int flags = (other_flag | do_opt_mmp | do_opt_mcp | do_opt_mcache
+			| do_opt_msecurity | do_opt_mhard_float);
+  dsp_flag |= do_opt_mdsp | do_opt_medsp;
+  isa_flag |= do_opt_mtrust | do_opt_mvdsp;
+
+  if (dsp_flag)
+    flags |= CSKY_ARCH_DSP;
+
+  if (mach_flag != 0)
+    {
+      if ((mach_flag & CSKY_ARCH_MASK) != arch_flag && arch_flag != 0)
+	as_warn ("-mcpu conflict with -march option, actually use -mcpu");
+      if ((mach_flag & ~CSKY_ARCH_MASK) != flags && flags != 0)
+	as_warn ("-mcpu conflict with other model parameters, actually use -mcpu");
+    }
+  else if (arch_flag != 0)
+    mach_flag |= arch_flag | flags;
+  else
+    {
+#ifdef TARGET_WITH_CPU
+      int i = 0;
+      for (; csky_cpus[i].name != NULL; i++)
+	{
+	  if (strcmp (TARGET_WITH_CPU, csky_cpus[i].name) == 0)
+	    {
+	      mach_flag |= csky_cpus[i].mach_flag;
+	      isa_flag = csky_cpus[i].isa_flag;
+	      break;
+	    }
+	}
+#else
+#if _CSKY_ABI==1
+      mach_flag |= CSKY_ARCH_610 | flags;
+#else
+      mach_flag |= CSKY_ARCH_810_BASE | flags;
+#endif
+#endif
+    }
+
+  if (IS_CSKY_ARCH_610 (mach_flag) || IS_CSKY_ARCH_510 (mach_flag))
+    {
+      if ((mach_flag & CSKY_ARCH_MP) && (mach_flag & CSKY_ARCH_MAC))
+	as_fatal ("520/620 conflicts with -mmp option");
+      else if ((mach_flag & CSKY_ARCH_MP) && (mach_flag & CSKY_ARCH_DSP))
+	as_fatal ("510e/610e conflicts with -mmp option");
+      else if ((mach_flag & CSKY_ARCH_DSP) && (mach_flag & CSKY_ARCH_MAC))
+	as_fatal ("520/620 conflicts with 510e/610e or -mdsp option");
+    }
+  if (IS_CSKY_ARCH_510 (mach_flag) && (mach_flag & CSKY_ARCH_FLOAT))
+    {
+      mach_flag = (mach_flag & (~CSKY_ARCH_MASK));
+      mach_flag |= CSKY_ARCH_610;
+    }
+
+  /* Find bfd_mach_flag, it will set to bfd backend data.  */
+  for (p_arch = csky_archs; p_arch->arch_flag != 0; p_arch++)
+    if ((mach_flag & CSKY_ARCH_MASK) == (p_arch->arch_flag & CSKY_ARCH_MASK))
+      {
+	bfd_mach_flag =  p_arch->bfd_mach_flag;
+	break;
+      }
+
+  /* Find isa_flag.  */
+  for (p_cpu = csky_cpus; p_cpu->mach_flag != 0; p_cpu++)
+    if ((mach_flag & CPU_ARCH_MASK) == p_cpu->mach_flag)
+      {
+	isa_flag |= p_cpu->isa_flag;
+	break;
+      }
+
+  /* Check if -mdsp and -medsp conflict. If cpu is ck803, we will
+     use enhanced dsp instruction. Otherwise, we will use normal dsp.  */
+  if (dsp_flag)
+    {
+      if (IS_CSKY_ARCH_803 (mach_flag))
+	{
+	  /* In 803, dspv1 is conflict with dspv2. We keep dspv2.  */
+	  if ((dsp_flag & CSKY_DSP_FLAG_V1) && (dsp_flag & CSKY_DSP_FLAG_V2))
+	    as_warn ("Option -mdsp conflicts with -medsp, only enabling -medsp");
+	  isa_flag &= ~(CSKY_ISA_MAC_DSP | CSKY_ISA_DSP);
+	  isa_flag |= CSKY_ISA_DSP_ENHANCE;
+	}
+      else
+	{
+	  isa_flag &= ~CSKY_ISA_DSP_ENHANCE;
+	  as_warn ("-medsp option is only supported by ck803s, ignoring -medsp");
+	}
+      ;
+    }
+
+  if (do_use_branchstub == -1)
+    do_use_branchstub = !IS_CSKY_ARCH_V1 (mach_flag);
+  else if (do_use_branchstub == 1)
+    {
+      if (IS_CSKY_ARCH_V1 (mach_flag))
+	{
+	  as_warn ("csky abiv1 (ck510/ck610) does not support -mbranch-stub.");
+	  do_use_branchstub = 0;
+	}
+      else if (do_force2bsr == 0)
+	{
+	  as_warn ("-mno-force2bsr is ignored with -mbranch-stub");
+	  do_force2bsr = 1;
+	}
+    }
+
+  if (IS_CSKY_ARCH_801 (mach_flag) || IS_CSKY_ARCH_802 (mach_flag))
+    {
+      if (!do_force2bsr)
+	as_warn ("-mno-force2bsr is ignored for ck801/ck802");
+      do_force2bsr = 1;
+    }
+  else if (do_force2bsr == -1)
+    do_force2bsr = do_use_branchstub;
+
+  if (do_pff == -1)
+    {
+      if (IS_CSKY_ARCH_V1 (mach_flag))
+	do_pff = 1;
+      else
+	do_pff = 0;
+    }
+
+  if (do_extend_lrw == -1)
+    {
+      if (IS_CSKY_ARCH_801 (mach_flag))
+	do_extend_lrw = 1;
+      else
+	do_extend_lrw = 0;
+    }
+  if (do_intr_stack == -1)
+    {
+      /* control interrupt stack module, 801&802&803 default on
+	 807&810, default off.  */
+      if (IS_CSKY_ARCH_807 (mach_flag) || IS_CSKY_ARCH_810 (mach_flag))
+	do_intr_stack = 0;
+      else
+	do_intr_stack = 1;
+    }
+  /* TODO: add isa_flag(SIMP/CACHE/APS).  */
+  isa_flag |= (mach_flag & CSKY_ARCH_MAC) ? CSKY_ISA_MAC : 0;
+  isa_flag |= (mach_flag & CSKY_ARCH_MP) ? CSKY_ISA_MP : 0;
+  isa_flag |= (mach_flag & CSKY_ARCH_CP) ? CSKY_ISA_CP : 0;
+
+  /* Set abi flag and get table address.  */
+  if (IS_CSKY_ARCH_V1 (mach_flag))
+    {
+      mach_flag = mach_flag | CSKY_ABI_V1;
+      opcode = csky_v1_opcodes;
+      macro = v1_macros_table;
+      SPANPANIC = v1_SPANPANIC;
+      SPANCLOSE = v1_SPANCLOSE;
+      SPANEXIT  = v1_SPANEXIT;
+      md_relax_table = csky_relax_table;
+    }
+  else
+    {
+      mach_flag = mach_flag | CSKY_ABI_V2;
+      opcode = csky_v2_opcodes;
+      macro = v2_macros_table;
+      SPANPANIC = v2_SPANPANIC;
+      if (do_extend_lrw)
+	{
+	  SPANCLOSE = v2_SPANCLOSE_ELRW;
+	  SPANEXIT  = v2_SPANEXIT_ELRW;
+	}
+      else
+	{
+	  SPANCLOSE = v2_SPANCLOSE;
+	  SPANEXIT  = v2_SPANEXIT;
+	}
+      md_relax_table = csky_relax_table;
+    }
+
+  /* Establish hash table for opcodes and macros.  */
+  csky_macros_hash = hash_new ();
+  csky_opcodes_hash = hash_new ();
+  for ( ; opcode->mnemonic != NULL; opcode++)
+    if ((isa_flag & (opcode->isa_flag16 | opcode->isa_flag32)) != 0)
+      hash_insert (csky_opcodes_hash, opcode->mnemonic, (char *)opcode);
+  for ( ; macro->name != NULL; macro++)
+    if ((isa_flag & macro->isa_flag) != 0)
+      hash_insert (csky_macros_hash, macro->name, (char *)macro);
+  if (do_nolrw && (isa_flag & CSKYV2_ISA_1E2) != 0)
+    hash_insert (csky_macros_hash,
+		 v2_lrw_macro_opcode.name,
+		 (char *)&v2_lrw_macro_opcode);
+  /* Set e_flag to ELF Head.  */
+  bfd_set_private_flags (stdoutput, mach_flag);
+  /* Set bfd_mach to bfd backend data.  */
+  bfd_set_arch_mach (stdoutput, bfd_arch_csky, bfd_mach_flag);
+}
+
+
+/* The C-SKY assembler emits mapping symbols $t and $d to mark the
+   beginning of a sequence of instructions and data (such as a constant pool),
+   respectively.  This is similar to what ARM does.  */
+
+static void
+make_mapping_symbol (map_state state, valueT value, fragS *frag)
+{
+  symbolS * symbolP;
+  const char * symname;
+  int type;
+  switch (state)
+    {
+    case MAP_DATA:
+      symname = "$d";
+      type = BSF_NO_FLAGS;
+      break;
+    case MAP_TEXT:
+      symname = "$t";
+      type = BSF_NO_FLAGS;
+      break;
+    default:
+      abort ();
+    }
+
+  symbolP = symbol_new (symname, now_seg, value, frag);
+  symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
+}
+
+/* We need to keep track of whether we are emitting code or data; this
+   function switches state and emits a mapping symbol if necessary.  */
+
+static void
+mapping_state (map_state state)
+{
+  map_state current_state
+    = seg_info (now_seg)->tc_segment_info_data.current_state;
+
+  if (current_state == state)
+    return;
+  else if (current_state == MAP_UNDEFINED && state == MAP_DATA)
+    return;
+  else if (current_state == MAP_UNDEFINED && state == MAP_TEXT)
+   {
+     struct frag * const frag_first = seg_info (now_seg)->frchainP->frch_root;
+     if (frag_now != frag_first || frag_now_fix () > 0)
+       make_mapping_symbol (MAP_DATA, (valueT) 0, frag_first);
+   }
+
+  seg_info (now_seg)->tc_segment_info_data.current_state = state;
+  make_mapping_symbol (state, (valueT) frag_now_fix (), frag_now);
+}
+
+/* Dump the literal pool.  */
+static void
+dump_literals (int isforce)
+{
+#define CSKYV1_BR_INSN  0xF000
+#define CSKYV2_BR_INSN  0x0400
+  unsigned int i;
+  struct literal * p;
+  struct literal * p_tls;
+  symbolS * brarsym = NULL;
+
+  /* V1 nop encoding:  0x1200 : mov r0, r0.  */
+  static char v1_nop_insn_big[2] = {0x12, 0x00};
+  static char v1_nop_insn_little[2] = {0x00, 0x12};
+
+  if (poolsize == 0)
+    return;
+
+  /* Must we branch around the literal table?  */
+  if (isforce)
+    {
+      char brarname[8];
+      make_internal_label (brarname, POOL_END_LABEL, poolnumber);
+      brarsym = symbol_make (brarname);
+      symbol_table_insert (brarsym);
+      mapping_state (MAP_TEXT);
+      if (IS_CSKY_ARCH_V1 (mach_flag))
+	{
+	  csky_insn.output
+	    = frag_var (rs_machine_dependent,
+			csky_relax_table[C (UNCD_JUMP_S, DISP32)].rlx_length,
+			csky_relax_table[C (UNCD_JUMP_S, DISP12)].rlx_length,
+			C (UNCD_JUMP_S, 0), brarsym, 0, 0);
+	  md_number_to_chars (csky_insn.output, CSKYV1_BR_INSN, 2);
+	}
+      else
+	{
+	  csky_insn.output
+	    = frag_var (rs_machine_dependent,
+			UNCD_DISP16_LEN,
+			UNCD_DISP10_LEN,
+			UNCD_DISP10,
+			brarsym, 0, 0);
+	  md_number_to_chars (csky_insn.output, CSKYV2_BR_INSN, 2);
+	}
+    }
+  /* Make sure that the section is sufficiently aligned and that
+     the literal table is aligned within it.  */
+  if (do_pff)
+    {
+      valueT br_self;
+      csky_insn.output = frag_more (2);
+      /* .Lxx: br .Lxx  */
+      if (IS_CSKY_V1 (mach_flag))
+	br_self = CSKYV1_BR_INSN | 0x7ff;
+      else
+	br_self = CSKYV2_BR_INSN;
+      md_number_to_chars (csky_insn.output, br_self, 2);
+      if (!isforce)
+	{
+	  csky_insn.output = frag_more (2);
+	  /* .Lxx: br .Lxx  */
+	  md_number_to_chars (csky_insn.output, br_self, 2);
+	}
+    }
+  mapping_state (MAP_DATA);
+
+  record_alignment (now_seg, 2);
+  if (IS_CSKY_ARCH_V1 (mach_flag))
+    frag_align_pattern (2,
+			(target_big_endian
+			 ? v1_nop_insn_big : v1_nop_insn_little),
+			2, 0);
+  else
+    frag_align (2, 0, 3);
+
+  colon (S_GET_NAME (poolsym));
+
+  for (i = 0, p = litpool; i < poolsize; i += (p->isdouble ? 2 : 1), p++)
+    {
+      insn_reloc = p->r_type;
+      if (insn_reloc == BFD_RELOC_CKCORE_TLS_IE32
+	  || insn_reloc == BFD_RELOC_CKCORE_TLS_LDM32
+	  || insn_reloc == BFD_RELOC_CKCORE_TLS_GD32)
+	{
+	  p_tls = litpool_tls + count_tls;
+	  p_tls->tls_addend.frag = p->tls_addend.frag;
+	  p_tls->tls_addend.offset = p->tls_addend.offset;
+	  literal_insn_offset = p_tls;
+	  count_tls++;
+	}
+      if (p->isdouble)
+	{
+	  if (target_big_endian)
+	    {
+	      p->e.X_add_number = p->dbnum >> 32;
+	      emit_expr (& p->e, 4);
+	      p->e.X_add_number = p->dbnum & 0xffffffff;
+	      emit_expr (& p->e, 4);
+	    }
+	  else
+	    {
+	      p->e.X_add_number = p->dbnum & 0xffffffff;
+	      emit_expr (& p->e, 4);
+	      p->e.X_add_number = p->dbnum >> 32;
+	      emit_expr (& p->e, 4);
+	    }
+	}
+      else
+	emit_expr (& p->e, 4);
+    }
+
+  if (isforce && IS_CSKY_ARCH_V2 (mach_flag))
+    {
+      /* Add one nop insn at end of literal for disassembler.  */
+      mapping_state (MAP_TEXT);
+      csky_insn.output = frag_more (2);
+      md_number_to_chars (csky_insn.output, CSKYV2_INST_NOP, 2);
+    }
+
+  insn_reloc = BFD_RELOC_NONE;
+
+  if (brarsym != NULL)
+    colon (S_GET_NAME (brarsym));
+  poolsize = 0;
+}
+
+static int
+enter_literal (expressionS *e,
+	       int ispcrel,
+	       unsigned char isdouble,
+	       uint64_t dbnum)
+{
+  unsigned int i;
+  struct literal * p;
+  if (poolsize >= MAX_POOL_SIZE - 2)
+    {
+      /* The literal pool is as full as we can handle. We have
+	 to be 2 entries shy of the 1024/4=256 entries because we
+	 have to allow for the branch (2 bytes) and the alignment
+	 (2 bytes before the first insn referencing the pool and
+	 2 bytes before the pool itself) == 6 bytes, rounds up
+	 to 2 entries.  */
+
+      /* Save the parsed symbol's reloc.  */
+      enum bfd_reloc_code_real last_reloc_before_dump = insn_reloc;
+      dump_literals (1);
+      insn_reloc = last_reloc_before_dump;
+    }
+
+  if (poolsize == 0)
+    {
+      /* Create new literal pool.  */
+      if (++ poolnumber > 0xFFFF)
+	as_fatal (_("more than 65K literal pools"));
+
+      make_internal_label (poolname, POOL_START_LABEL, poolnumber);
+      poolsym = symbol_make (poolname);
+      symbol_table_insert (poolsym);
+      poolspan = 0;
+    }
+
+  /* Search pool for value so we don't have duplicates.  */
+  for (p = litpool, i = 0; i < poolsize; i += (p->isdouble ? 2 : 1), p++)
+    {
+      if (e->X_op == p->e.X_op
+	  && e->X_add_symbol == p->e.X_add_symbol
+	  && e->X_add_number == p->e.X_add_number
+	  && ispcrel == p->ispcrel
+	  && insn_reloc == p->r_type
+	  && isdouble == p->isdouble
+	  && insn_reloc != BFD_RELOC_CKCORE_TLS_GD32
+	  && insn_reloc != BFD_RELOC_CKCORE_TLS_LDM32
+	  && insn_reloc != BFD_RELOC_CKCORE_TLS_LDO32
+	  && insn_reloc != BFD_RELOC_CKCORE_TLS_IE32
+	  && insn_reloc != BFD_RELOC_CKCORE_TLS_LE32)
+	{
+	  p->refcnt ++;
+	  return i;
+	}
+    }
+  p->refcnt = 1;
+  p->ispcrel = ispcrel;
+  p->e = *e;
+  p->r_type = insn_reloc;
+  p->isdouble = isdouble;
+  if (isdouble)
+    p->dbnum = dbnum;
+
+  if (insn_reloc == BFD_RELOC_CKCORE_TLS_GD32
+      || insn_reloc == BFD_RELOC_CKCORE_TLS_LDM32
+      || insn_reloc == BFD_RELOC_CKCORE_TLS_IE32)
+    {
+      p->tls_addend.frag  = frag_now;
+      p->tls_addend.offset = csky_insn.output - frag_now->fr_literal;
+      literal_insn_offset = p;
+    }
+  poolsize += (p->isdouble ? 2 : 1);
+  return i;
+}
+
+/* Check whether we must dump the literal pool here.
+   kind == 0 is any old instruction.
+   kind  > 0 means we just had a control transfer instruction.
+   kind == 1 means within a function.
+   kind == 2 means we just left a function.
+
+   OFFSET is the length of the insn being processed.
+
+   SPANCLOSE and SPANEXIT are smaller numbers than SPANPANIC.
+   SPANPANIC means that we must dump now.
+   The dump_literals (1) call inserts a branch around the table, so
+   we first look to see if its a situation where we won't have to
+   insert a branch (e.g., the previous instruction was an unconditional
+   branch).
+   
+   SPANPANIC is the point where we must dump a single-entry pool.
+   it accounts for alignments and an inserted branch.
+   the 'poolsize*2' accounts for the scenario where we do:
+   lrw r1,lit1; lrw r2,lit2; lrw r3,lit3
+   Note that the 'lit2' reference is 2 bytes further along
+   but the literal it references will be 4 bytes further along,
+   so we must consider the poolsize into this equation.
+   This is slightly over-cautious, but guarantees that we won't
+   panic because a relocation is too distant.  */
+
+static void
+check_literals (int kind, int offset)
+{
+  poolspan += offset;
+
+  if ((poolspan > SPANEXIT || do_func_dump)
+      && kind > 1
+      && (do_br_dump || do_func_dump))
+    dump_literals (0);
+  else if (poolspan > SPANCLOSE && (kind > 0) && do_br_dump)
+    dump_literals (0);
+  else if (poolspan
+	   >= (SPANPANIC - (IS_CSKY_ARCH_V1 (mach_flag) ?  poolsize * 2 : 0)))
+    dump_literals (1);
+  /* We have not dumped literal pool before insn1,
+     and will not dump literal pool between insn1 and insnN+1,
+     so reset poolspan to original length.  */
+  else if (do_noliteraldump == 1)
+    poolspan -= offset;
+
+  if (do_noliteraldump == 1)
+    do_noliteraldump = 0;
+}
+
+/* The next group of functions are helpers for parsing various kinds
+   of instruction operand syntax.  */
+
+/* Parse operands of the form
+   <symbol>@GOTOFF+<nnn>
+   and similar .plt or .got references.
+
+   If we find one, set up the correct relocation in RELOC and copy the
+   input string, minus the `@GOTOFF' into a malloc'd buffer for
+   parsing by the calling routine.  Return this buffer, and if ADJUST
+   is non-null set it to the length of the string we removed from the
+   input line.  Otherwise return NULL.  */
+
+static char *
+lex_got (enum bfd_reloc_code_real *reloc,
+	 int *adjust)
+{
+  struct _gotrel
+  {
+    const char *str;
+    const enum bfd_reloc_code_real rel;
+  };
+  static const struct _gotrel gotrel[] =
+    {
+      { "GOTOFF",     BFD_RELOC_CKCORE_GOTOFF      },
+      { "GOTPC",      BFD_RELOC_CKCORE_GOTPC       },
+      { "GOTTPOFF",   BFD_RELOC_CKCORE_TLS_IE32    },
+      { "GOT",        BFD_RELOC_CKCORE_GOT32       },
+      { "PLT",        BFD_RELOC_CKCORE_PLT32       },
+      { "BTEXT",      BFD_RELOC_CKCORE_TOFFSET_LO16},
+      { "BDATA",      BFD_RELOC_CKCORE_DOFFSET_LO16},
+      { "TLSGD32",    BFD_RELOC_CKCORE_TLS_GD32    },
+      { "TLSLDM32",   BFD_RELOC_CKCORE_TLS_LDM32   },
+      { "TLSLDO32",   BFD_RELOC_CKCORE_TLS_LDO32   },
+      { "TPOFF",      BFD_RELOC_CKCORE_TLS_LE32    }
+    };
+
+  char *cp;
+  unsigned int j;
+
+  for (cp = input_line_pointer; *cp != '@'; cp++)
+    if (is_end_of_line[(unsigned char) *cp])
+      return NULL;
+
+  for (j = 0; j < sizeof (gotrel) / sizeof (gotrel[0]); j++)
+    {
+      int len = strlen (gotrel[j].str);
+
+      if (strncasecmp (cp + 1, gotrel[j].str, len) == 0)
+	{
+	  if (gotrel[j].rel != 0)
+	    {
+	      *reloc = gotrel[j].rel;
+	      if (adjust)
+		*adjust = len;
+
+	      /* input_line_pointer is the str pointer after relocation
+		 token like @GOTOFF.  */
+	      input_line_pointer += len + 1;
+	      return input_line_pointer;
+	    }
+
+	  csky_show_error (ERROR_RELOC_ILLEGAL, 0,
+			   (void *)gotrel[j].str, NULL);
+	  return NULL;
+	}
+    }
+
+  /* Might be a symbol version string.  Don't as_bad here.  */
+  return NULL;
+}
+
+/* Parse an expression, returning it in E.  */
+
+static char *
+parse_exp (char *s, expressionS *e)
+{
+  char *save;
+  char *new;
+
+  /* Skip whitespace.  */
+  while (ISSPACE (*s))
+    ++s;
+
+  save = input_line_pointer;
+  input_line_pointer = s;
+
+  insn_reloc = BFD_RELOC_NONE;
+  expression (e);
+  lex_got (&insn_reloc, NULL);
+
+  if (e->X_op == O_absent)
+    SET_ERROR_NUMBER (ERROR_MISSING_OPERAND, NULL);
+
+  new = input_line_pointer;
+  input_line_pointer = save;
+
+  return new;
+}
+
+static char *
+parse_fexp (char *s, expressionS *e, unsigned char isdouble, uint64_t *dbnum)
+{
+  int length;                       /* Number of chars in an object.  */
+  register char const *err = NULL;  /* Error from scanning float literal.  */
+  char temp[8];
+
+  /* input_line_pointer->1st char of a flonum (we hope!).  */
+  input_line_pointer = s;
+
+  if (input_line_pointer[0] == '0'
+      && ISALPHA (input_line_pointer[1]))
+    input_line_pointer += 2;
+
+  if (isdouble)
+    err = md_atof (100, temp, &length);
+  else
+    err = md_atof (102, temp, &length);
+  know (length <= 8);
+  know (err != NULL || length > 0);
+
+  if (!is_end_of_line[(unsigned char) *input_line_pointer])
+    as_bad (_("the second operand must be immediate !"));
+  while (!is_end_of_line[(unsigned char) *input_line_pointer])
+    input_line_pointer++;
+
+  if (err)
+    {
+      as_bad (_("bad floating literal: %s"), err);
+      as_bad (_("the second operand is illegal!"));
+      while (!is_end_of_line[(unsigned char) *input_line_pointer])
+	input_line_pointer++;
+      know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
+      return input_line_pointer;
+    }
+
+  e->X_add_symbol = 0x0;
+  e->X_op_symbol = 0x0;
+  e->X_op = O_constant;
+  e->X_unsigned = 1;
+  e->X_md = 0x0;
+
+  if (!isdouble)
+    {
+      if (target_big_endian)
+	e->X_add_number = (((temp[0] << 24) & 0xffffffff)
+			   | ((temp[1] << 16) & 0xffffff)
+			   | ((temp[2] << 8) & 0xffff)
+			   | (temp[3] & 0xff));
+      else
+	e->X_add_number = (((temp[3] << 24) & 0xffffffff)
+			   | ((temp[2] << 16) & 0xffffff)
+			   | ((temp[1] << 8) & 0xffff)
+			   | (temp[0] & 0xff));
+    }
+  else
+    {
+      if (target_big_endian)
+	{
+	  *dbnum = (((temp[0] << 24) & 0xffffffff)
+		    | ((temp[1] << 16) & 0xffffff)
+		    | ((temp[2] << 8) & 0xffff)
+		    | (temp[3] & 0xff));
+	  *dbnum <<= 32;
+	  *dbnum |= (((temp[4] << 24) & 0xffffffff)
+		     | ((temp[5] << 16) & 0xffffff)
+		     | ((temp[6] << 8) & 0xffff)
+		     | (temp[7] & 0xff));
+	}
+      else
+	{
+	  *dbnum = (((temp[7] << 24) & 0xffffffff)
+		    | ((temp[6] << 16) & 0xffffff)
+		    | ((temp[5] << 8) & 0xffff)
+		    | (temp[4] & 0xff));
+	  *dbnum <<= 32;
+	  *dbnum |= (((temp[3] << 24) & 0xffffffff)
+		     | ((temp[2] << 16) & 0xffffff)
+		     | ((temp[1] << 8) & 0xffff)
+		     | (temp[0] & 0xff));
+      }
+    }
+  return input_line_pointer;
+}
+
+static char *
+parse_rt (char *s,
+	  int ispcrel,
+	  expressionS *ep,
+	  long reg ATTRIBUTE_UNUSED)
+{
+  expressionS e;
+  int n;
+
+  if (ep)
+    /* Indicate nothing there.  */
+    ep->X_op = O_absent;
+
+  if (*s == '[')
+    {
+      s = parse_exp (s + 1, &e);
+
+      if (*s == ']')
+	s++;
+      else
+	SET_ERROR_NUMBER (ERROR_MISSING_RSQUARE_BRACKETS, NULL);
+
+      if (ep)
+       *ep = e;
+    }
+  else
+    {
+      s = parse_exp (s, &e);
+      if (BFD_RELOC_CKCORE_DOFFSET_LO16 == insn_reloc
+	   || BFD_RELOC_CKCORE_TOFFSET_LO16 == insn_reloc)
+	{
+	  if (ep)
+	    *ep = e;
+	  return s;
+	}
+      if (ep)
+	*ep = e;
+      /* If the instruction has work, literal handling is in the work.  */
+      if (!csky_insn.opcode->work)
+	{
+	  n = enter_literal (&e, ispcrel, 0, 0);
+	  if (ep)
+	   *ep = e;
+
+	  /* Create a reference to pool entry.  */
+	  ep->X_op = O_symbol;
+	  ep->X_add_symbol = poolsym;
+	  ep->X_add_number = n << 2;
+	}
+    }
+  return s;
+}
+
+static char *
+parse_rtf (char *s, int ispcrel, expressionS *ep)
+{
+  expressionS e;
+  int n = 0;
+
+  if (ep)
+    /* Indicate nothing there.  */
+    ep->X_op = O_absent;
+
+  if (*s == '[')
+    {
+      s = parse_exp (s + 1, & e);
+      
+      if (*s == ']')
+	s++;
+      else
+	as_bad (_("missing ']'"));
+      
+      if (ep)
+	*ep = e;
+    }
+  else
+    {
+      if (strstr (csky_insn.opcode->mnemonic, "flrws"))
+	{
+	  uint64_t dbnum;
+	  s = parse_fexp (s, &e, 0, &dbnum);
+	  n = enter_literal (& e, ispcrel, 0, dbnum);
+	}
+      else if (strstr (csky_insn.opcode->mnemonic, "flrwd"))
+	{
+	  uint64_t dbnum;
+	  s = parse_fexp (s, &e, 1, &dbnum);
+	  n = enter_literal (& e, ispcrel, 1, dbnum);
+	}
+      else
+	as_bad (_("Error: no such opcode"));
+      
+      if (ep)
+	*ep = e;
+      
+      /* Create a reference to pool entry.  */
+      ep->X_op         = O_symbol;
+      ep->X_add_symbol = poolsym;
+      ep->X_add_number = n << 2;
+    }
+  return s;
+}
+
+static bfd_boolean
+parse_type_ctrlreg (char** oper)
+{
+  int i = -1;
+  int len = 0;
+
+  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++;
+	}
+    }
+
+  if (IS_CSKY_V2 (mach_flag))
+    {
+      char *s = *oper;
+      int crx;
+      int sel;
+      if (i != -1)
+	{
+	  crx = i;
+	  sel = 0;
+	}
+      else
+	{
+	  if (s[0] == 'c' && s[1] == 'r')
+	    {
+	      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_NUMBER (ERROR_REG_OVER_RANGE, "control");
+		      return FALSE;
+		    }
+		  if (*s == ',')
+		    s++;
+		  else
+		    {
+		      SET_ERROR_NUMBER (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_NUMBER (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_NUMBER (ERROR_MISSING_LANGLE_BRACKETS, NULL);
+		  return FALSE;
+		}
+	    }
+	  else
+	    {
+	      SET_ERROR_NUMBER (ERROR_CREG_ILLEGAL, NULL);
+	      return FALSE;
+	    }
+	}
+	i = (sel << 5) | crx;
+    }
+  csky_insn.val[csky_insn.idx++] = i;
+  return TRUE;
+}
+
+static bfd_boolean
+is_reg_sp_with_bracket (char **oper)
+{
+  const char **regs;
+  int sp_idx;
+  int len;
+
+  if (IS_CSKY_V1 (mach_flag))
+    sp_idx = 0;
+  else
+    sp_idx = 14;
+
+  if (**oper != '(')
+      return FALSE;
+  *oper += 1;
+  regs = csky_general_reg;
+  len = strlen (regs[sp_idx]);
+  if (memcmp (*oper, regs[sp_idx], len) == 0)
+    {
+      *oper += len;
+      if (**oper != ')')
+	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;
+	}
+    }
+  return FALSE;
+}
+
+static bfd_boolean
+is_reg_sp (char **oper)
+{
+  const char **regs;
+  int sp_idx;
+  int len;
+  if (IS_CSKY_V1 (mach_flag))
+    sp_idx = 0;
+  else
+    sp_idx = 14;
+
+  regs = csky_general_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;
+    }
+  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_NUMBER (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_NUMBER (ERROR_REG_OVER_RANGE, reg);
+	  return -1;
+	}
+    }
+  else if (reg > 31 || reg < 0)
+    {
+      SET_ERROR_NUMBER (ERROR_REG_OVER_RANGE, reg);
+      return -1;
+    }
+
+  return reg;
+}
+
+static int
+csky_get_freg_val (char *str, int *len)
+{
+  int reg = 0;
+  char *s = NULL;
+  if ((str[0] == 'v' || str[0] == 'f') && (str[1] == 'r'))
+    {
+      /* It is fpu register.  */
+      s = &str[2];
+      while (ISDIGIT (*s))
+	{
+	  reg = reg * 10 + (*s) - '0';
+	  s++;
+	}
+      if (reg > 31)
+	return -1;
+    }
+  else
+    return -1;
+  *len = s - str;
+  return reg;
+}
+
+static bfd_boolean
+is_reglist_legal (char **oper)
+{
+  int reg1 = -1;
+  int reg2 = -1;
+  int len = 0;
+  reg1 = csky_get_reg_val  (*oper, &len);
+  *oper += len;
+
+  if (reg1 == -1 || (IS_CSKY_V1 (mach_flag) && (reg1 == 0 || reg1 == 15)))
+    {
+      SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			"The first reg must not be r0/r15");
+      return FALSE;
+    }
+
+  if (**oper != '-')
+    {
+      SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			"The operand format must be rx-ry");
+      return FALSE;
+    }
+  *oper += 1;
+
+  reg2 = csky_get_reg_val  (*oper, &len);
+  *oper += len;
+
+  if (reg2 == -1 || (IS_CSKY_V1 (mach_flag) && reg1 == 15))
+    {
+      SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			"The operand format must be r15 in C-SKY V1");
+      return FALSE;
+    }
+  if (IS_CSKY_V2 (mach_flag))
+    {
+      if (reg2 < reg1)
+	{
+	  SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			    "The operand format must be rx-ry (rx < ry)");
+	  return FALSE;
+	}
+      reg2 = reg2 - reg1;
+      reg1 <<= 5;
+      reg1 |= reg2;
+    }
+  csky_insn.val[csky_insn.idx++] = reg1;
+  return TRUE;
+}
+
+static bfd_boolean
+is_freglist_legal (char **oper)
+{
+  int reg1 = -1;
+  int reg2 = -1;
+  int len = 0;
+  reg1 = csky_get_freg_val  (*oper, &len);
+  *oper += len;
+
+  if (reg1 == -1)
+    {
+      SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			"The fpu register format is not recognized.");
+      return FALSE;
+    }
+
+  if (**oper != '-')
+    {
+      SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			"The operand format must be vrx-vry/frx-fry.");
+      return FALSE;
+    }
+  *oper += 1;
+
+  reg2 = csky_get_freg_val  (*oper, &len);
+  *oper += len;
+
+  if (reg2 == -1)
+    {
+      SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			"The fpu register format is not recognized.");
+      return FALSE;
+    }
+  if (reg2 < reg1)
+    {
+      SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			"The operand format must be rx-ry(rx < ry)");
+      return FALSE;
+    }
+  reg2 = reg2 - reg1;
+  reg2 <<= 4;
+  reg1 |= reg2;
+  csky_insn.val[csky_insn.idx++] = reg1;
+  return TRUE;
+}
+
+static bfd_boolean
+is_reglist_dash_comma_legal (char **oper, struct operand *oprnd)
+{
+  int reg1 = -1;
+  int reg2 = -1;
+  int len = 0;
+  int list = 0;
+  int flag = 0;
+  int temp = 0;
+  while (**oper != '\n' && **oper != '\0')
+    {
+      reg1 = csky_get_reg_val  (*oper, &len);
+      if (reg1 == -1)
+	{
+	  SET_ERROR_NUMBER (ERROR_REG_LIST, NULL);
+	  return FALSE;
+	}
+      flag |= (1 << reg1);
+      *oper += len;
+      if (**oper == '-')
+	{
+	  *oper += 1;
+	  reg2 = csky_get_reg_val  (*oper, &len);
+	  if (reg2 == -1)
+	    {
+	      SET_ERROR_NUMBER (ERROR_REG_LIST, NULL);
+	      return FALSE;
+	    }
+	  *oper += len;
+	  if (reg1 > reg2)
+	    {
+	      SET_ERROR_NUMBER (ERROR_REG_LIST, NULL);
+	      return FALSE;
+	    }
+	  while (reg2 >= reg1)
+	    {
+	      flag |= (1 << reg2);
+	      reg2--;
+	    }
+	}
+      if (**oper == ',')
+	*oper += 1;
+    }
+  /* The reglist: r4-r11, r15, r16-r17, r28.  */
+#define REGLIST_BITS         0x10038ff0
+  if (flag & ~(REGLIST_BITS))
+    {
+      SET_ERROR_NUMBER (ERROR_REG_LIST, NULL);
+      return FALSE;
+    }
+  /* Check r4-r11.  */
+  int i = 4;
+  while (i <= 11)
+    {
+      if (flag & (1 << i))
+	temp = i - 4 + 1;
+      i++;
+    }
+  list |= temp;
+
+  /* Check r15.  */
+  if (flag & (1 << 15))
+    list |= (1 << 4);
+
+  /* Check r16-r17.  */
+  i = 16;
+  temp = 0;
+  while (i <= 17)
+    {
+      if (flag & (1 << i))
+	temp = i - 16 + 1;
+      i++;
+    }
+  list |= (temp << 5);
+
+  /* Check r28.  */
+  if (flag & (1 << 28))
+    list |= (1 << 8);
+  if (oprnd->mask == OPRND_MASK_0_4 && (list & ~OPRND_MASK_0_4))
+    {
+      SET_ERROR_NUMBER (ERROR_REG_LIST, NULL);
+      return FALSE;
+    }
+  csky_insn.val[csky_insn.idx++] = list;
+  return TRUE;
+}
+
+static bfd_boolean
+is_reg_lshift_illegal (char **oper, int is_float)
+{
+  int value;
+  int len;
+  int reg;
+  reg = csky_get_reg_val  (*oper, &len);
+  if (reg == -1)
+    {
+      SET_ERROR_NUMBER (ERROR_REG_FORMAT, "The register must be r0-r31.");
+      return FALSE;
+    }
+
+  *oper += len;
+  if ((*oper)[0] != '<' || (*oper)[1] != '<')
+    {
+      SET_ERROR_NUMBER (ERROR_UNDEFINE,
+			"Operand format error; should be (rx, ry << n)");
+      return FALSE;
+    }
+  *oper += 2;
+
+  expressionS e;
+  char *new_oper = parse_exp (*oper, &e);
+  if (e.X_op == O_constant)
+    {
+      *oper = new_oper;
+      /* The immediate must be in [0, 3].  */
+      if (e.X_add_number < 0 || e.X_add_number > 3)
+	{
+	  SET_ERROR_NUMBER (ERROR_IMM_OVERFLOW, NULL);
+	  return FALSE;
+	}
+    }
+  else
+    {
+      SET_ERROR_NUMBER (ERROR_EXP_CONSTANT, NULL);
+      return FALSE;
+    }
+  if (is_float)
+    value = (reg << 2) | e.X_add_number;
+  else
+    value = (reg << 5) | (1 << e.X_add_number);
+  csky_insn.val[csky_insn.idx++] = value;
+
+  return TRUE;
+}
+
+static bfd_boolean
+is_imm_over_range (char **oper, int min, int max, int ext)
+{
+  expressionS e;
+  bfd_boolean ret = FALSE;
+  char *new_oper = parse_exp (*oper, &e);
+  if (e.X_op == O_constant)
+    {
+      ret = TRUE;
+      *oper = new_oper;
+      if ((int)e.X_add_number != ext
+	  && (e.X_add_number < min || e.X_add_number > max))
+	{
+	  ret = FALSE;
+	  SET_ERROR_NUMBER (ERROR_IMM_OVERFLOW, NULL);
+	}
+      csky_insn.val[csky_insn.idx++] = e.X_add_number;
+    }
+
+  return ret;
+}
+
+static bfd_boolean
+is_oimm_over_range (char **oper, int min, int max)
+{
+  expressionS e;
+  bfd_boolean ret = FALSE;
+  char *new_oper = parse_exp (*oper, &e);
+  if (e.X_op == O_constant)
+    {
+      ret = TRUE;
+      *oper = new_oper;
+      if (e.X_add_number < min || e.X_add_number > max)
+	{
+	  ret = FALSE;
+	  SET_ERROR_NUMBER (ERROR_IMM_OVERFLOW, NULL);
+	}
+      csky_insn.val[csky_insn.idx++] = e.X_add_number - 1;
+    }
+
+  return ret;
+}
+
+static bfd_boolean
+is_psr_bit (char **oper)
+{
+  const struct psrbit *bits;
+  int i = 0;
+
+  if (IS_CSKY_V1 (mach_flag))
+    bits = cskyv1_psr_bits;
+  else
+    bits = cskyv2_psr_bits;
+
+  while (bits[i].name != NULL)
+    {
+      if (bits[i].isa && !(bits[i].isa & isa_flag))
+	{
+	  i++;
+	  continue;
+	}
+      if (strncasecmp (*oper, bits[i].name, strlen (bits[i].name)) == 0)
+	{
+	  *oper += strlen (bits[i].name);
+	  csky_insn.val[csky_insn.idx] |= bits[i].value;
+	  return TRUE;
+	}
+      i++;
+    }
+  SET_ERROR_NUMBER (ERROR_OPCODE_PSRBIT, NULL);
+  return FALSE;
+}
+
+static bfd_boolean
+parse_type_cpidx (char** oper)
+{
+  char *s = *oper;
+  int idx;
+  if (s[0] == 'c' && s[1] == 'p')
+    {
+      if (ISDIGIT (s[2]) && ISDIGIT (s[3]) && ! ISDIGIT (s[4]))
+	{
+	  idx = (s[2] - '0') * 10 + s[3] - '0';
+	  *oper += 4;
+	}
+      else if (ISDIGIT (s[2]) && !ISDIGIT (s[3]))
+	{
+	  idx = s[2] - '0';
+	  *oper += 3;
+	}
+      else
+	return FALSE;
+    }
+  else
+    {
+      expressionS e;
+      *oper = parse_exp (*oper, &e);
+      if (e.X_op != O_constant)
+	{
+	  /* Can not recognize the operand.  */
+	  return FALSE;
+	}
+      idx = e.X_add_number;
+    }
+
+  csky_insn.val[csky_insn.idx++] = idx;
+
+  return TRUE;
+}
+
+static bfd_boolean
+parse_type_cpreg (char** oper)
+{
+  const char **regs = csky_cp_reg;
+  int i;
+  int len;
+
+  for (i = 0; i < (int)(sizeof (csky_cp_reg) / sizeof (char *)); i++)
+    {
+      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_NUMBER (ERROR_CPREG_ILLEGAL, *oper);
+  return FALSE;
+}
+
+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++)
+    {
+      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_NUMBER (ERROR_CPREG_ILLEGAL, *oper);
+  return FALSE;
+}
+
+static bfd_boolean
+parse_type_areg (char** oper)
+{
+  int i = 0;
+  int len = 0;
+  i = csky_get_reg_val (*oper, &len);
+  if (i == -1)
+    {
+      SET_ERROR_NUMBER (ERROR_GREG_ILLEGAL, NULL);
+      return FALSE;
+    }
+  *oper += len;
+  csky_insn.val[csky_insn.idx++] = i;
+
+  return TRUE;
+}
+
+static bfd_boolean
+parse_type_freg (char** oper, int even)
+{
+  int reg;
+  int len;
+  reg = csky_get_freg_val (*oper, &len);
+  if (reg == -1)
+    {
+      SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			"The fpu register format is not recognized.");
+      return FALSE;
+    }
+  *oper += len;
+  csky_insn.opcode_end = *oper;
+  if (even && reg & 0x1)
+    {
+      SET_ERROR_NUMBER (ERROR_EXP_EVEN_FREG, NULL);
+      return FALSE;
+    }
+  csky_insn.val[csky_insn.idx++] = reg;
+  return TRUE;
+}
+
+static bfd_boolean
+parse_ldst_imm (char **oper, struct csky_opcode_info *op ATTRIBUTE_UNUSED,
+		struct operand *oprnd)
+{
+  unsigned int mask = oprnd->mask;
+  int max = 1;
+  int shift = 0;
+
+  shift = oprnd->shift;
+
+  while (mask)
+    {
+      if (mask & 1)
+	max <<= 1;
+      mask >>= 1;
+    }
+  max = max << shift;
+
+  if (**oper == '\0' || **oper == ')')
+    {
+      csky_insn.val[csky_insn.idx++] = 0;
+      return TRUE;
+    }
+
+  expressionS e;
+  *oper = parse_exp (*oper, &e);
+  if (e.X_op != O_constant)
+    /* Not a constant.  */
+    return FALSE;
+  else if (e.X_add_number < 0 || e.X_add_number >= max)
+    {
+      /* Out of range.  */
+      SET_ERROR_NUMBER (ERROR_IMM_OVERFLOW, NULL);
+      return FALSE;
+    }
+  if ((e.X_add_number % (1 << shift)) != 0)
+    {
+      /* Not aligned.  */
+      SET_ERROR_NUMBER (ERROR_OFFSET_UNALIGNED, ((unsigned long)1 << shift));
+      return FALSE;
+    }
+
+  csky_insn.val[csky_insn.idx++] = e.X_add_number >> shift;
+
+  return TRUE;
+
+}
+
+static unsigned int
+csky_count_operands (char *str)
+{
+  char *oper_end = str;
+  unsigned int oprnd_num;
+  int bracket_cnt = 0;
+
+  if (is_end_of_line[(unsigned char) *oper_end])
+    oprnd_num = 0;
+  else
+    oprnd_num = 1;
+
+  /* Count how many operands.  */
+  if (oprnd_num)
+    while (!is_end_of_line[(unsigned char) *oper_end])
+      {
+	if (*oper_end == '(' || *oper_end == '<')
+	  {
+	    bracket_cnt++;
+	    oper_end++;
+	    continue;
+	  }
+	if (*oper_end == ')' || *oper_end == '>')
+	  {
+	    bracket_cnt--;
+	    oper_end++;
+	    continue;
+	  }
+	if (!bracket_cnt && *oper_end == ',')
+	  oprnd_num++;
+	oper_end++;
+      }
+  return oprnd_num;
+}
+
+/* End of the operand parsing helper functions.  */
+
+/* Parse the opcode part of an instruction.  Fill in the csky_insn
+   state and return true on success, false otherwise.  */
+static bfd_boolean
+parse_opcode (char *str)
+{
+#define IS_OPCODE32F(a) (*(a - 2) == '3' && *(a - 1) == '2')
+#define IS_OPCODE16F(a) (*(a - 2) == '1' && *(a - 1) == '6')
+
+  /* TRUE if this opcode has a suffix, like 'lrw.h'.  */
+  unsigned int has_suffix = FALSE;
+  unsigned int nlen = 0;
+  char *opcode_end;
+  char name[OPCODE_MAX_LEN + 1];
+  char macro_name[OPCODE_MAX_LEN + 1];
+
+  /* Remove space ahead of string.  */
+  while (ISSPACE (*str))
+    str++;
+  opcode_end = str;
+
+  /* Find the opcode end.  */
+  while (nlen < OPCODE_MAX_LEN
+	 && !is_end_of_line [(unsigned char) *opcode_end]
+	 && *opcode_end != ' ')
+    {
+      /* Is csky force 32 or 16 instruction?  */
+      if (IS_CSKY_V2 (mach_flag)
+	  && *opcode_end == '.' && has_suffix == FALSE)
+	{
+	  has_suffix = TRUE;
+	  if (IS_OPCODE32F (opcode_end))
+	    {
+	      csky_insn.flag_force = INSN_OPCODE32F;
+	      nlen -= 2;
+	    }
+	  else if (IS_OPCODE16F (opcode_end))
+	    {
+	      csky_insn.flag_force = INSN_OPCODE16F;
+	      nlen -= 2;
+	    }
+	}
+      name[nlen] = *opcode_end;
+      nlen++;
+      opcode_end++;
+    }
+
+  /* Is csky force 32 or 16 instruction?  */
+  if (has_suffix == FALSE)
+    {
+      if (IS_CSKY_V2 (mach_flag) && IS_OPCODE32F (opcode_end))
+	{
+	  csky_insn.flag_force = INSN_OPCODE32F;
+	  nlen -= 2;
+	}
+      else if (IS_OPCODE16F (opcode_end))
+	{
+	  csky_insn.flag_force = INSN_OPCODE16F;
+	  nlen -= 2;
+	}
+    }
+  name[nlen] = '\0';
+
+  /* Generate macro_name for finding hash in macro hash_table.  */
+  if (has_suffix == TRUE)
+    nlen += 2;
+  strncpy (macro_name, str, nlen);
+  macro_name[nlen] = '\0';
+
+  /* Get csky_insn.opcode_end.  */
+  while (ISSPACE (*opcode_end))
+    opcode_end++;
+  csky_insn.opcode_end = opcode_end;
+
+  /* Count the operands.  */
+  csky_insn.number = csky_count_operands (opcode_end);
+
+  /* Find hash by name in csky_macros_hash and csky_opcodes_hash.  */
+  csky_insn.macro = (struct csky_macro_info *) hash_find (csky_macros_hash,
+							  macro_name);
+  csky_insn.opcode = (struct csky_opcode *) hash_find (csky_opcodes_hash,
+							name);
+
+  if (csky_insn.macro == NULL && csky_insn.opcode == NULL)
+    return FALSE;
+  return TRUE;
+}
+
+
+/* Main dispatch routine to parse operand OPRND for opcode OP from string
+   *OPER.  */
+static bfd_boolean
+get_operand_value (struct csky_opcode_info *op,
+		   char **oper, struct operand *oprnd)
+{
+  struct soperand *soprnd = NULL;
+  if (oprnd->mask == HAS_SUB_OPERAND)
+    {
+      /* It has sub operand, it must be like:
+	 (oprnd1, oprnd2)
+	 or
+	 <oprnd1, oprnd2>
+	 We will check the format here.  */
+      soprnd = (struct soperand *) oprnd;
+      char lc = 0;
+      char rc = 0;
+      char *s = *oper;
+      int  bracket_cnt = 0;
+      if (oprnd->type == OPRND_TYPE_BRACKET)
+	{
+	  lc = '(';
+	  rc = ')';
+	}
+      else if (oprnd->type == OPRND_TYPE_ABRACKET)
+	{
+	  lc = '<';
+	  rc = '>';
+	}
+
+      if (**oper == lc)
+	{
+	  *oper += 1;
+	  s += 1;
+	}
+      else
+	{
+	  SET_ERROR_NUMBER ((oprnd->type == OPRND_TYPE_BRACKET
+			     ? ERROR_MISSING_LBRACKET
+			     : ERROR_MISSING_LANGLE_BRACKETS), NULL);
+	  return FALSE;
+	}
+
+      /* If the oprnd2 is an immediate, it can not be parsed
+	 that end with ')'/'>'.  Modify ')'/'>' to '\0'.  */
+      while ((*s != rc || bracket_cnt != 0) && (*s != '\n' && *s != '\0'))
+	{
+	  if (*s == lc)
+	    bracket_cnt++;
+	  else if (*s == rc)
+	    bracket_cnt--;
+	  s++;
+	}
+
+      if (*s == rc)
+	*s = '\0';
+      else
+	{
+	  SET_ERROR_NUMBER ((oprnd->type == OPRND_TYPE_BRACKET
+			     ? ERROR_MISSING_RBRACKET
+			     : ERROR_MISSING_RANGLE_BRACKETS), NULL);
+	  return FALSE;
+	}
+
+      if (get_operand_value (op, oper, &soprnd->subs[0]) == FALSE)
+	{
+	  *s = rc;
+	  return FALSE;
+	}
+      if (**oper == ',')
+	*oper += 1;
+      if (get_operand_value (op, oper, &soprnd->subs[1]) == FALSE)
+	{
+	  *s = rc;
+	  return FALSE;
+	}
+
+      *s = rc;
+      *oper += 1;
+      return TRUE;
+    }
+
+  switch (oprnd->type)
+    {
+      /* TODO: add opcode type here, log errors in the function.
+	 If REGLIST, then j = csky_insn.number - 1.
+	 If there is needed to parse expressions, it will be
+	 handled here.  */
+    case OPRND_TYPE_CTRLREG:
+      /* some parse.  */
+      return parse_type_ctrlreg (oper);
+    case OPRND_TYPE_AREG:
+      return parse_type_areg (oper);
+    case OPRND_TYPE_FREG:
+    case OPRND_TYPE_VREG:
+      return parse_type_freg (oper, 0);
+    case OPRND_TYPE_FEREG:
+      return parse_type_freg (oper, 1);
+    case OPRND_TYPE_CPCREG:
+      return parse_type_cpcreg (oper);
+    case OPRND_TYPE_CPREG:
+      return parse_type_cpreg (oper);
+    case OPRND_TYPE_CPIDX:
+      return parse_type_cpidx (oper);
+    case OPRND_TYPE_GREG0_7:
+    case OPRND_TYPE_GREG0_15:
+      {
+	int len;
+	long reg;
+	reg = csky_get_reg_val (*oper, &len);
+	
+	if (reg == -1)
+	  {
+	    SET_ERROR_NUMBER (ERROR_GREG_ILLEGAL, NULL);
+	    return FALSE;
+	  }
+	else if ((oprnd->type == OPRND_TYPE_GREG0_7 && reg > 7)
+		 || (oprnd->type == OPRND_TYPE_GREG0_15 && reg > 15))
+	  {
+	    SET_ERROR_NUMBER (ERROR_REG_OVER_RANGE, reg);
+	    return FALSE;
+	  }
+	*oper += len;
+	csky_insn.val[csky_insn.idx++] = reg;
+	return TRUE;
+      }
+    case OPRND_TYPE_REGnsplr:
+      {
+	int len;
+	long reg;
+	reg = csky_get_reg_val (*oper, &len);
+	
+	if (reg == -1
+	    || (IS_CSKY_V1 (mach_flag)
+		&& (reg == V1_REG_SP || reg == V1_REG_LR)))
+	  {
+	    SET_ERROR_NUMBER (ERROR_REG_OVER_RANGE, reg);
+	    return FALSE;
+	  }
+	csky_insn.val[csky_insn.idx++] = reg;
+	*oper += len;
+	return TRUE;;
+      }
+    case OPRND_TYPE_REGnr4_r7:
+      {
+	int len;
+	int reg;
+	if (**oper == '(')
+	  *oper += 1;
+	reg = csky_get_reg_val (*oper, &len);
+	if (reg == -1 || (reg <= 7 && reg >= 4))
+	  return FALSE;
+
+	csky_insn.val[csky_insn.idx++] = reg;
+	*oper += len;
+
+	if (**oper == ')')
+	  *oper += 1;
+	return TRUE;;
+      }
+    case OPRND_TYPE_REGr4_r7:
+      if (memcmp (*oper, "r4-r7", sizeof ("r4-r7") - 1) == 0)
+	{
+	  *oper += sizeof ("r4-r7") - 1;
+	  csky_insn.val[csky_insn.idx++] = 0;
+	  return TRUE;
+	}
+      SET_ERROR_NUMBER (ERROR_OPCODE_ILLEGAL, NULL);
+      return FALSE;
+    case OPRND_TYPE_IMM_LDST:
+      return parse_ldst_imm (oper, op, oprnd);
+    case OPRND_TYPE_IMM_FLDST:
+      return parse_ldst_imm (oper, op, oprnd);
+    case OPRND_TYPE_IMM1b:
+      return is_imm_over_range (oper, 0, 1, -1);
+    case OPRND_TYPE_IMM2b:
+      return is_imm_over_range (oper, 0, 3, -1);
+    case OPRND_TYPE_IMM2b_JMPIX:
+      /* ck802j support jmpix16, but not support jmpix32.  */
+      if (IS_CSKY_ARCH_802 (mach_flag)
+	  && (op->opcode & 0xffff0000) != 0)
+	{
+	  SET_ERROR_NUMBER (ERROR_OPCODE_ILLEGAL, NULL);
+	  return FALSE;
+	}
+      *oper = parse_exp (*oper, &csky_insn.e1);
+      if (csky_insn.e1.X_op == O_constant)
+	{
+	  csky_insn.opcode_end = *oper;
+	  if (csky_insn.e1.X_add_number & 0x7)
+	    {
+	      SET_ERROR_NUMBER (ERROR_JMPIX_OVER_RANGE, NULL);
+	      return FALSE;
+	    }
+	  csky_insn.val[csky_insn.idx++]
+	    = (csky_insn.e1.X_add_number >> 3) - 2;
+	}
+      return TRUE;
+    case OPRND_TYPE_IMM4b:
+      return is_imm_over_range (oper, 0, 15, -1);
+      break;
+    case OPRND_TYPE_IMM5b:
+      return is_imm_over_range (oper, 0, 31, -1);
+      /* This type for "bgeni" in csky v1 ISA.  */
+    case OPRND_TYPE_IMM5b_7_31:
+      if (is_imm_over_range (oper, 0, 31, -1))
+	{
+	  int val = csky_insn.val[csky_insn.idx - 1];
+	  /* immediate values of 0 -> 6 translate to movi.  */
+	  if (val <= 6)
+	    {
+	      const char *name = "movi";
+	      csky_insn.opcode = (struct csky_opcode *)
+		hash_find (csky_opcodes_hash, name);
+	      csky_insn.val[csky_insn.idx - 1] = 1 << val;
+	    }
+	  return TRUE;
+	}
+      else
+	return FALSE;
+
+    case OPRND_TYPE_IMM5b_1_31:
+      return is_imm_over_range (oper, 1, 31, -1);
+    case OPRND_TYPE_IMM5b_POWER:
+      if (is_imm_over_range (oper, 1, ~(1 << 31), 1 << 31))
+	{
+	  int log;
+	  int val = csky_insn.val[csky_insn.idx - 1];
+	  log = csky_log_2 (val);
+	  csky_insn.val[csky_insn.idx - 1] = log;
+	  return (log == -1 ? FALSE : TRUE);
+	}
+      else
+	return FALSE;
+
+      /* This type for "mgeni" in csky v1 ISA.  */
+      case OPRND_TYPE_IMM5b_7_31_POWER:
+	if (is_imm_over_range (oper, 1, ~(1 << 31), 1 << 31))
+	  {
+	    int log;
+	    int val = csky_insn.val[csky_insn.idx - 1];
+	    log = csky_log_2 (val);
+	    /* Immediate values of 0 -> 6 translate to movi.  */
+	    if (log <= 6)
+	      {
+		const char *name = "movi";
+		csky_insn.opcode = (struct csky_opcode *)
+		  hash_find (csky_opcodes_hash, name);
+		as_warn (_("translating mgeni to movi"));
+	      }
+	    else
+	      csky_insn.val[csky_insn.idx - 1] = log;
+	    return (log == -1 ? FALSE : TRUE);
+	  }
+	else
+	  return FALSE;
+
+    case OPRND_TYPE_IMM5b_RORI:
+      {
+	unsigned max_shift = IS_CSKY_V1 (mach_flag) ? 31 : 32;
+
+	if (is_imm_over_range (oper, 1, max_shift, -1))
+	  {
+	    int i = csky_insn.idx - 1;
+	    csky_insn.val[i] = 32 - csky_insn.val[i];
+	    return TRUE;
+	  }
+	else
+	  return FALSE;
+      }
+
+    case OPRND_TYPE_IMM5b_BMASKI:
+      /* For csky v1 bmask inst.  */
+      
+      if (!is_imm_over_range (oper, 8, 31, 0))
+	{
+	  unsigned int mask_val = csky_insn.val[csky_insn.idx - 1];
+	  if (mask_val > 0 && mask_val < 8)
+	    {
+	      const char *op_movi = "movi";
+	      csky_insn.opcode = (struct csky_opcode *)
+		hash_find (csky_opcodes_hash, op_movi);
+	      if (csky_insn.opcode == NULL)
+		return FALSE;
+	      csky_insn.val[csky_insn.idx - 1] = (1 << mask_val) - 1;
+	      return TRUE;
+	    }
+	}
+      return TRUE;
+
+      case OPRND_TYPE_IMM8b_BMASKI:
+      /* For csky v2 bmask, which will transfer to 16bits movi.  */
+	if (is_imm_over_range (oper, 1, 8, -1))
+	  {
+	    unsigned int mask_val = csky_insn.val[csky_insn.idx - 1];
+	    csky_insn.val[csky_insn.idx - 1] = (1 << mask_val) - 1;
+	    return TRUE;
+	  }
+	return FALSE;
+    case OPRND_TYPE_OIMM4b:
+      return is_oimm_over_range (oper, 1, 16);
+    case OPRND_TYPE_OIMM5b:
+      return is_oimm_over_range (oper, 1, 32);
+    case OPRND_TYPE_OIMM5b_IDLY:
+      if (is_imm_over_range (oper, 0, 32, -1))
+	{
+	  /* imm5b for idly n: 0<=n<4, imm5b=3; 4<=n<=32, imm5b=n-1.  */
+	  unsigned long imm = csky_insn.val[csky_insn.idx - 1];
+	  if (imm < 4)
+	    {
+	      csky_show_error (WARNING_IDLY, 0, (void *)imm, NULL);
+	      imm = 3;
+	    }
+	  else imm--;
+	  csky_insn.val[csky_insn.idx - 1] = imm;
+	  return TRUE;
+	}
+      else
+	return FALSE;
+
+      /* For csky v2 bmask inst.  */
+    case OPRND_TYPE_OIMM5b_BMASKI:
+      if (!is_oimm_over_range (oper, 17, 32))
+	{
+	  int mask_val = csky_insn.val[csky_insn.idx - 1];
+	  if (mask_val + 1 == 0)
+	    return TRUE;
+	  if (mask_val > 0 && mask_val < 16)
+	    {
+	      const char *op_movi = "movi";
+	      csky_insn.opcode = (struct csky_opcode *)
+		hash_find (csky_opcodes_hash, op_movi);
+	      if (csky_insn.opcode == NULL)
+		return FALSE;
+	      csky_insn.val[csky_insn.idx - 1] = (1 << (mask_val + 1)) - 1;
+	      return TRUE;
+	    }
+	}
+      return TRUE;
+    case OPRND_TYPE_IMM7b:
+      return is_imm_over_range (oper, 0, 127, -1);
+    case OPRND_TYPE_IMM8b:
+      return is_imm_over_range (oper, 0, 255, -1);
+    case OPRND_TYPE_IMM12b:
+      return is_imm_over_range (oper, 0, 4095, -1);
+    case OPRND_TYPE_IMM15b:
+      return is_imm_over_range (oper, 0, 0xfffff, -1);
+    case OPRND_TYPE_IMM16b:
+      return is_imm_over_range (oper, 0, 65535, -1);
+    case OPRND_TYPE_OIMM16b:
+      return is_oimm_over_range (oper, 1, 65536);
+    case OPRND_TYPE_IMM32b:
+      {
+	expressionS e;
+	char *new_oper = parse_exp (*oper, &e);
+	if (e.X_op == O_constant)
+	  {
+	    *oper = new_oper;
+	    csky_insn.val[csky_insn.idx++] = e.X_add_number;
+	    return TRUE;
+	  }
+	return FALSE;
+      }
+    case OPRND_TYPE_IMM16b_MOVIH:
+    case OPRND_TYPE_IMM16b_ORI:
+      {
+	bfd_reloc_code_real_type r = BFD_RELOC_NONE;
+	int len;
+	char *curr = *oper;
+	char * save = input_line_pointer;
+	/* get the reloc type, and set "@GOTxxx" as ' '  */
+	while (**oper != '@' && **oper != '\0')
+	  *oper += 1;
+	if (**oper != '\0')
+	  {
+	    input_line_pointer = *oper;
+	    lex_got (&r, &len);
+	    while (*(*oper + len + 1) != '\0')
+	      {
+		**oper = *(*oper + len + 1);
+		*(*oper + len + 1) = '\0';
+		*oper += 1;
+	      }
+	    **oper = '\0';
+	  }
+	input_line_pointer = save;
+	*oper = parse_exp (curr, &csky_insn.e1);
+	return TRUE;
+      }
+    case OPRND_TYPE_PSR_BITS_LIST:
+      {
+	int ret = TRUE;
+	if (csky_insn.number == 0)
+	  ret = FALSE;
+	else
+	  {
+	    csky_insn.val[csky_insn.idx] = 0;
+	    if (is_psr_bit (oper) != FALSE)
+	      while (**oper == ',')
+		{
+		  *oper += 1;
+		  if (is_psr_bit (oper) == FALSE)
+		    {
+		      ret = FALSE;
+		      break;
+		    }
+		}
+	    else
+	      ret = FALSE;
+	    if (ret == TRUE && IS_CSKY_V1 (mach_flag)
+		&& csky_insn.val[csky_insn.idx] > 8)
+	      ret = FALSE;
+	  }
+	if (!ret)
+	  SET_ERROR_NUMBER (ERROR_OPERANDS_ILLEGAL, csky_insn.opcode_end);
+	return ret;
+      }
+    case OPRND_TYPE_RM:
+      {
+	/* FPU round mode.  */
+	static const char *round_mode[] =
+	  {
+	    "rm_nearest",
+	    "rm_zero",
+	    "rm_posinf",
+	    "rm_neginf",
+	    NULL
+	  };
+	int i;
+	for (i = 0; round_mode[i]; i++)
+	  if (strncasecmp (*oper, round_mode[i], strlen (round_mode[i])) == 0)
+	    {
+	      *oper += strlen (round_mode[i]);
+	      csky_insn.val[csky_insn.idx++] = i;
+	      return TRUE;
+	    }
+	return FALSE;
+      }
+
+    case OPRND_TYPE_REGLIST_COMMA:
+    case OPRND_TYPE_BRACKET:
+      /* TODO: using sub operand union.  */
+    case OPRND_TYPE_ABRACKET:
+      /* TODO: using sub operand union.  */
+    case OPRND_TYPE_REGLIST_DASH:
+      return is_reglist_legal (oper);
+    case OPRND_TYPE_FREGLIST_DASH:
+      return is_freglist_legal (oper);
+    case OPRND_TYPE_AREG_WITH_BRACKET:
+      {
+	int len;
+	int reg;
+	if (**oper != '(')
+	  {
+	    SET_ERROR_NUMBER (ERROR_MISSING_LBRACKET, NULL);
+	    return FALSE;
+	  }
+	*oper += 1;
+	reg = csky_get_reg_val (*oper, &len);
+	if (reg == -1)
+	  {
+	    SET_ERROR_NUMBER (ERROR_EXP_GREG, NULL);
+	    return FALSE;
+	  }
+	*oper += len;
+	if (**oper != ')')
+	  {
+	    SET_ERROR_NUMBER (ERROR_MISSING_RBRACKET, NULL);
+	    return FALSE;
+	  }
+	*oper += 1;
+	csky_insn.val[csky_insn.idx++] = reg;
+	return TRUE;
+      }
+    case OPRND_TYPE_REGsp:
+      return is_reg_sp (oper);
+    case OPRND_TYPE_REGbsp:
+      return is_reg_sp_with_bracket (oper);
+      /* For jmpi.  */
+    case OPRND_TYPE_OFF8b:
+    case OPRND_TYPE_OFF16b:
+      *oper = parse_rt (*oper, 1, &csky_insn.e1, -1);
+      csky_insn.val[csky_insn.idx++] = 0;
+      return TRUE;
+    case OPRND_TYPE_LABEL_WITH_BRACKET:
+    case OPRND_TYPE_CONSTANT:
+    case OPRND_TYPE_ELRW_CONSTANT:
+      if (**oper == '[')
+	csky_insn.val[csky_insn.idx++] = 0;
+      else
+	csky_insn.val[csky_insn.idx++] = NEED_OUTPUT_LITERAL;
+      *oper = parse_rt (*oper, 0, &csky_insn.e1, -1);
+      return TRUE;
+    case OPRND_TYPE_FCONSTANT:
+      *oper = parse_rtf (*oper, 0, &csky_insn.e1);
+      return TRUE;
+      
+    case OPRND_TYPE_SFLOAT:
+      *oper = parse_fexp (*oper, &csky_insn.e1, 0, &csky_insn.dbnum);
+      if (csky_insn.e1.X_op == O_absent)
+	return FALSE;
+      return TRUE;
+
+    case OPRND_TYPE_DFLOAT:
+      *oper = parse_fexp (*oper, &csky_insn.e1, 1, &csky_insn.dbnum);
+      if (csky_insn.e1.X_op == O_absent)
+	return FALSE;
+      return TRUE;
+      
+      /* For grs v2.  */
+    case OPRND_TYPE_IMM_OFF18b:
+      *oper = parse_exp (*oper, &csky_insn.e1);
+      return TRUE;
+      
+    case OPRND_TYPE_BLOOP_OFF4b:
+      *oper = parse_exp (*oper, &csky_insn.e2);
+      if (csky_insn.e2.X_op == O_symbol)
+	{
+	  csky_insn.opcode_end = *oper;
+	  return TRUE;
+	}
+      else
+	return FALSE;
+      
+    case OPRND_TYPE_BLOOP_OFF12b:
+    case OPRND_TYPE_OFF10b:
+    case OPRND_TYPE_OFF11b:
+    case OPRND_TYPE_OFF16b_LSL1:
+    case OPRND_TYPE_OFF26b:
+      *oper = parse_exp (*oper, &csky_insn.e1);
+      if (csky_insn.e1.X_op == O_symbol)
+	{
+	  csky_insn.opcode_end = *oper;
+	  return TRUE;
+	}
+      else
+	return FALSE;
+      /* For xtrb0(1)(2)(3) and div in csky v1 ISA.  */
+    case OPRND_TYPE_REG_r1a:
+      {
+	int reg = 0;
+	int len = 0;
+	reg = csky_get_reg_val (*oper, &len);
+	if (reg == -1)
+	  {
+	    SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			      "The first operand must be register r1.");
+	    return FALSE;
+	  }
+	if (reg != 1)
+	  mov_r1_after = TRUE;
+	*oper += len;
+	csky_insn.opcode_end = *oper;
+	csky_insn.val[csky_insn.idx++] = reg;
+	return TRUE;
+      }
+    case OPRND_TYPE_REG_r1b:
+      {
+	int reg = 0;
+	int len = 0;
+	reg = csky_get_reg_val (*oper, &len);
+	if (reg == -1)
+	  {
+	    SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			      "The second operand must be register r1.");
+	    return FALSE;
+	  }
+	if (reg != 1)
+	  {
+	    unsigned int mov_insn = CSKYV1_INST_MOV_R1_RX;
+	    mov_insn |= reg << 4;
+	    mov_r1_before = TRUE;
+	    csky_insn.output = frag_more (2);
+	    dwarf2_emit_insn (0);
+	    md_number_to_chars (csky_insn.output, mov_insn, 2);
+	  }
+	*oper += len;
+	csky_insn.opcode_end = *oper;
+	csky_insn.val[csky_insn.idx++] = reg;
+	return TRUE;
+      }
+    case OPRND_TYPE_DUMMY_REG:
+      {
+	int reg = 0;
+	int len = 0;
+	reg = csky_get_reg_val (*oper, &len);
+	if (reg == -1)
+	  {
+	    SET_ERROR_NUMBER (ERROR_GREG_ILLEGAL, NULL);
+	    return FALSE;
+	  }
+	if (reg != csky_insn.val[0])
+	  {
+	    SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+			      "The second register must be the same as the first.");
+	    return FALSE;
+	  }
+	*oper += len;
+	csky_insn.opcode_end = *oper;
+	csky_insn.val[csky_insn.idx++] = reg;
+	return TRUE;
+      }
+    case OPRND_TYPE_2IN1_DUMMY:
+      {
+	int reg = 0;
+	int len = 0;
+	int max = 0;
+	int min = 0;
+	reg = csky_get_reg_val (*oper, &len);
+	if (reg == -1)
+	  {
+	    SET_ERROR_NUMBER (ERROR_GREG_ILLEGAL, NULL);
+	    return FALSE;
+	  }
+	/* dummy reg's real type should be same with first operand.  */
+	if (op->oprnd.oprnds[0].type == OPRND_TYPE_GREG0_15)
+	  max = 15;
+	else if (op->oprnd.oprnds[0].type == OPRND_TYPE_GREG0_7)
+	  max = 7;
+	else
+	  return FALSE;
+	if (reg < min || reg > max)
+	  return FALSE;
+	csky_insn.val[csky_insn.idx++] = reg;
+	/* if it is the last operands.  */
+	if (csky_insn.idx > 2)
+	  {
+	    /* For "insn rz, rx, ry", if rx or ry is equal to rz,
+	       we can output the insn like "insn rz, rx".  */
+	    if (csky_insn.val[0] ==  csky_insn.val[1])
+	      csky_insn.val[1] = 0;
+	    else if (csky_insn.val[0] ==  csky_insn.val[2])
+	      csky_insn.val[2] = 0;
+	    else
+	      return FALSE;
+	  }
+	*oper += len;
+	csky_insn.opcode_end = *oper;
+	return TRUE;
+      }
+    case OPRND_TYPE_DUP_GREG0_7:
+    case OPRND_TYPE_DUP_GREG0_15:
+    case OPRND_TYPE_DUP_AREG:
+      {
+	long reg = 0;
+	int len = 0;
+	long max_reg;
+	unsigned int shift_num;
+	if (oprnd->type == OPRND_TYPE_DUP_GREG0_7)
+	  {
+	    max_reg = 7;
+	    shift_num = 3;
+	  }
+	else if (oprnd->type == OPRND_TYPE_DUP_GREG0_15)
+	  {
+	    max_reg = 15;
+	    shift_num = 4;
+	  }
+	else
+	  {
+	    max_reg = 31;
+	    shift_num = 5;
+	  }
+	reg = csky_get_reg_val (*oper, &len);
+	if (reg == -1)
+	  {
+	    if (max_reg == 31)
+	      SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+				"The register must be r0-r31");
+	    else
+	      SET_ERROR_NUMBER (ERROR_REG_FORMAT,
+				"The register must be r0-r15");
+	    return FALSE;
+	  }
+	if (reg > max_reg)
+	  {
+	    SET_ERROR_NUMBER (ERROR_REG_OVER_RANGE, reg);
+	    return FALSE;
+	  }
+	reg |= reg << shift_num;
+	*oper += len;
+	csky_insn.opcode_end = *oper;
+	csky_insn.val[csky_insn.idx++] = reg;
+	return TRUE;
+      }
+    case OPRND_TYPE_CONST1:
+      *oper = parse_exp (*oper, &csky_insn.e1);
+      if (csky_insn.e1.X_op == O_constant)
+	{
+	  csky_insn.opcode_end = *oper;
+	  if (csky_insn.e1.X_add_number != 1)
+	    return FALSE;
+	  csky_insn.val[csky_insn.idx++] = 1;
+	  return TRUE;
+	}
+    case OPRND_TYPE_UNCOND10b:
+    case OPRND_TYPE_UNCOND16b:
+      *oper = parse_exp (*oper, &csky_insn.e1);
+      if (csky_insn.e1.X_op == O_constant)
+	return FALSE;
+      input_line_pointer = *oper;
+      csky_insn.opcode_end = *oper;
+      csky_insn.relax.max = UNCD_DISP16_LEN;
+      csky_insn.relax.var = UNCD_DISP10_LEN;
+      csky_insn.relax.subtype = UNCD_DISP10;
+      csky_insn.val[csky_insn.idx++] = 0;
+      return TRUE;
+    case OPRND_TYPE_COND10b:
+    case OPRND_TYPE_COND16b:
+      *oper = parse_exp (*oper, &csky_insn.e1);
+      if (csky_insn.e1.X_op == O_constant)
+	return FALSE;
+      input_line_pointer = *oper;
+      csky_insn.opcode_end = *oper;
+      /* CK801 doesn't have 32-bit bt/bf insns; relax to a short
+	 jump around a 32-bit unconditional branch instead.  */
+      if (IS_CSKY_ARCH_801 (mach_flag))
+	{
+	  csky_insn.relax.max = SCOND_DISP16_LEN;
+	  csky_insn.relax.var = SCOND_DISP10_LEN;
+	  csky_insn.relax.subtype = SCOND_DISP10;
+	}
+      else
+	{
+	  csky_insn.relax.max = COND_DISP16_LEN;
+	  csky_insn.relax.var = COND_DISP10_LEN;
+	  csky_insn.relax.subtype = COND_DISP10;
+	}
+      csky_insn.val[csky_insn.idx++] = 0;
+      return TRUE;
+    case OPRND_TYPE_JCOMPZ:
+      *oper = parse_exp (*oper, &csky_insn.e1);
+      if (csky_insn.e1.X_op == O_constant)
+	return FALSE;
+      input_line_pointer = *oper;
+      csky_insn.opcode_end = *oper;
+      csky_insn.relax.max = JCOMPZ_DISP32_LEN;
+      csky_insn.relax.var = JCOMPZ_DISP16_LEN;
+      csky_insn.relax.subtype = JCOMPZ_DISP16;
+      csky_insn.max = JCOMPZ_DISP32_LEN;
+      csky_insn.val[csky_insn.idx++] = 0;
+      return TRUE;
+    case OPRND_TYPE_JBTF:
+      *oper = parse_exp (*oper, &csky_insn.e1);
+      input_line_pointer = *oper;
+      csky_insn.opcode_end = *oper;
+      csky_insn.relax.max = csky_relax_table[C (COND_JUMP_S, DISP32)].rlx_length;
+      csky_insn.relax.var = csky_relax_table[C (COND_JUMP_S, DISP12)].rlx_length;
+      csky_insn.relax.subtype = C (COND_JUMP_S, 0);
+      csky_insn.val[csky_insn.idx++] = 0;
+      csky_insn.max = C32_LEN_S + 2;
+      return TRUE;
+    case OPRND_TYPE_JBR:
+      *oper = parse_exp (*oper, &csky_insn.e1);
+      input_line_pointer = *oper;
+      csky_insn.opcode_end = *oper;
+      csky_insn.relax.max = csky_relax_table[C (UNCD_JUMP_S, DISP32)].rlx_length;
+      csky_insn.relax.var = csky_relax_table[C (UNCD_JUMP_S, DISP12)].rlx_length;
+      csky_insn.relax.subtype = C (UNCD_JUMP_S, 0);
+      csky_insn.val[csky_insn.idx++] = 0;
+      csky_insn.max = U32_LEN_S + 2;
+      return TRUE;
+    case OPRND_TYPE_JBSR:
+      if (do_force2bsr)
+	*oper = parse_exp (*oper, &csky_insn.e1);
+      else
+	*oper = parse_rt (*oper, 1, &csky_insn.e1, -1);
+      input_line_pointer = *oper;
+      csky_insn.opcode_end = *oper;
+      csky_insn.val[csky_insn.idx++] = 0;
+      return TRUE;
+    case OPRND_TYPE_REGLIST_DASH_COMMA:
+      return is_reglist_dash_comma_legal (oper, oprnd);
+      
+    case OPRND_TYPE_MSB2SIZE:
+    case OPRND_TYPE_LSB2SIZE:
+      {
+	expressionS e;
+	char *new_oper = parse_exp (*oper, &e);
+	if (e.X_op == O_constant)
+	  {
+	    *oper = new_oper;
+	    if (e.X_add_number > 31)
+	      {
+		SET_ERROR_NUMBER (ERROR_IMM_OVERFLOW, NULL);
+		return FALSE;
+	      }
+	    csky_insn.val[csky_insn.idx++] = e.X_add_number;
+	    if (oprnd->type == OPRND_TYPE_LSB2SIZE)
+	      {
+		if (csky_insn.val[csky_insn.idx - 1] > csky_insn.val[csky_insn.idx - 2])
+		  {
+		    SET_ERROR_NUMBER (ERROR_IMM_OVERFLOW, NULL);
+		    return FALSE;
+		  }
+		csky_insn.val[csky_insn.idx - 2] -= e.X_add_number;
+	      }
+	    return TRUE;
+	  }
+	
+      }
+    case OPRND_TYPE_AREG_WITH_LSHIFT:
+      return is_reg_lshift_illegal (oper, 0);
+    case OPRND_TYPE_AREG_WITH_LSHIFT_FPU:
+      return is_reg_lshift_illegal (oper, 1);
+    case OPRND_TYPE_FREG_WITH_INDEX:
+      if (parse_type_freg (oper, 0))
+	{
+	  if (**oper == '[')
+	    {
+	      (*oper)++;
+	      if (is_imm_over_range (oper, 0, 0xf, -1))
+		{
+		  if (**oper == ']')
+		    {
+		      unsigned int idx = --csky_insn.idx;
+		      unsigned int val = csky_insn.val[idx];
+		      (*oper)++;
+		      csky_insn.val[idx - 1] |= val << 4;
+		      return TRUE;
+		    }
+		  else
+		    SET_ERROR_NUMBER (ERROR_MISSING_RSQUARE_BRACKETS, NULL);
+		}
+	    }
+	  else
+	    SET_ERROR_NUMBER (ERROR_MISSING_LSQUARE_BRACKETS, NULL);
+	}
+      return FALSE;
+
+    default:
+      break;
+      /* error code.  */
+    }
+  return FALSE;
+}
+
+/* Subroutine of parse_operands.  */
+
+static bfd_boolean
+parse_operands_op (char *str, struct csky_opcode_info *op)
+{
+  int i;
+  int j;
+  char *oper = str;
+  int flag_pass;
+
+  for (i = 0; i < OP_TABLE_NUM && op[i].operand_num != -2; i++)
+    {
+      flag_pass = TRUE;
+      csky_insn.idx = 0;
+      oper = str;
+      /* if operand_num = -1, it is a insn with a REGLIST type operand.i.  */
+      if (!(op[i].operand_num == csky_insn.number
+	    || (op[i].operand_num == -1 && csky_insn.number != 0)))
+	{
+	  /* The smaller err_num is more serious.  */
+	  SET_ERROR_NUMBER (ERROR_OPERANDS_NUMBER, op[i].operand_num);
+	  flag_pass = FALSE;
+	  continue;
+	}
+
+      for (j = 0; j < csky_insn.number; j++)
+	{
+	  while (ISSPACE (*oper))
+	    oper++;
+	  flag_pass = get_operand_value (&op[i], &oper,
+					 &op[i].oprnd.oprnds[j]);
+	  if (flag_pass == FALSE)
+	    break;
+	  while (ISSPACE (*oper))
+	    oper++;
+	  /* Skip the ','.  */
+	  if (j < csky_insn.number - 1 && op[i].operand_num != -1)
+	    {
+	      if (*oper == ',')
+		oper++;
+	      else
+		{
+		  SET_ERROR_NUMBER (ERROR_MISSING_COMMA, NULL);
+		  flag_pass = FALSE;
+		  break;
+		}
+	    }
+	  else if (!is_end_of_line[(unsigned char) *oper])
+	    {
+	      SET_ERROR_NUMBER (ERROR_BAD_END, NULL);
+	      flag_pass = FALSE;
+	      break;
+	    }
+	  else
+	    break;
+	}
+      /* Parse operands in one table end.  */
+
+      if (flag_pass == TRUE)
+	{
+	  /* Parse operands success, set opcode_idx.  */
+	  csky_insn.opcode_idx = i;
+	  return TRUE;
+	}
+      else
+	error_state.opnum = j + 1;
+    }
+  /* Parse operands in ALL tables end.  */
+  return FALSE;
+}
+
+/* Parse the operands according to operand type.  */
+
+static bfd_boolean
+parse_operands (char *str)
+{
+  char *oper = str;
+
+  /* Parse operands according to flag_force.  */
+  if (csky_insn.flag_force == INSN_OPCODE16F
+      && (csky_insn.opcode->isa_flag16 & isa_flag) != 0)
+    {
+      if (parse_operands_op (oper, csky_insn.opcode->op16) == TRUE)
+	{
+	  csky_insn.isize = 2;
+	  return TRUE;
+	}
+      return FALSE;
+    }
+  else if (csky_insn.flag_force == INSN_OPCODE32F
+	   && (csky_insn.opcode->isa_flag32 & isa_flag) != 0)
+    {
+      if (parse_operands_op (oper, csky_insn.opcode->op32) == TRUE)
+	{
+	  csky_insn.isize = 4;
+	  return TRUE;
+	}
+      return FALSE;
+    }
+  else
+    {
+      if ((csky_insn.opcode->isa_flag16 & isa_flag) != 0
+	  && parse_operands_op (oper, csky_insn.opcode->op16) == TRUE)
+	{
+	  csky_insn.isize = 2;
+	  return TRUE;
+	}
+      if ((csky_insn.opcode->isa_flag32 & isa_flag) != 0
+	  && parse_operands_op (oper, csky_insn.opcode->op32) == TRUE)
+	{
+	  csky_insn.isize = 4;
+	  return TRUE;
+	}
+      return FALSE;
+    }
+}
+
+static bfd_boolean
+csky_generate_frags (void)
+{
+  /* frag more relax reloc.  */
+  if (csky_insn.flag_force == INSN_OPCODE16F
+      || !IS_SUPPORT_OPCODE32 (csky_insn.opcode))
+    {
+      csky_insn.output = frag_more (csky_insn.isize);
+      if (csky_insn.opcode->reloc16)
+	{
+	  /* 16 bits opcode force, should generate fixup.  */
+	  reloc_howto_type *howto;
+	  howto = bfd_reloc_type_lookup (stdoutput,
+					 csky_insn.opcode->reloc16);
+	  fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		       2, &csky_insn.e1, howto->pc_relative,
+		       csky_insn.opcode->reloc16);
+	}
+    }
+  else if (csky_insn.flag_force == INSN_OPCODE32F)
+    {
+      csky_insn.output = frag_more (csky_insn.isize);
+      if (csky_insn.opcode->reloc32)
+	{
+	  reloc_howto_type *howto;
+	  howto = bfd_reloc_type_lookup (stdoutput,
+					 csky_insn.opcode->reloc32);
+	  fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		       4, &csky_insn.e1, howto->pc_relative,
+		       csky_insn.opcode->reloc32);
+	}
+    }
+  else if (csky_insn.opcode->relax)
+    /* Generate the relax information.  */
+    csky_insn.output = frag_var (rs_machine_dependent,
+				 csky_insn.relax.max,
+				 csky_insn.relax.var,
+				 csky_insn.relax.subtype,
+				 csky_insn.e1.X_add_symbol,
+				 csky_insn.e1.X_add_number, 0);
+  else
+    {
+      csky_insn.output = frag_more (csky_insn.isize);
+      if (csky_insn.opcode->reloc16 && csky_insn.isize == 2)
+	{
+	  reloc_howto_type *howto;
+	  howto = bfd_reloc_type_lookup (stdoutput,
+					 csky_insn.opcode->reloc16);
+	  fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		       2, &csky_insn.e1, howto->pc_relative,
+		       csky_insn.opcode->reloc16);
+	}
+      else if (csky_insn.opcode->reloc32 && csky_insn.isize == 4)
+	{
+	  reloc_howto_type *howto;
+	  howto = bfd_reloc_type_lookup (stdoutput,
+					 csky_insn.opcode->reloc32);
+	  fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		       4, &csky_insn.e1, howto->pc_relative,
+		       csky_insn.opcode->reloc32);
+	}
+    }
+  return TRUE;
+}
+
+
+/* Return the bits of VAL shifted according to MASK.  The bits of MASK
+   need not be contiguous.  */
+
+static int
+generate_masked_value (int mask, int val)
+{
+  int ret = 0;
+  int bit;
+
+  for (bit = 1; mask; bit = bit << 1)
+    if (mask & bit)
+      {
+	if (val & 0x1)
+	  ret |= bit;
+	val = val >> 1;
+	mask &= ~bit;
+      }
+  return ret;
+}
+
+/* Return the result of masking operand number OPRND_IDX into the
+   instruction word according to the information in OPRND.  */
+
+static int
+generate_masked_operand (struct operand *oprnd, int *oprnd_idx)
+{
+  struct soperand *soprnd = NULL;
+  int mask;
+  int val;
+  if ((unsigned int)oprnd->mask == HAS_SUB_OPERAND)
+    {
+      soprnd = (struct soperand *) oprnd;
+      generate_masked_operand (&soprnd->subs[0], oprnd_idx);
+      generate_masked_operand (&soprnd->subs[1], oprnd_idx);
+      return 0;
+    }
+  mask = oprnd->mask;
+  val = csky_insn.val[*oprnd_idx];
+  (*oprnd_idx)++;
+  val = generate_masked_value (mask, val);
+  csky_insn.inst |= val;
+
+  return 0;
+}
+
+static bfd_boolean
+csky_generate_insn (void)
+{
+  int i = 0;
+  struct csky_opcode_info *opinfo = NULL;
+
+  if (csky_insn.isize == 4)
+    opinfo = &csky_insn.opcode->op32[csky_insn.opcode_idx];
+  else if (csky_insn.isize == 2)
+    opinfo = &csky_insn.opcode->op16[csky_insn.opcode_idx];
+
+  int sidx = 0;
+  csky_insn.inst = opinfo->opcode;
+  if (opinfo->operand_num == -1)
+    {
+      generate_masked_operand (&opinfo->oprnd.oprnds[i], &sidx);
+      return 0;
+    }
+  else
+    for (i = 0; i < opinfo->operand_num; i++)
+      generate_masked_operand (&opinfo->oprnd.oprnds[i], &sidx);
+  return 0;
+}
+
+
+/* Main entry point for assembling a single instruction.  */
+void
+md_assemble (char *str)
+{
+  bfd_boolean must_check_literals = TRUE;
+  csky_insn.isize = 0;
+  csky_insn.idx = 0;
+  csky_insn.max = 0;
+  csky_insn.flag_force = INSN_OPCODE;
+  csky_insn.macro = NULL;
+  csky_insn.opcode = NULL;
+  memset (csky_insn.val, 0, sizeof (int) * MAX_OPRND_NUM);
+  /* Initialize err_num.  */
+  error_state.err_num = ERROR_NONE;
+  mov_r1_before = FALSE;
+  mov_r1_after = FALSE;
+
+  mapping_state (MAP_TEXT);
+  /* Tie dwarf2 debug info to every insn if set option --gdwarf2.  */
+  dwarf2_emit_insn (0);
+  while (ISSPACE (* str))
+    str++;
+  /* Get opcode from str.  */
+  if (parse_opcode (str) == FALSE)
+    {
+      csky_show_error (ERROR_OPCODE_ILLEGAL, 0, NULL, NULL);
+      return;
+    }
+
+  /* If it is a macro instruction, handle it.  */
+  if (csky_insn.macro != NULL)
+    {
+      if (csky_insn.number == csky_insn.macro->oprnd_num)
+	{
+	  csky_insn.macro->handle_func ();
+	  return;
+	}
+      else if (error_state.err_num > ERROR_OPERANDS_NUMBER)
+	SET_ERROR_NUMBER (ERROR_OPERANDS_NUMBER, csky_insn.macro->oprnd_num);
+    }
+
+  if (csky_insn.opcode == NULL)
+    {
+      SET_ERROR_NUMBER (ERROR_OPCODE_ILLEGAL, NULL);
+      csky_show_error (error_state.err_num, error_state.opnum,
+		       (void *)error_state.arg1, (void *)error_state.arg1);
+      return;
+    }
+
+  /* Parse the operands according to operand type.  */
+  if (parse_operands (csky_insn.opcode_end) == FALSE)
+    {
+      csky_show_error (error_state.err_num, error_state.opnum,
+		        (void *)error_state.arg1,  (void *)error_state.arg1);
+      return;
+    }
+
+  /* if this insn has work in opcode table, then do it.  */
+  if (csky_insn.opcode->work != NULL)
+      must_check_literals = csky_insn.opcode->work ();
+  else
+    {
+      /* Generate relax or reloc if necessary.  */
+      csky_generate_frags ();
+      /* Generate the insn by mask.  */
+      csky_generate_insn ();
+      /* Write inst to frag.  */
+      csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+    }
+
+  /* Adjust for xtrb0/xtrb1/xtrb2/xtrb3/divs/divu in csky v1 ISA.  */
+  if (mov_r1_after == TRUE)
+    {
+      unsigned int mov_insn = CSKYV1_INST_MOV_RX_R1;
+      mov_insn |= csky_insn.val[0];
+      mov_r1_before = TRUE;
+      csky_insn.output = frag_more (2);
+      dwarf2_emit_insn (0);
+      md_number_to_chars (csky_insn.output, mov_insn, 2);
+      csky_insn.isize += 2;
+    }
+  if (mov_r1_before == TRUE)
+    csky_insn.isize += 2;
+
+  /* Check literal.  */
+  if (must_check_literals)
+    {
+      if (csky_insn.max == 0)
+	check_literals (csky_insn.opcode->transfer, csky_insn.isize);
+      else
+	check_literals (csky_insn.opcode->transfer, csky_insn.max);
+    }
+
+  insn_reloc = BFD_RELOC_NONE;
+}
+
+/* Attempt to handle option with value C, returning non-zero on success.  */
+int
+md_parse_option (int c, const char *arg)
+{
+  switch (c)
+    {
+    case 0:
+      break;
+    case OPTION_MARCH:
+      parse_arch (arg);
+      break;
+    case OPTION_MCPU:
+      parse_cpu (arg);
+      break;
+    default:
+      return 0;
+    }
+  return 1;
+}
+
+/* Convert a machine dependent frag.  */
+#define PAD_LITERAL_LENGTH                        6
+#define opposite_of_stored_comp(insn)             (insn ^ 0x04000000)
+#define opposite_of_stored_compz(insn)            (insn ^ 0x00200000)
+#define make_insn(total_length, opcode, operand, operand_length)	\
+  do { 									\
+    if (total_length > 0)						\
+      {									\
+	csky_write_insn (buf,						\
+			 opcode | (operand & ((1 << operand_length) - 1)), \
+			 total_length);					\
+	buf += total_length;						\
+	fragp->fr_fix += total_length;					\
+      }									\
+  } while (0)
+
+#define make_literal(fragp, literal_offset)				\
+  do {									\
+    make_insn (literal_offset, PAD_FILL_CONTENT, 0, 0);			\
+    fix_new (fragp, fragp->fr_fix, 4, fragp->fr_symbol,			\
+	     fragp->fr_offset, 0, BFD_RELOC_CKCORE_ADDR32);		\
+    make_insn (4, 0, 0, 0);						\
+    make_insn (2 - literal_offset, PAD_FILL_CONTENT, 0, 0);		\
+  } while (0)
+
+void
+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec,  fragS *fragp)
+{
+  offsetT disp;
+  char *buf = fragp->fr_fix + fragp->fr_literal;
+
+  gas_assert (fragp->fr_symbol);
+  if (IS_EXTERNAL_SYM (fragp->fr_symbol, asec))
+    disp = 0;
+  else
+    disp = (S_GET_VALUE (fragp->fr_symbol)
+	    + fragp->fr_offset
+	    - fragp->fr_address
+	    - fragp->fr_fix);
+
+  switch (fragp->fr_subtype)
+    {
+      /* generate new insn.  */
+    case C (COND_JUMP, DISP12):
+    case C (UNCD_JUMP, DISP12):
+    case C (COND_JUMP_PIC, DISP12):
+    case C (UNCD_JUMP_PIC, DISP12):
+      {
+#define CSKY_V1_B_MASK   0xf8
+	unsigned char t0;
+	disp -= 2;
+	if (disp & 1)
+	  {
+	    /* Error. odd displacement at %x, next_inst-2.  */
+	    ;
+	  }
+	disp >>= 1;
+	
+	if (!target_big_endian)
+	  {
+	    t0 = buf[1] & CSKY_V1_B_MASK;
+	    md_number_to_chars (buf, disp, 2);
+	    buf[1] = (buf[1] & ~CSKY_V1_B_MASK) | t0;
+	  }
+	else
+	  {
+	    t0 = buf[0] & CSKY_V1_B_MASK;
+	    md_number_to_chars (buf, disp, 2);
+	    buf[0] = (buf[0] & ~CSKY_V1_B_MASK) | t0;
+	  }
+	fragp->fr_fix += 2;
+	break;
+      }
+    case C (COND_JUMP, DISP32):
+    case C (COND_JUMP, UNDEF_WORD_DISP):
+      {
+	/* A conditional branch wont fit into 12 bits:
+	   b!cond 1f
+	   jmpi 0f
+	   .align 2
+	   0: .long disp
+	   1:
+	*/
+	int first_inst = fragp->fr_fix + fragp->fr_address;
+	int is_unaligned = (first_inst & 3);
+	
+	if (!target_big_endian)
+	  {
+	    /* b!cond instruction.  */
+	    buf[1] ^= 0x08;
+	    /* jmpi instruction.  */
+	    buf[2] = CSKYV1_INST_JMPI & 0xff;
+	    buf[3] = CSKYV1_INST_JMPI >> 8;
+	  }
+	else
+	  {
+	    /* b!cond instruction.  */
+	    buf[0] ^= 0x08;
+	    /* jmpi instruction.  */
+	    buf[2] = CSKYV1_INST_JMPI >> 8;
+	    buf[3] = CSKYV1_INST_JMPI & 0xff;
+	  }
+	
+	if (is_unaligned)
+	  {
+	    if (!target_big_endian)
+	      {
+		/* bt/bf: jump to pc + 2 + (4 << 1).  */
+		buf[0] = 4;
+		/* jmpi: jump to MEM (pc + 2 + (1 << 2)).  */
+		buf[2] = 1;
+	      }
+	    else
+	      {
+		/* bt/bf: jump to pc + 2 + (4 << 1).  */
+		buf[1] = 4;
+		/* jmpi: jump to MEM (pc + 2 + (1 << 2)).  */
+		buf[3] = 1;
+	      }
+	    /* Aligned 4 bytes.  */
+	    buf[4] = 0;
+	    buf[5] = 0;
+	    /* .long  */
+	    buf[6] = 0;
+	    buf[7] = 0;
+	    buf[8] = 0;
+	    buf[9] = 0;
+	    
+	    /* Make reloc for the long disp.  */
+	    fix_new (fragp, fragp->fr_fix + 6, 4,
+		     fragp->fr_symbol, fragp->fr_offset, 0, BFD_RELOC_32);
+	    fragp->fr_fix += C32_LEN;
+	  }
+	else
+	  {
+	    if (!target_big_endian)
+	      {
+		/* bt/bf: jump to pc + 2 + (3 << 1).  */
+		buf[0] = 3;
+		/* jmpi: jump to MEM (pc + 2 + (0 << 2)).  */
+		buf[2] = 0;
+	      }
+	    else
+	      {
+		/* bt/bf: jump to pc + 2 + (3 << 1).  */
+		buf[1] = 3;
+		/* jmpi: jump to MEM (pc + 2 + (0 << 2)).  */
+		buf[3] = 0;
+	      }
+	    /* .long  */
+	    buf[4] = 0;
+	    buf[5] = 0;
+	    buf[6] = 0;
+	    buf[7] = 0;
+	    
+	    /* Make reloc for the long disp.  */
+	    fix_new (fragp, fragp->fr_fix + 4, 4,
+		     fragp->fr_symbol, fragp->fr_offset, 0, BFD_RELOC_32);
+	    fragp->fr_fix += C32_LEN;
+	    
+	    /* Frag is actually shorter (see the other side of this ifdef)
+	       but gas isn't prepared for that.  We have to re-adjust
+	       the branch displacement so that it goes beyond the
+	       full length of the fragment, not just what we actually
+	       filled in.  */
+	    if (!target_big_endian)
+	      buf[0] = 4;
+	    else
+	      buf[1] = 4;
+	  }
+      }
+      break;
+      
+    case C (COND_JUMP_PIC, DISP32):
+    case C (COND_JUMP_PIC, UNDEF_WORD_DISP):
+      {
+#define BYTE_1(a) (target_big_endian ? ((a) & 0xff) : ((a) >> 8))
+#define BYTE_0(a) (target_big_endian ? ((a) >> 8) : ((a) & 0xff))
+	/* b!cond 1f
+	   subi sp, 8
+	   stw  r15, (sp, 0)
+	   bsr  .L0
+	   .L0:
+	   lrw r1, 0f
+	   add r1, r15
+	   addi sp, 8
+	   jmp r1
+	   .align 2
+	   0: .long (tar_addr - pc)
+	   1:
+	*/
+	int first_inst = fragp->fr_fix + fragp->fr_address;
+	int is_unaligned = (first_inst & 3);
+	disp -= 8;
+	/* Toggle T/F bit.  */
+	if (! target_big_endian)
+	  buf[1] ^= 0x08;
+	else
+	  buf[0] ^= 0x08;
+	buf[2] = BYTE_0 (CSKYV1_INST_SUBI | (7 << 4));     /* subi r0, 8.  */
+	buf[3] = BYTE_1 (CSKYV1_INST_SUBI | (7 << 4));
+	buf[4] = BYTE_0 (CSKYV1_INST_STW  | (15 << 8));    /* stw r15, r0.  */
+	buf[5] = BYTE_1 (CSKYV1_INST_STW  | (15 << 8));
+	buf[6] = BYTE_0 (CSKYV1_INST_BSR);                 /* bsr pc + 2.  */
+	buf[7] = BYTE_1 (CSKYV1_INST_BSR);
+	buf[8] = BYTE_0 (CSKYV1_INST_LRW | (1 << 8));      /* lrw r1, (tar_addr - pc).  */
+	buf[9] = BYTE_1 (CSKYV1_INST_LRW | (1 << 8));
+	buf[10] = BYTE_0 (CSKYV1_INST_ADDU | (15 << 4) | 1);  /* add r1, r15.  */
+	buf[11] = BYTE_1 (CSKYV1_INST_ADDU | (15 << 4) | 1);
+	buf[12] = BYTE_0 (CSKYV1_INST_LDW | (15 << 8));     /* ldw r15, r0.  */
+	buf[13] = BYTE_1 (CSKYV1_INST_LDW | (15 << 8));
+	buf[14] = BYTE_0 (CSKYV1_INST_ADDI | (7 << 4));     /* addi r0, 8.  */
+	buf[15] = BYTE_1 (CSKYV1_INST_ADDI | (7 << 4));
+	buf[16] = BYTE_0 (CSKYV1_INST_JMP | 1);             /* jmp r1.  */
+	buf[17] = BYTE_1 (CSKYV1_INST_JMP | 1);
+	
+	if (!is_unaligned)
+	  {
+	    if (!target_big_endian)
+	      {
+		buf[0] = 11;
+		buf[8] = 3;
+		buf[20] = disp & 0xff;
+		buf[21] = (disp >> 8) & 0xff;
+		buf[22] = (disp >> 16) & 0xff;
+		buf[23] = (disp >> 24) & 0xff;
+	      }
+	    else /* if !target_big_endian.  */
+	      {
+		buf[1] = 11;
+		buf[9] = 3;
+		buf[20] = (disp >> 24) & 0xff;
+		buf[21] = (disp >> 16) & 0xff;
+		buf[22] = (disp >> 8) & 0xff;
+		buf[23] = disp & 0xff;
+	      }
+	    buf[18] = 0;  /* alignment.  */
+	    buf[19] = 0;
+	    fragp->fr_fix += C32_LEN_PIC;
+	  }
+	else  /* if !is_unaligned.  */
+	  {
+	    if (!target_big_endian)
+	      {
+		buf[0] = 11;
+		buf[8] = 2;
+		buf[18] = disp & 0xff;
+		buf[19] = (disp >> 8) & 0xff;
+		buf[20] = (disp >> 16) & 0xff;
+		buf[21] = (disp >> 24) & 0xff;
+	      }
+	    else /* if !target_big_endian.  */
+	      {
+		buf[1] = 11;
+		buf[9] = 2;
+		buf[18] = (disp >> 24) & 0xff;
+		buf[19] = (disp >> 16) & 0xff;
+		buf[20] = (disp >> 8) & 0xff;
+		buf[21] = disp & 0xff;
+	      }
+	    fragp->fr_fix += C32_LEN_PIC;
+	    
+	  } /* end if is_unaligned.  */
+      } /* end case C (COND_JUMP_PIC, DISP32)/C (COND_JUMP_PIC, UNDEF_WORD_DISP).  */
+      break;
+    case C (UNCD_JUMP, DISP32):
+    case C (UNCD_JUMP, UNDEF_WORD_DISP):
+      {
+	/* jmpi 0f
+	   .align 2
+	   0: .long disp.  */
+	int first_inst = fragp->fr_fix + fragp->fr_address;
+	int is_unaligned = (first_inst & 3);
+	/* Build jmpi.  */
+	buf[0] = BYTE_0 (CSKYV1_INST_JMPI);
+	buf[1] = BYTE_1 (CSKYV1_INST_JMPI);
+	if (!is_unaligned)
+	  {
+	    if (!target_big_endian)
+	      buf[0] = 1;
+	    else
+	      buf[1] = 1;
+	    /* Alignment.  */
+	    buf[2] = 0;
+	    buf[3] = 0;
+	    /* .long  */
+	    buf[4] = 0;
+	    buf[5] = 0;
+	    buf[6] = 0;
+	    buf[7] = 0;
+	    fix_new (fragp, fragp->fr_fix + 4, 4,
+		     fragp->fr_symbol, fragp->fr_offset, 0, BFD_RELOC_32);
+	    fragp->fr_fix += U32_LEN;
+	  }
+	else /* if is_unaligned.  */
+	  {
+	    if (!target_big_endian)
+	      buf[0] = 0;
+	    else
+	      buf[1] = 0;
+	    /* .long  */
+	    buf[2] = 0;
+	    buf[3] = 0;
+	    buf[4] = 0;
+	    buf[5] = 0;
+	    fix_new (fragp, fragp->fr_fix + 2, 4,
+		     fragp->fr_symbol, fragp->fr_offset, 0, BFD_RELOC_32);
+	    fragp->fr_fix += U32_LEN;
+	    
+	  }
+      }
+      break;
+    case C (UNCD_JUMP_PIC, DISP32):
+    case C (UNCD_JUMP_PIC, UNDEF_WORD_DISP):
+      {
+	/*    subi sp, 8
+	      stw  r15, (sp)
+	      bsr  .L0
+	      .L0:
+	      lrw  r1, 0f
+	      add  r1, r15
+	      ldw  r15, (sp)
+	      addi sp, 8
+	      jmp r1
+	      .align 2
+	      0: .long (tar_add - pc)
+	      1:
+	*/
+	/* If the b!cond is 4 byte aligned, the literal which would
+	   go at x+4 will also be aligned.  */
+	int first_inst = fragp->fr_fix + fragp->fr_address;
+	int is_unaligned = (first_inst & 3);
+	disp -= 6;
+	
+	buf[0] = BYTE_0 (CSKYV1_INST_SUBI | (7 << 4));     /* subi r0, 8.  */
+	buf[1] = BYTE_1 (CSKYV1_INST_SUBI | (7 << 4));
+	buf[2] = BYTE_0 (CSKYV1_INST_STW  | (15 << 8));    /* stw r15, r0.  */
+	buf[3] = BYTE_1 (CSKYV1_INST_STW  | (15 << 8));
+	buf[4] = BYTE_0 (CSKYV1_INST_BSR);                 /* bsr pc + 2.  */
+	buf[5] = BYTE_1 (CSKYV1_INST_BSR);
+	buf[6] = BYTE_0 (CSKYV1_INST_LRW | (1 << 8));      /* lrw r1, (tar_addr - pc).  */
+	buf[7] = BYTE_1 (CSKYV1_INST_LRW | (1 << 8));
+	buf[8] = BYTE_0 (CSKYV1_INST_ADDU | (15 << 4) | 1);  /* add r1, r15.  */
+	buf[9] = BYTE_1 (CSKYV1_INST_ADDU | (15 << 4) | 1);
+	buf[10] = BYTE_0 (CSKYV1_INST_LDW | (15 << 8));     /* ldw r15, r0.  */
+	buf[11] = BYTE_1 (CSKYV1_INST_LDW | (15 << 8));
+	buf[12] = BYTE_0 (CSKYV1_INST_ADDI | (7 << 4));     /* addi r0, 8.  */
+	buf[13] = BYTE_1 (CSKYV1_INST_ADDI | (7 << 4));
+	buf[14] = BYTE_0 (CSKYV1_INST_JMP | 1);             /* jmp r1.  */
+	buf[15] = BYTE_1 (CSKYV1_INST_JMP | 1);
+	
+	if (is_unaligned)
+	  {
+	    if (!target_big_endian)
+	      {
+		buf[6] = 3;
+		buf[18] = disp & 0xff;
+		buf[19] = (disp >> 8) & 0xff;
+		buf[20] = (disp >> 16) & 0xff;
+		buf[21] = (disp >> 24) & 0xff;
+	      }
+	    else
+	      {
+		buf[7] = 3;
+		buf[18] = (disp >> 24) & 0xff;
+		buf[19] = (disp >> 16) & 0xff;
+		buf[20] = (disp >> 8) & 0xff;
+		buf[21] = disp & 0xff;
+	      }
+	    buf[16] = 0;
+	    buf[17] = 0;
+	    fragp->fr_fix += U32_LEN_PIC;
+	  }
+	else
+	  {
+	    if (!target_big_endian)
+	      {
+		buf[6] = 2;
+		buf[16] = disp & 0xff;
+		buf[17] = (disp >> 8) & 0xff;
+		buf[18] = (disp >> 16) & 0xff;
+		buf[19] = (disp >> 24) & 0xff;
+	      }
+	    else
+	      {
+		buf[7] = 2;
+		buf[16] = (disp >> 24) & 0xff;
+		buf[17] = (disp >> 16) & 0xff;
+		buf[18] = (disp >> 8) & 0xff;
+		buf[19] = disp & 0xff;
+	      }
+	    fragp->fr_fix += U32_LEN_PIC;
+	  }
+      }
+      break;
+    case COND_DISP10:
+    case SCOND_DISP10:
+    case UNCD_DISP10:
+    case JCOND_DISP10:
+    case JUNCD_DISP10:
+      {
+	unsigned int inst = csky_read_insn (buf, 2);
+	inst |= (disp >> 1) & ((1 << 10) - 1);
+	csky_write_insn (buf, inst, 2);
+	fragp->fr_fix += 2;
+	break;
+      }
+    case SCOND_DISP16:
+      {
+	unsigned int inst = csky_read_insn (buf, 2);
+	
+	if (inst == CSKYV2_INST_BT16)
+	  inst = CSKYV2_INST_BF16;
+	else
+	  inst = CSKYV2_INST_BT16;
+	make_insn (2, inst, (2 + 4) >> 1, 10);
+	if (IS_EXTERNAL_SYM (fragp->fr_symbol, asec))
+	  fix_new (fragp, fragp->fr_fix, 4,
+		   fragp->fr_symbol, fragp->fr_offset, 1,
+		   BFD_RELOC_CKCORE_PCREL_IMM16BY2);
+	disp -= 2;
+	inst = CSKYV2_INST_BR32 | ((disp >> 1) & ((1 << 16) - 1));
+	csky_write_insn (buf, inst, 4);
+	fragp->fr_fix += 4;
+	break;
+      }
+    case COND_DISP16:
+    case JCOND_DISP16:
+      {
+	unsigned int inst = csky_read_insn (buf, 2);
+	
+	if (inst == CSKYV2_INST_BT16)
+	  inst = CSKYV2_INST_BT32;
+	else
+	  inst = CSKYV2_INST_BF32;
+	if (IS_EXTERNAL_SYM (fragp->fr_symbol, asec))
+	  fix_new (fragp, fragp->fr_fix, 4,
+		   fragp->fr_symbol, fragp->fr_offset, 1,
+		   BFD_RELOC_CKCORE_PCREL_IMM16BY2);
+	inst |= (disp >> 1) & ((1 << 16) - 1);
+	csky_write_insn (buf, inst, 4);
+	fragp->fr_fix += 4;
+	break;
+      }
+    case LRW_DISP7:
+      {
+	unsigned int inst = csky_read_insn (buf, 2);
+	int imm;
+	imm = (disp + 2) >> 2;
+	inst |= (imm >> 5) << 8;
+	make_insn (2, inst, (imm & 0x1f), 5);
+	break;
+      }
+    case LRW2_DISP8:
+      {
+	unsigned int inst = csky_read_insn (buf, 2);
+	int imm = (disp + 2) >> 2;
+	if (imm >= 0x80)
+	  {
+	    inst &= 0xe0;
+	    inst |= (~((imm >> 5) << 8)) & 0x300;
+	    make_insn (2, inst, (~imm & 0x1f), 5);
+	  }
+	else
+	  {
+	    inst |= (imm >> 5) << 8;
+	    make_insn (2, inst, (imm & 0x1f), 5);
+	  }
+	break;
+      }
+    case LRW_DISP16:
+      {
+	unsigned int inst = csky_read_insn (buf, 2);
+	inst = CSKYV2_INST_LRW32 | (((inst & 0xe0) >> 5) << 16);
+	if (IS_EXTERNAL_SYM (fragp->fr_symbol, asec))
+	  fix_new (fragp, fragp->fr_fix, 4,
+		   fragp->fr_symbol, fragp->fr_offset, 1,
+		   BFD_RELOC_CKCORE_PCREL_IMM16BY4);
+	make_insn (4, inst, ((disp + 2) >> 2), 16);
+	break;
+      }
+    case JCOMPZ_DISP16:
+      {
+	unsigned int inst = csky_read_insn (buf, 4);
+	make_insn (4, inst, disp >> 1, 16);
+      }
+      break;
+    case JCOMPZ_DISP32:
+      {
+	unsigned int inst = csky_read_insn (buf, 4);
+	int literal_offset;
+	make_insn (4, opposite_of_stored_compz (inst),
+		   (4 + 4 + PAD_LITERAL_LENGTH) >> 1, 16);
+	literal_offset = ((fragp->fr_address + fragp->fr_fix) % 4 == 0
+			  ? 0 : 2);
+	make_insn (4, CSKYV2_INST_JMPI32, (4 + literal_offset + 2) >> 2, 10);
+	make_literal (fragp, literal_offset);
+      }
+      break;
+    case JUNCD_DISP16:
+    case UNCD_DISP16:
+      {
+	if (IS_EXTERNAL_SYM (fragp->fr_symbol, asec))
+	  fix_new (fragp, fragp->fr_fix, 4,
+		   fragp->fr_symbol, fragp->fr_offset, 1,
+		   BFD_RELOC_CKCORE_PCREL_IMM16BY2);
+	make_insn (4, CSKYV2_INST_BR32, disp >> 1, 16);
+      }
+      break;
+    case JCOND_DISP32:
+      {
+	/* 'jbt'/'jbf'-> <bf16/bt16>; jmpi32; [pad16]+literal32  */
+	unsigned int inst = csky_read_insn (buf, 2);
+	int literal_offset;
+	
+	if (inst == CSKYV2_INST_BT16)
+	  inst = CSKYV2_INST_BF16;
+	else
+	  inst = CSKYV2_INST_BT16;
+	make_insn (2, inst, (2 + 4 + PAD_LITERAL_LENGTH) >> 1, 10);
+	literal_offset = ((fragp->fr_address + fragp->fr_fix) % 4 == 0
+			  ? 0 : 2);
+	make_insn (4, CSKYV2_INST_JMPI32, (4 + literal_offset + 2) >> 2, 10);
+	make_literal (fragp, literal_offset);
+	break;
+      }
+    case JUNCD_DISP32:
+      {
+	int literal_offset;
+	literal_offset = ((fragp->fr_address + fragp->fr_fix) % 4 == 0
+			  ? 0 : 2);
+	make_insn (4, CSKYV2_INST_JMPI32, (4 + literal_offset + 2) >> 2, 10);
+	make_literal (fragp, literal_offset);
+      }
+      break;
+    case RELAX_OVERFLOW:
+      csky_branch_report_error (fragp->fr_file, fragp->fr_line,
+				fragp->fr_symbol, disp);
+      break;
+    default:
+      abort ();
+      break;
+    }
+}
+
+/* Round up a section size to the appropriate boundary.  */
+
+valueT
+md_section_align (segT segment ATTRIBUTE_UNUSED,
+		  valueT size)
+{
+  return size;
+}
+
+/* MD interface: Symbol and relocation handling.  */
+
+void md_csky_end (void)
+{
+  dump_literals (0);
+}
+
+/* Return the address within the segment that a PC-relative fixup is
+   relative to.  */
+
+long
+md_pcrel_from_section (fixS * fixP, segT seg)
+{
+  /* If the symbol is undefined or defined in another section
+     we leave the add number alone for the linker to fix it later.  */
+  if (fixP->fx_addsy != (symbolS *) NULL
+      && (! S_IS_DEFINED (fixP->fx_addsy)
+	  || S_GET_SEGMENT (fixP->fx_addsy) != seg))
+    return fixP->fx_size;
+
+  /* The case where we are going to resolve things.  */
+  return  fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
+}
+
+/* csky_cons_fix_new is called via the expression parsing code when a
+   reloc is needed.  We use this hook to get the correct .got reloc.  */
+void
+csky_cons_fix_new (fragS *frag,
+		   unsigned int off,
+		   unsigned int len,
+		   expressionS *exp,
+		   bfd_reloc_code_real_type reloc)
+
+{
+  if (BFD_RELOC_CKCORE_GOTOFF == insn_reloc
+      || BFD_RELOC_CKCORE_GOTPC == insn_reloc
+      || BFD_RELOC_CKCORE_GOT32 == insn_reloc
+      || BFD_RELOC_CKCORE_PLT32 == insn_reloc
+      || BFD_RELOC_CKCORE_TLS_LE32 == insn_reloc
+      || BFD_RELOC_CKCORE_TLS_GD32 == insn_reloc
+      || BFD_RELOC_CKCORE_TLS_LDM32 == insn_reloc
+      || BFD_RELOC_CKCORE_TLS_LDO32 == insn_reloc
+      || BFD_RELOC_CKCORE_TLS_IE32 == insn_reloc)
+    {
+      reloc = insn_reloc;
+      if (BFD_RELOC_CKCORE_TLS_IE32 == insn_reloc
+	  || BFD_RELOC_CKCORE_TLS_GD32 == insn_reloc
+	  || BFD_RELOC_CKCORE_TLS_LDM32 == insn_reloc)
+	{
+	  exp->X_add_number = (offsetT) (&literal_insn_offset->tls_addend);
+	  if (count_tls > 1024)
+	    as_bad (_("tls variable number %u more than 1024, array overflow"),
+		    count_tls);
+	}
+    }
+  else
+    switch (len)
+      {
+      case 1:
+	reloc = BFD_RELOC_8;
+	break;
+      case 2:
+	reloc = BFD_RELOC_16;
+	break;
+      case 4:
+	reloc = BFD_RELOC_32;
+	break;
+      case 8:
+	reloc = BFD_RELOC_64;
+	break;
+      default:
+	as_bad (_("unsupported BFD relocation size %u"), len);
+	reloc = BFD_RELOC_32;
+	break;
+      }
+  fix_new_exp (frag, off, (int) len, exp, 0, reloc);
+}
+
+/* See whether we need to force a relocation into the output file.
+   This is used to force out switch and PC relative relocations when
+   relaxing.  */
+
+int
+csky_force_relocation (fixS * fix)
+{
+  if (fix->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+      || fix->fx_r_type == BFD_RELOC_VTABLE_ENTRY
+      || fix->fx_r_type == BFD_RELOC_RVA
+      || fix->fx_r_type == BFD_RELOC_CKCORE_ADDR_HI16
+      || fix->fx_r_type == BFD_RELOC_CKCORE_ADDR_LO16
+      || fix->fx_r_type == BFD_RELOC_CKCORE_TOFFSET_LO16
+      || fix->fx_r_type == BFD_RELOC_CKCORE_DOFFSET_LO16)
+    return 1;
+
+  if (fix->fx_addsy == NULL)
+    return 0;
+
+  if (do_use_branchstub
+      && fix->fx_r_type == BFD_RELOC_CKCORE_PCREL_IMM26BY2
+      && (symbol_get_bfdsym (fix->fx_addsy)->flags & BSF_FUNCTION))
+    return 1;
+  return S_FORCE_RELOC (fix->fx_addsy, fix->fx_subsy == NULL);
+}
+
+/* Return true if the fix can be handled by GAS, false if it must
+   be passed through to the linker.  */
+
+bfd_boolean
+csky_fix_adjustable (fixS * fixP)
+{
+  if (fixP->fx_addsy == NULL)
+    return 1;
+
+  /* We need the symbol name for the VTABLE entries.  */
+  if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
+      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_PLT32
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_GOT32
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_PLT12
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_GOT12
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_GOT_HI16
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_GOT_LO16
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_PLT_HI16
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_PLT_LO16
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_GOTOFF
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_GOTOFF_HI16
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_GOTOFF_LO16
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_ADDR_HI16
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_ADDR_LO16
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_GOT_IMM18BY4
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_PLT_IMM18BY4
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_GOTOFF_IMM18
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_TLS_LE32
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_TLS_IE32
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_TLS_GD32
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_TLS_LDM32
+      || fixP->fx_r_type == BFD_RELOC_CKCORE_TLS_LDO32)
+    return 0;
+
+  if (do_use_branchstub
+      && fixP->fx_r_type == BFD_RELOC_CKCORE_PCREL_IMM26BY2
+      && (symbol_get_bfdsym (fixP->fx_addsy)->flags & BSF_FUNCTION))
+    return 0;
+
+  return 1;
+}
+
+void
+md_apply_fix (fixS   *fixP,
+	      valueT *valP,
+	      segT   seg)
+{
+  reloc_howto_type *howto;
+  /* Note: use offsetT because it is signed, valueT is unsigned.  */
+  offsetT val = *valP;
+  char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
+
+  /* if fx_done = 0, fixup will also be processed in
+   * tc_gen_reloc() after md_apply_fix().  */
+  fixP->fx_done = 0;
+
+  /* If the fix is relative to a symbol which is not defined, or not
+     in the same segment as the fix, we cannot resolve it here.  */
+  if (IS_CSKY_V1 (mach_flag) && fixP->fx_addsy != NULL
+      && (! S_IS_DEFINED (fixP->fx_addsy)
+	  || S_GET_SEGMENT (fixP->fx_addsy) != seg))
+    {
+      switch (fixP->fx_r_type)
+       {
+	 /* Data fx_addnumber is greater than 16 bits,
+	    so fx_addnumber is assigned zero.  */
+       case BFD_RELOC_CKCORE_PCREL_JSR_IMM11BY2:
+	 *valP = 0;
+	 break;
+       case BFD_RELOC_CKCORE_TLS_IE32:
+       case BFD_RELOC_CKCORE_TLS_LDM32:
+       case BFD_RELOC_CKCORE_TLS_GD32:
+	 {
+	   struct tls_addend *ta;
+	   ta = (struct tls_addend*)(fixP->fx_offset);
+	   fixP->fx_offset
+	     = (fixP->fx_frag->fr_address + fixP->fx_where
+		- (ta->frag->fr_address + ta->offset));
+	 }
+       case BFD_RELOC_CKCORE_TLS_LE32:
+       case BFD_RELOC_CKCORE_TLS_LDO32:
+	 S_SET_THREAD_LOCAL (fixP->fx_addsy);
+	 break;
+       default:
+	 break;
+       }
+#ifdef OBJ_ELF
+      /* For ELF we can just return and let the reloc that will be generated
+	 take care of everything.  For COFF we still have to insert 'val'
+	 into the insn since the addend field will be ignored.  */
+      return;
+#endif
+    }
+
+  /* We can handle these relocs.  */
+  switch (fixP->fx_r_type)
+    {
+    case BFD_RELOC_CKCORE_PCREL32:
+      break;
+    case BFD_RELOC_VTABLE_INHERIT:
+      fixP->fx_r_type = BFD_RELOC_CKCORE_GNU_VTINHERIT;
+      if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy)
+	  && !S_IS_WEAK (fixP->fx_addsy))
+	S_SET_WEAK (fixP->fx_addsy);
+      break;
+    case BFD_RELOC_VTABLE_ENTRY:
+      fixP->fx_r_type = BFD_RELOC_CKCORE_GNU_VTENTRY;
+      break;
+    case BFD_RELOC_CKCORE_GOT12:
+    case BFD_RELOC_CKCORE_PLT12:
+    case BFD_RELOC_CKCORE_ADDR_HI16:
+    case BFD_RELOC_CKCORE_ADDR_LO16:
+    case BFD_RELOC_CKCORE_TOFFSET_LO16:
+    case BFD_RELOC_CKCORE_DOFFSET_LO16:
+    case BFD_RELOC_CKCORE_GOT_HI16:
+    case BFD_RELOC_CKCORE_GOT_LO16:
+    case BFD_RELOC_CKCORE_PLT_HI16:
+    case BFD_RELOC_CKCORE_PLT_LO16:
+    case BFD_RELOC_CKCORE_GOTPC_HI16:
+    case BFD_RELOC_CKCORE_GOTPC_LO16:
+    case BFD_RELOC_CKCORE_GOTOFF_HI16:
+    case BFD_RELOC_CKCORE_GOTOFF_LO16:
+    case BFD_RELOC_CKCORE_DOFFSET_IMM18:
+    case BFD_RELOC_CKCORE_DOFFSET_IMM18BY2:
+    case BFD_RELOC_CKCORE_DOFFSET_IMM18BY4:
+    case BFD_RELOC_CKCORE_GOTOFF_IMM18:
+    case BFD_RELOC_CKCORE_GOT_IMM18BY4:
+    case BFD_RELOC_CKCORE_PLT_IMM18BY4:
+      break;
+    case BFD_RELOC_CKCORE_TLS_IE32:
+    case BFD_RELOC_CKCORE_TLS_LDM32:
+    case BFD_RELOC_CKCORE_TLS_GD32:
+      {
+	struct tls_addend * ta;
+	ta = (struct tls_addend*)(fixP->fx_offset);
+	fixP->fx_offset= (fixP->fx_frag->fr_address + fixP->fx_where)
+	  - (ta->frag->fr_address + ta->offset);
+      }
+    case BFD_RELOC_CKCORE_TLS_LE32:
+    case BFD_RELOC_CKCORE_TLS_LDO32:
+      S_SET_THREAD_LOCAL (fixP->fx_addsy);
+      break;
+    case BFD_RELOC_32:
+      fixP->fx_r_type = BFD_RELOC_CKCORE_ADDR32;
+    case BFD_RELOC_16:
+    case BFD_RELOC_8:
+      if (fixP->fx_addsy == NULL)
+	{
+	  if (fixP->fx_size == 4)
+	    ;
+	  else if (fixP->fx_size == 2 && val >= -32768 && val <= 32767)
+	    ;
+	  else if (fixP->fx_size == 1 && val >= -256 && val <= 255)
+	    ;
+	  else
+	    abort ();
+	  md_number_to_chars (buf, val, fixP->fx_size);
+	  fixP->fx_done = 1;
+	}
+      break;
+    case BFD_RELOC_CKCORE_PCREL_JSR_IMM11BY2:
+      if (fixP->fx_addsy == 0 && val > -2 KB && val < 2 KB)
+	{
+	  long nval = (val >> 1) & 0x7ff;
+	  nval |= CSKYV1_INST_BSR;
+	  csky_write_insn (buf, nval, 2);
+	  fixP->fx_done = 1;
+	}
+      else
+	*valP = 0;
+      break;
+    case BFD_RELOC_CKCORE_PCREL_JSR_IMM26BY2:
+      if (fixP->fx_addsy == 0)
+	{
+	  if (val >= -(1 << 26) && val < (1 << 26))
+	    {
+	      unsigned int nval = ((val + fixP->fx_size) >> 1) & 0x3ffffff;
+	      nval |= CSKYV2_INST_BSR32;
+	      
+	      csky_write_insn (buf, nval, 4);
+	    }
+	  /* If bsr32 cannot reach,
+	     generate 'lrw r25,label;jsr r25' instead of 'jsri label'.  */
+	  else if (IS_CSKY_ARCH_810 (mach_flag))
+	    {
+	      howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+	      valueT opcode = csky_read_insn (buf, 4);
+	      opcode = (opcode & howto->dst_mask) | CSKYV2_INST_JSRI_TO_LRW;
+	      csky_write_insn (buf, opcode, 4);
+	      opcode = CSKYV2_INST_JSR_R26;
+	      csky_write_insn (buf + 4, opcode, 4);
+	    }
+	  fixP->fx_done = 1;
+	}
+      break;
+      
+    default:
+      {
+	valueT opcode;
+	offsetT min, max;
+	unsigned int issigned = 0;
+	
+	if (fixP->fx_addsy)
+	  break;
+	
+	howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+	if (howto == NULL)
+	  {
+	    if (fixP->fx_size == 4
+		|| (fixP->fx_size == 2 && val >= -32768 && val <= 32767)
+		|| (fixP->fx_size == 1 && val >= -256 && val <= 255))
+	      {
+		md_number_to_chars (buf, val, fixP->fx_size);
+		fixP->fx_done = 1;
+		break;
+	      }
+	    else
+	      abort ();
+	  }
+	
+	if (IS_CSKY_V2 (mach_flag))
+	  val += fixP->fx_size;
+	
+	if (howto->rightshift == 2)
+	  val += 2;
+	
+	val >>= howto->rightshift;
+	
+	switch (fixP->fx_r_type)
+	  {
+	    /* Offset is unsigned.  */
+	  case BFD_RELOC_CKCORE_PCREL_IMM8BY4:
+	  case BFD_RELOC_CKCORE_PCREL_IMM10BY4:
+	  case BFD_RELOC_CKCORE_PCREL_IMM16BY4:
+	    max = (offsetT) howto->dst_mask;
+	    min = 0;
+	    break;
+	    /* lrw16.  */
+	  case BFD_RELOC_CKCORE_PCREL_IMM7BY4:
+	    if (do_extend_lrw)
+	      max = (offsetT)((1 << (howto->bitsize + 1)) - 2);
+	    else
+	      max = (offsetT)((1 << howto->bitsize) - 1);
+	    min = 0;
+	    break;
+	    /* flrws, flrwd: the offset bits are divided in two parts.  */
+	  case BFD_RELOC_CKCORE_PCREL_FLRW_IMM8BY4:
+	    max = (offsetT)((1 << howto->bitsize) - 1);
+	    min = 0;
+	    break;
+	    /* Offset is signed.  */
+	  default:
+	    max = (offsetT)(howto->dst_mask >> 1);
+	    min = - max - 1;
+	    issigned = 1;
+	  }
+	if (val < min || val > max)
+	  {
+	    csky_branch_report_error (fixP->fx_file, fixP->fx_line,
+				      fixP->fx_addsy, val);
+	    return;
+	  }
+	opcode = csky_read_insn (buf, fixP->fx_size);
+	/* Clear redundant bits brought from the last
+	   operation if there is any.  */
+	if (do_extend_lrw && (opcode & 0xfc00) == CSKYV2_INST_LRW16)
+	  val &= 0xff;
+	else
+	  val &= issigned ? (offsetT)(howto->dst_mask) : max;
+	
+	if (fixP->fx_r_type == BFD_RELOC_CKCORE_PCREL_BLOOP_IMM4BY4)
+	  val = (val & 0xf) << 12;
+	
+	if (fixP->fx_size == 2  && (opcode & 0xfc00) == CSKYV2_INST_LRW16)
+	  {
+	    /* 8 bit offset lrw16.  */
+	    if (val >= 0x80)
+	      csky_write_insn (buf,
+			       ((~val & 0x1f)
+				| ((~val & 0x60) << 3) | (opcode & 0xe0)),
+			       fixP->fx_size);
+	    /* 7 bit offset lrw16.  */
+	    else
+	      csky_write_insn (buf,
+			       (val & 0x1f) | ((val & 0x60) << 3) | opcode,
+			       fixP->fx_size);
+	  }
+	else if (fixP->fx_size == 4
+		 && (opcode & 0xfe1ffe00) == CSKYV2_INST_FLRW)
+	  csky_write_insn (buf,
+			   ((val & 0xf) << 4) | ((val & 0xf0) << 17) | opcode,
+			   fixP->fx_size);
+	else
+	  csky_write_insn (buf, val | opcode, fixP->fx_size);
+	fixP->fx_done = 1;
+	break;
+      }
+    }
+  fixP->fx_addnumber = val;
+}
+
+/* Translate internal representation of relocation info to BFD target
+   format.  */
+
+arelent *
+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
+{
+  arelent *rel;
+
+  rel = xmalloc (sizeof (arelent));
+  rel->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+  *rel->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
+  rel->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+  rel->addend = fixP->fx_offset;
+  if (rel->howto == NULL)
+    {
+      as_bad_where (fixP->fx_file, fixP->fx_line,
+		    _("Cannot represent relocation type %s"),
+		    bfd_get_reloc_code_name (fixP->fx_r_type));
+
+      /* Set howto to a garbage value so that we can keep going.  */
+      rel->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
+    }
+  gas_assert (rel->howto != NULL);
+  rel->address = fixP->fx_frag->fr_address + fixP->fx_where;
+  return rel;
+}
+
+/* Relax a fragment by scanning TC_GENERIC_RELAX_TABLE.  */
+long
+csky_relax_frag (segT segment, fragS *fragP, long stretch)
+{
+  const relax_typeS *this_type;
+  const relax_typeS *start_type;
+  relax_substateT next_state;
+  relax_substateT this_state;
+  offsetT growth;
+  offsetT aim;
+  addressT target;
+  addressT address;
+  symbolS *symbolP;
+  const relax_typeS *table;
+
+  target = fragP->fr_offset;
+  address = fragP->fr_address;
+  table = TC_GENERIC_RELAX_TABLE;
+  this_state = fragP->fr_subtype;
+  start_type = this_type = table + this_state;
+  symbolP = fragP->fr_symbol;
+
+  if (symbolP)
+    {
+      fragS *sym_frag;
+
+      sym_frag = symbol_get_frag (symbolP);
+
+#ifndef DIFF_EXPR_OK
+      know (sym_frag != NULL);
+#endif
+      know (S_GET_SEGMENT (symbolP) != absolute_section
+	    || sym_frag == &zero_address_frag);
+      target += S_GET_VALUE (symbolP);
+
+      /* If SYM_FRAG has yet to be reached on this pass, assume it
+	 will move by STRETCH just as we did, unless there is an
+	 alignment frag between here and SYM_FRAG.  An alignment may
+	 well absorb any STRETCH, and we don't want to choose a larger
+	 branch insn by overestimating the needed reach of this
+	 branch.  It isn't critical to calculate TARGET exactly;  We
+	 know we'll be doing another pass if STRETCH is non-zero.  */
+
+      if (stretch != 0
+	  && sym_frag->relax_marker != fragP->relax_marker
+	  && S_GET_SEGMENT (symbolP) == segment)
+	{
+	  fragS *f;
+
+	  /* Adjust stretch for any alignment frag.  Note that if have
+	     been expanding the earlier code, the symbol may be
+	     defined in what appears to be an earlier frag.  FIXME:
+	     This doesn't handle the fr_subtype field, which specifies
+	     a maximum number of bytes to skip when doing an
+	     alignment.  */
+	  for (f = fragP; f != NULL && f != sym_frag; f = f->fr_next)
+	    {
+	      if (f->fr_type == rs_align || f->fr_type == rs_align_code)
+		{
+		  if (stretch < 0)
+		    stretch = -((-stretch)
+				& ~((1 << (int) f->fr_offset) - 1));
+		  else
+		    stretch &= ~((1 << (int) f->fr_offset) - 1);
+		}
+	      if (stretch == 0)
+		break;
+	    }
+	  if (f != 0)
+	    target += stretch;
+	}
+    }
+
+  aim = target - address - fragP->fr_fix;
+
+  /* If the fragP->fr_symbol is extern symbol, aim should be 0.  */
+  if (fragP->fr_symbol && S_GET_SEGMENT (symbolP) != segment)
+    aim = 0;
+
+  if (aim < 0)
+    {
+      /* Look backwards.  */
+      for (next_state = this_type->rlx_more; next_state;)
+	if (aim >= this_type->rlx_backward)
+	  next_state = 0;
+	else
+	  {
+	    /* Grow to next state.  */
+	    this_state = next_state;
+	    this_type = table + this_state;
+	    next_state = this_type->rlx_more;
+	  }
+    }
+  else
+    {
+      /* Look forwards.  */
+      for (next_state = this_type->rlx_more; next_state;)
+	if (aim <= this_type->rlx_forward)
+	  next_state = 0;
+	else
+	  {
+	    /* Grow to next state.  */
+	    this_state = next_state;
+	    this_type = table + this_state;
+	    next_state = this_type->rlx_more;
+	  }
+    }
+
+  growth = this_type->rlx_length - start_type->rlx_length;
+  if (growth != 0)
+    fragP->fr_subtype = this_state;
+  return growth;
+}
+
+int
+md_estimate_size_before_relax (fragS * fragp,
+			       segT  segtype)
+{
+  switch (fragp->fr_subtype)
+    {
+    case COND_DISP10:
+    case COND_DISP16:
+    case SCOND_DISP10:
+    case SCOND_DISP16:
+    case UNCD_DISP10:
+    case UNCD_DISP16:
+    case JCOND_DISP10:
+    case JCOND_DISP16:
+    case JCOND_DISP32:
+    case JUNCD_DISP10:
+    case JUNCD_DISP16:
+    case JUNCD_DISP32:
+    case JCOMPZ_DISP16:
+    case JCOMPZ_DISP32:
+    case BSR_DISP26:
+    case LRW_DISP7:
+    case LRW2_DISP8:
+    case LRW_DISP16:
+      gas_assert (fragp->fr_symbol);
+      if (IS_EXTERNAL_SYM (fragp->fr_symbol, segtype))
+	while (csky_relax_table[fragp->fr_subtype].rlx_more > RELAX_OVERFLOW)
+	  fragp->fr_subtype = csky_relax_table[fragp->fr_subtype].rlx_more;
+      return csky_relax_table[fragp->fr_subtype].rlx_length;
+      
+      /* C-SKY V1 relaxes.  */
+    case C (UNCD_JUMP, UNDEF_DISP):
+    case C (UNCD_JUMP_PIC, UNDEF_DISP):
+      if (!fragp->fr_symbol)
+	fragp->fr_subtype = C (UNCD_JUMP_S, DISP12);
+      else if (S_GET_SEGMENT (fragp->fr_symbol) == segtype)
+	fragp->fr_subtype = C (UNCD_JUMP_S, DISP12);
+      else
+	fragp->fr_subtype = C (UNCD_JUMP_S, UNDEF_WORD_DISP);
+      break;
+      
+    case C (COND_JUMP, UNDEF_DISP):
+    case C (COND_JUMP_PIC, UNDEF_DISP):
+      if (fragp->fr_symbol
+	  && S_GET_SEGMENT (fragp->fr_symbol) == segtype)
+	/* Got a symbol and it's defined in this segment, become byte
+	   sized. Maybe it will fix up.  */
+	fragp->fr_subtype = C (COND_JUMP_S, DISP12);
+      else if (fragp->fr_symbol)
+	/* It's got a segment, but it's not ours, so it will always be
+	   long.  */
+	fragp->fr_subtype = C (COND_JUMP_S, UNDEF_WORD_DISP);
+      else
+	/* We know the abs value.  */
+	fragp->fr_subtype = C (COND_JUMP_S, DISP12);
+      break;
+      
+    case C (UNCD_JUMP, DISP12):
+    case C (UNCD_JUMP, DISP32):
+    case C (UNCD_JUMP, UNDEF_WORD_DISP):
+    case C (COND_JUMP, DISP12):
+    case C (COND_JUMP, DISP32):
+    case C (COND_JUMP, UNDEF_WORD_DISP):
+    case C (UNCD_JUMP_PIC, DISP12):
+    case C (UNCD_JUMP_PIC, DISP32):
+    case C (UNCD_JUMP_PIC, UNDEF_WORD_DISP):
+    case C (COND_JUMP_PIC, DISP12):
+    case C (COND_JUMP_PIC, DISP32):
+    case C (COND_JUMP_PIC, UNDEF_WORD_DISP):
+    case RELAX_OVERFLOW:
+      break;
+
+    default:
+      abort ();
+    }
+  return csky_relax_table[fragp->fr_subtype].rlx_length;
+}
+
+/* Parse opcode like: "op oprnd1, oprnd2, oprnd3".  */
+
+static void
+csky_macro_md_assemble (const char *op,
+			const char *oprnd1,
+			const char *oprnd2,
+			const char *oprnd3)
+{
+  char str[80];
+  str[0] = '\0';
+  strcat (str, op);
+  if (oprnd1 != NULL)
+    {
+      strcat (str, " ");
+      strcat (str, oprnd1);
+      if (oprnd2 != NULL)
+	{
+	  strcat (str, ",");
+	  strcat (str, oprnd2);
+	  if (oprnd3 != NULL)
+	    {
+	      strcat (str, ",");
+	      strcat (str, oprnd3);
+	    }
+	}
+    }
+  md_assemble (str);
+  return;
+}
+
+/* Get the string of operand.  */
+
+static int
+csky_get_macro_operand (char *src_s, char *dst_s, char end_sym)
+{
+  int nlen = 0;
+  while (ISSPACE (*src_s))
+    ++src_s;
+  while (*src_s != end_sym)
+    dst_s[nlen++] = *(src_s++);
+  dst_s[nlen] = '\0';
+  return nlen;
+}
+
+/* idly 4 -> idly4.  */
+
+static void
+csky_idly (void)
+{
+  char *s = csky_insn.opcode_end;
+  if (!is_imm_over_range (&s, 4, 4, -1))
+    {
+      as_bad (_("operand must be 4."));
+      return;
+    }
+  csky_macro_md_assemble ("idly4", NULL, NULL, NULL);
+  return;
+}
+
+/* rolc rd, 1 or roltc rd, 1 -> addc rd, rd.  */
+
+static void
+csky_rolc (void)
+{
+  char reg[10];
+  char *s = csky_insn.opcode_end;
+
+  s += csky_get_macro_operand (s, reg, ',');
+  ++s;
+
+  if (is_imm_over_range (&s, 1, 1, -1))
+    {
+      csky_macro_md_assemble ("addc", reg, reg, NULL);
+      return;
+    }
+  else
+    as_bad (_("operand must be 1."));
+}
+
+/* sxtrb0(1)(2) r1, rx -> xtbr0(1)(2) r1,rx; sextb r1.  */
+
+static void
+csky_sxtrb (void)
+{
+  char reg1[10];
+  char reg2[10];
+
+  char *s = csky_insn.opcode_end;
+  s += csky_get_macro_operand (s, reg1, ',');
+  ++s;
+  csky_get_macro_operand (s, reg2, '\0');
+
+  csky_macro_md_assemble (csky_insn.macro->name + 1, reg1, reg2, NULL);
+  csky_macro_md_assemble ("sextb", reg1, NULL, NULL);
+  return;
+}
+
+static void
+csky_movtf (void)
+{
+  char reg1[10];
+  char reg2[10];
+  char reg3[10];
+
+  char *s = csky_insn.opcode_end;
+  s += csky_get_macro_operand (s, reg1, ',');
+  ++s;
+
+  s += csky_get_macro_operand (s, reg2, ',');
+  ++s;
+
+  s += csky_get_macro_operand (s, reg3, '\0');
+  ++s;
+  csky_macro_md_assemble ("movt", reg1, reg2, NULL);
+  csky_macro_md_assemble ("movf", reg1, reg3, NULL);
+  return;
+}
+
+static bfd_boolean
+get_macro_reg_vals (int *reg1, int *reg2, int *reg3)
+{
+  int nlen;
+  char *s = csky_insn.opcode_end;
+
+  *reg1 = csky_get_reg_val (s, &nlen);
+  s += nlen;
+  if (*s != ',')
+    {
+      csky_show_error (ERROR_MISSING_COMMA, 0, NULL, NULL);
+      return FALSE;
+    }
+  s++;
+  *reg2 = csky_get_reg_val (s, &nlen);
+  s += nlen;
+  if (*s != ',')
+    {
+      csky_show_error (ERROR_MISSING_COMMA, 0, NULL, NULL);
+      return FALSE;
+    }
+  s++;
+  *reg3 = csky_get_reg_val (s, &nlen);
+  s += nlen;
+  if (*s != '\0')
+    {
+      csky_show_error (ERROR_BAD_END, 0, NULL, NULL);
+      return FALSE;
+    }
+  if (*reg1 == -1 || *reg2 == -1 || *reg3 == -1)
+    {
+      as_bad ("%s register is over range.", csky_insn.opcode_end);
+      return FALSE;
+    }
+  if (*reg1 != *reg2)
+    {
+      as_bad ("the first two registers must be same number.");
+      return FALSE;
+    }
+  if (*reg1 >= 15 || *reg3 >= 15)
+    {
+      as_bad ("64 bit operator src/dst register be less than 15.");
+      return FALSE;
+    }
+  return TRUE;
+}
+
+/* addc64 rx, rx, ry -> cmplt rx, rx, addc  rx, ry, addc  rx+1, ry+1.  */
+
+static void
+csky_addc64 (void)
+{
+  int reg1;
+  int reg2;
+  int reg3;
+
+  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);
+  return;
+}
+
+/* subc64 rx, rx, ry -> cmphs rx, rx, subc  rx, ry, subc  rx+1, ry+1.  */
+
+static void
+csky_subc64 (void)
+{
+  int reg1;
+  int reg2;
+  int reg3;
+
+  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);
+  return;
+}
+
+/* or64 rx, rx, ry -> or rx, ry, or rx+1, ry+1.  */
+
+static void
+csky_or64 (void)
+{
+  int reg1;
+  int reg2;
+  int reg3;
+
+  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);
+  return;
+}
+
+/* xor64 rx, rx, ry -> xor rx, ry, xor rx+1, ry+1.  */
+
+static void
+csky_xor64 (void)
+{
+  int reg1;
+  int reg2;
+  int reg3;
+
+  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);
+  return;
+}
+
+/* The following are V2 macro instructions.  */
+
+/* neg rd -> not rd, rd; addi rd, 1.  */
+
+static void
+csky_neg (void)
+{
+  char reg1[10];
+
+  char *s = csky_insn.opcode_end;
+  s += csky_get_macro_operand (s, reg1, '\0');
+  ++s;
+
+  csky_macro_md_assemble ("not", reg1, reg1, NULL);
+  csky_macro_md_assemble ("addi", reg1, "1", NULL);
+  return;
+}
+
+/* rsubi rd, imm16 -> not rd; addi rd, imm16 + 1  */
+
+static void
+csky_rsubi (void)
+{
+  char reg1[10];
+  char str_imm16[20];
+  unsigned int imm16 = 0;
+  expressionS e;
+  char *s = csky_insn.opcode_end;
+  s += csky_get_macro_operand (s, reg1, ',');
+  ++s;
+
+  s = parse_exp (s, &e);
+  if (e.X_op == O_constant)
+    imm16 = e.X_add_number;
+  else
+    csky_show_error (ERROR_IMM_ILLEGAL, 2, NULL, NULL);
+
+  sprintf (str_imm16, "%d", imm16 + 1);
+
+  csky_macro_md_assemble ("not", reg1, reg1, NULL);
+  csky_macro_md_assemble ("addi", reg1, str_imm16, NULL);
+  return;
+}
+
+/* Such as: asrc rd -> asrc rd, rd, 1.  */
+
+static void
+csky_arith (void)
+{
+  char reg1[10];
+  char *s = csky_insn.opcode_end;
+  s += csky_get_macro_operand (s, reg1, '\0');
+  ++s;
+  csky_macro_md_assemble (csky_insn.macro->name, reg1, reg1, "1");
+  return;
+}
+
+/* decne rd ->  if ck802: subi rd, 1; cmpnei rd, 0.
+   else: decne rd, rd, 1  */
+
+static void
+csky_decne (void)
+{
+  char reg1[10];
+  char *s = csky_insn.opcode_end;
+  s += csky_get_macro_operand (s, reg1, '\0');
+  ++s;
+  if (IS_CSKY_ARCH_802 (mach_flag))
+    {
+      csky_macro_md_assemble ("subi", reg1, "1", NULL);
+      csky_macro_md_assemble ("cmpnei", reg1, "0", NULL);
+    }
+  else
+    csky_macro_md_assemble ("decne", reg1, reg1, "1");
+  return;
+}
+
+/* If -mnolrw, lrw rd, imm -> movih rd, imm_hi16; ori rd, imm_lo16.  */
+
+static void
+csky_lrw (void)
+{
+  char reg1[10];
+  char imm[40];
+  char imm_hi16[40];
+  char imm_lo16[40];
+
+  char *s = csky_insn.opcode_end;
+  s += csky_get_macro_operand (s, reg1, ',');
+  ++s;
+  s += csky_get_macro_operand (s, imm, '\0');
+  ++s;
+
+  imm_hi16[0] = '\0';
+  strcat (imm_hi16, "(");
+  strcat (imm_hi16, imm);
+  strcat (imm_hi16, ") >> 16");
+  imm_lo16[0] = '\0';
+  strcat (imm_lo16, "(");
+  strcat (imm_lo16, imm);
+  strcat (imm_lo16, ") & 0xffff");
+
+  csky_macro_md_assemble ("movih", reg1, imm_hi16,  NULL);
+  csky_macro_md_assemble ("ori", reg1, reg1, imm_lo16);
+
+  return;
+}
+
+/* The following are worker functions for C-SKY v1.  */
+
+bfd_boolean
+v1_work_lrw (void)
+{
+  int reg;
+  int output_literal = csky_insn.val[1];
+
+  reg = csky_insn.val[0];
+  csky_insn.isize = 2;
+  csky_insn.output = frag_more (2);
+  if (csky_insn.e1.X_op == O_constant
+      && csky_insn.e1.X_add_number <= 0x7f
+      && csky_insn.e1.X_add_number >= 0)
+    /* lrw to movi.  */
+    csky_insn.inst = 0x6000 | reg | (csky_insn.e1.X_add_number << 4);
+  else
+    {
+      csky_insn.inst = csky_insn.opcode->op16[0].opcode;
+      csky_insn.inst |= reg << 8;
+      if (output_literal)
+	{
+	  int n = enter_literal (&csky_insn.e1, 0, 0, 0);
+
+	  /* Create a reference to pool entry.  */
+	  csky_insn.e1.X_op = O_symbol;
+	  csky_insn.e1.X_add_symbol = poolsym;
+	  csky_insn.e1.X_add_number = n << 2;
+	}
+
+      if (insn_reloc == BFD_RELOC_CKCORE_TLS_GD32
+	  || insn_reloc == BFD_RELOC_CKCORE_TLS_LDM32
+	  || insn_reloc == BFD_RELOC_CKCORE_TLS_IE32)
+	{
+	  literal_insn_offset->tls_addend.frag  = frag_now;
+	  literal_insn_offset->tls_addend.offset
+	    = (csky_insn.output
+	       - literal_insn_offset->tls_addend.frag->fr_literal);
+	}
+      fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal, 2,
+		   &csky_insn.e1, 1, BFD_RELOC_CKCORE_PCREL_IMM8BY4);
+    }
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+
+  return TRUE;
+}
+
+bfd_boolean
+v1_work_fpu_fo (void)
+{
+  int i = 0;
+  int inst;
+  int greg = -1;
+  char buff[50];
+  struct csky_opcode_info *opinfo = NULL;
+
+  if (csky_insn.isize == 4)
+    opinfo = &csky_insn.opcode->op32[csky_insn.opcode_idx];
+  else if (csky_insn.isize == 2)
+    opinfo = &csky_insn.opcode->op16[csky_insn.opcode_idx];
+
+  /* Firstly, get general reg.  */
+  for (i = 0;i < opinfo->operand_num; i++)
+    if (opinfo->oprnd.oprnds[i].type == OPRND_TYPE_GREG0_15)
+      greg = csky_insn.val[i];
+  gas_assert (greg != -1);
+
+  /* Secondly, get float inst.  */
+  csky_generate_insn ();
+  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);
+  md_assemble (buff);
+  sprintf (buff, "cpwir %s", csky_general_reg[greg]);
+  md_assemble (buff);
+
+  return FALSE;
+}
+
+bfd_boolean
+v1_work_fpu_fo_fc (void)
+{
+  int i = 0;
+  int inst;
+  int greg = -1;
+  char buff[50];
+  struct csky_opcode_info *opinfo = NULL;
+
+  if (csky_insn.isize == 4)
+    opinfo = &csky_insn.opcode->op32[csky_insn.opcode_idx];
+  else if (csky_insn.isize == 2)
+    opinfo = &csky_insn.opcode->op16[csky_insn.opcode_idx];
+
+  /* Firstly, get general reg.  */
+  for (i = 0;i < opinfo->operand_num; i++)
+    if (opinfo->oprnd.oprnds[i].type == OPRND_TYPE_GREG0_15)
+      greg = csky_insn.val[i];
+  gas_assert (greg != -1);
+
+  /* Secondly, get float inst.  */
+  csky_generate_insn ();
+  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);
+  md_assemble (buff);
+  sprintf (buff, "cpwir %s", csky_general_reg[greg]);
+  md_assemble (buff);
+  sprintf (buff, "cprc");
+  md_assemble (buff);
+
+  return FALSE;
+}
+
+bfd_boolean
+v1_work_fpu_write (void)
+{
+  int greg;
+  int freg;
+  char buff[50];
+
+  greg = csky_insn.val[0];
+  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]);
+  md_assemble (buff);
+
+  return FALSE;
+}
+
+bfd_boolean
+v1_work_fpu_read (void)
+{
+  int greg;
+  int freg;
+  char buff[50];
+
+  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]);
+  md_assemble (buff);
+
+  return FALSE;
+}
+
+bfd_boolean
+v1_work_fpu_writed (void)
+{
+  int greg;
+  int freg;
+  char buff[50];
+
+  greg = csky_insn.val[0];
+  freg = csky_insn.val[1];
+
+  if (greg & 0x1)
+    {
+      as_bad ("Even register number expected, but got \"r%d\"", greg);
+      return FALSE;
+    }
+  /* 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]);
+  else
+    sprintf (buff, "cpwgr %s,%s",
+	     csky_general_reg[greg], csky_cp_reg[freg]);
+  md_assemble (buff);
+  if (target_big_endian)
+    sprintf (buff, "cpwgr %s,%s",
+	     csky_general_reg[greg], csky_cp_reg[freg + 1]);
+  else
+    sprintf (buff, "cpwgr %s,%s",
+	     csky_general_reg[greg + 1], csky_cp_reg[freg + 1]);
+  md_assemble (buff);
+
+  return FALSE;
+}
+
+bfd_boolean
+v1_work_fpu_readd (void)
+{
+  int greg;
+  int freg;
+  char buff[50];
+
+  greg = csky_insn.val[0];
+  freg = csky_insn.val[1];
+
+  if (greg & 0x1)
+    {
+      as_bad ("Even register number expected, but got \"r%d\"", greg);
+      return FALSE;
+    }
+  /* 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]);
+  else
+    sprintf (buff, "cprgr %s,%s",
+	     csky_general_reg[greg], csky_cp_reg[freg]);
+  md_assemble (buff);
+  if (target_big_endian)
+    sprintf (buff, "cprgr %s,%s",
+	     csky_general_reg[greg], csky_cp_reg[freg + 1]);
+  else
+    sprintf (buff, "cprgr %s,%s",
+	     csky_general_reg[greg + 1], csky_cp_reg[freg + 1]);
+  md_assemble (buff);
+
+  return FALSE;
+}
+
+/* The following are for csky pseudo handling.  */
+
+bfd_boolean
+v1_work_jbsr (void)
+{
+  csky_insn.output = frag_more (2);
+  if (do_force2bsr)
+    /* Generate fixup BFD_RELOC_CKCORE_PCREL_IMM11BY2.  */
+    fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		 2, & csky_insn.e1, 1, BFD_RELOC_CKCORE_PCREL_IMM11BY2);
+  else
+    {
+      /* Using jsri instruction.  */
+      const char *name = "jsri";
+      csky_insn.opcode = (struct csky_opcode *)
+	hash_find (csky_opcodes_hash, name);
+      csky_insn.opcode_idx = 0;
+      csky_insn.isize = 2;
+
+      int n = enter_literal (&csky_insn.e1, 1, 0, 0);
+
+      /* Create a reference to pool entry.  */
+      csky_insn.e1.X_op = O_symbol;
+      csky_insn.e1.X_add_symbol = poolsym;
+      csky_insn.e1.X_add_number = n << 2;
+
+      /* Generate fixup BFD_RELOC_CKCORE_PCREL_IMM8BY4.  */
+      fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		   2, & csky_insn.e1, 1, BFD_RELOC_CKCORE_PCREL_IMM8BY4);
+
+      if (csky_insn.e1.X_op != O_absent && do_jsri2bsr)
+	/* Generate fixup BFD_RELOC_CKCORE_PCREL_JSR_IMM11BY2.  */
+	fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		     2, & (litpool + (csky_insn.e1.X_add_number >> 2))->e,
+		     1, BFD_RELOC_CKCORE_PCREL_JSR_IMM11BY2);
+    }
+  csky_generate_insn ();
+
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+
+  return TRUE;
+}
+
+/* The following are worker functions for csky v2 instruction handling.  */
+
+/* For nie/nir/ipush/ipop.  */
+bfd_boolean
+v2_work_istack (void)
+{
+  if (!do_intr_stack)
+    {
+      csky_show_error (ERROR_OPCODE_ILLEGAL, 0, NULL, NULL);
+      return FALSE;
+    }
+  csky_insn.output = frag_more (csky_insn.isize);
+  csky_insn.inst = csky_insn.opcode->op16[0].opcode;
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_btsti (void)
+{
+  if (!do_extend_lrw
+      && (csky_insn.flag_force == INSN_OPCODE16F
+	  || IS_CSKY_ARCH_801 (mach_flag)))
+    {
+      csky_show_error (ERROR_OPCODE_ILLEGAL, 0, NULL, NULL);
+      return FALSE;
+    }
+  if (!do_extend_lrw && csky_insn.isize == 2)
+    csky_insn.isize = 4;
+  /* Generate relax or reloc if necessary.  */
+  csky_generate_frags ();
+  /* Generate the insn by mask.  */
+  csky_generate_insn ();
+  /* Write inst to frag.  */
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_addi (void)
+{
+  csky_insn.isize = 2;
+  if (csky_insn.number == 2)
+    {
+      if (csky_insn.val[0] == 14
+	  && csky_insn.val[1] >= 0 && csky_insn.val[1] <= 0x1fc
+	  && (csky_insn.val[1] & 0x3) == 0
+	  && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  /* addi sp, sp, imm.  */
+	  csky_insn.inst = 0x1400 | ((csky_insn.val[1] >> 2) & 0x1f);
+	  csky_insn.inst |= (csky_insn.val[1] << 1) & 0x300;
+	  csky_insn.output = frag_more (2);
+	}
+      else if (csky_insn.val[0] < 8
+	       && csky_insn.val[1] >= 1 && csky_insn.val[1] <= 0x100
+	       && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  csky_insn.inst = 0x2000 | (csky_insn.val[0] << 8);
+	  csky_insn.inst |=  (csky_insn.val[1] - 1);
+	  csky_insn.output = frag_more (2);
+	}
+      else if (csky_insn.val[1] >= 1 && csky_insn.val[1] <= 0x10000
+	       && csky_insn.flag_force != INSN_OPCODE16F)
+	{
+	  csky_insn.inst = 0xe4000000 | (csky_insn.val[0] << 21);
+	  csky_insn.inst |= csky_insn.val[0] << 16;
+	  csky_insn.inst |= (csky_insn.val[1] - 1);
+	  csky_insn.isize = 4;
+	  csky_insn.output = frag_more (4);
+	}
+      else
+	{
+	  csky_show_error (ERROR_OPERANDS_ILLEGAL, 0,
+			   csky_insn.opcode_end, NULL);
+	  return FALSE;
+	}
+    }
+  else if (csky_insn.number == 3)
+    {
+      if (csky_insn.val[0] == 14
+	  && csky_insn.val[1] == 14
+	  && csky_insn.val[2] >= 0 && csky_insn.val[2] <= 0x1fc
+	  && (csky_insn.val[2] & 0x3) == 0
+	  && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  csky_insn.inst = 0x1400 | ((csky_insn.val[2] >> 2) & 0x1f);
+	  csky_insn.inst |= (csky_insn.val[2] << 1) & 0x300;
+	  csky_insn.output = frag_more (2);
+	}
+      else if (csky_insn.val[0] < 8
+	       && csky_insn.val[1] == 14
+	       && csky_insn.val[2] >= 0 && csky_insn.val[2] <= 0x3fc
+	       && (csky_insn.val[2] & 0x3) == 0
+	       && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  csky_insn.inst = 0x1800 | (csky_insn.val[0] << 8);
+	  csky_insn.inst |= csky_insn.val[2] >> 2;
+	  csky_insn.output = frag_more (2);
+	}
+      else if (csky_insn.val[0] < 8
+	       && csky_insn.val[0] == csky_insn.val[1]
+	       && csky_insn.val[2] >= 1 && csky_insn.val[2] <= 0x100
+	       && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  csky_insn.inst = 0x2000 | (csky_insn.val[0] << 8);
+	  csky_insn.inst |=  (csky_insn.val[2] - 1);
+	  csky_insn.output = frag_more (2);
+	}
+      else if (csky_insn.val[0] < 8
+	       && csky_insn.val[1] < 8
+	       && csky_insn.val[2] >= 1 && csky_insn.val[2] <= 0x8
+	       && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  csky_insn.inst = 0x5802 | (csky_insn.val[0] << 5);
+	  csky_insn.inst |= csky_insn.val[1] << 8;
+	  csky_insn.inst |= (csky_insn.val[2] - 1) << 2;
+	  csky_insn.output = frag_more (2);
+	}
+      else if (csky_insn.val[1] == 28
+	       && csky_insn.val[2] >= 1 && csky_insn.val[2] <= 0x40000
+	       && csky_insn.flag_force != INSN_OPCODE16F)
+	{
+	  csky_insn.inst = 0xcc1c0000 | (csky_insn.val[0] << 21);
+	  csky_insn.isize = 4;
+	  csky_insn.output = frag_more (4);
+	  if (insn_reloc == BFD_RELOC_CKCORE_GOTOFF)
+	    {
+	      fix_new_exp (frag_now, csky_insn.output-frag_now->fr_literal,
+			   4, &csky_insn.e1, 0, BFD_RELOC_CKCORE_GOTOFF_IMM18);
+	    }
+	  else
+	    csky_insn.inst |= (csky_insn.val[2] - 1);
+	}
+      else if (csky_insn.val[2] >= 1 && csky_insn.val[2] <= 0x1000
+	       && csky_insn.flag_force != INSN_OPCODE16F)
+	{
+	  csky_insn.inst = 0xe4000000 | (csky_insn.val[0] << 21);
+	  csky_insn.inst |= csky_insn.val[1] << 16;
+	  csky_insn.inst |= (csky_insn.val[2] - 1);
+	  csky_insn.isize = 4;
+	  csky_insn.output = frag_more (4);
+	}
+      else
+	{
+	  csky_show_error (ERROR_OPERANDS_ILLEGAL, 0,
+			   (char *)csky_insn.opcode_end, NULL);
+	  return FALSE;
+	}
+    }
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_subi (void)
+{
+  csky_insn.isize = 2;
+  if (csky_insn.number == 2)
+    {
+      if (csky_insn.val[0] == 14
+	  && csky_insn.val[1] >= 0 && csky_insn.val[2] <= 0x1fc
+	  && (csky_insn.val[1] & 0x3) == 0
+	  && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  csky_insn.inst = 0x1420 | ((csky_insn.val[1] >> 2) & 0x1f);
+	  csky_insn.inst |= (csky_insn.val[1] << 1) & 0x300;
+	}
+      else if (csky_insn.val[0] < 8
+	       && csky_insn.val[1] >= 1 && csky_insn.val[1] <= 0x100
+	       && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  csky_insn.inst = 0x2800 | (csky_insn.val[0] << 8);
+	  csky_insn.inst |=  (csky_insn.val[1] - 1);
+	}
+      else if (csky_insn.val[1] >= 1 && csky_insn.val[1] <= 0x10000
+	       && csky_insn.flag_force != INSN_OPCODE16F)
+	{
+	  csky_insn.inst = 0xe4001000 | (csky_insn.val[0] << 21);
+	  csky_insn.inst |= csky_insn.val[0] << 16;
+	  csky_insn.inst |= (csky_insn.val[1] - 1);
+	  csky_insn.isize = 4;
+	}
+      else
+	{
+	  csky_show_error (ERROR_OPERANDS_ILLEGAL, 0,
+			   (char *)csky_insn.opcode_end, NULL);
+	  return FALSE;
+	}
+    }
+  else if (csky_insn.number == 3)
+    {
+      if (csky_insn.val[0] == 14
+	  && csky_insn.val[1] == 14
+	  && csky_insn.val[2] >= 0 && csky_insn.val[2] <= 0x1fc
+	  && (csky_insn.val[2] & 0x3) == 0
+	  && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  csky_insn.inst = 0x1420 | ((csky_insn.val[2] >> 2) & 0x1f);
+	  csky_insn.inst |= (csky_insn.val[2] << 1) & 0x300;
+	}
+
+      else if (csky_insn.val[0] < 8
+	       && csky_insn.val[0] == csky_insn.val[1]
+	       && csky_insn.val[2] >= 1 && csky_insn.val[2] <= 0x100
+	       && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  csky_insn.inst = 0x2800 | (csky_insn.val[0] << 8);
+	  csky_insn.inst |=  (csky_insn.val[2] - 1);
+	}
+      else if (csky_insn.val[0] < 8
+	       && csky_insn.val[1] < 8
+	       && csky_insn.val[2] >= 1 && csky_insn.val[2] <= 0x8
+	       && csky_insn.flag_force != INSN_OPCODE32F)
+	{
+	  csky_insn.inst = 0x5803 | (csky_insn.val[0] << 5);
+	  csky_insn.inst |= csky_insn.val[1] << 8;
+	  csky_insn.inst |= (csky_insn.val[2] - 1) << 2;
+	}
+      else if (csky_insn.val[2] >= 1 && csky_insn.val[2] <= 0x1000
+	       && csky_insn.flag_force != INSN_OPCODE16F)
+	{
+	  csky_insn.inst = 0xe4001000 | (csky_insn.val[0] << 21);
+	  csky_insn.inst |= csky_insn.val[1] << 16;
+	  csky_insn.inst |= (csky_insn.val[2] - 1);
+	  csky_insn.isize = 4;
+	}
+      else
+	{
+	  csky_show_error (ERROR_OPERANDS_ILLEGAL, 0,
+			   (char *)csky_insn.opcode_end, NULL);
+	  return FALSE;
+	}
+    }
+  csky_insn.output = frag_more (csky_insn.isize);
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_add_sub (void)
+{
+  if (csky_insn.number == 3
+	   && (csky_insn.val[0] == csky_insn.val[1]
+	      || csky_insn.val[0] == csky_insn.val[2])
+	   && csky_insn.val[0] <= 15
+	   && csky_insn.val[1] <= 15
+	   && csky_insn.val[2] <= 15)
+    {
+      if (!strstr (csky_insn.opcode->mnemonic, "sub")
+	  || csky_insn.val[0] == csky_insn.val[1])
+	{
+	  csky_insn.opcode_idx = 0;
+	  csky_insn.isize = 2;
+	  if (csky_insn.val[0] == csky_insn.val[1])
+	    csky_insn.val[1] = csky_insn.val[2];
+
+	  csky_insn.number = 2;
+
+	}
+    }
+  if (csky_insn.isize == 4
+      && IS_CSKY_ARCH_801 (mach_flag))
+    {
+      if (csky_insn.number == 3)
+	{
+	  if (csky_insn.val[0] > 7)
+	    csky_show_error (ERROR_REG_OVER_RANGE, 1,
+			     (void *)(long)csky_insn.val[0], NULL);
+	  if (csky_insn.val[1] > 7)
+	    csky_show_error (ERROR_REG_OVER_RANGE, 2,
+			     (void *)(long)csky_insn.val[1], NULL);
+	  if (csky_insn.val[2] > 7)
+	    csky_show_error (ERROR_REG_OVER_RANGE, 3,
+			     (void *)(long)csky_insn.val[2], NULL);
+	}
+      else
+	{
+	  if (csky_insn.val[0] > 15)
+	    csky_show_error (ERROR_REG_OVER_RANGE, 1,
+			     (void *)(long)csky_insn.val[0], NULL);
+	  if (csky_insn.val[1] > 15)
+	    csky_show_error (ERROR_REG_OVER_RANGE, 2,
+			     (void *)(long)csky_insn.val[1], NULL);
+	}
+      return FALSE;
+    }
+  /* sub rz, rx.  */
+  /* Generate relax or reloc if necessary.  */
+  csky_generate_frags ();
+  /* Generate the insn by mask.  */
+  csky_generate_insn ();
+  /* Write inst to frag.  */
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_rotlc (void)
+{
+  const char *name = "addc";
+  csky_insn.opcode
+    = (struct csky_opcode *) hash_find (csky_opcodes_hash, name);
+  csky_insn.opcode_idx = 0;
+  if (csky_insn.isize == 2)
+    {
+      /* addc rz, rx.  */
+      csky_insn.number = 2;
+      csky_insn.val[1] = csky_insn.val[0];
+    }
+  else
+    {
+      csky_insn.number = 3;
+      /* addc rz, rx, ry.  */
+      csky_insn.val[1] = csky_insn.val[0];
+      csky_insn.val[2] = csky_insn.val[0];
+    }
+  /* Generate relax or reloc if necessary.  */
+  csky_generate_frags ();
+  /* Generate the insn by mask.  */
+  csky_generate_insn ();
+  /* Write inst to frag.  */
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_bgeni (void)
+{
+  const char *name = NULL;
+  int imm = csky_insn.val[1];
+  int val = 1 << imm;
+  if (imm < 16)
+      name = "movi";
+  else
+    {
+      name = "movih";
+      val >>= 16;
+    }
+  csky_insn.opcode
+    = (struct csky_opcode *) hash_find (csky_opcodes_hash, name);
+  csky_insn.opcode_idx = 0;
+  csky_insn.val[1] = val;
+
+  /* Generate relax or reloc if necessary.  */
+  csky_generate_frags ();
+  /* Generate the insn by mask.  */
+  csky_generate_insn ();
+  /* Write inst to frag.  */
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_not (void)
+{
+  const char *name = "nor";
+  csky_insn.opcode
+    = (struct csky_opcode *) hash_find (csky_opcodes_hash, name);
+  csky_insn.opcode_idx = 0;
+  if (csky_insn.number == 1)
+    {
+      csky_insn.val[1] = csky_insn.val[0];
+      if (csky_insn.val[0] < 16)
+	{
+	  /* 16 bits nor rz, rz.  */
+	  csky_insn.number = 2;
+	  csky_insn.isize = 2;
+	}
+      else
+	{
+	  csky_insn.val[2] = csky_insn.val[0];
+	  csky_insn.number = 3;
+	  csky_insn.isize = 4;
+	}
+    }
+  if (csky_insn.number == 2)
+    {
+      if (csky_insn.val[0] == csky_insn.val[1]
+	  && csky_insn.val[0] < 16)
+	{
+	  /* 16 bits nor rz, rz.  */
+	  csky_insn.number = 2;
+	  csky_insn.isize = 2;
+	}
+      else
+	{
+	  csky_insn.val[2] = csky_insn.val[1];
+	  csky_insn.number = 3;
+	  csky_insn.isize = 4;
+	}
+    }
+
+  /* Generate relax or reloc if necessary.  */
+  csky_generate_frags ();
+  /* Generate the insn by mask.  */
+  csky_generate_insn ();
+  /* Write inst to frag.  */
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_jbtf (void)
+{
+  if (csky_insn.e1.X_add_symbol == NULL || csky_insn.e1.X_op == O_constant)
+    {
+      csky_show_error (ERROR_UNDEFINE, 0, (void *)"operand is invalid", NULL);
+      return FALSE;
+    }
+
+  if (IS_CSKY_ARCH_801 (mach_flag))
+    {
+      /* CK801 doesn't have 32-bit bt/bf insns or a jump insn with a
+	 range larger than SCOND_DISP16.  Relax to a short jump around
+	 an unconditional branch, and give up if that overflows too.  */
+      csky_insn.output = frag_var (rs_machine_dependent,
+				   SCOND_DISP16_LEN,
+				   SCOND_DISP10_LEN,
+				   SCOND_DISP10,
+				   csky_insn.e1.X_add_symbol,
+				   csky_insn.e1.X_add_number,
+				   0);
+      csky_insn.isize = 2;
+      csky_insn.max = SCOND_DISP16_LEN;
+      csky_insn.inst = csky_insn.opcode->op16[0].opcode;
+    }
+  else if (do_long_jump)
+    {
+      /* Generate relax with jcondition.  */
+      csky_insn.output = frag_var (rs_machine_dependent,
+				   JCOND_DISP32_LEN,
+				   JCOND_DISP10_LEN,
+				   JCOND_DISP10,
+				   csky_insn.e1.X_add_symbol,
+				   csky_insn.e1.X_add_number,
+				   0);
+      csky_insn.isize = 2;
+      csky_insn.max = JCOND_DISP32_LEN;
+      csky_insn.inst = csky_insn.opcode->op16[0].opcode;
+    }
+  else
+    {
+      /* Generate relax with condition.  */
+      csky_insn.output = frag_var (rs_machine_dependent,
+				   COND_DISP16_LEN,
+				   COND_DISP10_LEN,
+				   COND_DISP10,
+				   csky_insn.e1.X_add_symbol,
+				   csky_insn.e1.X_add_number,
+				   0);
+      csky_insn.isize = 2;
+      csky_insn.max = COND_DISP16_LEN;
+      csky_insn.inst = csky_insn.opcode->op16[0].opcode;
+    }
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_jbr (void)
+{
+  if (csky_insn.e1.X_add_symbol == NULL || csky_insn.e1.X_op == O_constant)
+    {
+      csky_show_error (ERROR_UNDEFINE, 0, (void *)"operand is invalid", NULL);
+      return FALSE;
+    }
+
+  if (do_long_jump
+      && !IS_CSKY_ARCH_801 (mach_flag)
+      && !IS_CSKY_ARCH_802 (mach_flag))
+    {
+      csky_insn.output = frag_var (rs_machine_dependent,
+				   JUNCD_DISP32_LEN,
+				   JUNCD_DISP10_LEN,
+				   JUNCD_DISP10,
+				   csky_insn.e1.X_add_symbol,
+				   csky_insn.e1.X_add_number,
+				   0);
+
+      csky_insn.inst = csky_insn.opcode->op16[0].opcode;
+      csky_insn.max = JUNCD_DISP32_LEN;
+      csky_insn.isize = 2;
+    }
+  else
+    {
+      /* Generate relax with condition.  */
+      csky_insn.output = frag_var (rs_machine_dependent,
+				   UNCD_DISP16_LEN,
+				   UNCD_DISP10_LEN,
+				   UNCD_DISP10,
+				   csky_insn.e1.X_add_symbol,
+				   csky_insn.e1.X_add_number,
+				   0);
+      csky_insn.isize = 2;
+      csky_insn.max = UNCD_DISP16_LEN;
+      csky_insn.inst = csky_insn.opcode->op16[0].opcode;
+
+    }
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+#define SIZE_V2_MOVI16(x)         ((addressT)x <= 0xff)
+#define SIZE_V2_MOVI32(x)         ((addressT)x <= 0xffff)
+#define SIZE_V2_MOVIH(x)          ((addressT)x <= 0xffffffff && (((addressT)x & 0xffff) == 0))
+
+bfd_boolean
+v2_work_lrw (void)
+{
+  int reg = csky_insn.val[0];
+  int output_literal = csky_insn.val[1];
+  int is_done = 0;
+
+  /* If the second operand is O_constant, We can use movi/movih
+     instead of lrw.  */
+  if (csky_insn.e1.X_op == O_constant)
+    {
+      /* 801 only has movi16.  */
+      if (SIZE_V2_MOVI16 (csky_insn.e1.X_add_number) && reg < 8)
+	{
+	  /* movi16 instead.  */
+	  csky_insn.output = frag_more (2);
+	  csky_insn.inst = (CSKYV2_INST_MOVI16 | (reg << 8)
+			    | (csky_insn.e1.X_add_number));
+	  csky_insn.isize = 2;
+	  is_done = 1;
+	}
+      else if (SIZE_V2_MOVI32 (csky_insn.e1.X_add_number)
+	       && !IS_CSKY_ARCH_801 (mach_flag))
+	{
+	  /* movi32 instead.  */
+	  csky_insn.output = frag_more (4);
+	  csky_insn.inst = (CSKYV2_INST_MOVI32 | (reg << 16)
+			    | (csky_insn.e1.X_add_number));
+	  csky_insn.isize = 4;
+	  is_done = 1;
+	}
+      else if (SIZE_V2_MOVIH (csky_insn.e1.X_add_number)
+	       && !IS_CSKY_ARCH_801 (mach_flag))
+	{
+	  /* movih instead.  */
+	  csky_insn.output = frag_more (4);
+	  csky_insn.inst = (CSKYV2_INST_MOVIH | (reg << 16)
+			    | ((csky_insn.e1.X_add_number >> 16) & 0xffff));
+	  csky_insn.isize = 4;
+	  is_done = 1;
+	}
+    }
+
+  if (is_done)
+    {
+      csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+      return TRUE;
+    }
+
+  if (output_literal)
+    {
+      int n = enter_literal (&csky_insn.e1, 0, 0, 0);
+      /* Create a reference to pool entry.  */
+      csky_insn.e1.X_op = O_symbol;
+      csky_insn.e1.X_add_symbol = poolsym;
+      csky_insn.e1.X_add_number = n << 2;
+    }
+  /* If 16bit force.  */
+  if (csky_insn.flag_force == INSN_OPCODE16F)
+    {
+      /* Generate fixup.  */
+      if (reg > 7)
+	{
+	  csky_show_error (ERROR_UNDEFINE, 0,
+			   (void *)"The register is out of range.", NULL);
+	  return FALSE;
+	}
+      csky_insn.isize = 2;
+      csky_insn.output = frag_more (2);
+
+      if (insn_reloc == BFD_RELOC_CKCORE_TLS_GD32
+	  || insn_reloc == BFD_RELOC_CKCORE_TLS_LDM32
+	  || insn_reloc == BFD_RELOC_CKCORE_TLS_IE32)
+	{
+	  literal_insn_offset->tls_addend.frag = frag_now;
+	  literal_insn_offset->tls_addend.offset
+	    = csky_insn.output - frag_now->fr_literal;
+	}
+      csky_insn.inst = csky_insn.opcode->op16[0].opcode | (reg << 5);
+      csky_insn.max = 4;
+      fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		   2, &csky_insn.e1, 1, BFD_RELOC_CKCORE_PCREL_IMM7BY4);
+    }
+  else if (csky_insn.flag_force == INSN_OPCODE32F)
+    {
+      csky_insn.isize = 4;
+      csky_insn.output = frag_more (4);
+      if (insn_reloc == BFD_RELOC_CKCORE_TLS_GD32
+	  || insn_reloc == BFD_RELOC_CKCORE_TLS_LDM32
+	  || insn_reloc == BFD_RELOC_CKCORE_TLS_IE32)
+       {
+	  literal_insn_offset->tls_addend.frag = frag_now;
+	  literal_insn_offset->tls_addend.offset
+	    = csky_insn.output - frag_now->fr_literal;
+       }
+      csky_insn.inst = csky_insn.opcode->op32[0].opcode | (reg << 16);
+      fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		   4, &csky_insn.e1, 1, BFD_RELOC_CKCORE_PCREL_IMM16BY4);
+    }
+  else if (!is_done)
+    {
+      if (reg < 8)
+	{
+	  csky_insn.isize = 2;
+
+	  if (insn_reloc == BFD_RELOC_CKCORE_TLS_GD32
+	      || insn_reloc == BFD_RELOC_CKCORE_TLS_LDM32
+	      || insn_reloc == BFD_RELOC_CKCORE_TLS_IE32)
+	    literal_insn_offset->tls_addend.frag = frag_now;
+
+	  csky_insn.output = frag_var (rs_machine_dependent,
+				       LRW_DISP16_LEN,
+				       LRW_DISP7_LEN,
+				       (do_extend_lrw
+					? LRW2_DISP8 : LRW_DISP7),
+				       csky_insn.e1.X_add_symbol,
+				       csky_insn.e1.X_add_number, 0);
+	  if (insn_reloc == BFD_RELOC_CKCORE_TLS_GD32
+	      || insn_reloc == BFD_RELOC_CKCORE_TLS_LDM32
+	      || insn_reloc == BFD_RELOC_CKCORE_TLS_IE32)
+	    {
+	      if (literal_insn_offset->tls_addend.frag->fr_next != frag_now)
+		literal_insn_offset->tls_addend.frag
+		  = literal_insn_offset->tls_addend.frag->fr_next;
+	      literal_insn_offset->tls_addend.offset
+		= (csky_insn.output
+		   - literal_insn_offset->tls_addend.frag->fr_literal);
+	    }
+	  csky_insn.inst = csky_insn.opcode->op16[0].opcode | (reg << 5);
+	  csky_insn.max = LRW_DISP16_LEN;
+	  csky_insn.isize = 2;
+	}
+      else
+	{
+	  csky_insn.isize = 4;
+	  csky_insn.output = frag_more (4);
+	  if (insn_reloc == BFD_RELOC_CKCORE_TLS_GD32
+	      || insn_reloc == BFD_RELOC_CKCORE_TLS_LDM32
+	      || insn_reloc == BFD_RELOC_CKCORE_TLS_IE32)
+	   {
+	      literal_insn_offset->tls_addend.frag = frag_now;
+	      literal_insn_offset->tls_addend.offset
+		= csky_insn.output - frag_now->fr_literal;
+	   }
+	  csky_insn.inst = csky_insn.opcode->op32[0].opcode | (reg << 16);
+	  fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		       4, &csky_insn.e1, 1, BFD_RELOC_CKCORE_PCREL_IMM16BY4);
+       }
+    }
+
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_lrsrsw (void)
+{
+  int reg = csky_insn.val[0];
+  csky_insn.output = frag_more (4);
+  csky_insn.inst = csky_insn.opcode->op32[0].opcode | (reg << 21);
+  csky_insn.isize = 4;
+
+  switch (insn_reloc)
+    {
+      case BFD_RELOC_CKCORE_GOT32:
+	fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		     4, &csky_insn.e1, 0, BFD_RELOC_CKCORE_GOT_IMM18BY4);
+	break;
+      case BFD_RELOC_CKCORE_PLT32:
+	fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		     4, &csky_insn.e1, 0, BFD_RELOC_CKCORE_PLT_IMM18BY4);
+	break;
+      default:
+	fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		     4, &csky_insn.e1, 1, BFD_RELOC_CKCORE_DOFFSET_IMM18BY4);
+	break;
+    }
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_jbsr (void)
+{
+  if (do_force2bsr
+      || IS_CSKY_ARCH_801 (mach_flag)
+      || IS_CSKY_ARCH_802 (mach_flag))
+    {
+      csky_insn.output = frag_more (4);
+      fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		   4, &csky_insn.e1, 1, BFD_RELOC_CKCORE_PCREL_IMM26BY2);
+      csky_insn.isize = 4;
+      csky_insn.inst = CSKYV2_INST_BSR32;
+    }
+  else
+    {
+      int n = enter_literal (&csky_insn.e1, 0, 0, 0);
+      csky_insn.output = frag_more (4);
+      csky_insn.e1.X_op = O_symbol;
+      csky_insn.e1.X_add_symbol = poolsym;
+      csky_insn.e1.X_add_number = n << 2;
+      fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		 4, &csky_insn.e1, 1, BFD_RELOC_CKCORE_PCREL_IMM16BY4);
+      if (do_jsri2bsr || IS_CSKY_ARCH_810 (mach_flag))
+	fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		     4,
+		     &(litpool + (csky_insn.e1.X_add_number >> 2))->e,
+		     1,
+		     BFD_RELOC_CKCORE_PCREL_JSR_IMM26BY2);
+      csky_insn.inst = CSKYV2_INST_JSRI32;
+      csky_insn.isize = 4;
+      if (IS_CSKY_ARCH_810 (mach_flag))
+	{
+	  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+	  csky_insn.output = frag_more (4);
+	  dwarf2_emit_insn (0);
+	  /* Insert "mov r0, r0".  */
+	  csky_insn.inst = CSKYV2_INST_MOV_R0_R0;
+	  csky_insn.max = 8;
+	}
+    }
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_jsri (void)
+{
+  /* dump literal.  */
+  int n = enter_literal (&csky_insn.e1, 1, 0, 0);
+  csky_insn.e1.X_op = O_symbol;
+  csky_insn.e1.X_add_symbol = poolsym;
+  csky_insn.e1.X_add_number = n << 2;
+
+  /* Generate relax or reloc if necessary.  */
+  csky_generate_frags ();
+  /* Generate the insn by mask.  */
+  csky_generate_insn ();
+  /* Write inst to frag.  */
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  /* Control 810 not to generate jsri.  */
+  if (IS_CSKY_ARCH_810 (mach_flag))
+    {
+      /* Look at adding the R_PCREL_JSRIMM26BY2.
+	 For 'jbsr .L1', this reloc type's symbol
+	 is bound to '.L1', isn't bound to literal pool.  */
+      fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		   4, &(litpool + (csky_insn.e1.X_add_number >> 2))->e, 1,
+		   BFD_RELOC_CKCORE_PCREL_JSR_IMM26BY2);
+      csky_insn.output = frag_more (4);
+      dwarf2_emit_insn (0);
+      /* The opcode of "mov32 r0,r0".  */
+      csky_insn.inst = CSKYV2_INST_MOV_R0_R0;
+      /* The effect of this value is to check literal.  */
+      csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+      csky_insn.max = 8;
+    }
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_movih (void)
+{
+  int rz = csky_insn.val[0];
+  csky_insn.output = frag_more (4);
+  csky_insn.inst = csky_insn.opcode->op32[0].opcode | (rz << 16);
+  if (csky_insn.e1.X_op == O_constant)
+    {
+      if (csky_insn.e1.X_unsigned == 1 && csky_insn.e1.X_add_number > 0xffff)
+	{
+	  csky_show_error (ERROR_IMM_OVERFLOW, 2, NULL, NULL);
+	  return FALSE;
+	}
+      else if (csky_insn.e1.X_unsigned == 0 && csky_insn.e1.X_add_number < 0)
+	{
+	  csky_show_error (ERROR_IMM_OVERFLOW, 2, NULL, NULL);
+	  return FALSE;
+	}
+      else
+	csky_insn.inst |= (csky_insn.e1.X_add_number & 0xffff);
+    }
+  else if (csky_insn.e1.X_op == O_right_shift
+	   || (csky_insn.e1.X_op == O_symbol && insn_reloc != BFD_RELOC_NONE))
+    {
+      if (csky_insn.e1.X_op_symbol != 0
+	  && csky_insn.e1.X_op_symbol->sy_value.X_op == O_constant
+	  && 16 == csky_insn.e1.X_op_symbol->sy_value.X_add_number)
+	{
+	  csky_insn.e1.X_op = O_symbol;
+	  if (insn_reloc == BFD_RELOC_CKCORE_GOT32)
+	    insn_reloc = BFD_RELOC_CKCORE_GOT_HI16;
+	  else if (insn_reloc == BFD_RELOC_CKCORE_PLT32)
+	    insn_reloc = BFD_RELOC_CKCORE_PLT_HI16;
+	  else if (insn_reloc == BFD_RELOC_CKCORE_GOTPC)
+	    insn_reloc = BFD_RELOC_CKCORE_GOTPC_HI16;
+	  else if (insn_reloc == BFD_RELOC_CKCORE_GOTOFF)
+	    insn_reloc = BFD_RELOC_CKCORE_GOTOFF_HI16;
+	  else
+	    insn_reloc = BFD_RELOC_CKCORE_ADDR_HI16;
+	  fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		       4, &csky_insn.e1, 0, insn_reloc);
+	}
+      else
+	{
+	  void *arg = (void *)"the second operand must be \"SYMBOL >> 16\"";
+	  csky_show_error (ERROR_UNDEFINE, 0, arg, NULL);
+	  return FALSE;
+	}
+    }
+  csky_insn.isize = 4;
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+
+  return TRUE;
+}
+
+bfd_boolean
+v2_work_ori (void)
+{
+  int rz = csky_insn.val[0];
+  int rx = csky_insn.val[1];
+  csky_insn.output = frag_more (4);
+  csky_insn.inst = csky_insn.opcode->op32[0].opcode | (rz << 21) | (rx << 16);
+  if (csky_insn.e1.X_op == O_constant)
+    {
+      if (csky_insn.e1.X_add_number <= 0xffff
+	  && csky_insn.e1.X_add_number >= 0)
+	csky_insn.inst |= csky_insn.e1.X_add_number;
+      else
+	{
+	  csky_show_error (ERROR_IMM_OVERFLOW, 3, NULL, NULL);
+	  return FALSE;
+	}
+    }
+  else if (csky_insn.e1.X_op == O_bit_and)
+    {
+      if (csky_insn.e1.X_op_symbol->sy_value.X_op == O_constant
+	  && 0xffff == csky_insn.e1.X_op_symbol->sy_value.X_add_number)
+	{
+	  csky_insn.e1.X_op = O_symbol;
+	  if (insn_reloc == BFD_RELOC_CKCORE_GOT32)
+	    insn_reloc = BFD_RELOC_CKCORE_GOT_LO16;
+	  else if (insn_reloc == BFD_RELOC_CKCORE_PLT32)
+	    insn_reloc = BFD_RELOC_CKCORE_PLT_LO16;
+	  else if (insn_reloc == BFD_RELOC_CKCORE_GOTPC)
+	    insn_reloc = BFD_RELOC_CKCORE_GOTPC_LO16;
+	  else if (insn_reloc == BFD_RELOC_CKCORE_GOTOFF)
+	    insn_reloc = BFD_RELOC_CKCORE_GOTOFF_LO16;
+	  else
+	    insn_reloc = BFD_RELOC_CKCORE_ADDR_LO16;
+	  fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		       4, &csky_insn.e1, 0, insn_reloc);
+	}
+      else
+	{
+	  void *arg = (void *)"the third operand must be \"SYMBOL & 0xffff\"";
+	  csky_show_error (ERROR_UNDEFINE, 0, arg, NULL);
+	  return FALSE;
+	}
+    }
+  csky_insn.isize = 4;
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+bfd_boolean
+float_work_fmovi (void)
+{
+  int rx = csky_insn.val[0];
+  offsetT add_number = csky_insn.e1.X_add_number;
+  int imm4 = 0;
+  int imm8 = 0;
+
+  csky_insn.inst = csky_insn.opcode->op32[0].opcode | rx;
+
+  if (strstr (csky_insn.opcode->mnemonic, "fmovis"))
+    {
+      /* fmovis frx, float.  */
+      imm4 = 11 - (((add_number & 0x7f800000) >> 23)  - 127);
+      /* Check float range.  */
+      if ((add_number & 0x00007fff) || imm4 < 0 || imm4 > 15)
+	{
+	  csky_show_error (ERROR_IMM_OVERFLOW, 2, NULL, NULL);
+	  return FALSE;
+	}
+      imm8 = (add_number & 0x007f8000) >> 15;
+      csky_insn.inst |= (((imm8 & 0xf) << 4)
+			 | ((imm8 & 0xf0) << 17)
+			 | ((imm4 & 0xf) << 16)
+			 | ((add_number & 0x80000000) >> 11));
+    }
+  else
+    {
+      /* fmovid frx, float.  */
+      imm4 = 11 - (((csky_insn.dbnum & 0x7ff0000000000000ULL) >> 52)  - 1023);
+      /* Check float range.  */
+      if ((csky_insn.dbnum & 0x00000fffffffffffULL) || imm4 < 0 || imm4 > 15)
+	{
+	  csky_show_error (ERROR_IMM_OVERFLOW, 2, NULL, NULL);
+	  return FALSE;
+	}
+      imm8 = (csky_insn.dbnum & 0x000ff00000000000ULL) >> 44;
+      csky_insn.inst |= (((imm8 & 0xf) << 4)
+			 | ((imm8 & 0xf0) << 17)
+			 | ((imm4 & 0xf) << 16)
+			 | ((csky_insn.dbnum & 0x8000000000000000ULL) >> 43));
+    }
+  csky_insn.output = frag_more (4);
+  csky_insn.isize = 4;
+  csky_write_insn (csky_insn.output, csky_insn.inst, csky_insn.isize);
+  return TRUE;
+}
+
+bfd_boolean
+dsp_work_bloop (void)
+{
+  int reg = csky_insn.val[0];
+  csky_insn.output = frag_more (4);
+  csky_insn.inst = csky_insn.opcode->op32[0].opcode | (reg << 16);
+  csky_insn.isize = 4;
+
+  if (csky_insn.e1.X_op == O_symbol
+      && csky_insn.e2.X_op == O_symbol)
+    {
+	fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		     4, &csky_insn.e1, 1,
+		     BFD_RELOC_CKCORE_PCREL_BLOOP_IMM12BY4);
+	fix_new_exp (frag_now, csky_insn.output - frag_now->fr_literal,
+		     4, &csky_insn.e2, 1,
+		     BFD_RELOC_CKCORE_PCREL_BLOOP_IMM4BY4);
+    }
+
+  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
+   data directive in the text section.  FUNC is one of the standard
+   gas functions to handle these directives, like "stringer" for the
+   .string directive, and ARG is the argument to FUNC.  csky_pool_count
+   essentially wraps the call with the constant pool magic.  */
+
+static void
+csky_pool_count (void (*func) (int), int arg)
+{
+  const fragS *curr_frag = frag_now;
+  offsetT added = -frag_now_fix_octets ();
+
+  (*func) (arg);
+
+  while (curr_frag != frag_now)
+    {
+      added += curr_frag->fr_fix;
+      curr_frag = curr_frag->fr_next;
+    }
+
+  added += frag_now_fix_octets ();
+  poolspan += added;
+}
+
+/* Support the .literals directive.  */
+static void
+csky_s_literals (int ignore ATTRIBUTE_UNUSED)
+{
+  dump_literals (0);
+  demand_empty_rest_of_line ();
+}
+
+/* Support the .string, etc directives.  */
+static void
+csky_stringer (int append_zero)
+{
+  if (now_seg == text_section)
+    csky_pool_count (stringer, append_zero);
+  else
+    stringer (append_zero);
+
+  /* We call check_literals here in case a large number of strings are
+     being placed into the text section with a sequence of stringer
+     directives.  In theory we could be upsetting something if these
+     strings are actually in an indexed table instead of referenced by
+     individual labels.  Let us hope that that never happens.  */
+  check_literals (2, 0);
+}
+
+/* Support integer-mode constructors like .word, .byte, etc.  */
+static void
+csky_cons (int nbytes)
+{
+  mapping_state (MAP_DATA);
+  if (nbytes == 4)  /* @GOT.  */
+    {
+      do
+	{
+	  bfd_reloc_code_real_type reloc;
+	  expressionS exp;
+
+	  reloc = BFD_RELOC_NONE;
+	  expression (&exp);
+	  lex_got (&reloc, NULL);
+
+	  if (exp.X_op == O_symbol && reloc != BFD_RELOC_NONE)
+	    {
+	      reloc_howto_type *howto
+		= bfd_reloc_type_lookup (stdoutput, reloc);
+	      int size = bfd_get_reloc_size (howto);
+
+	      if (size > nbytes)
+		as_bad ("%s relocations do not fit in %d bytes",
+			howto->name, nbytes);
+	      else
+		{
+		  register char *p = frag_more ((int) nbytes);
+		  int offset = nbytes - size;
+		  
+		  fix_new_exp (frag_now,
+			       p - frag_now->fr_literal + offset,
+			       size, &exp, 0, reloc);
+		}
+	    }
+	  else
+	    emit_expr (&exp, (unsigned int) nbytes);
+	  if (now_seg == text_section)
+	    poolspan += nbytes;
+	}
+      while (*input_line_pointer++ == ',');
+
+      /* Put terminator back into stream.  */
+      input_line_pointer --;
+      demand_empty_rest_of_line ();
+
+      return;
+    }
+
+  if (now_seg == text_section)
+    csky_pool_count (cons, nbytes);
+  else
+    cons (nbytes);
+
+  /* In theory we ought to call check_literals (2,0) here in case
+     we need to dump the literal table.  We cannot do this however,
+     as the directives that we are intercepting may be being used
+     to build a switch table, and we must not interfere with its
+     contents.  Instead we cross our fingers and pray...  */
+}
+
+/* Support floating-mode constant directives like .float and .double.  */
+static void
+csky_float_cons (int float_type)
+{
+  mapping_state (MAP_DATA);
+  if (now_seg == text_section)
+    csky_pool_count (float_cons, float_type);
+  else
+    float_cons (float_type);
+
+  /* See the comment in csky_cons () about calling check_literals.
+      It is unlikely that a switch table will be constructed using
+      floating point values, but it is still likely that an indexed
+      table of floating point constants is being created by these
+      directives, so again we must not interfere with their placement.  */
+}
+
+
+/* Support the .fill directive.  */
+static void
+csky_fill (int ignore)
+{
+  if (now_seg == text_section)
+    csky_pool_count (s_fill, ignore);
+  else
+    s_fill (ignore);
+
+  check_literals (2, 0);
+}
+
+/* Handle the section changing pseudo-ops.  These call through to the
+   normal implementations, but they dump the literal pool first.  */
+
+static void
+csky_s_text (int ignore)
+{
+  dump_literals (0);
+
+#ifdef OBJ_ELF
+  obj_elf_text (ignore);
+#else
+  s_text (ignore);
+#endif
+}
+
+static void
+csky_s_data (int ignore)
+{
+  dump_literals (0);
+
+#ifdef OBJ_ELF
+  obj_elf_data (ignore);
+#else
+  s_data (ignore);
+#endif
+}
+
+static void
+csky_s_section (int ignore)
+{
+  /* Scan forwards to find the name of the section.  If the section
+     being switched to is ".line" then this is a DWARF1 debug section
+     which is arbitrarily placed inside generated code.  In this case
+     do not dump the literal pool because it is a) inefficient and
+     b) would require the generation of extra code to jump around the
+     pool.  */
+  char * ilp = input_line_pointer;
+
+  while (*ilp != 0 && ISSPACE (*ilp))
+    ++ ilp;
+
+  if (strncmp (ilp, ".line", 5) == 0
+      && (ISSPACE (ilp[5]) || *ilp == '\n' || *ilp == '\r'))
+    ;
+  else
+    dump_literals (0);
+
+#ifdef OBJ_ELF
+  obj_elf_section (ignore);
+#endif
+#ifdef OBJ_COFF
+  obj_coff_section (ignore);
+#endif
+}
+
+static void
+csky_s_bss (int needs_align)
+{
+  dump_literals (0);
+  s_lcomm_bytes (needs_align);
+}
+
+#ifdef OBJ_ELF
+static void
+csky_s_comm (int needs_align)
+{
+  dump_literals (0);
+  obj_elf_common (needs_align);
+}
+#endif
+
+/* Handle the .no_literal_dump directive.  */
+static void
+csky_noliteraldump (int ignore ATTRIBUTE_UNUSED)
+{
+  do_noliteraldump = 1;
+  int insn_num = get_absolute_expression ();
+  /* The insn after '.no_literal_dump insn_num' is insn1,
+   * Don't dump literal pool between insn1 and insn(insn_num+1)
+   * The insn cannot be the insn generate literal, like lrw & jsri.  */
+  check_literals (0, insn_num * 2);
+}
+
+/* Handle the .align directive.
+   We must check literals before doing alignment.  For example, if
+   '.align n', add (2^n-1) to poolspan and check literals.  */
+static void
+csky_s_align_ptwo (int arg)
+{
+  /* Get the .align's first absolute number.  */
+  char * temp_pointer = input_line_pointer;
+  int align = get_absolute_expression ();
+  check_literals (0, (1 << align) - 1);
+  input_line_pointer = temp_pointer;
+
+  /* Do alignment.  */
+  s_align_ptwo (arg);
+}
+
+/* Handle the .stack_size directive.  */
+static void
+csky_stack_size (int arg ATTRIBUTE_UNUSED)
+{
+  expressionS exp;
+  stack_size_entry *sse
+    = (stack_size_entry *) xcalloc (1, sizeof (stack_size_entry));
+
+  expression (&exp);
+  if (exp.X_op == O_symbol)
+    sse->function = exp.X_add_symbol;
+  else
+    {
+      as_bad (_("the first operand must be a symbol"));
+      ignore_rest_of_line ();
+      free (sse);
+      return;
+    }
+
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer != ',')
+    {
+      as_bad (_("missing stack size"));
+      ignore_rest_of_line ();
+      free (sse);
+      return;
+    }
+
+  ++input_line_pointer;
+  expression (&exp);
+  if (exp.X_op == O_constant)
+    {
+      if (exp.X_add_number < 0 || exp.X_add_number > 0xffffffff)
+	{
+	  as_bad (_("the second operand must be 0x0-0xffffffff"));
+	  ignore_rest_of_line ();
+	  free (sse);
+	  return;
+	}
+      else
+	sse->stack_size = exp.X_add_number;
+    }
+  else
+    {
+      as_bad (_("the second operand must be a constant"));
+      ignore_rest_of_line ();
+      free (sse);
+      return;
+    }
+
+  if (*last_stack_size_data != NULL)
+    last_stack_size_data = &((*last_stack_size_data)->next);
+
+  *last_stack_size_data = sse;
+}
+
+/* This table describes all the machine specific pseudo-ops the assembler
+   has to support.  The fields are:
+     pseudo-op name without dot
+     function to call to execute this pseudo-op
+     Integer arg to pass to the function.  */
+
+const pseudo_typeS md_pseudo_table[] =
+{
+  { "export",   s_globl,          0 },
+  { "import",   s_ignore,         0 },
+  { "literals", csky_s_literals, 0 },
+  { "page",     listing_eject,    0 },
+
+  /* The following are to intercept the placement of data into the text
+     section (eg addresses for a switch table), so that the space they
+     occupy can be taken into account when deciding whether or not to
+     dump the current literal pool.
+     XXX - currently we do not cope with the .space and .dcb.d directives.  */
+  { "ascii",    csky_stringer,       8 + 0 },
+  { "asciz",    csky_stringer,       8 + 1 },
+  { "byte",     csky_cons,           1 },
+  { "dc",       csky_cons,           2 },
+  { "dc.b",     csky_cons,           1 },
+  { "dc.d",     csky_float_cons,    'd'},
+  { "dc.l",     csky_cons,           4 },
+  { "dc.s",     csky_float_cons,    'f'},
+  { "dc.w",     csky_cons,           2 },
+  { "dc.x",     csky_float_cons,    'x'},
+  { "double",   csky_float_cons,    'd'},
+  { "float",    csky_float_cons,    'f'},
+  { "hword",    csky_cons,           2 },
+  { "int",      csky_cons,           4 },
+  { "long",     csky_cons,           4 },
+  { "octa",     csky_cons,          16 },
+  { "quad",     csky_cons,           8 },
+  { "short",    csky_cons,           2 },
+  { "single",   csky_float_cons,    'f'},
+  { "string",   csky_stringer,       8 + 1 },
+  { "word",     csky_cons,           4 },
+  { "fill",     csky_fill,           0 },
+
+  /* Allow for the effect of section changes.  */
+  { "text",      csky_s_text,    0 },
+  { "data",      csky_s_data,    0 },
+  { "bss",       csky_s_bss,     1 },
+#ifdef OBJ_ELF
+  { "comm",      csky_s_comm,    0 },
+#endif
+  { "section",   csky_s_section, 0 },
+  { "section.s", csky_s_section, 0 },
+  { "sect",      csky_s_section, 0 },
+  { "sect.s",    csky_s_section, 0 },
+  /* When ".no_literal_dump N" is in front of insn1,
+   * and instruction sequence is:
+   *               insn1
+   *               insn2
+   *               ......
+   *               insnN+1
+   * it means literal will not dump between insn1 and insnN+1
+   * The insn can not be the insn generate literal, like lrw & jsri*/
+  { "no_literal_dump",	csky_noliteraldump,	0 },
+  { "align",		csky_s_align_ptwo,	 0 },
+  { "stack_size",	csky_stack_size,	 0 },
+  {0,       0,            0}
+};
+
+/* Implement tc_cfi_frame_initial_instructions.  */
+void csky_cfi_frame_initial_instructions (void)
+{
+  int sp_reg = IS_CSKY_V1 (mach_flag) ? 0 : 14;
+  cfi_add_CFA_def_cfa_register (sp_reg);
+}
+
+/* Implement tc_regname_to_dw2regnum.  */
+int tc_csky_regname_to_dw2regnum (char *regname)
+{
+  int reg_num = -1;
+  int len;
+
+  /* FIXME the reg should be parsed according to
+     the abi version.  */
+  reg_num = csky_get_reg_val (regname, &len);
+  return reg_num;
+}
diff --git a/gas/config/tc-csky.h b/gas/config/tc-csky.h
new file mode 100644
index 0000000..cadc28f
--- /dev/null
+++ b/gas/config/tc-csky.h
@@ -0,0 +1,97 @@ 
+/* tc-csky.h -- Header file for tc-csky.c
+   Copyright (C) 1989-2018 Free Software Foundation, Inc.
+   Contributed by C-SKY Microsystems and Mentor Graphics.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GAS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#ifndef TC_CSKY
+#define TC_CSKY 1
+
+#define WORKING_DOT_WORD
+
+#define TARGET_ARCH    bfd_arch_csky
+
+#define LISTING_HEADER "CSKY GAS"
+
+#ifdef OBJ_ELF
+#define TARGET_FORMAT elf32_csky_target_format ()
+#endif
+
+#define TARGET_BYTES_BIG_ENDIAN 0
+
+#define MD_PCREL_FROM_SECTION(F,S) md_pcrel_from_section (F, S)
+
+#define TC_GENERIC_RELAX_TABLE     csky_relax_table
+
+#define md_end                        md_csky_end
+#define md_relax_frag                 csky_relax_frag
+#define DOUBLESLASH_LINE_COMMENTS
+#define LOCAL_LABELS_FB     1
+#define PAD_LITERAL_LENGTH  6
+#define PAD_FILL_CONTENT    0x1c00
+
+/* Reloc API.  */
+#define EXTERN_FORCE_RELOC 0
+#define TC_CONS_FIX_NEW               csky_cons_fix_new
+#define TC_FORCE_RELOCATION(fix)      csky_force_relocation (fix)
+#define tc_fix_adjustable(FIX)        csky_fix_adjustable (FIX)
+#define TC_SEGMENT_INFO_TYPE          csky_segment_info_type
+
+/* Dwarf API*/
+#define DWARF2_LINE_MIN_INSN_LENGTH   2
+#define DWARF2_ADDR_SIZE(bfd)   4
+#define DWARF2_FDE_RELOC_SIZE   4
+#define TARGET_USE_CFIPOP 1
+#define tc_cfi_frame_initial_instructions csky_cfi_frame_initial_instructions
+#define tc_regname_to_dw2regnum tc_csky_regname_to_dw2regnum
+#define DWARF2_DEFAULT_RETURN_COLUMN 15
+#define DWARF2_CIE_DATA_ALIGNMENT (-4)
+
+typedef enum
+{
+  MAP_UNDEFINED = 0,
+  MAP_DATA,
+  MAP_TEXT,
+} map_state;
+
+typedef struct
+{
+  map_state current_state;
+} csky_segment_info_type;
+
+#include "write.h"
+extern const relax_typeS csky_relax_table [];
+
+extern void md_csky_end (void);
+extern long md_pcrel_from_section (fixS * fixP, segT seg);
+extern void csky_cons_fix_new (fragS *frag,
+			       unsigned int off,
+			       unsigned int len,
+			       expressionS *exp,
+			       bfd_reloc_code_real_type reloc);
+extern int csky_force_relocation (fixS * fix);
+extern bfd_boolean csky_fix_adjustable (fixS * fixP);
+extern void csky_cfi_frame_initial_instructions (void);
+extern int tc_csky_regname_to_dw2regnum (char *regname);
+extern long csky_relax_frag (segT segment, fragS *fragP, long stretch);
+
+#ifdef OBJ_ELF
+const char * elf32_csky_target_format (void);
+#endif
+
+#endif
diff --git a/gas/config/te-csky_abiv1.h b/gas/config/te-csky_abiv1.h
new file mode 100644
index 0000000..5185abc
--- /dev/null
+++ b/gas/config/te-csky_abiv1.h
@@ -0,0 +1,24 @@ 
+/* Environment definitions for C-SKY ABIV2 bare-metal targets.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   Contributed by C-SKY Microsystems and Mentor Graphics.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 3,
+   or (at your option) any later version.
+
+   GAS is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+   the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#include "obj-format.h"
+
+#define _CSKY_ABI    1
diff --git a/gas/config/te-csky_abiv1_linux.h b/gas/config/te-csky_abiv1_linux.h
new file mode 100644
index 0000000..1999bf7
--- /dev/null
+++ b/gas/config/te-csky_abiv1_linux.h
@@ -0,0 +1,24 @@ 
+/* Environment definitions for C-SKY ABIV1 Linux targets.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   Contributed by C-SKY Microsystems and Mentor Graphics.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 3,
+   or (at your option) any later version.
+
+   GAS is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+   the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#include "obj-format.h"
+
+#define _CSKY_ABI    1
diff --git a/gas/config/te-csky_abiv2.h b/gas/config/te-csky_abiv2.h
new file mode 100644
index 0000000..c0b649d
--- /dev/null
+++ b/gas/config/te-csky_abiv2.h
@@ -0,0 +1,26 @@ 
+/* Environment definitions for C-SKY ABIV2 bare-metal targets.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   Contributed by C-SKY Microsystems and Mentor Graphics.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 3,
+   or (at your option) any later version.
+
+   GAS is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+   the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#define INCLUDE_BRANCH_STUB
+
+#include "obj-format.h"
+
+#define _CSKY_ABI    2
diff --git a/gas/config/te-csky_abiv2_linux.h b/gas/config/te-csky_abiv2_linux.h
new file mode 100644
index 0000000..06854f3
--- /dev/null
+++ b/gas/config/te-csky_abiv2_linux.h
@@ -0,0 +1,24 @@ 
+/* Environment definitions for C-SKY ABIV2 Linux targets.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+   Contributed by C-SKY Microsystems and Mentor Graphics.
+
+   This file is part of GAS, the GNU Assembler.
+
+   GAS is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 3,
+   or (at your option) any later version.
+
+   GAS is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
+   the GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GAS; see the file COPYING.  If not, write to the Free
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#include "obj-format.h"
+
+#define _CSKY_ABI    2
diff --git a/gas/configure.tgt b/gas/configure.tgt
index 3d0415c..60fd642 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -173,6 +173,11 @@  case ${generic_target} in
 
   crx-*-elf*)				fmt=elf ;;
 
+  csky-*-elf*abiv1)			fmt=elf em=csky_abiv1 ;;
+  csky-*-elf*)				fmt=elf em=csky_abiv2 ;;
+  csky-*-linux*abiv1)			fmt=elf em=csky_abiv1_linux ;;
+  csky-*-linux*)			fmt=elf em=csky_abiv2_linux ;;
+
   d10v-*-*)				fmt=elf ;;
   d30v-*-*)				fmt=elf ;;
   dlx-*-*)				fmt=elf ;;
@@ -431,7 +436,7 @@  case ${generic_target} in
 esac
 
 case ${cpu_type} in
-  aarch64 | alpha | arm | i386 | ia64 | microblaze | mips | ns32k | or1k | or1knd | pdp11 | ppc | riscv | sparc | z80 | z8k)
+  aarch64 | alpha | arm | csky | i386 | ia64 | microblaze | mips | ns32k | or1k | or1knd | pdp11 | ppc | riscv | sparc | z80 | z8k)
     bfd_gas=yes
     ;;
 esac
diff --git a/gas/doc/Makefile.am b/gas/doc/Makefile.am
index c9c3405..bf802c9 100644
--- a/gas/doc/Makefile.am
+++ b/gas/doc/Makefile.am
@@ -54,6 +54,7 @@  CPU_DOCS = \
 	c-bfin.texi \
 	c-cr16.texi \
 	c-cris.texi \
+	c-csky.texi \
 	c-d10v.texi \
 	c-epiphany.texi \
 	c-h8300.texi \
diff --git a/gas/doc/Makefile.in b/gas/doc/Makefile.in
index a126e2f..7d09af4 100644
--- a/gas/doc/Makefile.in
+++ b/gas/doc/Makefile.in
@@ -329,6 +329,7 @@  CPU_DOCS = \
 	c-bfin.texi \
 	c-cr16.texi \
 	c-cris.texi \
+	c-csky.texi \
 	c-d10v.texi \
 	c-epiphany.texi \
 	c-h8300.texi \
diff --git a/gas/doc/all.texi b/gas/doc/all.texi
index 2b8af69..ef103de 100644
--- a/gas/doc/all.texi
+++ b/gas/doc/all.texi
@@ -32,6 +32,7 @@ 
 @set Blackfin
 @set CR16
 @set CRIS
+@set CSKY
 @set D10V
 @set D30V
 @set EPIPHANY
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index b6b16b7..6d30b53 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -306,6 +306,26 @@  gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
 @c Deprecated -- deliberately not documented.
 @c [@b{-h}] [@b{-H}]
 @end ifset
+@ifset CSKY
+
+@emph{Target C-SKY options:}
+   [@b{-march=@var{arch}}] [@b{-mcpu=@var{cpu}}]
+   [@b{-EL}] [@b{-mlittle-endian}] [@b{-EB}] [@b{-mbig-endian}]
+   [@b{-fpic}] [@b{-pic}]
+   [@b{-mljump}] [@b{-mno-ljump}]
+   [@b{-force2bsr}] [@b{-mforce2bsr}] [@b{-no-force2bsr}] [@b{-mno-force2bsr}] 
+   [@b{-jsri2bsr}] [@b{-mjsri2bsr}] [@b{-no-jsri2bsr }] [@b{-mno-jsri2bsr}] 
+   [@b{-mnolrw }] [@b{-mno-lrw}]
+   [@b{-melrw}] [@b{-mno-elrw}] 
+   [@b{-mlaf }] [@b{-mliterals-after-func}] 
+   [@b{-mno-laf}] [@b{-mno-literals-after-func}] 
+   [@b{-mlabr}] [@b{-mliterals-after-br}] 
+   [@b{-mno-labr}] [@b{-mnoliterals-after-br}] 
+   [@b{-mistack}] [@b{-mno-istack}] 
+   [@b{-mhard-float}] [@b{-mmp}] [@b{-mcp}] [@b{-mcache}] 
+   [@b{-msecurity}] [@b{-mtrust}] 
+   [@b{-mdsp}] [@b{-medsp}] [@b{-mvdsp}] 
+@end ifset
 @ifset D10V
 
 @emph{Target D10V options:}
@@ -976,6 +996,25 @@  the Blackfin processor family.
 See the info pages for documentation of the CRIS-specific options.
 @end ifset
 
+@ifset CSKY
+
+@ifclear man
+@xref{C-SKY Options}, for the options available when @value{AS} is
+configured for the C-SKY processor family.
+@end ifclear
+
+@ifset man
+@c man begin OPTIONS
+The following options are available when @value{AS} is configured for
+the C-SKY processor family.
+@c man end
+@c man begin INCLUDE
+@include c-csky.texi
+@c ended inside the included file
+@end ifset
+
+@end ifset
+
 @ifset D10V
 The following options are available when @value{AS} is configured for
 a D10V processor.
@@ -7526,6 +7565,9 @@  subject, see the hardware manufacturer's manual.
 @ifset CRIS
 * CRIS-Dependent::              CRIS Dependent Features
 @end ifset
+@ifset CSKY
+* C-SKY-Dependent::             C-SKY Dependent Features
+@end ifset
 @ifset D10V
 * D10V-Dependent::              D10V Dependent Features
 @end ifset
@@ -7709,6 +7751,10 @@  subject, see the hardware manufacturer's manual.
 @include c-cris.texi
 @end ifset
 
+@ifset CSKY
+@include c-csky.texi
+@end ifset
+
 @ifset Renesas-all
 @ifclear GENERIC
 @node Machine Dependencies
diff --git a/gas/doc/c-csky.texi b/gas/doc/c-csky.texi
new file mode 100644
index 0000000..351d873
--- /dev/null
+++ b/gas/doc/c-csky.texi
@@ -0,0 +1,195 @@ 
+@c Copyright (C) 2012-2018 Free Software Foundation, Inc.
+@c This is part of the GAS manual.
+@c For copying conditions, see the file as.texinfo.
+@c man end
+@ifset GENERIC
+@page
+@node C-SKY-Dependent
+@chapter C-SKY Dependent Features
+@end ifset
+@ifclear GENERIC
+@node Machine Dependencies
+@chapter C-SKY Dependent Features
+@end ifclear
+
+@cindex C-SKY support
+@menu
+* C-SKY Options::              Options
+* C-SKY Syntax::               Syntax
+@end menu
+
+@node C-SKY Options
+@section Options
+@cindex C-SKY options
+@cindex options for C-SKY
+
+@c man begin OPTIONS
+@table @gcctabopt
+
+@cindex @code{march} command-line option, C-SKY
+@item -march=@var{archname}
+Assemble for architecture @var{archname}.  The @option{--help} option
+lists valid values for @var{archname}.
+
+@cindex @code{mcpu} command-line option, C-SKY
+@item -mcpu=@var{cpuname}
+Assemble for architecture @var{cpuname}.  The @option{--help} option
+lists valid values for @var{cpuname}.
+
+@cindex @code{EL} command-line option, C-SKY
+@cindex @code{mlittle-endian} command-line option, C-SKY
+@item -EL
+@itemx -mlittle-endian
+Generate little-endian output.
+
+@cindex @code{EB} command-line option, C-SKY
+@cindex @code{mbig-endian} command-line option, C-SKY
+@item -EB
+@itemx -mbig-endian
+Generate big-endian output.
+
+@cindex @code{fpic} command-line option, C-SKY
+@cindex @code{pic} command-line option, C-SKY
+@item -fpic
+@itemx -pic
+Generate position-independent code.
+
+@cindex @code{mljump} command-line option, C-SKY
+@cindex @code{mno-ljump} command-line option, C-SKY
+@item -mljump
+@itemx -mno-ljump
+Enable/disable transformation of the short branch instructions 
+@code{jbf}, @code{jbt}, and @code{jbr} to @code{jmpi}.
+This option is for V2 processors only.
+
+@cindex @code{mbranch-stub} command-line option, C-SKY
+@cindex @code{mno-branch-stub} command-line option, C-SKY
+@item -mbranch-stub
+@itemx -mno-branch-stub
+Pass through @code{R_CKCORE_PCREL_IMM26BY2} relocations for @code{bsr} 
+instructions to the linker.
+
+This option is only available for bare-metal C-SKY V2 ELF targets,
+where it is enabled by default.  It cannot be used in code that will be
+dynamically linked against shared libraries.
+
+@cindex @code{force2bsr} command-line option, C-SKY
+@cindex @code{mforce2bsr} command-line option, C-SKY
+@cindex @code{no-force2bsr} command-line option, C-SKY
+@cindex @code{mno-force2bsr} command-line option, C-SKY
+@item -force2bsr
+@itemx -mforce2bsr
+@itemx -no-force2bsr
+@itemx -mno-force2bsr
+Enable/disable transformation of @code{jbsr} instructions to @code{bsr}.
+This option is always enabled (and @option{-mno-force2bsr} is ignored)
+for CK801/CK802 targets.  It is also always enabled when 
+@option{-mbranch-stub} is in effect.
+
+@cindex @code{jsri2bsr} command-line option, C-SKY
+@cindex @code{mjsri2bsr} command-line option, C-SKY
+@cindex @code{no-jsri2bsr} command-line option, C-SKY
+@cindex @code{mno-jsri2bsr} command-line option, C-SKY
+@item -jsri2bsr
+@itemx -mjsri2bsr
+@itemx -no-jsri2bsr
+@itemx -mno-jsri2bsr
+Enable/disable transformation of @code{jsri} instructions to @code{bsr}.
+This option is enabled by default.
+
+@cindex @code{mnolrw} command-line option, C-SKY
+@cindex @code{mno-lrw} command-line option, C-SKY
+@item -mnolrw
+@itemx -mno-lrw
+Enable/disable transformation of @code{lrw} instructions into a
+@code{movih}/@code{ori} pair.
+
+@cindex @code{melrw} command-line option, C-SKY
+@cindex @code{mno-elrw} command-line option, C-SKY
+@item -melrw
+@itemx -mno-elrw
+Enable/disable extended @code{lrw} instructions.
+This option is enabled by default for CK800-series processors.
+
+@cindex @code{mlaf} command-line option, C-SKY
+@cindex @code{mliterals-after-func} command-line option, C-SKY
+@cindex @code{mno-laf} command-line option, C-SKY
+@cindex @code{mno-literals-after-func} command-line option, C-SKY
+@item -mlaf
+@itemx -mliterals-after-func
+@itemx -mno-laf
+@itemx -mno-literals-after-func
+Enable/disable placement of literal pools after each function.
+
+@cindex @code{mlabr} command-line option, C-SKY
+@cindex @code{mliterals-after-br} command-line option, C-SKY
+@cindex @code{mno-labr} command-line option, C-SKY
+@cindex @code{mnoliterals-after-br} command-line option, C-SKY
+@item -mlabr
+@itemx -mliterals-after-br
+@itemx -mno-labr
+@itemx -mnoliterals-after-br
+Enable/disable placement of literal pools after unconditional branches.
+This option is enabled by default.
+
+@cindex @code{mistack} command-line option, C-SKY
+@cindex @code{mno-istack} command-line option, C-SKY
+@item -mistack
+@itemx -mno-istack
+Enable/disable interrupt stack instructions.  This option is enabled by 
+default on CK801, CK802, and CK802 processors.
+
+@end table
+
+The following options explicitly enable certain optional instructions.
+These features are also enabled implicitly by using @code{-mcpu=} to specify
+a processor that supports it.
+
+@table @gcctabopt
+@cindex @code{mhard-float} command-line option, C-SKY
+@item -mhard-float
+Enable hard float instructions.
+
+@cindex @code{mmp} command-line option, C-SKY
+@item -mmp
+Enable multiprocessor instructions.
+
+@cindex @code{mcp} command-line option, C-SKY
+@item -mcp
+Enable coprocessor instructions.
+
+@cindex @code{mcache} command-line option, C-SKY
+@item -mcache
+Enable cache prefetch instruction.
+
+@cindex @code{msecurity} command-line option, C-SKY
+@item -msecurity
+Enable C-SKY security instructions.
+
+@cindex @code{mtrust} command-line option, C-SKY
+@item -mtrust
+Enable C-SKY trust instructions.
+
+@cindex @code{mdsp} command-line option, C-SKY
+@item -mdsp
+Enable DSP instructions.
+
+@cindex @code{medsp} command-line option, C-SKY
+@item -medsp
+Enable enhanced DSP instructions.
+
+@cindex @code{mvdsp} command-line option, C-SKY
+@item -mvdsp
+Enable vector DSP instructions.
+
+@end table
+@c man end
+
+@node C-SKY Syntax
+@section Syntax
+
+@code{@value{AS}} implements the standard C-SKY assembler syntax
+documented in the
+@cite{C-SKY V2 CPU Applications Binary Interface Standards Manual}.
+
+
diff --git a/gas/testsuite/gas/csky/801_relax.d b/gas/testsuite/gas/csky/801_relax.d
new file mode 100644
index 0000000..1677fb1
--- /dev/null
+++ b/gas/testsuite/gas/csky/801_relax.d
@@ -0,0 +1,14 @@ 
+#name: csky - 801_relax
+#as: -march=ck801
+#objdump: -d
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*2:\s*0803\s*bt\s*0x8\s*.*
+\s*4:\s*e800025c\s*br\s*0x4bc\s*.*
+#...
+\s*4bc:\s*0c03\s*bf\s*0x4c2\s*.*
+\s*4be:\s*e800fda2\s*br\s*0x2\s*.*
+#...
diff --git a/gas/testsuite/gas/csky/801_relax.s b/gas/testsuite/gas/csky/801_relax.s
new file mode 100644
index 0000000..1b18526
--- /dev/null
+++ b/gas/testsuite/gas/csky/801_relax.s
@@ -0,0 +1,16 @@ 
+# Test ck801 jbf/jbt branch relaxation.  
+
+        addu a1, a2, a3
+.L1:
+        jbf .L2
+        addu a3, a2, a1
+
+        .rept 600
+        nop
+        .endr
+
+
+        addu a1, a2, a3
+.L2:
+        jbt .L1
+        addu a3, a2, a1
diff --git a/gas/testsuite/gas/csky/802j.d b/gas/testsuite/gas/csky/802j.d
new file mode 100644
index 0000000..af7c857
--- /dev/null
+++ b/gas/testsuite/gas/csky/802j.d
@@ -0,0 +1,13 @@ 
+# name: csky - 802j
+#as: -mcpu=ck802j -W
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*1463\s*ipop
+\s*[0-9a-f]*:\s*1462\s*ipush
+\s*[0-9a-f]*:\s*1460\s*nie
+\s*[0-9a-f]*:\s*1461\s*nir
+\s*[0-9a-f]*:\s*3ae0\s*jmpix\s*r2,\s*16.*
diff --git a/gas/testsuite/gas/csky/802j.s b/gas/testsuite/gas/csky/802j.s
new file mode 100644
index 0000000..4528b38
--- /dev/null
+++ b/gas/testsuite/gas/csky/802j.s
@@ -0,0 +1,8 @@ 
+.text
+all:
+    ipop
+    ipush
+    nie
+    nir
+    jmpix r2, 16
+
diff --git a/gas/testsuite/gas/csky/all.d b/gas/testsuite/gas/csky/all.d
new file mode 100644
index 0000000..c5da5b0
--- /dev/null
+++ b/gas/testsuite/gas/csky/all.d
@@ -0,0 +1,150 @@ 
+# name: csky - all
+#as: -mcpu=ck610e -W
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*0000\s*bkpt
+\s*[0-9a-f]*:\s*0001\s*sync
+\s*[0-9a-f]*:\s*0002\s*rte
+\s*[0-9a-f]*:\s*0002\s*rte
+\s*[0-9a-f]*:\s*0003\s*rfi
+\s*[0-9a-f]*:\s*0004\s*stop
+\s*[0-9a-f]*:\s*0005\s*wait
+\s*[0-9a-f]*:\s*0006\s*doze
+\s*[0-9a-f]*:\s*0007\s*idly4
+\s*[0-9a-f]*:\s*000b\s*trap\s*3
+\s*[0-9a-f]*:\s*0021\s*mvc\s*r1
+\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*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
+\s*[0-9a-f]*:\s*00b2\s*incf\s*r2, r2, 1
+\s*[0-9a-f]*:\s*00c1\s*jmp\s*r1
+\s*[0-9a-f]*:\s*00d1\s*jsr\s*r1
+\s*[0-9a-f]*:\s*00eb\s*ff1\s*r11, r11
+\s*[0-9a-f]*:\s*00f1\s*brev\s*r1, r1
+\s*[0-9a-f]*:\s*0102\s*xtrb3\s*r1, r2
+\s*[0-9a-f]*:\s*0112\s*xtrb2\s*r1, r2
+\s*[0-9a-f]*:\s*0122\s*xtrb1\s*r1, r2
+\s*[0-9a-f]*:\s*0132\s*xtrb0\s*r1, r2
+\s*[0-9a-f]*:\s*0132\s*xtrb0\s*r1, r2
+\s*[0-9a-f]*:\s*0132\s*xtrb0\s*r1, r2
+\s*[0-9a-f]*:\s*1213\s*mov\s*r3, r1
+\s*[0-9a-f]*:\s*0142\s*zextb\s*r2, r2
+\s*[0-9a-f]*:\s*0152\s*sextb\s*r2, r2
+\s*[0-9a-f]*:\s*0162\s*zexth\s*r2, r2
+\s*[0-9a-f]*:\s*0172\s*sexth\s*r2, r2
+\s*[0-9a-f]*:\s*0182\s*declt\s*r2, r2, 1
+\s*[0-9a-f]*:\s*01b1\s*decne\s*r1, r1, 1
+\s*[0-9a-f]*:\s*01a1\s*decgt\s*r1, r1, 1
+\s*[0-9a-f]*:\s*01c1\s*clrt\s*r1
+\s*[0-9a-f]*:\s*01d1\s*clrf\s*r1
+\s*[0-9a-f]*:\s*01e3\s*abs\s*r3, r3
+\s*[0-9a-f]*:\s*01fc\s*not\s*r12, r12
+\s*[0-9a-f]*:\s*0221\s*movt\s*r1, r2
+\s*[0-9a-f]*:\s*0343\s*mult\s*r3, r3, r4
+\s*[0-9a-f]*:\s*0587\s*subu\s*r7, r7, r8
+\s*[0-9a-f]*:\s*0587\s*subu\s*r7, r7, r8
+\s*[0-9a-f]*:\s*06a9\s*addc\s*r9, r9, r10
+\s*[0-9a-f]*:\s*07cb\s*subc\s*r11, r11, r12
+\s*[0-9a-f]*:\s*0adc\s*movf\s*r12, r13
+\s*[0-9a-f]*:\s*0bdc\s*lsr\s*r12, r12, r13
+\s*[0-9a-f]*:\s*0ced\s*cmphs\s*r13, r14
+\s*[0-9a-f]*:\s*0ded\s*cmplt\s*r13, r14
+\s*[0-9a-f]*:\s*0eed\s*tst\s*r13, r14
+\s*[0-9a-f]*:\s*0fed\s*cmpne\s*r13, r14
+\s*[0-9a-f]*:\s*11f7\s*psrclr\s*ie, fe, ee
+\s*[0-9a-f]*:\s*1253\s*mov\s*r3, r5
+\s*[0-9a-f]*:\s*1332\s*bgenr\s*r2, r3
+\s*[0-9a-f]*:\s*1643\s*and\s*r3, r3, r4
+\s*[0-9a-f]*:\s*1543\s*ixw\s*r3, r3, r4
+\s*[0-9a-f]*:\s*1a43\s*asr\s*r3, r3, r4
+\s*[0-9a-f]*:\s*1c43\s*addu\s*r3, r3, r4
+\s*[0-9a-f]*:\s*1d32\s*ixh\s*r2, r2, r3
+\s*[0-9a-f]*:\s*1f43\s*andn\s*r3, r3, r4
+\s*[0-9a-f]*:\s*21f3\s*addi\s*r3, r3, 32
+\s*[0-9a-f]*:\s*23f3\s*cmplti\s*r3, 32
+\s*[0-9a-f]*:\s*2413\s*subi\s*r3, r3, 2
+\s*[0-9a-f]*:\s*2823\s*rsubi\s*r3, r3, 2
+\s*[0-9a-f]*:\s*2a33\s*cmpnei\s*r3, 3
+\s*[0-9a-f]*:\s*2c83\s*bmaski\s*r3, 8
+\s*[0-9a-f]*:\s*2c13\s*divu\s*r3, r3, r1
+\s*[0-9a-f]*:\s*2c22\s*mflos\s*r2
+\s*[0-9a-f]*:\s*2c32\s*mfhis\s*r2
+\s*[0-9a-f]*:\s*2c42\s*mtlo\s*r2
+\s*[0-9a-f]*:\s*2c52\s*mthi\s*r2
+\s*[0-9a-f]*:\s*2c62\s*mflo\s*r2
+\s*[0-9a-f]*:\s*2c72\s*mfhi\s*r2
+\s*[0-9a-f]*:\s*2e33\s*andi\s*r3, r3, 3
+\s*[0-9a-f]*:\s*3033\s*bclri\s*r3, r3, 3
+\s*[0-9a-f]*:\s*3293\s*bgeni\s*r3, 9
+\s*[0-9a-f]*:\s*6403\s*movi\s*r3, 64
+\s*[0-9a-f]*:\s*3213\s*divs\s*r3, r3, r1
+\s*[0-9a-f]*:\s*1221\s*mov\s*r1, r2
+\s*[0-9a-f]*:\s*3213\s*divs\s*r3, r3, r1
+\s*[0-9a-f]*:\s*3493\s*bseti\s*r3, r3, 9
+\s*[0-9a-f]*:\s*3693\s*btsti\s*r3, 9
+\s*[0-9a-f]*:\s*3803\s*xsr\s*r3, r3, 1
+\s*[0-9a-f]*:\s*3823\s*rotli\s*r3, r3, 2
+\s*[0-9a-f]*:\s*3a03\s*asrc\s*r3, r3, 1
+\s*[0-9a-f]*:\s*3a31\s*asri\s*r1, r1, 3
+\s*[0-9a-f]*:\s*67f7\s*movi\s*r7, 127
+\s*[0-9a-f]*:\s*8200\s*ld.w\s*r2,\s*\(r0,\s*0x0\)
+\s*[0-9a-f]*:\s*8210\s*ld.w\s*r2,\s*\(r0,\s*0x4\)
+\s*[0-9a-f]*:\s*8220\s*ld.w\s*r2,\s*\(r0,\s*0x8\)
+\s*[0-9a-f]*:\s*9200\s*st.w\s*r2,\s*\(r0,\s*0x0\)
+\s*[0-9a-f]*:\s*9210\s*st.w\s*r2,\s*\(r0,\s*0x4\)
+\s*[0-9a-f]*:\s*9220\s*st.w\s*r2,\s*\(r0,\s*0x8\)
+\s*[0-9a-f]*:\s*c210\s*ld.h\s*r2,\s*\(r0,\s*0x2\)
+\s*[0-9a-f]*:\s*c220\s*ld.h\s*r2,\s*\(r0,\s*0x4\)
+\s*[0-9a-f]*:\s*d210\s*st.h\s*r2,\s*\(r0,\s*0x2\)
+\s*[0-9a-f]*:\s*d220\s*st.h\s*r2,\s*\(r0,\s*0x4\)
+\s*[0-9a-f]*:\s*a200\s*ld.b\s*r2,\s*\(r0,\s*0x0\)
+\s*[0-9a-f]*:\s*a210\s*ld.b\s*r2,\s*\(r0,\s*0x1\)
+\s*[0-9a-f]*:\s*b200\s*st.b\s*r2,\s*\(r0,\s*0x0\)
+\s*[0-9a-f]*:\s*b210\s*st.b\s*r2,\s*\(r0,\s*0x1\)
+\s*[0-9a-f]*:\s*e798\s*bt\s*0x0.*
+\s*[0-9a-f]*:\s*ef97\s*bf\s*0x0.*
+\s*[0-9a-f]*:\s*f796\s*br\s*0x0.*
+\s*[0-9a-f]*:\s*0c00\s*cmphs\s*r0, r0
+\s*[0-9a-f]*:\s*0f00\s*cmpne\s*r0, r0
+\s*[0-9a-f]*:\s*2205\s*cmplti\s*r5, 1
+\s*[0-9a-f]*:\s*2263\s*cmplti\s*r3, 7
+\s*[0-9a-f]*:\s*2807\s*rsubi\s*r7, r7, 0
+\s*[0-9a-f]*:\s*2a06\s*cmpnei\s*r6, 0
+\s*[0-9a-f]*:\s*37f0\s*btsti\s*r0, 31
+\s*[0-9a-f]*:\s*31f3\s*bclri\s*r3, r3, 31
+\s*[0-9a-f]*:\s*6404\s*movi\s*r4, 64
+\s*[0-9a-f]*:\s*3274\s*bgeni\s*r4, 7
+\s*[0-9a-f]*:\s*3501\s*bseti\s*r1, r1, 16
+\s*[0-9a-f]*:\s*3644\s*btsti\s*r4, 4
+\s*[0-9a-f]*:\s*38c6\s*rotli\s*r6, r6, 12
+\s*[0-9a-f]*:\s*39f2\s*rotli\s*r2, r2, 31
+\s*[0-9a-f]*:\s*1200\s*mov\s*r0, r0
+\s*[0-9a-f]*:\s*0007\s*idly4
+\s*[0-9a-f]*:\s*0644\s*addc\s*r4, r4, r4
+\s*[0-9a-f]*:\s*0655\s*addc\s*r5, r5, r5
+\s*[0-9a-f]*:\s*0132\s*xtrb0\s*r1, r2
+\s*[0-9a-f]*:\s*0151\s*sextb\s*r1, r1
+\s*[0-9a-f]*:\s*0123\s*xtrb1\s*r1, r3
+\s*[0-9a-f]*:\s*0151\s*sextb\s*r1, r1
+\s*[0-9a-f]*:\s*0114\s*xtrb2\s*r1, r4
+\s*[0-9a-f]*:\s*0151\s*sextb\s*r1, r1
+\s*[0-9a-f]*:\s*0221\s*movt\s*r1, r2
+\s*[0-9a-f]*:\s*0a31\s*movf\s*r1, r3
+\s*[0-9a-f]*:\s*0d22\s*cmplt\s*r2, r2
+\s*[0-9a-f]*:\s*0672\s*addc\s*r2, r2, r7
+\s*[0-9a-f]*:\s*0683\s*addc\s*r3, r3, r8
+\s*[0-9a-f]*:\s*0c44\s*cmphs\s*r4, r4
+\s*[0-9a-f]*:\s*0764\s*subc\s*r4, r4, r6
+\s*[0-9a-f]*:\s*0775\s*subc\s*r5, r5, r7
+\s*[0-9a-f]*:\s*1e26\s*or\s*r6, r6, r2
+\s*[0-9a-f]*:\s*1e37\s*or\s*r7, r7, r3
+\s*[0-9a-f]*:\s*1715\s*xor\s*r5, r5, r1
+\s*[0-9a-f]*:\s*1726\s*xor\s*r6, r6, r2
diff --git a/gas/testsuite/gas/csky/all.s b/gas/testsuite/gas/csky/all.s
new file mode 100644
index 0000000..a21bd47
--- /dev/null
+++ b/gas/testsuite/gas/csky/all.s
@@ -0,0 +1,132 @@ 
+.text
+all:
+      bkpt
+      sync
+      rte
+      rfe
+      rfi
+      stop
+      wait
+      doze
+      idly4
+      trap 3
+      mvc  r1
+      mvcv r2
+      ldq r4-r7, (r2)
+      stq r4-r7, (r2)
+      ldm r1-r15, (r0)
+      dect r2
+      decf r2
+      inct r2
+      incf r2
+      jmp  r1
+      jsr  r1
+      ff1  r11
+      brev r1
+      xtrb3 r2
+      xtrb2 r2
+      xtrb1 r2
+      xtrb0 r2
+      xtrb0 r1, r2
+      xtrb0 r3, r2
+      zextb r2
+      sextb r2
+      zexth r2
+      sexth r2
+      declt r2
+      decne r1
+      decgt r1
+      clrt  r1
+      clrf  r1
+      abs   r3
+      not   r12
+      movt  r1, r2
+      mult  r3, r4
+      sub   r7, r8
+      subu  r7, r8
+      addc  r9, r10
+      subc  r11, r12
+      movf  r12, r13
+      lsr   r12, r13
+      cmphs r13, r14
+      cmplt r13, r14
+      tst r13, r14
+      cmpne r13, r14
+      psrclr ee, ie, fe
+      mov   r3, r5
+      bgenr r2, r3
+      and   r3, r4
+      ixw   r3, r4
+      asr   r3, r4
+      addu  r3, r4
+      ixh   r2, r3
+      andn  r3, r4
+      addi  r3, 32
+      cmplti  r3, 32
+      subi  r3, 2
+      rsubi  r3, 2
+      cmpnei  r3, 3
+      bmaski  r3, 8
+      divu  r3, r1
+      mflos r2
+      mfhis r2
+      mtlo r2
+      mthi r2
+      mflo r2
+      mfhi r2
+      andi  r3, 3
+      bclri  r3, 3
+      bgeni  r3, 9
+      bgeni  r3, 6
+      divs  r3, r1
+      divs  r3, r2
+      bseti  r3, 9
+      btsti  r3, 9
+      xsr   r3
+      rotli r3, 2
+      asrc  r3
+      asri r1, 3
+      movi r7, 127
+      ld   r2, (r0, 0)
+      ldw  r2, (r0, 4)
+      ld.w  r2, (r0, 8)
+      st   r2, (r0, 0)
+      stw  r2, (r0, 4)
+      st.w  r2, (r0, 8)
+      ldh  r2, (r0, 2)
+      ld.h  r2, (r0, 4)
+      sth  r2, (r0, 2)
+      st.h  r2, (r0, 4)
+      ldb  r2, (r0, 0)
+      ld.b  r2, (r0, 1)
+      stb  r2, (r0, 0)
+      st.b  r2, (r0, 1)
+      bt    all
+      bf    all
+      br    all
+      setc
+      clrc
+      tstle r5
+      cmplei r3, 6
+      neg   r7
+      tstne r6
+      tstlt r0
+      mclri  r3, 0x80000000
+      mgeni  r4, 0x40
+      mgeni  r4, 0x80
+      mseti  r1, 0x10000
+      mtsti r4, 16
+      rori  r6, 20
+      rotri r2, 1
+      nop
+      idly  4
+      rolc  r4, 1
+      rotlc r5, 1
+      sxtrb0 r1, r2
+      sxtrb1 r1, r3
+      sxtrb2 r1, r4
+      movtf r1, r2, r3
+      addc64 r2, r2, r7
+      subc64 r4, r4, r6
+      or64   r6, r6, r2
+      xor64  r5, r5, r1
diff --git a/gas/testsuite/gas/csky/bsr1.d b/gas/testsuite/gas/csky/bsr1.d
new file mode 100644
index 0000000..4de2aca
--- /dev/null
+++ b/gas/testsuite/gas/csky/bsr1.d
@@ -0,0 +1,14 @@ 
+# name: bsr1 - csky
+#as: -mcpu=ck610
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]:\s*ffff\s*bsr\s*0x0\s*\/\/\s*0\s*\<lable\>
+\s*[0-9a-f]:\s*f7fe\s*br\s*0x0\s*\/\/\s*0\s*\<lable*\>
+\s*[0-9a-f]:\s*e7fd\s*bt\s*0x0\s*\/\/\s*0\s*\<lable*\>
+\s*[0-9a-f]:\s*effc\s*bf\s*0x0\s*\/\/\s*0\s*\<lable*\>
+
+
diff --git a/gas/testsuite/gas/csky/bsr1.s b/gas/testsuite/gas/csky/bsr1.s
new file mode 100644
index 0000000..8cc5c81
--- /dev/null
+++ b/gas/testsuite/gas/csky/bsr1.s
@@ -0,0 +1,6 @@ 
+.text
+lable:
+  bsr lable
+  br lable
+  bt lable
+  bf lable
diff --git a/gas/testsuite/gas/csky/bsr2.d b/gas/testsuite/gas/csky/bsr2.d
new file mode 100644
index 0000000..41369cd
--- /dev/null
+++ b/gas/testsuite/gas/csky/bsr2.d
@@ -0,0 +1,11 @@ 
+# name: bsr2 - csky
+#as: -mcpu=ck610
+#objdump: -r
+
+.*: +file format .*csky.*
+
+RELOCATION RECORDS FOR \[\.text\]:
+#...
+[0-9a-f]*\s*R_CKCORE_PCREL_IMM11BY2\s*hello
+
+
diff --git a/gas/testsuite/gas/csky/bsr2.s b/gas/testsuite/gas/csky/bsr2.s
new file mode 100644
index 0000000..0bed607
--- /dev/null
+++ b/gas/testsuite/gas/csky/bsr2.s
@@ -0,0 +1,3 @@ 
+.text
+lable:
+   bsr hello
diff --git a/gas/testsuite/gas/csky/csky.exp b/gas/testsuite/gas/csky/csky.exp
new file mode 100644
index 0000000..1f18b39
--- /dev/null
+++ b/gas/testsuite/gas/csky/csky.exp
@@ -0,0 +1,7 @@ 
+#
+# Some CSKY tests
+#
+
+if {[istarget csky*-*-*]} {
+    run_dump_tests [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
+}
diff --git a/gas/testsuite/gas/csky/csky_vdsp.d b/gas/testsuite/gas/csky/csky_vdsp.d
new file mode 100644
index 0000000..0e2eaa2
--- /dev/null
+++ b/gas/testsuite/gas/csky/csky_vdsp.d
@@ -0,0 +1,364 @@ 
+# name: csky - vdsp
+#as: -mcpu=ck810v -W
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*f8623c02\s*vstrq\.8\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623d02\s*vstrq\.16\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623e02\s*vstrq\.32\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623402\s*vldrq\.8\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623502\s*vldrq\.16\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623602\s*vldrq\.32\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623802\s*vstrd\.8\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623902\s*vstrd\.16\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623a02\s*vstrd\.32\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623002\s*vldrd\.8\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623102\s*vldrd\.16\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8623202\s*vldrd\.32\s*fr2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f8022412\s*vldq\.8\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022512\s*vldq\.16\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022612\s*vldq\.32\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022c12\s*vstq\.8\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022d12\s*vstq\.16\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022e12\s*vstq\.32\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022022\s*vldd\.8\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022122\s*vldd\.16\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022222\s*vldd\.32\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022822\s*vstd\.8\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022922\s*vstd\.16\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*f8022a22\s*vstd\.32\s*fr2,\s*\(r2,\s*0x10\)
+\s*[0-9a-f]*:\s*c43eb020\s*vmulsh\s*r30,\s*r1
+\s*[0-9a-f]*:\s*c7e0b040\s*vmulsha\s*r0,\s*r31
+\s*[0-9a-f]*:\s*c58cb420\s*vmulsw\s*r12,\s*r12
+\s*[0-9a-f]*:\s*c6bcb440\s*vmulswa\s*r28,\s*r21
+\s*[0-9a-f]*:\s*c481b480\s*vmulsws\s*r1,\s*r4
+\s*[0-9a-f]*:\s*f9221201\s*vmfvr.u8\s*r1,\s*vr2\[9\]
+\s*[0-9a-f]*:\s*f8041223\s*vmfvr.u16\s*r3,\s*vr4\[0\]
+\s*[0-9a-f]*:\s*f8a8125f\s*vmfvr.u32\s*r31,\s*vr8\[5\]
+\s*[0-9a-f]*:\s*f824128d\s*vmfvr.s8\s*r13,\s*vr4\[1\]
+\s*[0-9a-f]*:\s*f9af12b7\s*vmfvr.s16\s*r23,\s*vr15\[13\]
+\s*[0-9a-f]*:\s*f8101305\s*vmtvr.u8\s*vr5\[0\],\s*r16
+\s*[0-9a-f]*:\s*f8ea1324\s*vmtvr.u16\s*vr4\[7\],\s*r10
+\s*[0-9a-f]*:\s*f9ea134f\s*vmtvr.u32\s*vr15\[15\],\s*r10
+\s*[0-9a-f]*:\s*f94a0e81\s*vdup.8\s*fr1,\s*vr10\[10\]
+\s*[0-9a-f]*:\s*f83a0e8f\s*vdup.16\s*fr15,\s*vr10\[1\]
+\s*[0-9a-f]*:\s*faaa0e87\s*vdup.32\s*fr7,\s*vr10\[5\]
+\s*[0-9a-f]*:\s*f8030c02\s*vmov\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030062\s*vcadd\.eu8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130062\s*vcadd\.eu16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030072\s*vcadd\.es8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130072\s*vcadd\.es16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030c22\s*vmov\.eu8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130c22\s*vmov\.eu16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030c32\s*vmov\.es8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130c32\s*vmov\.es16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130d02\s*vmov\.u16\.l\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030d02\s*vmov\.u32\.l\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130d12\s*vmov\.s16\.l\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030d12\s*vmov\.s32\.l\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130d42\s*vmov\.u16\.sl\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030d42\s*vmov\.u32\.sl\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130d52\s*vmov\.s16\.sl\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030d52\s*vmov\.s32\.sl\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130d62\s*vmov\.u16\.h\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030d62\s*vmov\.u32\.h\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130d72\s*vmov\.s16\.h\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030d72\s*vmov\.s32\.h\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130d82\s*vmov\.u16\.rh\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030d82\s*vmov\.u32\.rh\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130d92\s*vmov\.s16\.rh\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030d92\s*vmov\.s32\.rh\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130dc2\s*vstou\.u16\.sl\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030dc2\s*vstou\.u32\.sl\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130dd2\s*vstou\.s16\.sl\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030dd2\s*vstou\.s32\.sl\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030e62\s*vrev\.8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130e62\s*vrev\.16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030e62\s*vrev\.32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030ea2\s*vcnt1\.8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030ec2\s*vclz\.8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130ec2\s*vclz\.16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030ec2\s*vclz\.32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030ee2\s*vcls\.u8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130ee2\s*vcls\.u16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030ee2\s*vcls\.u32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030ef2\s*vcls\.s8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130ef2\s*vcls\.s16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030ef2\s*vcls\.s32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8031012\s*vabs\.s8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8131012\s*vabs\.s16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa031012\s*vabs\.s32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8031042\s*vabs\.u8\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8131042\s*vabs\.u16\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa031042\s*vabs\.u32\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8031052\s*vabs\.s8\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8131052\s*vabs\.s16\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa031052\s*vabs\.s32\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8031082\s*vneg\.u8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8131082\s*vneg\.u16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa031082\s*vneg\.u32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8031092\s*vneg\.s8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8131092\s*vneg\.s16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa031092\s*vneg\.s32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f80310c2\s*vneg\.u8\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f81310c2\s*vneg\.u16\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa0310c2\s*vneg\.u32\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f80310d2\s*vneg\.s8\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f81310d2\s*vneg\.s16\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa0310d2\s*vneg\.s32\.s\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030882\s*vcmphsz\.u8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130882\s*vcmphsz\.u16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030882\s*vcmphsz\.u32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8030892\s*vcmphsz\.s8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8130892\s*vcmphsz\.s16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa030892\s*vcmphsz\.s32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f80308a2\s*vcmpltz\.u8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f81308a2\s*vcmpltz\.u16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa0308a2\s*vcmpltz\.u32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f80308b2\s*vcmpltz\.s8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f81308b2\s*vcmpltz\.s16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa0308b2\s*vcmpltz\.s32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f80308c2\s*vcmpnez\.u8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f81308c2\s*vcmpnez\.u16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa0308c2\s*vcmpnez\.u32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f80308d2\s*vcmpnez\.s8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f80308d2\s*vcmpnez\.s8\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f81308d2\s*vcmpnez\.s16\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*fa0308d2\s*vcmpnez\.s32\s*vr2,\s*vr3
+\s*[0-9a-f]*:\s*f8830f42\s*vtrch\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930f42\s*vtrch\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830f42\s*vtrch\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830f62\s*vtrcl\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930f62\s*vtrcl\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830f62\s*vtrcl\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830002\s*vadd\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930002\s*vadd\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830002\s*vadd\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830012\s*vadd\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930012\s*vadd\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830012\s*vadd\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830022\s*vadd\.eu8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930022\s*vadd\.eu16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830032\s*vadd\.es8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930032\s*vadd\.es16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830042\s*vcadd\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930042\s*vcadd\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830042\s*vcadd\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830052\s*vcadd\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930052\s*vcadd\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830052\s*vcadd\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930142\s*vadd\.xu16\.sl\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830142\s*vadd\.xu32\.sl\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930152\s*vadd\.xs16\.sl\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830152\s*vadd\.xs32\.sl\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930162\s*vadd\.xu16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830162\s*vadd\.xu32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930172\s*vadd\.xs16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830172\s*vadd\.xs32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830182\s*vaddh\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930182\s*vaddh\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830182\s*vaddh\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830192\s*vaddh\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930192\s*vaddh\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830192\s*vaddh\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88301a2\s*vaddh\.u8\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89301a2\s*vaddh\.u16\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8301a2\s*vaddh\.u32\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88301b2\s*vaddh\.s8\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89301b2\s*vaddh\.s16\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8301b2\s*vaddh\.s32\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88301c2\s*vadd\.u8\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89301c2\s*vadd\.u16\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8301c2\s*vadd\.u32\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88301d2\s*vadd\.s8\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89301d2\s*vadd\.s16\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8301d2\s*vadd\.s32\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830202\s*vsub\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930202\s*vsub\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830202\s*vsub\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830212\s*vsub\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930212\s*vsub\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830212\s*vsub\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830222\s*vsub\.eu8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930222\s*vsub\.eu16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830232\s*vsub\.es8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930232\s*vsub\.es16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830242\s*vsabs\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930242\s*vsabs\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830242\s*vsabs\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830252\s*vsabs\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930252\s*vsabs\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830252\s*vsabs\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830262\s*vsabs\.eu8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930262\s*vsabs\.eu16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830272\s*vsabs\.es8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930272\s*vsabs\.es16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830282\s*vsabsa\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930282\s*vsabsa\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830282\s*vsabsa\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830292\s*vsabsa\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930292\s*vsabsa\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830292\s*vsabsa\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88302a2\s*vsabsa\.eu8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89302a2\s*vsabsa\.eu16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88302b2\s*vsabsa\.es8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89302b2\s*vsabsa\.es16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930362\s*vsub\.xu16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830362\s*vsub\.xu32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930372\s*vsub\.xs16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830372\s*vsub\.xs32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830382\s*vsubh\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930382\s*vsubh\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830382\s*vsubh\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830392\s*vsubh\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930392\s*vsubh\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830392\s*vsubh\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88303a2\s*vsubh\.u8\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89303a2\s*vsubh\.u16\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8303a2\s*vsubh\.u32\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88303b2\s*vsubh\.s8\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89303b2\s*vsubh\.s16\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8303b2\s*vsubh\.s32\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88303c2\s*vsub\.u8\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89303c2\s*vsub\.u16\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8303c2\s*vsub\.u32\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88303d2\s*vsub\.s8\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89303d2\s*vsub\.s16\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8303d2\s*vsub\.s32\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830402\s*vmul\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930402\s*vmul\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830402\s*vmul\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830412\s*vmul\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930412\s*vmul\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830412\s*vmul\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830422\s*vmul\.eu8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930422\s*vmul\.eu16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830432\s*vmul\.es8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930432\s*vmul\.es16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830442\s*vmula\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930442\s*vmula\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830442\s*vmula\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830452\s*vmula\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930452\s*vmula\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830452\s*vmula\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830462\s*vmula\.eu8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930462\s*vmula\.eu16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830462\s*vmula\.eu32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830472\s*vmula\.es8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930472\s*vmula\.es16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830472\s*vmula\.es32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830482\s*vmuls\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930482\s*vmuls\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830482\s*vmuls\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830492\s*vmuls\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930492\s*vmuls\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830492\s*vmuls\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88304a2\s*vmuls\.eu8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89304a2\s*vmuls\.eu16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88304b2\s*vmuls\.es8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89304b2\s*vmuls\.es16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830682\s*vshr\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930682\s*vshr\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830682\s*vshr\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830692\s*vshr\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930692\s*vshr\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830692\s*vshr\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88306c2\s*vshr\.u8\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89306c2\s*vshr\.u16\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8306c2\s*vshr\.u32\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88306d2\s*vshr\.s8\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89306d2\s*vshr\.s16\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8306d2\s*vshr\.s32\.r\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830782\s*vshl\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930782\s*vshl\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830782\s*vshl\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830792\s*vshl\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930792\s*vshl\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830792\s*vshl\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88307c2\s*vshl\.u8\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89307c2\s*vshl\.u16\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8307c2\s*vshl\.u32\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88307d2\s*vshl\.s8\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89307d2\s*vshl\.s16\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8307d2\s*vshl\.s32\.s\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830802\s*vcmphs\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930802\s*vcmphs\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830802\s*vcmphs\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830812\s*vcmphs\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930812\s*vcmphs\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830812\s*vcmphs\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830822\s*vcmplt\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930822\s*vcmplt\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830822\s*vcmplt\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830832\s*vcmplt\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930832\s*vcmplt\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830832\s*vcmplt\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830842\s*vcmpne\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930842\s*vcmpne\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830842\s*vcmpne\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830852\s*vcmpne\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930852\s*vcmpne\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830852\s*vcmpne\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830902\s*vmax\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930902\s*vmax\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830902\s*vmax\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830912\s*vmax\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930912\s*vmax\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830912\s*vmax\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830922\s*vmin\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930922\s*vmin\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830922\s*vmin\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830932\s*vmin\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930932\s*vmin\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830932\s*vmin\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830982\s*vcmax\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930982\s*vcmax\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830982\s*vcmax\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830992\s*vcmax\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930992\s*vcmax\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830992\s*vcmax\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88309a2\s*vcmin\.u8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89309a2\s*vcmin\.u16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8309a2\s*vcmin\.u32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f88309b2\s*vcmin\.s8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f89309b2\s*vcmin\.s16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa8309b2\s*vcmin\.s32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830a02\s*vand\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930a02\s*vand\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830a02\s*vand\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830a22\s*vandn\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930a22\s*vandn\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830a22\s*vandn\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830a42\s*vor\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930a42\s*vor\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830a42\s*vor\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830a62\s*vnor\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930a62\s*vnor\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830a62\s*vnor\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830a82\s*vxor\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930a82\s*vxor\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830a82\s*vxor\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830b22\s*vtst\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930b22\s*vtst\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830b22\s*vtst\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830f02\s*vbpermz\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930f02\s*vbpermz\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830f02\s*vbpermz\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830f22\s*vbperm\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930f22\s*vbperm\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830f22\s*vbperm\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830fc2\s*vdch\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930fc2\s*vdch\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830fc2\s*vdch\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830fe2\s*vdcl\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930fe2\s*vdcl\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830fe2\s*vdcl\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830f82\s*vich\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930f82\s*vich\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830f82\s*vich\.32\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8830fa2\s*vicl\.8\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*f8930fa2\s*vicl\.16\s*vr2,\s*vr3,\s*vr4
+\s*[0-9a-f]*:\s*fa830fa2\s*vicl\.32\s*vr2,\s*vr3,\s*vr4
diff --git a/gas/testsuite/gas/csky/csky_vdsp.s b/gas/testsuite/gas/csky/csky_vdsp.s
new file mode 100644
index 0000000..7ca46b7
--- /dev/null
+++ b/gas/testsuite/gas/csky/csky_vdsp.s
@@ -0,0 +1,359 @@ 
+
+.text
+vdsp_instructions:
+   vstrq.8 vr2, (r2, r3 << 0)
+   vstrq.16 vr2, (r2, r3 << 0)
+   vstrq.32 vr2, (r2, r3 << 0)
+   vldrq.8 vr2, (r2, r3 << 0)
+   vldrq.16 vr2, (r2, r3 << 0)
+   vldrq.32 vr2, (r2, r3 << 0)
+   vstrd.8 vr2, (r2, r3 << 0)
+   vstrd.16 vr2, (r2, r3 << 0)
+   vstrd.32 vr2, (r2, r3 << 0)
+   vldrd.8 vr2, (r2, r3 << 0)
+   vldrd.16 vr2, (r2, r3 << 0)
+   vldrd.32 vr2, (r2, r3 << 0)
+   vldq.8  vr2, (r2, 16)
+   vldq.16  vr2, (r2, 16)
+   vldq.32  vr2, (r2, 16)
+   vstq.8  vr2, (r2, 16)
+   vstq.16  vr2, (r2, 16)
+   vstq.32  vr2, (r2, 16)
+   vldd.8  vr2, (r2, 16)
+   vldd.16  vr2, (r2, 16)
+   vldd.32  vr2, (r2, 16)
+   vstd.8  vr2, (r2, 16)
+   vstd.16  vr2, (r2, 16)
+   vstd.32  vr2, (r2, 16)
+  vmulsh  r30, r1
+  vmulsha r0,  r31
+  vmulsw  r12, r12
+  vmulswa r28, r21
+  vmulsws r1,  r4
+  vmfvr.u8   r1,  vr2[9]
+  vmfvr.u16  r3,  fr4[0]
+  vmfvr.u32  r31, vr8[5]
+  vmfvr.s8   r13, fr4[1]
+  vmfvr.s16  r23, vr15[13]
+  vmtvr.u8   vr5[0],  r16
+  vmtvr.u16  fr4[7],  r10
+  vmtvr.u32  vr15 [ 15 ] ,  r10
+  vdup.8     vr1,  vr10[10]
+  vdup.16    vr15,  fr10[1]
+  vdup.32    fr7,  fr10[5]
+    vmov         vr2, vr3
+    vcadd.eu8    vr2, vr3
+    vcadd.eu16    vr2, vr3
+    vcadd.es8     vr2, vr3
+    vcadd.es16    vr2, vr3
+    vmov.eu8      vr2, vr3
+    vmov.eu16     vr2, vr3
+    vmov.es8      vr2, vr3
+    vmov.es16     vr2, vr3
+    vmov.u16.l    vr2, vr3
+    vmov.u32.l    vr2, vr3
+    vmov.s16.l    vr2, vr3
+    vmov.s32.l    vr2, vr3
+    vmov.u16.sl    vr2, vr3
+    vmov.u32.sl    vr2, vr3
+    vmov.s16.sl    vr2, vr3
+    vmov.s32.sl    vr2, vr3
+    vmov.u16.h    vr2, vr3
+    vmov.u32.h    vr2, vr3
+    vmov.s16.h    vr2, vr3
+    vmov.s32.h    vr2, vr3
+    vmov.u16.rh    vr2, vr3
+    vmov.u32.rh    vr2, vr3
+    vmov.s16.rh    vr2, vr3
+    vmov.s32.rh    vr2, vr3
+    vstou.u16.sl    vr2, vr3
+    vstou.u32.sl    vr2, vr3
+    vstou.s16.sl    vr2, vr3
+    vstou.s32.sl    vr2, vr3
+    vrev.8        vr2, vr3
+    vrev.16       vr2, vr3
+    vrev.32       vr2, vr3
+    vcnt1.8       vr2, vr3
+    vclz.8        vr2, vr3
+    vclz.16       vr2, vr3
+    vclz.32       vr2, vr3
+    vcls.u8       vr2, vr3
+    vcls.u16      vr2, vr3
+    vcls.u32      vr2, vr3
+    vcls.s8       vr2, vr3
+    vcls.s16      vr2, vr3
+    vcls.s32      vr2, vr3
+    vabs.s8       vr2, vr3
+    vabs.s16      vr2, vr3
+    vabs.s32      vr2, vr3
+    vabs.u8.s     vr2, vr3
+    vabs.u16.s    vr2, vr3
+    vabs.u32.s    vr2, vr3
+    vabs.s8.s     vr2, vr3
+    vabs.s16.s    vr2, vr3
+    vabs.s32.s    vr2, vr3
+    vneg.u8       vr2, vr3
+    vneg.u16      vr2, vr3
+    vneg.u32      vr2, vr3
+    vneg.s8       vr2, vr3
+    vneg.s16      vr2, vr3
+    vneg.s32      vr2, vr3
+    vneg.u8.s     vr2, vr3
+    vneg.u16.s    vr2, vr3
+    vneg.u32.s    vr2, vr3
+    vneg.s8.s     vr2, vr3
+    vneg.s16.s    vr2, vr3
+    vneg.s32.s    vr2, vr3
+    vcmphsz.u8    vr2, vr3
+    vcmphsz.u16    vr2, vr3
+    vcmphsz.u32    vr2, vr3
+    vcmphsz.s8    vr2, vr3
+    vcmphsz.s16    vr2, vr3
+    vcmphsz.s32    vr2, vr3
+    vcmpltz.u8    vr2, vr3
+    vcmpltz.u16    vr2, vr3
+    vcmpltz.u32    vr2, vr3
+    vcmpltz.s8    vr2, vr3
+    vcmpltz.s16    vr2, vr3
+    vcmpltz.s32    vr2, vr3
+    vcmpnez.u8    vr2, vr3
+    vcmpnez.u16    vr2, vr3
+    vcmpnez.u32    vr2, vr3
+    vcmpnez.s8     vr2, vr3
+    vcmpnez.s8     vr2, vr3
+    vcmpnez.s16    vr2, vr3
+    vcmpnez.s32    vr2, vr3
+    vtrch.8         vr2, vr3, vr4
+    vtrch.16         vr2, vr3, vr4
+    vtrch.32          vr2, vr3, vr4
+    vtrcl.8           vr2, vr3, vr4
+    vtrcl.16          vr2, vr3, vr4
+    vtrcl.32          vr2, vr3, vr4
+    vadd.u8           vr2, vr3, vr4
+    vadd.u16          vr2, vr3, vr4
+    vadd.u32          vr2, vr3, vr4
+    vadd.s8           vr2, vr3, vr4
+    vadd.s16          vr2, vr3, vr4
+    vadd.s32          vr2, vr3, vr4
+    vadd.eu8          vr2, vr3, vr4
+    vadd.eu16          vr2, vr3, vr4
+    vadd.es8           vr2, vr3, vr4
+    vadd.es16          vr2, vr3, vr4
+    vcadd.u8           vr2, vr3, vr4
+    vcadd.u16          vr2, vr3, vr4
+    vcadd.u32          vr2, vr3, vr4
+    vcadd.s8           vr2, vr3, vr4
+    vcadd.s16          vr2, vr3, vr4
+    vcadd.s32          vr2, vr3, vr4
+    vadd.xu16.sl      vr2, vr3, vr4
+    vadd.xu32.sl      vr2, vr3, vr4
+    vadd.xs16.sl      vr2, vr3, vr4
+    vadd.xs32.sl      vr2, vr3, vr4
+    vadd.xu16         vr2, vr3, vr4
+    vadd.xu32         vr2, vr3, vr4
+    vadd.xs16         vr2, vr3, vr4
+    vadd.xs32         vr2, vr3, vr4
+    vaddh.u8          vr2, vr3, vr4
+    vaddh.u16        vr2, vr3, vr4
+    vaddh.u32        vr2, vr3, vr4
+    vaddh.s8         vr2, vr3, vr4
+    vaddh.s16        vr2, vr3, vr4
+    vaddh.s32        vr2, vr3, vr4
+    vaddh.u8.r       vr2, vr3, vr4
+    vaddh.u16.r      vr2, vr3, vr4
+    vaddh.u32.r      vr2, vr3, vr4
+    vaddh.s8.r       vr2, vr3, vr4
+    vaddh.s16.r      vr2, vr3, vr4
+    vaddh.s32.r      vr2, vr3, vr4
+    vadd.u8.s        vr2, vr3, vr4
+    vadd.u16.s       vr2, vr3, vr4
+    vadd.u32.s       vr2, vr3, vr4
+    vadd.s8.s        vr2, vr3, vr4
+    vadd.s16.s       vr2, vr3, vr4
+    vadd.s32.s       vr2, vr3, vr4
+    vsub.u8          vr2, vr3, vr4
+    vsub.u16         vr2, vr3, vr4
+    vsub.u32         vr2, vr3, vr4
+    vsub.s8          vr2, vr3, vr4
+    vsub.s16         vr2, vr3, vr4
+    vsub.s32         vr2, vr3, vr4
+    vsub.eu8         vr2, vr3, vr4
+    vsub.eu16        vr2, vr3, vr4
+    vsub.es8         vr2, vr3, vr4
+    vsub.es16        vr2, vr3, vr4
+    vsabs.u8         vr2, vr3, vr4
+    vsabs.u16        vr2, vr3, vr4
+    vsabs.u32        vr2, vr3, vr4
+    vsabs.s8         vr2, vr3, vr4
+    vsabs.s16        vr2, vr3, vr4
+    vsabs.s32        vr2, vr3, vr4
+    vsabs.eu8        vr2, vr3, vr4
+    vsabs.eu16       vr2, vr3, vr4
+    vsabs.es8        vr2, vr3, vr4
+    vsabs.es16       vr2, vr3, vr4
+    vsabsa.u8        vr2, vr3, vr4
+    vsabsa.u16       vr2, vr3, vr4
+    vsabsa.u32       vr2, vr3, vr4
+    vsabsa.s8        vr2, vr3, vr4
+    vsabsa.s16       vr2, vr3, vr4
+    vsabsa.s32       vr2, vr3, vr4
+    vsabsa.eu8       vr2, vr3, vr4
+    vsabsa.eu16      vr2, vr3, vr4
+    vsabsa.es8       vr2, vr3, vr4
+    vsabsa.es16      vr2, vr3, vr4
+    vsub.xu16        vr2, vr3, vr4
+    vsub.xu32        vr2, vr3, vr4
+    vsub.xs16        vr2, vr3, vr4
+    vsub.xs32        vr2, vr3, vr4
+    vsubh.u8         vr2, vr3, vr4
+    vsubh.u16        vr2, vr3, vr4
+    vsubh.u32        vr2, vr3, vr4
+    vsubh.s8         vr2, vr3, vr4
+    vsubh.s16        vr2, vr3, vr4
+    vsubh.s32        vr2, vr3, vr4
+    vsubh.u8.r       vr2, vr3, vr4
+    vsubh.u16.r      vr2, vr3, vr4
+    vsubh.u32.r      vr2, vr3, vr4
+    vsubh.s8.r       vr2, vr3, vr4
+    vsubh.s16.r      vr2, vr3, vr4
+    vsubh.s32.r      vr2, vr3, vr4
+    vsub.u8.s        vr2, vr3, vr4
+    vsub.u16.s       vr2, vr3, vr4
+    vsub.u32.s       vr2, vr3, vr4
+    vsub.s8.s        vr2, vr3, vr4
+    vsub.s16.s       vr2, vr3, vr4
+    vsub.s32.s       vr2, vr3, vr4
+    vmul.u8          vr2, vr3, vr4
+    vmul.u16         vr2, vr3, vr4
+    vmul.u32         vr2, vr3, vr4
+    vmul.s8          vr2, vr3, vr4
+    vmul.s16         vr2, vr3, vr4
+    vmul.s32         vr2, vr3, vr4
+    vmul.eu8         vr2, vr3, vr4
+    vmul.eu16        vr2, vr3, vr4
+    vmul.es8         vr2, vr3, vr4
+    vmul.es16        vr2, vr3, vr4
+    vmula.u8         vr2, vr3, vr4
+    vmula.u16        vr2, vr3, vr4
+    vmula.u32        vr2, vr3, vr4
+    vmula.s8         vr2, vr3, vr4
+    vmula.s16        vr2, vr3, vr4
+    vmula.s32        vr2, vr3, vr4
+    vmula.eu8        vr2, vr3, vr4
+    vmula.eu16       vr2, vr3, vr4
+    vmula.eu32       vr2, vr3, vr4
+    vmula.es8        vr2, vr3, vr4
+    vmula.es16       vr2, vr3, vr4
+    vmula.es32       vr2, vr3, vr4
+    vmuls.u8         vr2, vr3, vr4
+    vmuls.u16        vr2, vr3, vr4
+    vmuls.u32        vr2, vr3, vr4
+    vmuls.s8         vr2, vr3, vr4
+    vmuls.s16        vr2, vr3, vr4
+    vmuls.s32        vr2, vr3, vr4
+    vmuls.eu8        vr2, vr3, vr4
+    vmuls.eu16       vr2, vr3, vr4
+    vmuls.es8        vr2, vr3, vr4
+    vmuls.es16       vr2, vr3, vr4
+    vshr.u8          vr2, vr3, vr4
+    vshr.u16         vr2, vr3, vr4
+    vshr.u32         vr2, vr3, vr4
+    vshr.s8          vr2, vr3, vr4
+    vshr.s16         vr2, vr3, vr4
+    vshr.s32         vr2, vr3, vr4
+    vshr.u8.r        vr2, vr3, vr4
+    vshr.u16.r       vr2, vr3, vr4
+    vshr.u32.r       vr2, vr3, vr4
+    vshr.s8.r        vr2, vr3, vr4
+    vshr.s16.r       vr2, vr3, vr4
+    vshr.s32.r       vr2, vr3, vr4
+    vshl.u8          vr2, vr3, vr4
+    vshl.u16         vr2, vr3, vr4
+    vshl.u32         vr2, vr3, vr4
+    vshl.s8          vr2, vr3, vr4
+    vshl.s16         vr2, vr3, vr4
+    vshl.s32         vr2, vr3, vr4
+    vshl.u8.s        vr2, vr3, vr4
+    vshl.u16.s       vr2, vr3, vr4
+    vshl.u32.s       vr2, vr3, vr4
+    vshl.s8.s        vr2, vr3, vr4
+    vshl.s16.s       vr2, vr3, vr4
+    vshl.s32.s       vr2, vr3, vr4
+    vcmphs.u8        vr2, vr3, vr4
+    vcmphs.u16       vr2, vr3, vr4
+    vcmphs.u32       vr2, vr3, vr4
+    vcmphs.s8        vr2, vr3, vr4
+    vcmphs.s16       vr2, vr3, vr4
+    vcmphs.s32       vr2, vr3, vr4
+    vcmplt.u8        vr2, vr3, vr4
+    vcmplt.u16       vr2, vr3, vr4
+    vcmplt.u32       vr2, vr3, vr4
+    vcmplt.s8        vr2, vr3, vr4
+    vcmplt.s16       vr2, vr3, vr4
+    vcmplt.s32       vr2, vr3, vr4
+    vcmpne.u8        vr2, vr3, vr4
+    vcmpne.u16       vr2, vr3, vr4
+    vcmpne.u32       vr2, vr3, vr4
+    vcmpne.s8        vr2, vr3, vr4
+    vcmpne.s16       vr2, vr3, vr4
+    vcmpne.s32       vr2, vr3, vr4
+    vmax.u8          vr2, vr3, vr4
+    vmax.u16         vr2, vr3, vr4
+    vmax.u32         vr2, vr3, vr4
+    vmax.s8          vr2, vr3, vr4
+    vmax.s16         vr2, vr3, vr4
+    vmax.s32         vr2, vr3, vr4
+    vmin.u8          vr2, vr3, vr4
+    vmin.u16         vr2, vr3, vr4
+    vmin.u32         vr2, vr3, vr4
+    vmin.s8          vr2, vr3, vr4
+    vmin.s16         vr2, vr3, vr4
+    vmin.s32         vr2, vr3, vr4
+    vcmax.u8         vr2, vr3, vr4
+    vcmax.u16        vr2, vr3, vr4
+    vcmax.u32        vr2, vr3, vr4
+    vcmax.s8         vr2, vr3, vr4
+    vcmax.s16        vr2, vr3, vr4
+    vcmax.s32        vr2, vr3, vr4
+    vcmin.u8         vr2, vr3, vr4
+    vcmin.u16        vr2, vr3, vr4
+    vcmin.u32        vr2, vr3, vr4
+    vcmin.s8         vr2, vr3, vr4
+    vcmin.s16        vr2, vr3, vr4
+    vcmin.s32        vr2, vr3, vr4
+    vand.8           vr2, vr3, vr4
+    vand.16          vr2, vr3, vr4
+    vand.32          vr2, vr3, vr4
+    vandn.8          vr2, vr3, vr4
+    vandn.16         vr2, vr3, vr4
+    vandn.32         vr2, vr3, vr4
+    vor.8            vr2, vr3, vr4
+    vor.16           vr2, vr3, vr4
+    vor.32           vr2, vr3, vr4
+    vnor.8           vr2, vr3, vr4
+    vnor.16          vr2, vr3, vr4
+    vnor.32          vr2, vr3, vr4
+    vxor.8           vr2, vr3, vr4
+    vxor.16          vr2, vr3, vr4
+    vxor.32          vr2, vr3, vr4
+    vtst.8           vr2, vr3, vr4
+    vtst.16          vr2, vr3, vr4
+    vtst.32          vr2, vr3, vr4
+    vbpermz.8        vr2, vr3, vr4
+    vbpermz.16       vr2, vr3, vr4
+    vbpermz.32       vr2, vr3, vr4
+    vbperm.8         vr2, vr3, vr4
+    vbperm.16        vr2, vr3, vr4
+    vbperm.32        vr2, vr3, vr4
+    vdch.8           vr2, vr3, vr4
+    vdch.16          vr2, vr3, vr4
+    vdch.32          vr2, vr3, vr4
+    vdcl.8           vr2, vr3, vr4
+    vdcl.16          vr2, vr3, vr4
+    vdcl.32          vr2, vr3, vr4
+    vich.8           vr2, vr3, vr4
+    vich.16          vr2, vr3, vr4
+    vich.32          vr2, vr3, vr4
+    vicl.8           vr2, vr3, vr4
+    vicl.16          vr2, vr3, vr4
+    vicl.32          vr2, vr3, vr4
diff --git a/gas/testsuite/gas/csky/cskyv2_all.d b/gas/testsuite/gas/csky/cskyv2_all.d
new file mode 100644
index 0000000..b17a5e7
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_all.d
@@ -0,0 +1,325 @@ 
+# name: csky - all
+#as: -mcpu=ck810 -W
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*0000\s*bkpt
+\s*[0-9a-f]*:\s*3316\s*movi\s*r3,\s*22
+\s*[0-9a-f]*:\s*ea100016\s*movi\s*r16,\s*22
+\s*[0-9a-f]*:\s*ea03012c\s*movi\s*r3,\s*300
+\s*[0-9a-f]*:\s*c4104834\s*lsli\s*r20,\s*r16,\s*0
+\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*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*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
+\s*[0-9a-f]*:\s*c4620101\s*subc\s*r1,\s*r2,\s*r3
+\s*[0-9a-f]*:\s*c4220101\s*subc\s*r1,\s*r2,\s*r1
+\s*[0-9a-f]*:\s*c6210101\s*subc\s*r1,\s*r1,\s*r17
+\s*[0-9a-f]*:\s*c7d20112\s*subc\s*r18,\s*r18,\s*r30
+\s*[0-9a-f]*:\s*650c\s*cmphs\s*r3,\s*r4
+\s*[0-9a-f]*:\s*650d\s*cmplt\s*r3,\s*r4
+\s*[0-9a-f]*:\s*650e\s*cmpne\s*r3,\s*r4
+\s*[0-9a-f]*:\s*64c3\s*mvcv\s*r3
+\s*[0-9a-f]*:\s*c4000610\s*mvcv\s*r16
+\s*[0-9a-f]*:\s*6848\s*and\s*r1,\s*r2
+\s*[0-9a-f]*:\s*6849\s*andn\s*r1,\s*r2
+\s*[0-9a-f]*:\s*690e\s*tst\s*r3,\s*r4
+\s*[0-9a-f]*:\s*c4902080\s*tst\s*r16,\s*r4
+\s*[0-9a-f]*:\s*680f\s*tstnbz\s*r3
+\s*[0-9a-f]*:\s*c4102100\s*tstnbz\s*r16
+\s*[0-9a-f]*:\s*c6f22432\s*or\s*r18,\s*r18,\s*r23
+\s*[0-9a-f]*:\s*6c49\s*xor\s*r1,\s*r2
+\s*[0-9a-f]*:\s*6c4a\s*nor\s*r1,\s*r2
+\s*[0-9a-f]*:\s*6c8f\s*mov\s*r2,\s*r3
+\s*[0-9a-f]*:\s*7808\s*jmp\s*r2
+\s*[0-9a-f]*:\s*e8d00000\s*jmp\s*r16
+\s*[0-9a-f]*:\s*7bc9\s*jsr\s*r2
+\s*[0-9a-f]*:\s*e8f00000\s*jsr\s*r16
+\s*[0-9a-f]*:\s*783c\s*rts
+\s*[0-9a-f]*:\s*e8cf0000\s*rts
+\s*[0-9a-f]*:\s*6c03\s*mov\s*r0, \s*r0
+\s*[0-9a-f]*:\s*c4364036\s*lsl\s*r22,\s*r22,\s*r1
+\s*[0-9a-f]*:\s*c4224041\s*lsr\s*r1,\s*r2,\s*r1
+\s*[0-9a-f]*:\s*704a\s*asr\s*r1,\s*r2
+\s*[0-9a-f]*:\s*c6014101\s*rotl\s*r1,\s*r1,\s*r16
+\s*[0-9a-f]*:\s*748c\s*zextb\s*r2,\s*r3
+\s*[0-9a-f]*:\s*748d\s*zexth\s*r2,\s*r3
+\s*[0-9a-f]*:\s*748e\s*sextb\s*r2,\s*r3
+\s*[0-9a-f]*:\s*748f\s*sexth\s*r2,\s*r3
+\s*[0-9a-f]*:\s*788e\s*revb\s*r2,\s*r3
+\s*[0-9a-f]*:\s*788f\s*revh\s*r2,\s*r3
+\s*[0-9a-f]*:\s*c4036090\s*revb\s*r16,\s*r3
+\s*[0-9a-f]*:\s*c4106102\s*revh\s*r2,\s*r16
+\s*[0-9a-f]*:\s*c6218421\s*mult\s*r1,\s*r1,\s*r17
+\s*[0-9a-f]*:\s*7d1c\s*mult\s*r4,\s*r7
+\s*[0-9a-f]*:\s*c6479027\s*mulsh\s*r7,\s*r7,\s*r18
+\s*[0-9a-f]*:\s*7ca1\s*mulsh\s*r2,\s*r8
+\s*[0-9a-f]*:\s*c43e943e\s*mulsw\s*r30,\s*r30,\s*r1
+\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*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*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*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*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*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
+\s*[0-9a-f]*:\s*e42101ff\s*addi\s*r1,\s*r1,\s*512
+\s*[0-9a-f]*:\s*5c42\s*addi\s*r2,\s*r4,\s*1
+\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*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*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
+\s*[0-9a-f]*:\s*e42111ff\s*subi\s*r1,\s*r1,\s*512
+\s*[0-9a-f]*:\s*5c43\s*subi\s*r2,\s*r4,\s*1
+\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*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*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
+\s*[0-9a-f]*:\s*60c2\s*subu\s*r3,\s*r0
+\s*[0-9a-f]*:\s*6242\s*subu\s*r9,\s*r0
+\s*[0-9a-f]*:\s*c417008d\s*subu\s*r13,\s*r23,\s*r0
+\s*[0-9a-f]*:\s*60c0\s*addu\s*r3,\s*r0
+\s*[0-9a-f]*:\s*6200\s*addu\s*r8,\s*r0
+\s*[0-9a-f]*:\s*c4030029\s*addu\s*r9,\s*r3,\s*r0
+\s*[0-9a-f]*:\s*60c0\s*addu\s*r3,\s*r0
+\s*[0-9a-f]*:\s*6240\s*addu\s*r9,\s*r0
+\s*[0-9a-f]*:\s*c417002d\s*addu\s*r13,\s*r23,\s*r0
+\s*[0-9a-f]*:\s*3921\s*cmplti\s*r1,\s*2
+\s*[0-9a-f]*:\s*eb320003\s*cmplti\s*r18,\s*4
+\s*[0-9a-f]*:\s*670c\s*cmphs\s*r3,\s*r12
+\s*[0-9a-f]*:\s*c6c30420\s*cmphs\s*r3,\s*r22
+\s*[0-9a-f]*:\s*6489\s*cmplt\s*r2,\s*r2
+\s*[0-9a-f]*:\s*c7220440\s*cmplt\s*r2,\s*r25
+\s*[0-9a-f]*:\s*3d20\s*cmplti\s*r5,\s*1
+\s*[0-9a-f]*:\s*eb390000\s*cmplti\s*r25,\s*1
+\s*[0-9a-f]*:\s*3a40\s*cmpnei\s*r2,\s*0
+\s*[0-9a-f]*:\s*eb580000\s*cmpnei\s*r24,\s*0
+\s*[0-9a-f]*:\s*c7e42880\s*btsti\s*r4,\s*31
+\s*[0-9a-f]*:\s*c7f82880\s*btsti\s*r24,\s*31
+\s*[0-9a-f]*:\s*6400\s*cmphs\s*r0,\s*r0
+\s*[0-9a-f]*:\s*6402\s*cmpne\s*r0,\s*r0
+\s*[0-9a-f]*:\s*6089\s*addc\s*r2,\s*r2
+\s*[0-9a-f]*:\s*c6100050\s*addc\s*r16,\s*r16,\s*r16
+\s*[0-9a-f]*:\s*c0a01820\s*sce\s*5
+\s*[0-9a-f]*:\s*c0002820\s*trap\s*2
+\s*[0-9a-f]*:\s*c4402c20\s*clrf\s*r2
+\s*[0-9a-f]*:\s*c7402c40\s*clrt\s*r26
+\s*[0-9a-f]*:\s*c0004020\s*rte
+\s*[0-9a-f]*:\s*c0004420\s*rfi
+\s*[0-9a-f]*:\s*c0004820\s*stop
+\s*[0-9a-f]*:\s*c0004c20\s*wait
+\s*[0-9a-f]*:\s*c0005020\s*doze
+\s*[0-9a-f]*:\s*c0005420\s*we
+\s*[0-9a-f]*:\s*c0005820\s*se
+\s*[0-9a-f]*:\s*c4000517\s*mvc\s*r23
+\s*[0-9a-f]*:\s*c4009823\s*mfhis\s*r3
+\s*[0-9a-f]*:\s*c4009891\s*mflos\s*r17
+\s*[0-9a-f]*:\s*c4009a00\s*mvtc
+\s*[0-9a-f]*:\s*c4009c32\s*mfhi\s*r18
+\s*[0-9a-f]*:\s*c4139c40\s*mthi\s*r19
+\s*[0-9a-f]*:\s*c4009c83\s*mflo\s*r3
+\s*[0-9a-f]*:\s*c4089d00\s*mtlo\s*r8
+\s*[0-9a-f]*:\s*c0000420\s*sync\s*0
+\s*[0-9a-f]*:\s*c0200420\s*sync\s*1
+\s*[0-9a-f]*:\s*c2800420\s*sync\s*20
+\s*[0-9a-f]*:\s*c0601c20\s*idly\s*4
+\s*[0-9a-f]*:\s*c0601c20\s*idly\s*4
+\s*[0-9a-f]*:\s*c0601c20\s*idly\s*4
+\s*[0-9a-f]*:\s*c0801c20\s*idly\s*5
+\s*[0-9a-f]*:\s*c3e01c20\s*idly\s*32
+\s*[0-9a-f]*:\s*fc2044d2\s*cprc\s*\<1,\s*1234\>
+\s*[0-9a-f]*:\s*fc2084d2\s*cpop\s*\<1,\s*1234\>
+\s*[0-9a-f]*:\s*fc3414d2\s*cpwgr\s*r20,\s*\<1,\s*1234\>
+\s*[0-9a-f]*:\s*fc3434d2\s*cpwcr\s*r20,\s*\<1,\s*1234\>
+\s*[0-9a-f]*:\s*fc3404d2\s*cprgr\s*r20,\s*\<1,\s*1234\>
+\s*[0-9a-f]*:\s*fc3424d2\s*cprcr\s*r20,\s*\<1,\s*1234\>
+\s*[0-9a-f]*:\s*320c\s*movi\s*r2,\s*12
+\s*[0-9a-f]*:\s*ea220010\s*movih\s*r2,\s*16
+\s*[0-9a-f]*:\s*ea021000\s*movi\s*r2,\s*4096
+\s*[0-9a-f]*:\s*ea220001\s*movih\s*r2,\s*1
+\s*[0-9a-f]*:\s*1491\s*pop\s*r4, r15
+\s*[0-9a-f]*:\s*1498\s*pop\s*r4-r11, r15
+\s*[0-9a-f]*:\s*ebc00100\s*pop\s*r28
+\s*[0-9a-f]*:\s*ebc00020\s*pop\s*r16
+\s*[0-9a-f]*:\s*14d1\s*push\s*r4, r15
+\s*[0-9a-f]*:\s*14d8\s*push\s*r4-r11, r15
+\s*[0-9a-f]*:\s*ebe00100\s*push\s*r28
+\s*[0-9a-f]*:\s*ebe00020\s*push\s*r16
+\s*[0-9a-f]*:\s*c4625c42\s*ins\s*r3,\s*r2,\s*4,\s*2
+\s*[0-9a-f]*:\s*c4425483\s*zext\s*r3,\s*r2,\s*4,\s*2
+\s*[0-9a-f]*:\s*c4425883\s*sext\s*r3,\s*r2,\s*4,\s*2
+\s*[0-9a-f]*:\s*e4622002\s*andi\s*r3,\s*r2,\s*2
+\s*[0-9a-f]*:\s*e4623002\s*andni\s*r3,\s*r2,\s* 2
+\s*[0-9a-f]*:\s*e462400c\s*xori\s*r3,\s*r2,\s* 12
+\s*[0-9a-f]*:\s*d0621c22\s*ldm\s*r3-r5,\s*\(r2\)
+\s*[0-9a-f]*:\s*d4621c22\s*stm\s*r3-r5,\s*\(r2\)
+\s*[0-9a-f]*:\s*c4410083\s*subu\s*r3,\s*r1,\s*r2
+\s*[0-9a-f]*:\s*d4220023\s*str\.b\s*r3,\s*\(r2,\s*r1\s*<<\s*0\)
+\s*[0-9a-f]*:\s*d4220423\s*str\.h\s*r3,\s*\(r2,\s*r1\s*<<\s*0\)
+\s*[0-9a-f]*:\s*d4220823\s*str\.w\s*r3,\s*\(r2,\s*r1\s*<<\s*0\)
+\s*[0-9a-f]*:\s*d0220043\s*ldr\.b\s*r3,\s*\(r2,\s*r1\s*<<\s*1\)
+\s*[0-9a-f]*:\s*d0220443\s*ldr\.h\s*r3,\s*\(r2,\s*r1\s*<<\s*1\)
+\s*[0-9a-f]*:\s*d0220843\s*ldr\.w\s*r3,\s*\(r2,\s*r1\s*<<\s*1\)
+\s*[0-9a-f]*:\s*d0621022\s*ldr\.bs\s*r2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*d0621042\s*ldr\.bs\s*r2,\s*\(r2,\s*r3\s*<<\s*1\)
+\s*[0-9a-f]*:\s*d0621082\s*ldr\.bs\s*r2,\s*\(r2,\s*r3\s*<<\s*2\)
+\s*[0-9a-f]*:\s*d0621102\s*ldr\.bs\s*r2,\s*\(r2,\s*r3\s*<<\s*3\)
+\s*[0-9a-f]*:\s*d0621422\s*ldr\.hs\s*r2,\s*\(r2,\s*r3\s*<<\s*0\)
+\s*[0-9a-f]*:\s*d0621442\s*ldr\.hs\s*r2,\s*\(r2,\s*r3\s*<<\s*1\)
+\s*[0-9a-f]*:\s*d0621482\s*ldr\.hs\s*r2,\s*\(r2,\s*r3\s*<<\s*2\)
+\s*[0-9a-f]*:\s*d0621502\s*ldr\.hs\s*r2,\s*\(r2,\s*r3\s*<<\s*3\)
+\s*[0-9a-f]*:\s*c4424d03\s*xsr\s*r3,\s*r2,\s*3
+\s*[0-9a-f]*:\s*c4424c83\s*asrc\s*r3,\s*r2,\s*3
+\s*[0-9a-f]*:\s*c4424c43\s*lsrc\s*r3,\s*r2,\s*3
+\s*[0-9a-f]*:\s*c4424c23\s*lslc\s*r3,\s*r2,\s*3
+\s*[0-9a-f]*:\s*c4824903\s*rotli\s*r3,\s*r2,\s*4
+\s*[0-9a-f]*:\s*c4014901\s*rotli\s*r1,\s*r1,\s*0
+\s*[0-9a-f]*:\s*c7e14901\s*rotli\s*r1,\s*r1,\s*31
+\s*[0-9a-f]*:\s*c7304901\s*rotli\s*r1,\s*r16,\s*25
+\s*[0-9a-f]*:\s*c7e14901\s*rotli\s*r1,\s*r1,\s*31
+\s*[0-9a-f]*:\s*c4014901\s*rotli\s*r1,\s*r1,\s*0
+\s*[0-9a-f]*:\s*c4f04901\s*rotli\s*r1,\s*r16,\s*7
+\s*[0-9a-f]*:\s*c4821083\s*decne\s*r3,\s*r2,\s*4
+\s*[0-9a-f]*:\s*c4821043\s*declt\s*r3,\s*r2,\s*4
+\s*[0-9a-f]*:\s*c4821023\s*decgt\s*r3,\s*r2,\s*4
+\s*[0-9a-f]*:\s*c4620d04\s*dect\s*r3,\s*r2,\s*4
+\s*[0-9a-f]*:\s*c4620c84\s*decf\s*r3,\s*r2,\s*4
+\s*[0-9a-f]*:\s*c4620c24\s*incf\s*r3,\s*r2,\s*4
+\s*[0-9a-f]*:\s*c4620c44\s*inct\s*r3,\s*r2,\s*4
+\s*[0-9a-f]*:\s*d0831c23\s*ldm\s*r4-r7,\s*\(r3\)
+\s*[0-9a-f]*:\s*d4831c23\s*stm\s*r4-r7,\s*\(r3\)
+\s*[0-9a-f]*:\s*c1007020\s*psrclr\s*ee
+\s*[0-9a-f]*:\s*c0607020\s*psrclr\s*fe,\s*af
+\s*[0-9a-f]*:\s*c1607420\s*psrset\s*ee,\s*fe,\s*af
+\s*[0-9a-f]*:\s*c1e07420\s*psrset\s*ee,\s*ie,\s*fe,\s*af
+\s*[0-9a-f]*:\s*c4140211\s*abs\s*r17,\s*r20
+\s*[0-9a-f]*:\s*c4155043\s*bgenr\s*r3,\s*r21
+\s*[0-9a-f]*:\s*c4016217\s*brev\s*r23,\s*r1
+\s*[0-9a-f]*:\s*c4037025\s*xtrb0\s*r5,\s*r3
+\s*[0-9a-f]*:\s*c4097043\s*xtrb1\s*r3,\s*r9
+\s*[0-9a-f]*:\s*c4147090\s*xtrb2\s*r16,\s*r20
+\s*[0-9a-f]*:\s*c418710b\s*xtrb3\s*r11,\s*r24
+\s*[0-9a-f]*:\s*c4157c22\s*ff0\s*r2,\s*r21
+\s*[0-9a-f]*:\s*c4017c52\s*ff1\s*r18,\s*r1
+\s*[0-9a-f]*:\s*c0026423\s*mtcr\s*r2,\s*cr<3,\s*0>
+\s*[0-9a-f]*:\s*c0026424\s*mtcr\s*r2,\s*cr<4,\s*0>
+\s*[0-9a-f]*:\s*c0026421\s*mtcr\s*r2,\s*cr<1,\s*0>
+\s*[0-9a-f]*:\s*c0006022\s*mfcr\s*r2,\s*cr<0,\s*0>
+\s*[0-9a-f]*:\s*c0006022\s*mfcr\s*r2,\s*cr<0,\s*0>
+\s*[0-9a-f]*:\s*c0006022\s*mfcr\s*r2,\s*cr<0,\s*0>
+\s*[0-9a-f]*:\s*6c8a\s*nor\s*r2,\s*r2
+\s*[0-9a-f]*:\s*c6102490\s*nor\s*r16,\s*r16,\s*r16
+\s*[0-9a-f]*:\s*c6102482\s*nor\s*r2,\s*r16,\s*r16
+\s*[0-9a-f]*:\s*6c8a\s*nor\s*r2,\s*r2
+\s*[0-9a-f]*:\s*c4830822\s*ixh\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*c4830842\s*ixw\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*c4830882\s*ixd\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*c4838042\s*divs\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*c4838022\s*divu\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*c4220c20\s*incf\s*r1,\s*r2,\s*0
+\s*[0-9a-f]*:\s*c6e20c40\s*inct\s*r23,\s*r2,\s*0
+\s*[0-9a-f]*:\s*ea0800ff\s*movi\s*r8,\s*255
+\s*[0-9a-f]*:\s*c7e05021\s*bmaski\s*r1,\s*32
+\s*[0-9a-f]*:\s*310f\s*movi\s*r1,\s*15
+\s*[0-9a-f]*:\s*c6005021\s*bmaski\s*r1,\s*17
+\s*[0-9a-f]*:\s*ea15ffff\s*movi\s*r21,\s*65535
+\s*[0-9a-f]*:\s*ea0dffff\s*movi\s*r13,\s*65535
+\s*[0-9a-f]*:\s*c7c05021\s*bmaski\s*r1,\s*31
+\s*[0-9a-f]*:\s*c7e05021\s*bmaski\s*r1,\s*32
+\s*[0-9a-f]*:\s*d8026002\s*pldr\s*\(r2,\s*0x8\)
+\s*[0-9a-f]*:\s*dc026002\s*pldw\s*\(r2,\s*0x8\)
+\s*[0-9a-f]*:\s*6c46\s*nor\s*r1,\s*r1
+\s*[0-9a-f]*:\s*2100\s*addi\s*r1,\s*1
+\s*[0-9a-f]*:\s*6c8a\s*nor\s*r2,\s*r2
+\s*[0-9a-f]*:\s*2217\s*addi\s*r2,\s*24
+\s*[0-9a-f]*:\s*c4034c83\s*asrc\s*r3,\s*r3,\s*1
+\s*[0-9a-f]*:\s*c4840c21\s*incf\s*r4,\s*r4,\s*1
+\s*[0-9a-f]*:\s*c5ad0c41\s*inct\s*r13,\s*r13,\s*1
+\s*[0-9a-f]*:\s*c6100c81\s*decf\s*r16,\s*r16,\s*1
+\s*[0-9a-f]*:\s*c4311031\s*decgt\s*r17,\s*r17,\s*1
+\s*[0-9a-f]*:\s*c4331053\s*declt\s*r19,\s*r19,\s*1
+\s*[0-9a-f]*:\s*c4341094\s*decne\s*r20,\s*r20,\s*1
+\s*[0-9a-f]*:\s*c7ff0d01\s*dect\s*r31,\s*r31,\s*1
+\s*[0-9a-f]*:\s*c40b4c2b\s*lslc\s*r11,\s*r11,\s*1
+\s*[0-9a-f]*:\s*c4194c59\s*lsrc\s*r25,\s*r25,\s*1
+\s*[0-9a-f]*:\s*c40c4d0c\s*xsr\s*r12,\s*r12,\s*1
+\s*[0-9a-f]*:\s*c4778057\s*divs\s*r23,\s*r23,\s*r3
+\s*[0-9a-f]*:\s*c7c18021\s*divu\s*r1,\s*r1,\s*r30
+\s*[0-9a-f]*:\s*c40d020d\s*abs\s*r13,\s*r13
+\s*[0-9a-f]*:\s*c40c620c\s*brev\s*r12,\s*r12
+\s*[0-9a-f]*:\s*c4087c48\s*ff1\s*r8,\s*r8
+\s*[0-9a-f]*:\s*6c46\s*nor\s*r1,\s*r1
+\s*[0-9a-f]*:\s*c6312491\s*nor\s*r17,\s*r17,\s*r17
+\s*[0-9a-f]*:\s*7488\s*zextb\s*r2,\s*r2
+\s*[0-9a-f]*:\s*c41355f3\s*zexth\s*r19,\s*r19
+\s*[0-9a-f]*:\s*c41d58fd\s*sextb\s*r29,\s*r29
+\s*[0-9a-f]*:\s*76ef\s*sexth\s*r11,\s*r11
+\s*[0-9a-f]*:\s*c6210821\s*ixh\s*r1,\s*r1,\s*r17
+\s*[0-9a-f]*:\s*c4370857\s*ixw\s*r23,\s*r23,\s*r1
+#...
+\s*[0-9a-f]*:\s*c4630083\s*subu\s*r3,\s*r3,\s*r3
+\s*[0-9a-f]*:\s*c63f0091\s*subu\s*r17,\s*r31,\s*r17
+\s*[0-9a-f]*:\s*492c\s*lsri\s*r1,\s*r1,\s*12
+\s*[0-9a-f]*:\s*c4554835\s*lsli\s*r21,\s*r21,\s*2
+\s*[0-9a-f]*:\s*c4419421\s*mulsw\s*r1,\s*r1,\s*r2
+\s*[0-9a-f]*:\s*e463207b\s*andi\s*r3,\s*r3,\s*123
+\s*[0-9a-f]*:\s*c5684908\s*rotli\s*r8,\s*r8,\s*11
+\s*[0-9a-f]*:\s*e860fdf8\s*bt\s*0x0.*
+\s*[0-9a-f]*:\s*e840fdf6\s*bf\s*0x0.*
+\s*[0-9a-f]*:\s*e860fdf4\s*bt\s*0x0.*
+\s*[0-9a-f]*:\s*e840fdf2\s*bf\s*0x0.*
+\s*[0-9a-f]*:\s*e800fdf0\s*br\s*0x0.*
+\s*[0-9a-f]*:\s*e800fdee\s*br\s*0x0.*
+\s*[0-9a-f]*:\s*e3fffdec\s*bsr\s*0x0.*
+\s*[0-9a-f]*:\s*cc500000\s*srs\.b\s*r2,\s*\[0x0\].*
+\s*[0-9a-f]*:\s*cc400000\s*lrs\.b\s*r2,\s*\[0x0\].*
+\s*[0-9a-f]*:\s*cc540000\s*srs\.h\s*r2,\s*\[0x0\].*
+\s*[0-9a-f]*:\s*cc440000\s*lrs\.h\s*r2,\s*\[0x0\].*
+\s*[0-9a-f]*:\s*cc580000\s*srs\.w\s*r2,\s*\[0x0\].*
+\s*[0-9a-f]*:\s*cc480000\s*lrs\.w\s*r2,\s*\[0x0\].*
+\s*[0-9a-f]*:\s*ec430002\s*ori\s*r2,\s*r3,\s*2
+\s*[0-9a-f]*:\s*ec43000a\s*ori\s*r2,\s*r3,\s*10
diff --git a/gas/testsuite/gas/csky/cskyv2_all.s b/gas/testsuite/gas/csky/cskyv2_all.s
new file mode 100644
index 0000000..c8b271b
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_all.s
@@ -0,0 +1,317 @@ 
+.text
+all:
+   bkpt
+   movi    r3, 22
+   movi    r16, 22
+   movi    r3, 300
+   lsli    r20, r16, 0
+   lsri    r8, r2, 20
+   asri    r1, r2, 7
+   addc    r1, r2
+   addc    r17, r1
+   addc    r1, r2, r3
+   addc    r1, r2, r1
+   addc    r1, r17
+   addc    r18, r18, r30
+   subc    r1, r2
+   subc    r17, r1
+   subc    r1, r2, r3
+   subc    r1, r2, r1
+   subc    r1, r17
+   subc    r18, r18, r30
+   cmphs   r3, r4
+   cmplt   r3, r4
+   cmpne   r3, r4
+   mvcv    r3
+   mvcv    r16
+   and     r1,  r2
+   andn    r1,  r2
+   tst     r3, r4
+   tst     r16, r4
+   tstnbz  r3
+   tstnbz  r16
+   or      r18, r23
+   xor     r1,  r1,  r2
+   nor     r1,  r2,  r1
+   mov     r2, r3
+   jmp     r2
+   jmp     r16
+   jsr     r2
+   jsr     r16
+   rts
+   rts32
+   nop
+   lsl     r22, r1
+   lsr     r1,  r2,  r1
+   asr     r1,  r1,  r2
+   rotl    r1,  r1,  r16
+   zextb   r2, r3
+   zexth   r2, r3
+   sextb   r2, r3
+   sexth   r2, r3
+   revb    r2, r3
+   revh    r2, r3
+   revb    r16, r3
+   revh    r2, r16
+   mult    r1,  r1,  r17
+   mul     r4,  r7
+   mulsh   r7,  r18
+   muls.h  r2,  r8
+   mulsw   r30, r30, r1
+   mulsw   r1,  r2
+   ld.b    r2, (r3, 4)
+   ld.h    r2, (r3, 4)
+   ld.w    r2, (r14, 4)
+   st.b    r2, (r3, 4)
+   st.h    r2, (r3, 4)
+   st.w    r2, (r14, 4)
+   ld.b    r8, (r3, 4)
+   ld.h    r2, (r8, 4)
+   ld.w    r2, (r14, 4)
+   st.b    r2, (r8, 4)
+   st.h    r2, (r8, 4)
+   st.w    r8, (r14, 4)
+   ld.bs   r2, (r3, 3)
+   ld.d    r2, (r3, 4)
+   st.d    r2, (r3, 4)
+   stex.w   r2, (r3, 4)
+   ldex.w   r2, (r3, 4)
+   addi    sp,  sp, 0x30
+   addi    r3,  sp, 0x4
+   addi    r1,  20
+   addi    r1,  r1, 20
+   addi    r21, 20
+   addi    r1,  0x200
+   addi    r2,  r4, 1
+   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
+   addi16  r1,  20
+   addi16  r2,  r4, 1
+   addi32  r2,  r4, 1
+   addi32  r3,  sp, 0x400
+   addi32  sp,  sp, 0x33
+   subi    sp,  sp, 0x30
+   subi    r1,  20
+   subi    r1,  r1, 20
+   subi    r21, 20
+   subi    r1,  0x200
+   subi    r2,  r4, 1
+   subi    r8,  r4, 1
+   subi    r1,  r4, 9
+   subi    r1,  r28, 9
+   subi    sp,  sp, 0x33
+   subi    sp,  sp, 0x200
+   subi16  r1,  20
+   subi16  r2,  r4, 1
+   subi32  r2,  r4, 1
+   subi32  sp,  sp, 0x33
+   sub     r3, r0
+   sub     r8, r0
+   sub     r9, r3, r0
+   sub     r3, r3, r0
+   sub     r9, r9, r0
+   sub     r13, r23, r0
+   add     r3, r0
+   add     r8, r0
+   add     r9, r3, r0
+   add     r3, r3, r0
+   add     r9, r9, r0
+   add     r13, r23, r0
+   cmplei  r1,   1
+   cmplei  r18,  3
+   cmpls   r12, r3
+   cmpls   r22, r3
+   cmpgt   r2, r2
+   cmpgt   r25, r2
+   tstle   r5
+   tstle   r25
+   tstne   r2
+   tstne   r24
+   tstlt   r4
+   tstlt   r24
+   setc
+   clrc
+   rotlc   r2, 1
+   rotlc   r16, 1
+   sce     5
+   trap    2
+   clrf    r2
+   clrt    r26
+   rte
+   rfi
+   stop
+   wait
+   doze
+   we
+   se
+   mvc    r23
+   mfhis  r3
+   mflos  r17
+   mvtc
+   mfhi   r18
+   mthi   r19
+   mflo   r3
+   mtlo   r8
+   sync   0
+   sync   1
+   sync   20
+   idly   0
+   idly   2
+   idly   4
+   idly   5
+   idly   32
+   cprc   <1, 1234>
+   cpop   <1, 1234>
+   cpwgr  r20, <1, 1234>
+   cpwcr  r20, <1, 1234>
+   cprgr  r20, <1, 1234>
+   cprcr  r20, <1, 1234>
+   movi   r2, 12
+   movih  r2, 16
+   bgeni  r2, 12
+   bgeni  r2, 16
+   pop    r4, r15
+   pop    r15, r4-r11
+   pop    r28
+   pop    r16
+   push   r4, r15
+   push   r15, r4-r11
+   push   r28
+   push   r16
+   ins    r3, r2, 4, 2
+   zext   r3, r2, 4, 2
+   sext   r3, r2, 4, 2
+   andi   r3, r2, 2
+   andni  r3, r2, 2
+   xori   r3, r2, 12
+   ldm    r3-r5, (r2)
+   stm    r3-r5, (r2)
+   rsub   r3, r2, r1
+   str.b  r3, (r2, r1 << 0)
+   str.h  r3, (r2, r1 << 0)
+   str.w  r3, (r2, r1 << 0)
+   ldr.b  r3, (r2, r1 << 1)
+   ldr.h  r3, (r2, r1 << 1)
+   ldr.w  r3, (r2, r1 << 1)
+   ldr.bs r2, (r2, r3 << 0)
+   ldr.bs r2, (r2, r3 << 1)
+   ldr.bs r2, (r2, r3 << 2)
+   ldr.bs r2, (r2, r3 << 3)
+   ldr.hs r2, (r2, r3 << 0)
+   ldr.hs r2, (r2, r3 << 1)
+   ldr.hs r2, (r2, r3 << 2)
+   ldr.hs r2, (r2, r3 << 3)
+   xsr    r3, r2, 3
+   asrc   r3, r2, 3
+   lsrc   r3, r2, 3
+   lslc   r3, r2, 3
+   rotli  r3, r2, 4
+   rotri  r1, 32
+   rotri  r1, 1
+   rotri  r1, r16, 7
+   rotli  r1, 31
+   rotli  r1, 0
+   rotli  r1, r16, 7
+   decne  r3, r2, 4
+   declt  r3, r2, 4
+   decgt  r3, r2, 4
+   dect   r3, r2, 4
+   decf   r3, r2, 4
+   incf   r3, r2, 4
+   inct   r3, r2, 4
+   ldq    r4-r7, (r3)
+   stq    r4-r7, (r3)
+   psrclr ee
+   psrclr af, fe
+   psrset ee, fe, af
+   psrset ie, ee, fe, af
+   abs    r17, r20
+   bgenr  r3,  r21
+   brev   r23, r1
+   xtrb0  r5,  r3
+   xtrb1  r3,  r9
+   xtrb2  r16, r20
+   xtrb3  r11, r24
+   ff0    r2,  r21
+   ff1    r18, r1
+   mtcr   r2, cr<3, 0>
+   mtcr   r2, cr4
+   mtcr   r2, vbr
+   mfcr   r2, cr<0, 0>
+   mfcr   r2, cr0
+   mfcr   r2, psr
+   not    r2
+   not    r16
+   not    r2, r16
+   not    r2, r2
+   ixh    r2, r3, r4
+   ixw    r2, r3, r4
+   ixd    r2, r3, r4
+   divs   r2, r3, r4
+   divu   r2, r3, r4
+   movf   r1, r2
+   movt   r23, r2
+   bmaski r8, 8
+   bmaski r1, 0
+   bmaski r1, 4
+   bmaski r1, 17
+   bmaski r21, 16
+   bmaski r13, 16
+   bmaski r1, 31
+   bmaski r1, 32
+   pldr   (r2, 0x8)
+   pldw   (r2, 0x8)
+   neg    r1
+   rsubi  r2, 23
+   asrc   r3
+   incf   r4
+   inct   r13
+   decf   r16
+   decgt  r17
+   declt  r19
+   decne  r20
+   dect   r31
+   lslc   r11
+   lsrc   r25
+   xsr    r12
+   divs   r23, r3
+   divu   r1,  r30
+   abs    r13
+   brev   r12
+   ff1    r8
+   not    r1
+   not    r17
+   zextb  r2
+   zexth  r19
+   sextb  r29
+   sexth  r11
+   ixh    r1,  r17
+   ixw    r23, r1
+   rsub   r3,  r3
+   rsub   r17, r31
+   lsri   r1,  12
+   lsli   r21, 2
+   mulsw  r1, r2
+   andi   r3, 123
+   rori   r8, 21
+   bt     all
+   bf     all
+   jbt    all
+   jbf    all
+   br     all
+   jbr    all
+   bsr    all
+   srs.b  r2, [all]
+   lrs.b  r2, [all]
+   srs.h  r2, [all]
+   lrs.h  r2, [all]
+   srs.w  r2, [all]
+   lrs.w  r2, [all]
+   ori    r2, r3, 2
+   ori    r2, r3, 10
+
diff --git a/gas/testsuite/gas/csky/cskyv2_dsp.d b/gas/testsuite/gas/csky/cskyv2_dsp.d
new file mode 100644
index 0000000..f2e3d33
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_dsp.d
@@ -0,0 +1,18 @@ 
+# name: csky - all
+#as: -mcpu=ck810e -W
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*c4818820\s*mulu\s*r1,\s*r4
+\s*[0-9a-f]*:\s*c6ec8840\s*mulua\s*r12,\s*r23
+\s*[0-9a-f]*:\s*c46f8880\s*mulus\s*r15,\s*r3
+\s*[0-9a-f]*:\s*c4418c20\s*muls\s*r1,\s*r2
+\s*[0-9a-f]*:\s*c4428c40\s*mulsa\s*r2,\s*r2
+\s*[0-9a-f]*:\s*c4638c80\s*mulss\s*r3,\s*r3
+\s*[0-9a-f]*:\s*c6689040\s*mulsha\s*r8,\s*r19
+\s*[0-9a-f]*:\s*c4319080\s*mulshs\s*r17,\s*r1
+\s*[0-9a-f]*:\s*c6ec9440\s*mulswa\s*r12,\s*r23
+\s*[0-9a-f]*:\s*c4a39480\s*mulsws\s*r3,\s*r5
diff --git a/gas/testsuite/gas/csky/cskyv2_dsp.s b/gas/testsuite/gas/csky/cskyv2_dsp.s
new file mode 100644
index 0000000..9c0666c
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_dsp.s
@@ -0,0 +1,11 @@ 
+.text
+  mulu  r1,  r4
+  mulua r12, r23
+  mulus r15, r3
+  muls  r1,  r2
+  mulsa r2,  r2
+  mulss r3,  r3
+  mulsha  r8,  r19
+  mulshs  r17, r1
+  mulswa  r12, r23
+  mulsws  r3,  r5
diff --git a/gas/testsuite/gas/csky/cskyv2_elrw.d b/gas/testsuite/gas/csky/cskyv2_elrw.d
new file mode 100644
index 0000000..5a52d5a
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_elrw.d
@@ -0,0 +1,10 @@ 
+# name: cskyv2 - elrw
+#as: -mcpu=ck801 -melrw
+#objdump: -D
+
+.*: +file format .*csky.*
+#...
+\s*[0-9a-f]*:\s*024e\s*lrw\s*r2,\s*0x1234.*
+#...
+\s*[0-9a-f]*:\s*c0004020\s*rte
+\s*[0-9a-f]*:\s*00001234\s*\.long\s*0x00001234
diff --git a/gas/testsuite/gas/csky/cskyv2_elrw.s b/gas/testsuite/gas/csky/cskyv2_elrw.s
new file mode 100644
index 0000000..07f8898
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_elrw.s
@@ -0,0 +1,6 @@ 
+.text
+   lrw r2, 0x1234
+.rept 351
+   nop
+.endr
+   rte
diff --git a/gas/testsuite/gas/csky/cskyv2_float.d b/gas/testsuite/gas/csky/cskyv2_float.d
new file mode 100644
index 0000000..f1039c9
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_float.d
@@ -0,0 +1,59 @@ 
+# name: csky - all
+#as: -mcpu=ck810f -W
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*f4000100\s*fcmpzhss\s*fr0
+\s*[0-9a-f]*:\s*f4010120\s*fcmpzlss\s*fr1
+\s*[0-9a-f]*:\s*f4050140\s*fcmpznes\s*fr5
+\s*[0-9a-f]*:\s*f4080160\s*fcmpzuos\s*fr8
+\s*[0-9a-f]*:\s*f40a0900\s*fcmpzhsd\s*fr10
+\s*[0-9a-f]*:\s*f40d0920\s*fcmpzlsd\s*fr13
+\s*[0-9a-f]*:\s*f40e0940\s*fcmpzned\s*fr14
+\s*[0-9a-f]*:\s*f40f0960\s*fcmpzuod\s*fr15
+\s*[0-9a-f]*:\s*f409008c\s*fmovs\s*fr12,\s*fr9
+\s*[0-9a-f]*:\s*f40000c1\s*fabss\s*fr1,\s*fr0
+\s*[0-9a-f]*:\s*f40100e2\s*fnegs\s*fr2,\s*fr1
+\s*[0-9a-f]*:\s*f4470180\s*fcmphss\s*fr7,\s*fr2
+\s*[0-9a-f]*:\s*f46601a0\s*fcmplts\s*fr6,\s*fr3
+\s*[0-9a-f]*:\s*f48201c0\s*fcmpnes\s*fr2,\s*fr4
+\s*[0-9a-f]*:\s*f4ac01e0\s*fcmpuos\s*fr12,\s*fr5
+\s*[0-9a-f]*:\s*f406032b\s*frecips\s*fr11,\s*fr6
+\s*[0-9a-f]*:\s*f407034a\s*fsqrts\s*fr10,\s*fr7
+\s*[0-9a-f]*:\s*f4080889\s*fmovd\s*fr9,\s*fr8
+\s*[0-9a-f]*:\s*f40908cd\s*fabsd\s*fr13,\s*fr9
+\s*[0-9a-f]*:\s*f40a08ee\s*fnegd\s*fr14,\s*fr10
+\s*[0-9a-f]*:\s*f56f0980\s*fcmphsd\s*fr15,\s*fr11
+\s*[0-9a-f]*:\s*f58009a0\s*fcmpltd\s*fr0,\s*fr12
+\s*[0-9a-f]*:\s*f5a309c0\s*fcmpned\s*fr3,\s*fr13
+\s*[0-9a-f]*:\s*f5c409e0\s*fcmpuod\s*fr4,\s*fr14
+\s*[0-9a-f]*:\s*f40f0b25\s*frecipd\s*fr5,\s*fr15
+\s*[0-9a-f]*:\s*f4080b48\s*fsqrtd\s*fr8,\s*fr8
+\s*[0-9a-f]*:\s*f4031081\s*fmovm\s*fr1,\s*fr3
+\s*[0-9a-f]*:\s*f40d10c3\s*fabsm\s*fr3,\s*fr13
+\s*[0-9a-f]*:\s*f40210ef\s*fnegm\s*fr15,\s*fr2
+\s*[0-9a-f]*:\s*f402180f\s*fstosi.rn\s*fr15,\s*fr2
+\s*[0-9a-f]*:\s*f402182e\s*fstosi.rz\s*fr14,\s*fr2
+\s*[0-9a-f]*:\s*f40f184d\s*fstosi.rpi\s*fr13,\s*fr15
+\s*[0-9a-f]*:\s*f40e186c\s*fstosi.rni\s*fr12,\s*fr14
+\s*[0-9a-f]*:\s*f40d188b\s*fstoui.rn\s*fr11,\s*fr13
+\s*[0-9a-f]*:\s*f40c18aa\s*fstoui.rz\s*fr10,\s*fr12
+\s*[0-9a-f]*:\s*f40b18c9\s*fstoui.rpi\s*fr9,\s*fr11
+\s*[0-9a-f]*:\s*f40a18e8\s*fstoui.rni\s*fr8,\s*fr10
+\s*[0-9a-f]*:\s*f4091907\s*fdtosi.rn\s*fr7,\s*fr9
+\s*[0-9a-f]*:\s*f4081926\s*fdtosi.rz\s*fr6,\s*fr8
+\s*[0-9a-f]*:\s*f4071945\s*fdtosi.rpi\s*fr5,\s*fr7
+\s*[0-9a-f]*:\s*f4061964\s*fdtosi.rni\s*fr4,\s*fr6
+\s*[0-9a-f]*:\s*f4051983\s*fdtoui.rn\s*fr3,\s*fr5
+\s*[0-9a-f]*:\s*f40419a2\s*fdtoui.rz\s*fr2,\s*fr4
+\s*[0-9a-f]*:\s*f40319c1\s*fdtoui.rpi\s*fr1,\s*fr3
+\s*[0-9a-f]*:\s*f40219e0\s*fdtoui.rni\s*fr0,\s*fr2
+\s*[0-9a-f]*:\s*f4011a0e\s*fsitos\s*fr14,\s*fr1
+\s*[0-9a-f]*:\s*f4001a2c\s*fuitos\s*fr12,\s*fr0
+\s*[0-9a-f]*:\s*f4021a8d\s*fsitod\s*fr13,\s*fr2
+\s*[0-9a-f]*:\s*f4041aab\s*fuitod\s*fr11,\s*fr4
+\s*[0-9a-f]*:\s*f4081ac2\s*fdtos\s*fr2,\s*fr8
+\s*[0-9a-f]*:\s*f40b1ae5\s*fstod\s*fr5,\s*fr11
diff --git a/gas/testsuite/gas/csky/cskyv2_float.s b/gas/testsuite/gas/csky/cskyv2_float.s
new file mode 100644
index 0000000..ff73391
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_float.s
@@ -0,0 +1,52 @@ 
+.text
+fcmpzhss  vr0
+fcmpzlss  vr1
+fcmpznes  vr5
+fcmpzuos  vr8
+fcmpzhsd  vr10
+fcmpzlsd  vr13
+fcmpzned  vr14
+fcmpzuod  vr15
+fmovs     vr12, fr9
+fabss     vr1,  fr0
+fnegs     vr2,  fr1
+fcmphss   vr7,  fr2
+fcmplts   vr6,  fr3
+fcmpnes   vr2,  fr4
+fcmpuos   vr12, fr5
+frecips   vr11, fr6
+fsqrts    vr10, fr7
+fmovd     vr9,  fr8
+fabsd     vr13, fr9
+fnegd     vr14, fr10
+fcmphsd   vr15, fr11
+fcmpltd   vr0,  fr12
+fcmpned   vr3,  fr13
+fcmpuod   vr4,  fr14
+frecipd   vr5,  fr15
+fsqrtd    vr8,  fr8
+fmovm     vr1,  fr3
+fabsm     vr3,  fr13
+fnegm     vr15, fr2
+fstosi.rn  vr15, vr2
+fstosi.rz  vr14, vr2
+fstosi.rpi vr13, vr15
+fstosi.rni vr12, vr14
+fstoui.rn  vr11, fr13
+fstoui.rz  vr10, fr12
+fstoui.rpi vr9, fr11
+fstoui.rni fr8, vr10
+fdtosi.rn  fr7, vr9
+fdtosi.rz  fr6, vr8
+fdtosi.rpi fr5, vr7
+fdtosi.rni fr4, vr6
+fdtoui.rn  fr3, fr5
+fdtoui.rz  fr2, fr4
+fdtoui.rpi fr1, fr3
+fdtoui.rni fr0, fr2
+fsitos   vr14, vr1
+fuitos   fr12, vr0
+fsitod   fr13, fr2
+fuitod   fr11, fr4
+fdtos    vr2, vr8
+fstod    fr5, vr11
diff --git a/gas/testsuite/gas/csky/cskyv2_lrw.d b/gas/testsuite/gas/csky/cskyv2_lrw.d
new file mode 100644
index 0000000..5b8ea04
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_lrw.d
@@ -0,0 +1,19 @@ 
+# name: cskyv2 - lrw
+#as: -mcpu=ck810 -W
+#objdump: -D
+
+.*: +file format .*csky.*
+#...
+00000000 <LRW>:
+\s*[0-9a-f]*:\s*ea020100\s*movi\s*r2,\s*256
+\s*[0-9a-f]*:\s*ea021000\s*movi\s*r2,\s*4096
+\s*[0-9a-f]*:\s*ea220001\s*movih\s*r2,\s*1
+\s*[0-9a-f]*:\s*1042\s*lrw\s*r2,\s*0x12341234.*
+\s*[0-9a-f]*:\s*1043\s*lrw\s*r2,\s*0x0.*
+\s*[0-9a-f]*:\s*1041\s*lrw\s*r2,\s*0x12341234.*
+#...
+00000012 <L1>:
+\s*[0-9a-f]*:\s*6c8f\s*mov\s*r2,\s*r3
+\s*[0-9a-f]*:\s*12341234\s*\.long\s*0x12341234
+\s*[0-9a-f]*:\s*00000000\s*\.long\s*0x00000000
+#...
diff --git a/gas/testsuite/gas/csky/cskyv2_lrw.s b/gas/testsuite/gas/csky/cskyv2_lrw.s
new file mode 100644
index 0000000..0ff6070
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_lrw.s
@@ -0,0 +1,11 @@ 
+.text
+LRW:
+   lrw      r2, 0x100
+   lrw16    r2, 0x1000
+   lrw32    r2, 0x10000
+   lrw      r2, 0x12341234
+   lrw      r2, L1
+   lrw      r2, [L1]
+
+L1:
+   mov      r2, r3
diff --git a/gas/testsuite/gas/csky/cskyv2_mnolrw1.d b/gas/testsuite/gas/csky/cskyv2_mnolrw1.d
new file mode 100644
index 0000000..8714677
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_mnolrw1.d
@@ -0,0 +1,23 @@ 
+# name: cskyv2 - nolrw
+#as: -mcpu=ck810 -mnolrw -W
+#objdump: -D
+
+.*: +file format .*csky.*
+#...
+00000000 <LRW>:
+\s*[0-9a-f]*:\s*ea220000\s*movih\s*r2,\s*0
+\s*[0-9a-f]*:\s*ec420100\s*ori\s*r2,\s*r2,\s*256
+\s*[0-9a-f]*:\s*ea220000\s*movih\s*r2,\s*0
+\s*[0-9a-f]*:\s*ec421000\s*ori\s*r2,\s*r2,\s*4096
+\s*[0-9a-f]*:\s*ea220001\s*movih\s*r2,\s*1
+\s*[0-9a-f]*:\s*ec420000\s*ori\s*r2,\s*r2,\s*0
+\s*[0-9a-f]*:\s*ea221234\s*movih\s*r2,\s*4660
+\s*[0-9a-f]*:\s*ec421234\s*ori\s*r2,\s*r2,\s*4660
+\s*[0-9a-f]*:\s*ea220000\s*movih\s*r2,\s*0
+\s*[0-9a-f]*:\s*ec420000\s*ori\s*r2,\s*r2,\s*0
+\s*[0-9a-f]*:\s*ea220000\s*movih\s*r2,\s*0
+\s*[0-9a-f]*:\s*ec420000\s*ori\s*r2,\s*r2,\s*0
+#...
+00000030 <L1>:
+\s*[0-9a-f]*:\s*6c8f\s*mov\s*r2,\s*r3
+#...
diff --git a/gas/testsuite/gas/csky/cskyv2_mnolrw1.s b/gas/testsuite/gas/csky/cskyv2_mnolrw1.s
new file mode 100644
index 0000000..0ff6070
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_mnolrw1.s
@@ -0,0 +1,11 @@ 
+.text
+LRW:
+   lrw      r2, 0x100
+   lrw16    r2, 0x1000
+   lrw32    r2, 0x10000
+   lrw      r2, 0x12341234
+   lrw      r2, L1
+   lrw      r2, [L1]
+
+L1:
+   mov      r2, r3
diff --git a/gas/testsuite/gas/csky/cskyv2_mnolrw2.d b/gas/testsuite/gas/csky/cskyv2_mnolrw2.d
new file mode 100644
index 0000000..2232e76
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_mnolrw2.d
@@ -0,0 +1,12 @@ 
+# name: csky - nolrw
+#as: -mcpu=ck810 -mnolrw -W
+#readelf: -r --wide
+
+
+Relocation section '.rela.text\' at offset .* contains 4 entries:
+#...
+00000020.*R_CKCORE_ADDR_HI16\s*00000030\s*L1\s*\+\s*0
+00000024.*R_CKCORE_ADDR_LO16\s*00000030\s*L1\s*\+\s*0
+00000028.*R_CKCORE_ADDR_HI16\s*00000030\s*L1\s*\+\s*0
+0000002c.*R_CKCORE_ADDR_LO16\s*00000030\s*L1\s*\+\s*0
+#pass
diff --git a/gas/testsuite/gas/csky/cskyv2_mnolrw2.s b/gas/testsuite/gas/csky/cskyv2_mnolrw2.s
new file mode 100644
index 0000000..0ff6070
--- /dev/null
+++ b/gas/testsuite/gas/csky/cskyv2_mnolrw2.s
@@ -0,0 +1,11 @@ 
+.text
+LRW:
+   lrw      r2, 0x100
+   lrw16    r2, 0x1000
+   lrw32    r2, 0x10000
+   lrw      r2, 0x12341234
+   lrw      r2, L1
+   lrw      r2, [L1]
+
+L1:
+   mov      r2, r3
diff --git a/gas/testsuite/gas/csky/enhance_dsp.d b/gas/testsuite/gas/csky/enhance_dsp.d
new file mode 100644
index 0000000..4317038
--- /dev/null
+++ b/gas/testsuite/gas/csky/enhance_dsp.d
@@ -0,0 +1,217 @@ 
+#name: csky - enhancedsp
+#as: -mcpu=ck803er1
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*d0038002\s*ldbi.b\s*r2,\s*\(r3\)
+\s*[0-9a-f]*:\s*d0038402\s*ldbi.h\s*r2,\s*\(r3\)
+\s*[0-9a-f]*:\s*d0038802\s*ldbi.w\s*r2,\s*\(r3\)
+#...
+\s*[0-9a-f]*:\s*e9c20ffa\s*bloop\s*r2,\s*0x0,\s*0xc.*
+\s*[0-9a-f]*:\s*d0038c02\s*pldbi.d\s*r2,\s*\(r3\)
+\s*[0-9a-f]*:\s*d0039002\s*ldbi.hs\s*r2,\s*\(r3\)
+\s*[0-9a-f]*:\s*d0039402\s*ldbi.bs\s*r2,\s*\(r3\)
+\s*[0-9a-f]*:\s*d4038002\s*stbi.b\s*r2,\s*\(r3\)
+\s*[0-9a-f]*:\s*d4038402\s*stbi.h\s*r2,\s*\(r3\)
+\s*[0-9a-f]*:\s*d4038802\s*stbi.w\s*r2,\s*\(r3\)
+\s*[0-9a-f]*:\s*d083a002\s*ldbir.b\s*r2,\s*\(r3\),\s*r4
+\s*[0-9a-f]*:\s*d083a402\s*ldbir.h\s*r2,\s*\(r3\),\s*r4
+\s*[0-9a-f]*:\s*d083a802\s*ldbir.w\s*r2,\s*\(r3\),\s*r4
+\s*[0-9a-f]*:\s*d083ac02\s*pldbir.d\s*r2,\s*\(r3\),\s*r4
+\s*[0-9a-f]*:\s*d083b402\s*ldbir.hs\s*r2,\s*\(r3\),\s*r4
+\s*[0-9a-f]*:\s*d083b002\s*ldbir.bs\s*r2,\s*\(r3\),\s*r4
+\s*[0-9a-f]*:\s*d483a002\s*stbir.b\s*r2,\s*\(r3\),\s*r4
+\s*[0-9a-f]*:\s*d483a402\s*stbir.h\s*r2,\s*\(r3\),\s*r4
+\s*[0-9a-f]*:\s*d483a802\s*stbir.w\s*r2,\s*\(r3\),\s*r4
+\s*[0-9a-f]*:\s*f883c042\s*padd\.8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c002\s*padd\.16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c142\s*padd\.u8\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c1c2\s*padd\.s8\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c102\s*padd\.u16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c182\s*padd\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c122\s*add\.u32\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c1a2\s*add\.s32\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c442\s*psub\.8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c402\s*psub\.16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c542\s*psub\.u8\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c5c2\s*psub\.s8\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c502\s*psub\.u16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c582\s*psub\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c522\s*sub\.u32\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c5a2\s*sub\.s32\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c242\s*paddh\.u8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c2c2\s*paddh\.s8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c202\s*paddh\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c282\s*paddh\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c222\s*addh\.u32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c2a2\s*addh\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c642\s*psubh\.u8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c6c2\s*psubh\.s8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c602\s*psubh\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c682\s*psubh\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c622\s*subh\.u32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c6a2\s*subh\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c862\s*pasx\.16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cc62\s*psax\.16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c9e2\s*pasx\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c962\s*pasx\.u16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cd62\s*psax\.u16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cde2\s*psax\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883ca62\s*pasxh\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cae2\s*pasxh\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883ce62\s*psaxh\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cee2\s*psaxh\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c842\s*pcmpne\.8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c802\s*pcmpne\.16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c942\s*pcmphs\.u8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c982\s*pcmphs\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c902\s*pcmphs\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883c9c2\s*pcmphs\.s8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883ca42\s*pcmplt\.u8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883ca02\s*pcmplt\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883ca82\s*pcmplt\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883ca02\s*pcmplt\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cc42\s*pmax\.u8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883ccc2\s*pmax\.s8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cc02\s*pmax\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cc82\s*pmax\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cc22\s*max\.u32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cca2\s*max\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cd42\s*pmin\.u8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cdc2\s*pmin\.s8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cd02\s*pmin\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cd82\s*pmin\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cd22\s*min\.u32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883cda2\s*min\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8229083\s*sel\s*r3,\s*r2,\s*r1,\s*r4
+\s*[0-9a-f]*:\s*f883e042\s*psabsa\.u8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883e142\s*psabsaa\.u8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883e262\s*divul\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883e2e2\s*divsl\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883e4c2\s*mulaca\.s8\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f9e3d1a2\s*asri\.s32\.r\s*r2,\s*r3,\s*16
+\s*[0-9a-f]*:\s*f8c3d1e2\s*asr\.s32\.r\s*r2,\s*r3,\s*r6
+\s*[0-9a-f]*:\s*f9e3d322\s*lsri\.u32\.r\s*r2,\s*r3,\s*16
+\s*[0-9a-f]*:\s*f8c3d362\s*lsr\.u32\.r\s*r2,\s*r3,\s*r6
+\s*[0-9a-f]*:\s*f9e3d522\s*lsli\.u32\.s\s*r2,\s*r3,\s*16
+\s*[0-9a-f]*:\s*f9e3d5a2\s*lsli\.s32\.s\s*r2,\s*r3,\s*16
+\s*[0-9a-f]*:\s*f8c3d562\s*lsl\.u32\.s\s*r2,\s*r3,\s*r6
+\s*[0-9a-f]*:\s*f8c3d5e2\s*lsl\.s32\.s\s*r2,\s*r3,\s*r6
+\s*[0-9a-f]*:\s*f8e3d082\s*pasri\.s16\s*r2,\s*r3,\s*8
+\s*[0-9a-f]*:\s*f8c3d0c2\s*pasr\.s16\s*r2,\s*r3,\s*r6
+\s*[0-9a-f]*:\s*f8e3d182\s*pasri\.s16\.r\s*r2,\s*r3,\s*8
+\s*[0-9a-f]*:\s*f8c3d1c2\s*pasr\.s16\.r\s*r2,\s*r3,\s*r6
+\s*[0-9a-f]*:\s*f8e3d202\s*plsri\.u16\s*r2,\s*r3,\s*8
+\s*[0-9a-f]*:\s*f883d242\s*plsr\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8e3d302\s*plsri\.u16\.r\s*r2,\s*r3,\s*8
+\s*[0-9a-f]*:\s*f883d342\s*plsr\.u16\.r\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8e3d402\s*plsli\.u16\s*r2,\s*r3,\s*8
+\s*[0-9a-f]*:\s*fa03d442\s*plsl\.u16\s*r2,\s*r3,\s*r16
+\s*[0-9a-f]*:\s*f8e3d502\s*plsli\.u16\.s\s*r2,\s*r3,\s*8
+\s*[0-9a-f]*:\s*f8e3d582\s*plsli\.s16\.s\s*r2,\s*r3,\s*8
+\s*[0-9a-f]*:\s*f883d542\s*plsl\.u16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883d5c2\s*plsl\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8a3a482\s*pkg\s*r2,\s*r3,\s*4,\s*r5,\s*3
+\s*[0-9a-f]*:\s*f8839882\s*dexti\s*r2,\s*r3,\s*r4,\s*4
+\s*[0-9a-f]*:\s*f8839ca2\s*dext\s*r2,\s*r3,\s*r4,\s*r5
+\s*[0-9a-f]*:\s*f883d842\s*pkgll\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883d862\s*pkghh\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f803d902\s*pext\.u8\.e\s*r2,\s*r3
+\s*[0-9a-f]*:\s*f803d982\s*pext\.s8\.e\s*r2,\s*r3
+\s*[0-9a-f]*:\s*f803d922\s*pextx\.u8\.e\s*r2,\s*r3
+\s*[0-9a-f]*:\s*f803d9a2\s*pextx\.s8\.e\s*r2,\s*r3
+\s*[0-9a-f]*:\s*f883da02\s*narl\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883da22\s*narh\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883da42\s*narlx\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883da62\s*narhx\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*fa03db02\s*clipi\.u32\s*r2,\s*r3,\s*16
+\s*[0-9a-f]*:\s*f9e3db82\s*clipi\.s32\s*r2,\s*r3,\s*16
+\s*[0-9a-f]*:\s*f883db22\s*clip\.u32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883dba2\s*clip\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f863dbc2\s*pclipi\.s16\s*r2,\s*r3,\s*4
+\s*[0-9a-f]*:\s*f883db42\s*pclipi\.u16\s*r2,\s*r3,\s*4
+\s*[0-9a-f]*:\s*f883dbe2\s*pclip\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f883db62\s*pclip\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f803dc82\s*pabs\.s8\.s\s*r2,\s*r3
+\s*[0-9a-f]*:\s*f803dca2\s*pabs\.s16\.s\s*r2,\s*r3
+\s*[0-9a-f]*:\s*f803dcc2\s*abs\.s32\.s\s*r2,\s*r3
+\s*[0-9a-f]*:\s*f803dd82\s*pneg\.s8\.s\s*r2,\s*r3
+\s*[0-9a-f]*:\s*f803dda2\s*pneg\.s16\.s\s*r2,\s*r3
+\s*[0-9a-f]*:\s*f803ddc2\s*neg\.s32\.s\s*r2,\s*r3
+\s*[0-9a-f]*:\s*f803de62\s*dup\.8\s*r2,\s*r3,\s*3
+\s*[0-9a-f]*:\s*f803df02\s*dup\.16\s*r2,\s*r3,\s*0
+\s*[0-9a-f]*:\s*f8838002\s*mul\.u32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838202\s*mul\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838082\s*mula\.u32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838282\s*mula\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88380c2\s*muls\.u32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88382c2\s*muls\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838182\s*mula\.u32\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838382\s*mula\.s32\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88381c2\s*muls\.u32\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88383c2\s*muls\.s32\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838402\s*mul\.s32\.h\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838602\s*mul\.s32\.rh\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838502\s*rmul\.s32\.h\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838702\s*rmul\.s32\.rh\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838582\s*mula\.s32\.hs\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88385c2\s*muls\.s32\.hs\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838782\s*mula\.s32\.rhs\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88387c2\s*muls\.s32\.rhs\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838802\s*mulxl\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838a02\s*mulxl\.s32\.r\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838c02\s*mulxh\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838e02\s*mulxh\.s32\.r\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838902\s*rmulxl\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838b02\s*rmulxl\.s32\.r\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838d02\s*rmulxh\.s32\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838f02\s*rmulxh\.s32\.r\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838982\s*mulaxl\.s32\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838b82\s*mulaxl\.s32\.rs\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838d82\s*mulaxh\.s32\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838f82\s*mulaxh\.s32\.rs\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838022\s*mulll\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838262\s*mulhh\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838222\s*mulhl\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838122\s*rmulll\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838362\s*rmulhh\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838322\s*rmulhl\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88381a2\s*mulall\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88383e2\s*mulahh\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88383a2\s*mulahl\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88380a2\s*mulall\.s16\.e\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88382e2\s*mulahh\.s16\.e\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88380e2\s*mulahl\.s16\.e\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88384a2\s*pmul\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88384e2\s*pmulx\.u16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838422\s*pmul\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838462\s*pmulx\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838522\s*prmul\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838562\s*prmulx\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88385a2\s*prmul\.s16\.h\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88387a2\s*prmul\.s16\.rh\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88385e2\s*prmulx\.s16\.h\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88387e2\s*prmulx\.s16\.rh\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838922\s*mulca\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838962\s*mulcax\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838a22\s*mulcs\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838a62\s*mulcsr\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838c22\s*mulcsx\.s16\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88389a2\s*mulaca\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88389e2\s*mulacax\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838ba2\s*mulacs\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838be2\s*mulacsr\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838da2\s*mulacsx\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838de2\s*mulsca\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838fa2\s*mulscax\.s16\.s\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88388a2\s*mulaca\.s16\.e\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f88388e2\s*mulacax\.s16\.e\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838aa2\s*mulacs\.s16\.e\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838ae2\s*mulacsr\.s16\.e\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838ca2\s*mulacsx\.s16\.e\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838ce2\s*mulsca\.s16\.e\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838ce2\s*mulsca\.s16\.e\s*r2,\s*r3,\s*r4
+\s*[0-9a-f]*:\s*f8838442\s*mula\.32\.l\s*r2,\s*r3,\s*r4
diff --git a/gas/testsuite/gas/csky/enhance_dsp.s b/gas/testsuite/gas/csky/enhance_dsp.s
new file mode 100644
index 0000000..0491a53
--- /dev/null
+++ b/gas/testsuite/gas/csky/enhance_dsp.s
@@ -0,0 +1,219 @@ 
+
+.text
+hello:
+.loop_start:
+    ldbi.b r2, (r3)
+    ldbi.h r2, (r3)
+    ldbi.w r2, (r3)
+.loop_end:
+    bloop r2, .loop_start, .loop_end
+    pldbi.d r2, (r3)
+    ldbi.hs r2, (r3)
+    ldbi.bs r2, (r3)
+    stbi.b r2, (r3)
+    stbi.h r2, (r3)
+    stbi.w r2, (r3)
+    ldbir.b r2, (r3), r4
+    ldbir.h r2, (r3), r4
+    ldbir.w r2, (r3), r4
+    pldbir.d r2, (r3), r4
+    ldbir.hs r2, (r3), r4
+    ldbir.bs r2, (r3), r4
+    stbir.b r2, (r3), r4
+    stbir.h r2, (r3), r4
+    stbir.w r2, (r3), r4
+
+    padd.8  r2, r3, r4
+    padd.16  r2, r3, r4
+    padd.u8.s  r2, r3, r4
+    padd.s8.s  r2, r3, r4
+    padd.u16.s  r2, r3, r4
+    padd.s16.s  r2, r3, r4
+    add.u32.s  r2, r3, r4
+    add.s32.s  r2, r3, r4
+    psub.8  r2, r3, r4
+    psub.16  r2, r3, r4
+    psub.u8.s  r2, r3, r4
+    psub.s8.s  r2, r3, r4
+    psub.u16.s  r2, r3, r4
+    psub.s16.s  r2, r3, r4
+    sub.u32.s  r2, r3, r4
+    sub.s32.s  r2, r3, r4
+    paddh.u8   r2, r3, r4
+    paddh.s8   r2, r3, r4
+    paddh.u16   r2, r3, r4
+    paddh.s16   r2, r3, r4
+    addh.u32   r2, r3, r4
+    addh.s32   r2, r3, r4
+    psubh.u8   r2, r3, r4
+    psubh.s8   r2, r3, r4
+    psubh.u16   r2, r3, r4
+    psubh.s16   r2, r3, r4
+    subh.u32   r2, r3, r4
+    subh.s32   r2, r3, r4
+
+    pasx.16    r2, r3, r4
+    psax.16    r2, r3, r4
+    pasx.s16.s    r2, r3, r4
+    pasx.u16.s    r2, r3, r4
+    psax.u16.s    r2, r3, r4
+    psax.s16.s    r2, r3, r4
+    pasxh.u16    r2, r3, r4
+    pasxh.s16    r2, r3, r4
+    psaxh.u16    r2, r3, r4
+    psaxh.s16    r2, r3, r4
+    pcmpne.8    r2, r3, r4
+    pcmpne.16    r2, r3, r4
+    pcmphs.u8    r2, r3, r4
+    pcmphs.s16    r2, r3, r4
+    pcmphs.u16    r2, r3, r4
+    pcmphs.s8    r2, r3, r4
+    pcmplt.u8    r2, r3, r4
+    pcmplt.u16    r2, r3, r4
+    pcmplt.s16    r2, r3, r4
+    pcmplt.u16    r2, r3, r4
+    pmax.u8    r2, r3, r4
+    pmax.s8    r2, r3, r4
+    pmax.u16    r2, r3, r4
+    pmax.s16    r2, r3, r4
+    max.u32    r2, r3, r4
+    max.s32    r2, r3, r4
+    pmin.u8    r2, r3, r4
+    pmin.s8    r2, r3, r4
+    pmin.u16    r2, r3, r4
+    pmin.s16    r2, r3, r4
+    min.u32    r2, r3, r4
+    min.s32    r2, r3, r4
+    sel   r3, r2, r1, r4
+
+    psabsa.u8  r2, r3, r4
+    psabsaa.u8  r2, r3, r4
+    divul       r2, r3, r4
+    divsl       r2, r3, r4
+    mulaca.s8   r2, r3, r4
+
+    asri.s32.r   r2, r3, 16
+    asr.s32.r   r2, r3, r6
+    lsri.u32.r  r2, r3, 16
+    lsr.u32.r   r2, r3, r6
+    lsli.u32.s   r2, r3, 16
+    lsli.s32.s   r2, r3, 16
+    lsl.u32.s    r2, r3, r6
+    lsl.s32.s    r2, r3, r6
+    pasri.s16   r2, r3, 8
+    pasr.s16    r2, r3, r6
+    pasri.s16.r  r2, r3, 8
+    pasr.s16.r   r2, r3, r6
+    plsri.u16    r2, r3, 8
+    plsr.u16     r2, r3, r4
+    plsri.u16.r  r2, r3, 8
+    plsr.u16.r   r2, r3, r4
+    plsli.u16    r2, r3, 8
+    plsl.u16     r2, r3, r16
+    plsli.u16.s  r2, r3, 8
+    plsli.s16.s  r2, r3, 8
+    plsl.u16.s   r2, r3, r4
+    plsl.s16.s   r2, r3, r4
+
+    pkg   r2, r3, 4, r5, 3
+    dexti  r2, r3, r4, 4
+    dext  r2, r3, r4, r5
+    pkgll r2, r3, r4
+    pkghh r2, r3, r4
+    pext.u8.e r2, r3
+    pext.s8.e r2, r3
+    pextx.u8.e r2, r3
+    pextx.s8.e r2, r3
+    narl r2, r3, r4
+    narh r2, r3, r4
+    narlx r2, r3, r4
+    narhx r2, r3, r4
+    clipi.u32 r2, r3, 16
+    clipi.s32 r2, r3, 16
+    clip.u32 r2, r3, r4
+    clip.s32 r2, r3, r4
+    pclipi.s16 r2, r3, 4
+    pclipi.u16 r2, r3, 4
+    pclip.s16 r2, r3, r4
+    pclip.u16 r2, r3, r4
+    pabs.s8.s  r2, r3
+    pabs.s16.s  r2, r3
+    abs.s32.s  r2, r3
+    pneg.s8.s  r2, r3
+    pneg.s16.s  r2, r3
+    neg.s32.s  r2, r3
+    dup.8  r2, r3, 3
+    dup.16  r2, r3, 0
+
+    mul.u32  r2, r3, r4
+    mul.s32  r2, r3, r4
+    mula.u32 r2, r3, r4
+    mula.s32 r2, r3, r4
+    muls.u32 r2, r3, r4
+    muls.s32 r2, r3, r4
+    mula.u32.s r2, r3, r4
+    mula.s32.s r2, r3, r4
+    muls.u32.s r2, r3, r4
+    muls.s32.s r2, r3, r4
+    mul.s32.h  r2, r3, r4
+    mul.s32.rh  r2, r3, r4
+    rmul.s32.h  r2, r3, r4
+    rmul.s32.rh  r2, r3, r4
+    mula.s32.hs r2, r3, r4
+    muls.s32.hs  r2, r3, r4
+    mula.s32.rhs r2, r3, r4
+    muls.s32.rhs  r2, r3, r4
+    mulxl.s32 r2, r3, r4
+    mulxl.s32.r  r2, r3, r4
+    mulxh.s32 r2, r3, r4
+    mulxh.s32.r r2, r3, r4
+    rmulxl.s32  r2, r3, r4
+    rmulxl.s32.r r2, r3, r4
+    rmulxh.s32 r2, r3, r4
+    rmulxh.s32.r r2, r3, r4
+    mulaxl.s32.s  r2, r3, r4
+    mulaxl.s32.rs r2, r3, r4
+    mulaxh.s32.s r2, r3, r4
+    mulaxh.s32.rs r2, r3, r4
+    mulll.s16 r2, r3, r4
+    mulhh.s16 r2, r3, r4
+    mulhl.s16 r2, r3, r4
+    rmulll.s16 r2, r3, r4
+    rmulhh.s16 r2, r3, r4
+    rmulhl.s16 r2, r3, r4
+    mulall.s16.s r2, r3, r4
+    mulahh.s16.s r2, r3, r4
+    mulahl.s16.s r2, r3, r4
+    mulall.s16.e  r2, r3, r4
+    mulahh.s16.e r2, r3, r4
+    mulahl.s16.e r2, r3, r4
+    pmul.u16 r2, r3, r4
+    pmulx.u16 r2, r3, r4
+    pmul.s16 r2, r3, r4
+    pmulx.s16 r2, r3, r4
+    prmul.s16 r2, r3, r4
+    prmulx.s16 r2, r3, r4
+    prmul.s16.h r2, r3, r4
+    prmul.s16.rh r2, r3, r4
+    prmulx.s16.h r2, r3, r4
+    prmulx.s16.rh r2, r3, r4
+    mulca.s16.s r2, r3, r4
+    mulcax.s16.s r2, r3, r4
+    mulcs.s16 r2, r3, r4
+    mulcsr.s16 r2, r3, r4
+    mulcsx.s16 r2, r3, r4
+    mulaca.s16.s r2, r3, r4
+    mulacax.s16.s r2, r3, r4
+    mulacs.s16.s r2, r3, r4
+    mulacsr.s16.s r2, r3, r4
+    mulacsx.s16.s r2, r3, r4
+    mulsca.s16.s r2, r3, r4
+    mulscax.s16.s r2, r3, r4
+    mulaca.s16.e r2, r3, r4
+    mulacax.s16.e r2, r3, r4
+    mulacs.s16.e r2, r3, r4
+    mulacsr.s16.e r2, r3, r4
+    mulacsx.s16.e r2, r3, r4
+    mulsca.s16.e r2, r3, r4
+    mulsca.s16.e r2, r3, r4
+    mula.32.l   r2, r3, r4
diff --git a/gas/testsuite/gas/csky/java.d b/gas/testsuite/gas/csky/java.d
new file mode 100644
index 0000000..f433d52
--- /dev/null
+++ b/gas/testsuite/gas/csky/java.d
@@ -0,0 +1,12 @@ 
+# name: csky - java
+#as: -mcpu=ck802j
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]:\s*14ac\s*bpop\.h\s*r3
+\s*[0-9a-f]:\s*14ae\s*bpop\.w\s*r3
+\s*[0-9a-f]:\s*14ec\s*bpush\.h\s*r3
+\s*[0-9a-f]:\s*14ee\s*bpush\.w\s*r3
diff --git a/gas/testsuite/gas/csky/java.s b/gas/testsuite/gas/csky/java.s
new file mode 100644
index 0000000..8f18f86
--- /dev/null
+++ b/gas/testsuite/gas/csky/java.s
@@ -0,0 +1,7 @@ 
+.text
+hello:
+   bpop.h  r3
+   bpop.w  r3
+   bpush.h  r3
+   bpush.w  r3
+
diff --git a/gas/testsuite/gas/csky/jbsr.d b/gas/testsuite/gas/csky/jbsr.d
new file mode 100644
index 0000000..c036910
--- /dev/null
+++ b/gas/testsuite/gas/csky/jbsr.d
@@ -0,0 +1,14 @@ 
+# name: jbsr - csky
+#as: -mcpu=ck610
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*ffff\s*bsr\s*0x0.*
+\s*[0-9a-f]*:\s*f7ff\s*br\s*0x2.*
+\s*[0-9a-f]*:\s*f7ff\s*br\s*0x4.*
+\s*[0-9a-f]*:\s*1200\s*\.short\s*0x1200.*
+\s*[0-9a-f]*:\s*00000000\s*\.long\s*0x00000000.*
+#...
diff --git a/gas/testsuite/gas/csky/jbsr.s b/gas/testsuite/gas/csky/jbsr.s
new file mode 100644
index 0000000..77ec2a5
--- /dev/null
+++ b/gas/testsuite/gas/csky/jbsr.s
@@ -0,0 +1,4 @@ 
+.text
+hello:
+    jbsr hello
+
diff --git a/gas/testsuite/gas/csky/jbt.d b/gas/testsuite/gas/csky/jbt.d
new file mode 100644
index 0000000..098bdc2
--- /dev/null
+++ b/gas/testsuite/gas/csky/jbt.d
@@ -0,0 +1,16 @@ 
+# name: jbt - csky
+#as: -mcpu=ck610
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*e7ff\s*bt\s*0x0.*
+\s*[0-9a-f]*:\s*e804\s*bf\s*0xc.*
+\s*[0-9a-f]*:\s*7001\s*jmpi\s*0x0.*
+\s*[0-9a-f]*:\s*0000\s*bkpt\s*
+\s*[0-9a-f]*:\s*0000\s*bkpt\s*
+\s*[0-9a-f]*:\s*0000\s*bkpt\s*
+\s*[0-9a-f]*:\s*1200\s*mov\s*r0,\s*r0
+#...
diff --git a/gas/testsuite/gas/csky/jbt.s b/gas/testsuite/gas/csky/jbt.s
new file mode 100644
index 0000000..10808df
--- /dev/null
+++ b/gas/testsuite/gas/csky/jbt.s
@@ -0,0 +1,10 @@ 
+.text
+hello:
+    jbt hello
+    jbt label
+.rept  33*1024
+    nop
+.endr
+
+label:
+    nop
diff --git a/gas/testsuite/gas/csky/jbt_pic.d b/gas/testsuite/gas/csky/jbt_pic.d
new file mode 100644
index 0000000..932cd7d
--- /dev/null
+++ b/gas/testsuite/gas/csky/jbt_pic.d
@@ -0,0 +1,23 @@ 
+# name: jbt - csky
+#as: -mcpu=ck610 -fpic
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*e7ff\s*bt\s*0x0.*
+\s*[0-9a-f]*:\s*e80b\s*bf\s*0x1a.*
+\s*[0-9a-f]*:\s*2470\s*subi\s*r0,\s*r0,\s*8
+\s*[0-9a-f]*:\s*9f00\s*st.w\s*r15,\s*\(r0,\s*0x0\)
+\s*[0-9a-f]*:\s*f800\s*bsr\s*0xa.*
+\s*[0-9a-f]*:\s*7102\s*lrw\s*r1,\s*0x10810.*
+\s*[0-9a-f]*:\s*1cf1\s*addu\s*r1,\s*r1,\s*r15
+\s*[0-9a-f]*:\s*8f00\s*ld.w\s*r15,\s*\(r0,\s*0x0\)
+\s*[0-9a-f]*:\s*2070\s*addi\s*r0,\s*r0,\s*8
+\s*[0-9a-f]*:\s*00c1\s*jmp\s*r1
+\s*[0-9a-f]*:\s*0810\s*cprgr\s*r0,\s*cpr1
+\s*[0-9a-f]*:\s*0001\s*sync
+\s*[0-9a-f]*:\s*0000\s*bkpt
+\s*[0-9a-f]*:\s*1200\s*mov\s*r0,\s*r0
+#...
diff --git a/gas/testsuite/gas/csky/jbt_pic.s b/gas/testsuite/gas/csky/jbt_pic.s
new file mode 100644
index 0000000..10808df
--- /dev/null
+++ b/gas/testsuite/gas/csky/jbt_pic.s
@@ -0,0 +1,10 @@ 
+.text
+hello:
+    jbt hello
+    jbt label
+.rept  33*1024
+    nop
+.endr
+
+label:
+    nop
diff --git a/gas/testsuite/gas/csky/jmpi1.d b/gas/testsuite/gas/csky/jmpi1.d
new file mode 100644
index 0000000..3cd1211
--- /dev/null
+++ b/gas/testsuite/gas/csky/jmpi1.d
@@ -0,0 +1,16 @@ 
+# name: jmpi1 - csky
+#as: -mcpu=ck610
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]:\s*0000\s*bkpt\s*
+\s*[0-9a-f]:\s*70[0-9a-f]*\s*jmpi\s*0x0\s*\/\/\s*from\s*address\s*pool\s*at\s*0x[0-9a-f]*
+\s*[0-9a-f]:\s*0000\s*bkpt\s*
+\s*[0-9a-f]:\s*f7ff\s*br\s*0x[0-9a-f]*\s*\/\/\s*[0-9a-f]*\s*\<LABEL\+0x[0-9a-f]*\>
+\s*[0-9a-f]:\s*f7ff\s*br\s*0x[0-9a-f]*\s*\/\/\s*[0-9a-f]*\s*\<LABEL\+0x[0-9a-f]*\>
+\s*[0-9a-f]:\s*1200\s*\.short\s*0x1200
+\s*[0-9a-f]:\s*00000000\s*\.long\s*0x00000000
+#...
diff --git a/gas/testsuite/gas/csky/jmpi1.s b/gas/testsuite/gas/csky/jmpi1.s
new file mode 100644
index 0000000..c7ad604
--- /dev/null
+++ b/gas/testsuite/gas/csky/jmpi1.s
@@ -0,0 +1,6 @@ 
+.text
+
+LABEL:
+  bkpt
+  jmpi LABEL
+  bkpt
diff --git a/gas/testsuite/gas/csky/jmpi2.d b/gas/testsuite/gas/csky/jmpi2.d
new file mode 100644
index 0000000..5d855cf
--- /dev/null
+++ b/gas/testsuite/gas/csky/jmpi2.d
@@ -0,0 +1,14 @@ 
+# name: jmpi2 - csky
+#as: -mcpu=ck610
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]:\s*0000\s*bkpt\s*
+\s*[0-9a-f]:\s*70[0-9a-f]*\s*jmpi\s*0x0\s*\/\/\s*from\s*address\s*pool\s*at\s*0x[0-9a-f]*
+\s*[0-9a-f]:\s*f7ff\s*br\s*0x[0-9a-f]*\s*\/\/\s*[0-9a-f]*\s*\<LABEL\+0x[0-9a-f]*\>
+\s*[0-9a-f]:\s*f7ff\s*br\s*0x[0-9a-f]*\s*\/\/\s*[0-9a-f]*\s*\<LABEL\+0x[0-9a-f]*\>
+\s*[0-9a-f]:\s*00000000\s*\.long\s*0x00000000
+#...
diff --git a/gas/testsuite/gas/csky/jmpi2.s b/gas/testsuite/gas/csky/jmpi2.s
new file mode 100644
index 0000000..91e209f
--- /dev/null
+++ b/gas/testsuite/gas/csky/jmpi2.s
@@ -0,0 +1,5 @@ 
+.text
+
+LABEL:
+  bkpt
+  jmpi LABEL2
diff --git a/gas/testsuite/gas/csky/jmpi3.d b/gas/testsuite/gas/csky/jmpi3.d
new file mode 100644
index 0000000..c19b04f
--- /dev/null
+++ b/gas/testsuite/gas/csky/jmpi3.d
@@ -0,0 +1,9 @@ 
+# name: jmpi2 - csky
+#as: -mcpu=ck610
+#readelf: -r --wide
+
+
+Relocation section '.rela.text\' at offset .* contains 1 entry:
+#...
+.*R_CKCORE_ADDR32[ \t]+00000000[ \t]+\.text \+[ \t]+[0-9a-f]+
+#pass
diff --git a/gas/testsuite/gas/csky/jmpi3.s b/gas/testsuite/gas/csky/jmpi3.s
new file mode 100644
index 0000000..c7ad604
--- /dev/null
+++ b/gas/testsuite/gas/csky/jmpi3.s
@@ -0,0 +1,6 @@ 
+.text
+
+LABEL:
+  bkpt
+  jmpi LABEL
+  bkpt
diff --git a/gas/testsuite/gas/csky/jmpiv2_1.d b/gas/testsuite/gas/csky/jmpiv2_1.d
new file mode 100644
index 0000000..d8006e7
--- /dev/null
+++ b/gas/testsuite/gas/csky/jmpiv2_1.d
@@ -0,0 +1,13 @@ 
+# name: jmpiv2_1 - csky
+#as: -mcpu=ck810
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]:\s*0000\s*bkpt\s*
+\s*[0-9a-f]:\s*eac00002\s*jmpi\s*0x0\s*\/\/\s*from\s*address\s*pool\s*at\s*0x[0-9a-f]*
+\s*[0-9a-f]:\s*0000\s*bkpt\s*
+\s*[0-9a-f]:\s*00000000\s*\.long\s*0x00000000
+#...
diff --git a/gas/testsuite/gas/csky/jmpiv2_1.s b/gas/testsuite/gas/csky/jmpiv2_1.s
new file mode 100644
index 0000000..c7ad604
--- /dev/null
+++ b/gas/testsuite/gas/csky/jmpiv2_1.s
@@ -0,0 +1,6 @@ 
+.text
+
+LABEL:
+  bkpt
+  jmpi LABEL
+  bkpt
diff --git a/gas/testsuite/gas/csky/jmpiv2_2.d b/gas/testsuite/gas/csky/jmpiv2_2.d
new file mode 100644
index 0000000..c0aef4a
--- /dev/null
+++ b/gas/testsuite/gas/csky/jmpiv2_2.d
@@ -0,0 +1,9 @@ 
+# name: jmpiv2_2 - csky
+#as: -mcpu=ck810
+#readelf: -r --wide
+
+
+Relocation section '.rela.text\' at offset .* contains 1 entry:
+#...
+.*R_CKCORE_ADDR32[ \t]+00000000[ \t]+\.text \+[ \t]+[0-9a-f]+
+#pass
diff --git a/gas/testsuite/gas/csky/jmpiv2_2.s b/gas/testsuite/gas/csky/jmpiv2_2.s
new file mode 100644
index 0000000..c7ad604
--- /dev/null
+++ b/gas/testsuite/gas/csky/jmpiv2_2.s
@@ -0,0 +1,6 @@ 
+.text
+
+LABEL:
+  bkpt
+  jmpi LABEL
+  bkpt
diff --git a/gas/testsuite/gas/csky/jsriv2_1.d b/gas/testsuite/gas/csky/jsriv2_1.d
new file mode 100644
index 0000000..524f847
--- /dev/null
+++ b/gas/testsuite/gas/csky/jsriv2_1.d
@@ -0,0 +1,13 @@ 
+# name: jsriv2_1 - csky
+#as: -mcpu=ck807
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]:\s*0000\s*bkpt
+\s*[0-9a-f]:\s*eae00002\s*jsri\s*0x0\s*\/\/\s*from\s*address\s*pool\s*at\s*0x[0-9a-f]*
+\s*[0-9a-f]:\s*0000\s*.short\s*0x0000
+\s*[0-9a-f]:\s*00000000\s*.long\s*0x00000000
+#...
diff --git a/gas/testsuite/gas/csky/jsriv2_1.s b/gas/testsuite/gas/csky/jsriv2_1.s
new file mode 100644
index 0000000..45ce734
--- /dev/null
+++ b/gas/testsuite/gas/csky/jsriv2_1.s
@@ -0,0 +1,5 @@ 
+.text
+
+LABEL:
+bkpt
+jsri LABEL
diff --git a/gas/testsuite/gas/csky/jsriv2_2.d b/gas/testsuite/gas/csky/jsriv2_2.d
new file mode 100644
index 0000000..3a373b5
--- /dev/null
+++ b/gas/testsuite/gas/csky/jsriv2_2.d
@@ -0,0 +1,14 @@ 
+# name: jsriv2_2 - csky
+#as: -mcpu=ck810
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]:\s*0000\s*bkpt
+\s*[0-9a-f]:\s*e3ffffff\s*bsr\s*0x0\s*\/\/\s*0\s*<LABEL>
+\s*[0-9a-f]:\s*c4004820\s*lsli\s*r0,\s*\s*r0,\s*0
+\s*[0-9a-f]:\s*0000\s*.short\s*0x0000
+\s*[0-9a-f]:\s*00000000\s*.long\s*0x00000000
+#...
diff --git a/gas/testsuite/gas/csky/jsriv2_2.s b/gas/testsuite/gas/csky/jsriv2_2.s
new file mode 100644
index 0000000..45ce734
--- /dev/null
+++ b/gas/testsuite/gas/csky/jsriv2_2.s
@@ -0,0 +1,5 @@ 
+.text
+
+LABEL:
+bkpt
+jsri LABEL
diff --git a/gas/testsuite/gas/csky/jsriv2_3.d b/gas/testsuite/gas/csky/jsriv2_3.d
new file mode 100644
index 0000000..9e46368
--- /dev/null
+++ b/gas/testsuite/gas/csky/jsriv2_3.d
@@ -0,0 +1,9 @@ 
+# name: jsriv2_3 - csky
+#as: -mcpu=ck807
+#readelf: -r --wide
+
+
+Relocation section '.rela.text\' at offset .* contains 1 entry:
+#...
+00000008.*R_CKCORE_ADDR32[ \t]+00000000[ \t]+\.text \+[ \t]+[0-9a-f]+
+#pass
diff --git a/gas/testsuite/gas/csky/jsriv2_3.s b/gas/testsuite/gas/csky/jsriv2_3.s
new file mode 100644
index 0000000..45ce734
--- /dev/null
+++ b/gas/testsuite/gas/csky/jsriv2_3.s
@@ -0,0 +1,5 @@ 
+.text
+
+LABEL:
+bkpt
+jsri LABEL
diff --git a/gas/testsuite/gas/csky/jsriv2_4.d b/gas/testsuite/gas/csky/jsriv2_4.d
new file mode 100644
index 0000000..851ef6a
--- /dev/null
+++ b/gas/testsuite/gas/csky/jsriv2_4.d
@@ -0,0 +1,9 @@ 
+# name: jsriv2_4 - csky
+#as: -mcpu=ck810
+#readelf: -r --wide
+
+
+Relocation section '.rela.text\' at offset .* contains 1 entry:
+#...
+0000000c.*R_CKCORE_ADDR32[ \t]+00000000[ \t]+\.text \+[ \t]+[0-9a-f]+
+#pass
diff --git a/gas/testsuite/gas/csky/jsriv2_4.s b/gas/testsuite/gas/csky/jsriv2_4.s
new file mode 100644
index 0000000..45ce734
--- /dev/null
+++ b/gas/testsuite/gas/csky/jsriv2_4.s
@@ -0,0 +1,5 @@ 
+.text
+
+LABEL:
+bkpt
+jsri LABEL
diff --git a/gas/testsuite/gas/csky/trust.d b/gas/testsuite/gas/csky/trust.d
new file mode 100644
index 0000000..1a87b4d
--- /dev/null
+++ b/gas/testsuite/gas/csky/trust.d
@@ -0,0 +1,17 @@ 
+# name: trust - csky
+#as: -mcpu=ck810t
+#objdump: -d
+
+.*: +file format .*csky.*
+
+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*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
new file mode 100644
index 0000000..781dc8c
--- /dev/null
+++ b/gas/testsuite/gas/csky/trust.s
@@ -0,0 +1,9 @@ 
+TRUST:
+     wsc
+     mfcr r4, psr
+     mfcr r4, rid
+     mtcr r4, gcr
+     mtcr r4, sedcr
+     mfcr r4, sepcr
+     psrset sie
+     psrclr sie
diff --git a/gas/testsuite/gas/csky/v1_float.d b/gas/testsuite/gas/csky/v1_float.d
new file mode 100644
index 0000000..995a77d
--- /dev/null
+++ b/gas/testsuite/gas/csky/v1_float.d
@@ -0,0 +1,222 @@ 
+# name: csky - v1-float
+#as: -mcpu=ck610ef -W
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe06002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe06402.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffec1002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffec9002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffed9002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffee1002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffed1002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffee9002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffef1002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffef9002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+#...
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe04403.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe04c03.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe05403.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe05c03.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe38c02.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe48c02.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe58c02.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe68c02.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe78c02.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe88c02.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe98c02.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffea8c02.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffeb8c02.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe04002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe04802.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe05002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe05802.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe31002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe41002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe51002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe61002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe71002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe81002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe91002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffea1002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffeb1002.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+#...
+\s*[0-9a-f]*:\s*744a\s*lrw\s*r4,\s*0xffe00840.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7449\s*lrw\s*r4,\s*0xffe00c40.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7449\s*lrw\s*r4,\s*0xffe01040.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7448\s*lrw\s*r4,\s*0xffe01440.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7448\s*lrw\s*r4,\s*0xffe01841.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7447\s*lrw\s*r4,\s*0xffe01c41.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7447\s*lrw\s*r4,\s*0xffe02041.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7446\s*lrw\s*r4,\s*0xffe02441.*
+\s*[0-9a-f]*:\s*3204\s*cpwir\s*r4
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7346\s*lrw\s*r3,\s*0xffe00400.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7345\s*lrw\s*r3,\s*0xffe00480.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7345\s*lrw\s*r3,\s*0xffe00500.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7344\s*lrw\s*r3,\s*0xffe00580.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7344\s*lrw\s*r3,\s*0xffe00600.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7343\s*lrw\s*r3,\s*0xffe00680.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7343\s*lrw\s*r3,\s*0xffe00700.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*000d\s*cprc
+\s*[0-9a-f]*:\s*7342\s*lrw\s*r3,\s*0xffe00780.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*000d\s*cprc
+#...
+\s*[0-9a-f]*:\s*7242\s*lrw\s*r2,\s*0xffe02801.*
+\s*[0-9a-f]*:\s*3202\s*cpwir\s*r2
+\s*[0-9a-f]*:\s*7242\s*lrw\s*r2,\s*0xffe02c02.*
+\s*[0-9a-f]*:\s*3202\s*cpwir\s*r2
+\s*[0-9a-f]*:\s*7242\s*lrw\s*r2,\s*0xffe03402.*
+\s*[0-9a-f]*:\s*3202\s*cpwir\s*r2
+\s*[0-9a-f]*:\s*7242\s*lrw\s*r2,\s*0xffe03002.*
+\s*[0-9a-f]*:\s*3202\s*cpwir\s*r2
+\s*[0-9a-f]*:\s*7242\s*lrw\s*r2,\s*0xffe03c02.*
+\s*[0-9a-f]*:\s*3202\s*cpwir\s*r2
+\s*[0-9a-f]*:\s*7242\s*lrw\s*r2,\s*0xffe03802.*
+\s*[0-9a-f]*:\s*3202\s*cpwir\s*r2
+\s*[0-9a-f]*:\s*7342\s*lrw\s*r3,\s*0xffe10002.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*7342\s*lrw\s*r3,\s*0xffe08002.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*7342\s*lrw\s*r3,\s*0xffe20002.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+\s*[0-9a-f]*:\s*7342\s*lrw\s*r3,\s*0xffe18002.*
+\s*[0-9a-f]*:\s*3203\s*cpwir\s*r3
+#...
+\s*[0-9a-f]*:\s*2642\s*cpwgr\s*r2,\s*cpr4
+\s*[0-9a-f]*:\s*0842\s*cprgr\s*r2,\s*cpr4
+\s*[0-9a-f]*:\s*2642\s*cpwgr\s*r2,\s*cpr4
+\s*[0-9a-f]*:\s*2653\s*cpwgr\s*r3,\s*cpr5
+\s*[0-9a-f]*:\s*0842\s*cprgr\s*r2,\s*cpr4
+\s*[0-9a-f]*:\s*0853\s*cprgr\s*r3,\s*cpr5
+\s*[0-9a-f]*:\s*f7ff\s*br\s*0x124.*
+\s*[0-9a-f]*:\s*f7ff\s*br\s*0x126.*
+\s*[0-9a-f]*:\s*ffe06002\s*\.long\s*0xffe06002
+\s*[0-9a-f]*:\s*ffe06402\s*\.long\s*0xffe06402
+\s*[0-9a-f]*:\s*ffec1002\s*\.long\s*0xffec1002
+\s*[0-9a-f]*:\s*ffec9002\s*\.long\s*0xffec9002
+\s*[0-9a-f]*:\s*ffed9002\s*\.long\s*0xffed9002
+\s*[0-9a-f]*:\s*ffee1002\s*\.long\s*0xffee1002
+\s*[0-9a-f]*:\s*ffed1002\s*\.long\s*0xffed1002
+\s*[0-9a-f]*:\s*ffee9002\s*\.long\s*0xffee9002
+\s*[0-9a-f]*:\s*ffef1002\s*\.long\s*0xffef1002
+\s*[0-9a-f]*:\s*ffef9002\s*\.long\s*0xffef9002
+\s*[0-9a-f]*:\s*ffe04403\s*\.long\s*0xffe04403
+\s*[0-9a-f]*:\s*ffe04c03\s*\.long\s*0xffe04c03
+\s*[0-9a-f]*:\s*ffe05403\s*\.long\s*0xffe05403
+\s*[0-9a-f]*:\s*ffe05c03\s*\.long\s*0xffe05c03
+\s*[0-9a-f]*:\s*ffe38c02\s*\.long\s*0xffe38c02
+\s*[0-9a-f]*:\s*ffe48c02\s*\.long\s*0xffe48c02
+\s*[0-9a-f]*:\s*ffe58c02\s*\.long\s*0xffe58c02
+\s*[0-9a-f]*:\s*ffe68c02\s*\.long\s*0xffe68c02
+\s*[0-9a-f]*:\s*ffe78c02\s*\.long\s*0xffe78c02
+\s*[0-9a-f]*:\s*ffe88c02\s*\.long\s*0xffe88c02
+\s*[0-9a-f]*:\s*ffe98c02\s*\.long\s*0xffe98c02
+\s*[0-9a-f]*:\s*ffea8c02\s*\.long\s*0xffea8c02
+\s*[0-9a-f]*:\s*ffeb8c02\s*\.long\s*0xffeb8c02
+\s*[0-9a-f]*:\s*ffe04002\s*\.long\s*0xffe04002
+\s*[0-9a-f]*:\s*ffe04802\s*\.long\s*0xffe04802
+\s*[0-9a-f]*:\s*ffe05002\s*\.long\s*0xffe05002
+\s*[0-9a-f]*:\s*ffe05802\s*\.long\s*0xffe05802
+\s*[0-9a-f]*:\s*ffe31002\s*\.long\s*0xffe31002
+\s*[0-9a-f]*:\s*ffe41002\s*\.long\s*0xffe41002
+\s*[0-9a-f]*:\s*ffe51002\s*\.long\s*0xffe51002
+\s*[0-9a-f]*:\s*ffe61002\s*\.long\s*0xffe61002
+\s*[0-9a-f]*:\s*ffe71002\s*\.long\s*0xffe71002
+\s*[0-9a-f]*:\s*ffe81002\s*\.long\s*0xffe81002
+\s*[0-9a-f]*:\s*ffe91002\s*\.long\s*0xffe91002
+\s*[0-9a-f]*:\s*ffea1002\s*\.long\s*0xffea1002
+\s*[0-9a-f]*:\s*ffeb1002\s*\.long\s*0xffeb1002
+\s*[0-9a-f]*:\s*ffe00840\s*\.long\s*0xffe00840
+\s*[0-9a-f]*:\s*ffe00c40\s*\.long\s*0xffe00c40
+\s*[0-9a-f]*:\s*ffe01040\s*\.long\s*0xffe01040
+\s*[0-9a-f]*:\s*ffe01440\s*\.long\s*0xffe01440
+\s*[0-9a-f]*:\s*ffe01841\s*\.long\s*0xffe01841
+\s*[0-9a-f]*:\s*ffe01c41\s*\.long\s*0xffe01c41
+\s*[0-9a-f]*:\s*ffe02041\s*\.long\s*0xffe02041
+\s*[0-9a-f]*:\s*ffe02441\s*\.long\s*0xffe02441
+\s*[0-9a-f]*:\s*ffe00400\s*\.long\s*0xffe00400
+\s*[0-9a-f]*:\s*ffe00480\s*\.long\s*0xffe00480
+\s*[0-9a-f]*:\s*ffe00500\s*\.long\s*0xffe00500
+\s*[0-9a-f]*:\s*ffe00580\s*\.long\s*0xffe00580
+\s*[0-9a-f]*:\s*ffe00600\s*\.long\s*0xffe00600
+\s*[0-9a-f]*:\s*ffe00680\s*\.long\s*0xffe00680
+\s*[0-9a-f]*:\s*ffe00700\s*\.long\s*0xffe00700
+\s*[0-9a-f]*:\s*ffe00780\s*\.long\s*0xffe00780
+\s*[0-9a-f]*:\s*ffe02801\s*\.long\s*0xffe02801
+\s*[0-9a-f]*:\s*ffe02c02\s*\.long\s*0xffe02c02
+\s*[0-9a-f]*:\s*ffe03402\s*\.long\s*0xffe03402
+\s*[0-9a-f]*:\s*ffe03002\s*\.long\s*0xffe03002
+\s*[0-9a-f]*:\s*ffe03c02\s*\.long\s*0xffe03c02
+\s*[0-9a-f]*:\s*ffe03802\s*\.long\s*0xffe03802
+\s*[0-9a-f]*:\s*ffe10002\s*\.long\s*0xffe10002
+\s*[0-9a-f]*:\s*ffe08002\s*\.long\s*0xffe08002
+\s*[0-9a-f]*:\s*ffe20002\s*\.long\s*0xffe20002
+\s*[0-9a-f]*:\s*ffe18002\s*\.long\s*0xffe18002
diff --git a/gas/testsuite/gas/csky/v1_float.s b/gas/testsuite/gas/csky/v1_float.s
new file mode 100644
index 0000000..14aa6ea
--- /dev/null
+++ b/gas/testsuite/gas/csky/v1_float.s
@@ -0,0 +1,80 @@ 
+.text
+
+L0:
+    fabsm    fr0, fr2, r4
+    fnegm    fr0, fr2, r4
+    faddm   fr0, fr2, fr4, r4
+    fsubm   fr0, fr2, fr4, r4
+    fmacm   fr0, fr2, fr4, r4
+    fmscm   fr0, fr2, fr4, r4
+    fmulm   fr0, fr2, fr4, r4
+    fnmacm   fr0, fr2, fr4, r4
+    fnmscm   fr0, fr2, fr4, r4
+    fnmulm   fr0, fr2, fr4, r4
+
+L1:
+    fabss   fr0, fr3, r4
+    fnegs   fr0, fr3, r4
+    fsqrts  fr0, fr3, r4
+    frecips  fr0, fr3, r4
+    fadds   fr0, fr2, fr3, r4
+    fsubs   fr0, fr2, fr3, r4
+    fmacs   fr0, fr2, fr3, r4
+    fmscs   fr0, fr2, fr3, r4
+    fmuls   fr0, fr2, fr3, r4
+    fdivs   fr0, fr2, fr3, r4
+    fnmacs   fr0, fr2, fr3, r4
+    fnmscs   fr0, fr2, fr3, r4
+    fnmuls   fr0, fr2, fr3, r4
+
+    fabsd   fr0, fr2, r4
+    fnegd   fr0, fr2, r4
+    fsqrtd  fr0, fr2, r4
+    frecipd  fr0, fr2, r4
+    faddd   fr0, fr2, fr4, r4
+    fsubd   fr0, fr2, fr4, r4
+    fmacd   fr0, fr2, fr4, r4
+    fmscd   fr0, fr2, fr4, r4
+    fmuld   fr0, fr2, fr4, r4
+    fdivd   fr0, fr2, fr4, r4
+    fnmacd   fr0, fr2, fr4, r4
+    fnmscd   fr0, fr2, fr4, r4
+    fnmuld   fr0, fr2, fr4, r4
+
+L2:
+    fcmphsd fr0, fr2, r4
+    fcmpltd fr0, fr2, r4
+    fcmpned fr0, fr2, r4
+    fcmpuod fr0, fr2, r4
+    fcmphss fr1, fr2, r4
+    fcmplts fr1, fr2, r4
+    fcmpnes fr1, fr2, r4
+    fcmpuos fr1, fr2, r4
+    fcmpzhsd fr0, r3
+    fcmpzltd fr0, r3
+    fcmpzned fr0, r3
+    fcmpzuod fr0, r3
+    fcmpzhss fr0, r3
+    fcmpzlts fr0, r3
+    fcmpznes fr0, r3
+    fcmpzuos fr0, r3
+
+L3:
+    fstod    fr0, fr1, r2
+    fdtos    fr0, fr2, r2
+    fsitos   fr0, fr2, r2
+    fsitod   fr0, fr2, r2
+    fuitos   fr0, fr2, r2
+    fuitod   fr0, fr2, r2
+    fstosi   fr0, fr2, RM_NEAREST, r3
+    fdtosi   fr0, fr2, RM_NEAREST, r3
+    fstoui   fr0, fr2, RM_NEAREST, r3
+    fdtoui   fr0, fr2, RM_NEAREST, r3
+
+L4:
+    fmts     r2, fr4
+    fmfs     r2, fr4
+    fmtd     r2, fr4
+    fmfd     r2, fr4
+
+
diff --git a/gas/testsuite/gas/csky/v2_float_part1.d b/gas/testsuite/gas/csky/v2_float_part1.d
new file mode 100644
index 0000000..aa0b0a4
--- /dev/null
+++ b/gas/testsuite/gas/csky/v2_float_part1.d
@@ -0,0 +1,54 @@ 
+# name: csky - v2-float
+#as: -mcpu=ck810ef -W
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*f4243403\s*fstms\s*fr3-fr4,\s*\(r4\)
+\s*[0-9a-f]*:\s*f4243003\s*fldms\s*fr3-fr4,\s*\(r4\)
+\s*[0-9a-f]*:\s*f4243603\s*fstmm\s*fr3-fr4,\s*\(r4\)
+\s*[0-9a-f]*:\s*f4243203\s*fldmm\s*fr3-fr4,\s*\(r4\)
+\s*[0-9a-f]*:\s*f4243503\s*fstmd\s*fr3-fr4,\s*\(r4\)
+\s*[0-9a-f]*:\s*f4243103\s*fldmd\s*fr3-fr4,\s*\(r4\)
+\s*[0-9a-f]*:\s*f4022600\s*fstm\s*fr0,\s*\(r2,\s*0x0\)
+\s*[0-9a-f]*:\s*f4022200\s*fldm\s*fr0,\s*\(r2,\s*0x0\)
+\s*[0-9a-f]*:\s*f4022610\s*fstm\s*fr0,\s*\(r2,\s*0x8\)
+\s*[0-9a-f]*:\s*f4022210\s*fldm\s*fr0,\s*\(r2,\s*0x8\)
+\s*[0-9a-f]*:\s*f4022510\s*fstd\s*fr0,\s*\(r2,\s*0x4\)
+\s*[0-9a-f]*:\s*f4022110\s*fldd\s*fr0,\s*\(r2,\s*0x4\)
+\s*[0-9a-f]*:\s*f4022410\s*fsts\s*fr0,\s*\(r2,\s*0x4\)
+\s*[0-9a-f]*:\s*f4022010\s*flds\s*fr0,\s*\(r2,\s*0x4\)
+\s*[0-9a-f]*:\s*f4822e02\s*fstrm\s*fr2,\s*\(r2,\s*r4\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f4822e42\s*fstrm\s*fr2,\s*\(r2,\s*r4\s*<<\s*2\)
+\s*[0-9a-f]*:\s*f4822d02\s*fstrd\s*fr2,\s*\(r2,\s*r4\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f4822d42\s*fstrd\s*fr2,\s*\(r2,\s*r4\s*<<\s*2\)
+\s*[0-9a-f]*:\s*f4822c02\s*fstrs\s*fr2,\s*\(r2,\s*r4\s*<<\s*0\)
+\s*[0-9a-f]*:\s*f4822c42\s*fstrs\s*fr2,\s*\(r2,\s*r4\s*<<\s*2\)
+\s*[0-9a-f]*:\s*f4831222\s*fnmulm\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f48312e2\s*fnmscm\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f48312c2\s*fnmacm\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f48312a2\s*fmscm\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4831282\s*fmacm\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4831202\s*fmulm\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4831022\s*fsubm\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4831002\s*faddm\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830a22\s*fnmuld\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830ae2\s*fnmscd\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830ac2\s*fnmacd\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830aa2\s*fmscd\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830a82\s*fmacd\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830b02\s*fdivd\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830a02\s*fmuld\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830822\s*fsubd\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830802\s*faddd\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830222\s*fnmuls\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f48302e2\s*fnmscs\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f48302c2\s*fnmacs\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f48302a2\s*fmscs\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830282\s*fmacs\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830302\s*fdivs\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830202\s*fmuls\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830022\s*fsubs\s*fr2,\s*fr3,\s*fr4
+\s*[0-9a-f]*:\s*f4830002\s*fadds\s*fr2,\s*fr3,\s*fr4
diff --git a/gas/testsuite/gas/csky/v2_float_part1.s b/gas/testsuite/gas/csky/v2_float_part1.s
new file mode 100644
index 0000000..826b32d
--- /dev/null
+++ b/gas/testsuite/gas/csky/v2_float_part1.s
@@ -0,0 +1,48 @@ 
+   .text
+L1:
+   fstms vr3-vr4, (r4)
+   fldms vr3-vr4, (r4)
+   fstmm vr3-vr4, (r4)
+   fldmm vr3-vr4, (r4)
+   fstmd vr3-vr4, (r4)
+   fldmd vr3-vr4, (r4)
+   fstm  vr0, (r2, 0)
+   fldm  vr0, (r2, 0)
+   fstm  vr0, (r2, 8)
+   fldm  vr0, (r2, 8)
+   fstd  vr0, (r2, 4)
+   fldd  vr0, (r2, 4)
+   fsts  vr0, (r2, 4)
+   flds  vr0, (r2, 4)
+   fstrm vr2, (r2, r4 << 0)
+   fstrm vr2, (r2, r4 << 2)
+   fstrd vr2, (r2, r4 << 0)
+   fstrd vr2, (r2, r4 << 2)
+   fstrs vr2, (r2, r4 << 0)
+   fstrs vr2, (r2, r4 << 2)
+   fnmulm   vr2, vr3, vr4
+   fnmscm   vr2, vr3, vr4
+   fnmacm   vr2, vr3, vr4
+   fmscm    vr2, vr3, vr4
+   fmacm    vr2, vr3, vr4
+   fmulm    vr2, vr3, vr4
+   fsubm    vr2, vr3, vr4
+   faddm    vr2, vr3, vr4
+   fnmuld   vr2, vr3, vr4
+   fnmscd   vr2, vr3, vr4
+   fnmacd   vr2, vr3, vr4
+   fmscd    vr2, vr3, vr4
+   fmacd    vr2, vr3, vr4
+   fdivd    vr2, vr3, vr4
+   fmuld    vr2, vr3, vr4
+   fsubd    vr2, vr3, vr4
+   faddd    vr2, vr3, vr4
+   fnmuls   vr2, vr3, vr4
+   fnmscs   vr2, vr3, vr4
+   fnmacs   vr2, vr3, vr4
+   fmscs    vr2, vr3, vr4
+   fmacs    vr2, vr3, vr4
+   fdivs    vr2, vr3, vr4
+   fmuls    vr2, vr3, vr4
+   fsubs    vr2, vr3, vr4
+   fadds    vr2, vr3, vr4
diff --git a/gas/testsuite/gas/csky/v2_float_part2.d b/gas/testsuite/gas/csky/v2_float_part2.d
new file mode 100644
index 0000000..94b04e0
--- /dev/null
+++ b/gas/testsuite/gas/csky/v2_float_part2.d
@@ -0,0 +1,20 @@ 
+# name: csky - v2-float-part2
+#as: -mcpu=ck807f -W
+#objdump: -D
+
+.*: +file format .*csky.*
+
+Disassembly of section \.text:
+#...
+\s*[0-9a-f]*:\s*f4003882\s*flrws\s*fr2,\s*3\.140000
+\s*[0-9a-f]*:\s*f50b1c02\s*fmovis\s*fr2,\s*1\.500000
+\s*[0-9a-f]*:\s*f51b1c02\s*fmovis\s*fr2,\s*-1\.500000
+\s*[0-9a-f]*:\s*f48a1c02\s*fmovis\s*fr2,\s*2\.500000
+#...
+\s*[0-9a-f]*:\s*f4003952\s*flrwd\s*fr2,\s*3\.140000
+\s*[0-9a-f]*:\s*f48a1e02\s*fmovid\s*fr2,\s*2\.500000
+\s*[0-9a-f]*:\s*f49a1e02\s*fmovid\s*fr2,\s*-2\.500000
+\s*[0-9a-f]*:\s*f51b1e02\s*fmovid\s*fr2,\s*-1\.500000
+\s*[0-9a-f]*:\s*4048f5c3\s*\.long\s*0x4048f5c3
+\s*[0-9a-f]*:\s*51eb851f\s*\.long\s*0x51eb851f
+\s*[0-9a-f]*:\s*40091eb8\s*\.long\s*0x40091eb8
diff --git a/gas/testsuite/gas/csky/v2_float_part2.s b/gas/testsuite/gas/csky/v2_float_part2.s
new file mode 100644
index 0000000..92c253b
--- /dev/null
+++ b/gas/testsuite/gas/csky/v2_float_part2.s
@@ -0,0 +1,10 @@ 
+only_in_803_807:
+   flrws    fr2, 3.14
+   fmovis   fr2, 1.5
+   fmovis   fr2, -1.5
+   fmovis   fr2, 2.5
+only_in_807:
+   flrwd    fr2, 3.14
+   fmovid   fr2, 2.5
+   fmovid   fr2, -2.5
+   fmovid   fr2, -1.5