Patchwork [2/6] Andes nds32: machine description of nds32 porting (3).

login
register
mail settings
Submitter Chung-Ju Wu
Date July 24, 2013, 3:52 p.m.
Message ID <51EFF82C.5050501@gmail.com>
Download mbox | patch
Permalink /patch/261441/
State New
Headers show

Comments

Chung-Ju Wu - July 24, 2013, 3:52 p.m.
Hi, Joseph,

Sorry for the late revised patch.
We have completed all of it based on your review comments.

On 7/10/13 7:53 AM, Joseph S. Myers wrote:
> The nds32_intrinsic.h header, being installed for users to use, should
> have the libgcc license exception.
>

Thanks for the comments.
We added GPLv3+exception in nds32_intrinsic.h header.

> You shouldn't need the separate t-mlibs-* files for each default
> endianness.  Just list both options in MULTILIB_OPTIONS, then define
> MULTILIB_DEFAULTS appropriately depending on the default endianness.
>

Thanks for the suggestion.
In the config.gcc, we used tm_defines for default endianness
so that we can define proper MULTILIB_DEFAULTS setting in nds32.h.
Now we can have only one t-mlibs used.


A revised patch is provided and here is a summary:

   1. Add GPLv3+exception copyright and license notice in nds32_intrinsic.h.
   2. Using only one t-mlibs is enough.
   3. Remove nds32-isa-v2.h, nds32-isa-v3.h, and nds32-isa-v3m.h.
   4. Add nds32-opts.h included by nds32.opt.


gcc/
2013-07-24  Chung-Ju Wu  <jasonwucj@gmail.com>
	    Shiva Chen  <shiva0217@gmail.com>

	* config/nds32/constants.md: New file.
	* config/nds32/constraints.md: New file.
	* config/nds32/iterators.md: New file.
	* config/nds32/nds32.doubleword.md: New file.
	* config/nds32/nds32.intrinsic.md: New file.
	* config/nds32/nds32_intrinsic.h: New file.
	* config/nds32/nds32-modes.def: New file.
	* config/nds32/nds32.multiple.md: New file.
	* config/nds32/nds32.opt: New file.
	* config/nds32/nds32-opts.h: New file.
	* config/nds32/nds32-protos.h: New file.
	* config/nds32/nds32.peephole2.md: New file.
	* config/nds32/pipelines.md: New file.
	* config/nds32/predicates.md: New file.
	* config/nds32/t-mlibs: New file.


Best regards,
jasonwucj

Patch

diff --git gcc/config/nds32/constants.md gcc/config/nds32/constants.md
new file mode 100644
index 0000000..af51117
--- /dev/null
+++ gcc/config/nds32/constants.md
@@ -0,0 +1,55 @@ 
+;; Constant defintions of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC 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.
+;;
+;; GCC 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 GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; Register numbers.
+(define_constants
+  [(R8_REGNUM  8)
+   (TA_REGNUM 15)
+   (FP_REGNUM 28)
+   (GP_REGNUM 29)
+   (LP_REGNUM 30)
+   (SP_REGNUM 31)
+  ])
+
+
+;; The unpec operation index.
+(define_c_enum "unspec_element" [
+  UNSPEC_STACK_PUSH_MULTIPLE
+  UNSPEC_STACK_POP_MULTIPLE
+  UNSPEC_STACK_V3PUSH
+  UNSPEC_STACK_V3POP
+  UNSPEC_FUNC_RETURN
+])
+
+
+;; The unspec_volatile operation index.
+(define_c_enum "unspec_volatile_element" [
+  UNSPEC_VOLATILE_ISYNC
+  UNSPEC_VOLATILE_ISB
+  UNSPEC_VOLATILE_MFSR
+  UNSPEC_VOLATILE_MFUSR
+  UNSPEC_VOLATILE_MTSR
+  UNSPEC_VOLATILE_MTUSR
+  UNSPEC_VOLATILE_SETGIE_EN
+  UNSPEC_VOLATILE_SETGIE_DIS
+])
+
+;; ------------------------------------------------------------------------
diff --git gcc/config/nds32/constraints.md gcc/config/nds32/constraints.md
new file mode 100644
index 0000000..40af0ca
--- /dev/null
+++ gcc/config/nds32/constraints.md
@@ -0,0 +1,248 @@ 
+;; Constraint definitions of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC 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.
+;;
+;; GCC 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 GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+;; Check 16.8.7 Defining Machine-Specific Constraints for detail.
+
+;; NO contrains can be prefixed with: E F V X g i m n o p r s
+;; Machine-dependent integer: I J K L M N O P
+;; Machine-dependent floating: G H
+
+
+(define_register_constraint "w" "(TARGET_ISA_V3 || TARGET_ISA_V3M) ? LOW_REGS : NO_REGS"
+  "LOW register class $r0 ~ $r7 constraint for V3 ISA")
+
+(define_register_constraint "l" "LOW_REGS"
+  "LOW register class $r0 ~ $r7")
+
+(define_register_constraint "d" "MIDDLE_REGS"
+  "MIDDLE register class $r0 ~ $r11, $r16 ~ $r19")
+
+(define_register_constraint "h" "HIGH_REGS"
+  "HIGH register class $r12 ~ $r14, $r20 ~ $r31")
+
+
+(define_register_constraint "t" "R15_TA_REG"
+  "Temporary Assist register $ta (i.e. $r15)")
+
+(define_register_constraint "k" "STACK_REG"
+  "Stack register $sp")
+
+
+(define_constraint "Iu03"
+  "Unsigned immediate 3-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 3) && ival >= 0")))
+
+(define_constraint "Iu04"
+  "Unsigned immediate 4-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 4) && ival >= 0")))
+
+(define_constraint "Is05"
+  "Signed immediate 5-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 4) && ival >= -(1 << 4)")))
+
+(define_constraint "Iu05"
+  "Unsigned immediate 5-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 5) && ival >= 0")))
+
+;; Ip05 is special and dedicated for v3 movpi45 instruction.
+;; movpi45 has imm5u field but the range is 16 ~ 47.
+(define_constraint "Ip05"
+  "Unsigned immediate 5-bit value for movpi45 instruction with range 16-47"
+  (and (match_code "const_int")
+       (match_test "ival < ((1 << 5) + 16)
+		    && ival >= (0 + 16)
+		    && (TARGET_ISA_V3 || TARGET_ISA_V3M)")))
+
+(define_constraint "Iu06"
+  "Unsigned immediate 6-bit value constraint for addri36.sp instruction"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 6)
+		    && ival >= 0
+		    && (ival % 4 == 0)
+		    && (TARGET_ISA_V3 || TARGET_ISA_V3M)")))
+
+(define_constraint "Iu08"
+  "Unsigned immediate 8-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 8) && ival >= 0")))
+
+(define_constraint "Iu09"
+  "Unsigned immediate 9-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 9) && ival >= 0")))
+
+
+(define_constraint "Is10"
+  "Signed immediate 10-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 9) && ival >= -(1 << 9)")))
+
+(define_constraint "Is11"
+  "Signed immediate 11-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 10) && ival >= -(1 << 10)")))
+
+
+(define_constraint "Is15"
+  "Signed immediate 15-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 14) && ival >= -(1 << 14)")))
+
+(define_constraint "Iu15"
+  "Unsigned immediate 15-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 15) && ival >= 0")))
+
+
+;; Ic15 is special and dedicated for performance extension
+;; 'bclr' (single-bit-clear) instruction.
+;; It is used in andsi3 pattern and recognized for the immediate
+;; which is NOT in the range of imm15u but OK for 'bclr' instruction.
+;; (If the immediate value IS in the range of imm15u,
+;;  we can directly use 'andi' instruction.)
+(define_constraint "Ic15"
+  "A constant which is not in the range of imm15u but ok for bclr instruction"
+  (and (match_code "const_int")
+       (match_test "(ival & 0xffff8000) && nds32_can_use_bclr_p (ival)")))
+
+;; Ie15 is special and dedicated for performance extension
+;; 'bset' (single-bit-set) instruction.
+;; It is used in iorsi3 pattern and recognized for the immediate
+;; which is NOT in the range of imm15u but OK for 'bset' instruction.
+;; (If the immediate value IS in the range of imm15u,
+;;  we can directly use 'ori' instruction.)
+(define_constraint "Ie15"
+  "A constant which is not in the range of imm15u but ok for bset instruction"
+  (and (match_code "const_int")
+       (match_test "(ival & 0xffff8000) && nds32_can_use_bset_p (ival)")))
+
+;; It15 is special and dedicated for performance extension
+;; 'btgl' (single-bit-toggle) instruction.
+;; It is used in xorsi3 pattern and recognized for the immediate
+;; which is NOT in the range of imm15u but OK for 'btgl' instruction.
+;; (If the immediate value IS in the range of imm15u,
+;;  we can directly use 'xori' instruction.)
+(define_constraint "It15"
+  "A constant which is not in the range of imm15u but ok for btgl instruction"
+  (and (match_code "const_int")
+       (match_test "(ival & 0xffff8000) && nds32_can_use_btgl_p (ival)")))
+
+
+;; Ii15 is special and dedicated for v3 isa
+;; 'bitci' (bit-clear-immediate) instruction.
+;; It is used in andsi3 pattern and recognized for the immediate whose
+;; (~ival) value is in the range of imm15u and OK for 'bitci' instruction.
+;; For example, 'andi $r0,$r0,0xfffffffc' can be presented
+;  with 'bitci $r0,$r0,3'.
+(define_constraint "Ii15"
+  "A constant whose compliment value is in the range of imm15u
+   and ok for bitci instruction"
+  (and (match_code "const_int")
+       (match_test "nds32_can_use_bitci_p (ival)")))
+
+
+(define_constraint "Is16"
+  "Signed immediate 16-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 15) && ival >= -(1 << 15)")))
+
+(define_constraint "Is17"
+  "Signed immediate 17-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 16) && ival >= -(1 << 16)")))
+
+
+(define_constraint "Is19"
+  "Signed immediate 19-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 18) && ival >= -(1 << 18)")))
+
+
+(define_constraint "Is20"
+  "Signed immediate 20-bit value"
+  (and (match_code "const_int")
+       (match_test "ival < (1 << 19) && ival >= -(1 << 19)")))
+
+
+(define_constraint "Ispl"
+  "The immediate value that need to be split"
+  (and (match_code "const_int")
+       (match_test "(ival & 0xfff) != 0")))
+
+(define_constraint "Ihig"
+  "The immediate value that can be simply set high 20-bit"
+  (and (match_code "const_int")
+       (match_test "(ival != 0) && ((ival & 0xfff) == 0)")))
+
+
+(define_constraint "Izeb"
+  "The immediate value 0xff"
+  (and (match_code "const_int")
+       (match_test "(ival == 0xff)")))
+
+(define_constraint "Ixls"
+  "The immediate value 0x01"
+  (and (match_code "const_int")
+       (match_test "TARGET_PERF_EXT && (ival == 0x1)")))
+
+(define_constraint "Ix11"
+  "The immediate value 0x7ff"
+  (and (match_code "const_int")
+       (match_test "TARGET_PERF_EXT && (ival == 0x7ff)")))
+
+(define_constraint "Ibms"
+  "The immediate value with power of 2"
+  (and (match_code "const_int")
+       (match_test "(TARGET_ISA_V3 || TARGET_ISA_V3M)
+		    && (floor_log2 (ival) < 8)
+		    && (ival > 0)
+		    && (ival == (1 << floor_log2 (ival)))")))
+
+(define_constraint "Ifex"
+  "The immediate value with power of 2 minus 1"
+  (and (match_code "const_int")
+       (match_test "(TARGET_ISA_V3 || TARGET_ISA_V3M)
+		    && (ival < 256)
+		    && (ival > 0)
+		    && (floor_log2 (ival + 1) - 1 < 8)
+		    && ((ival + 1) == (1 << floor_log2 (ival + 1)))")))
+
+
+(define_memory_constraint "U33"
+  "Memory constraint for 333 format"
+  (and (match_code "mem")
+       (match_test "nds32_mem_format (op) == ADDRESS_LO_REG_IMM3U")))
+
+(define_memory_constraint "U45"
+  "Memory constraint for 45 format"
+  (and (match_code "mem")
+       (match_test "nds32_mem_format (op) == ADDRESS_REG")))
+
+(define_memory_constraint "U37"
+  "Memory constraint for 37 format"
+  (and (match_code "mem")
+       (match_test "nds32_mem_format (op) == ADDRESS_SP_IMM7U
+		    || nds32_mem_format (op) == ADDRESS_FP_IMM7U")))
+
+;; ------------------------------------------------------------------------
diff --git gcc/config/nds32/iterators.md gcc/config/nds32/iterators.md
new file mode 100644
index 0000000..6ec5196
--- /dev/null
+++ gcc/config/nds32/iterators.md
@@ -0,0 +1,55 @@ 
+;; Code and mode itertator and attribute definitions
+;; of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC 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.
+;;
+;; GCC 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 GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+;;----------------------------------------------------------------------------
+;; Mode iterators.
+;;----------------------------------------------------------------------------
+
+;; A list of integer modes that are up to one word long.
+(define_mode_iterator QIHISI [QI HI SI])
+
+;; A list of integer modes that are up to one half-word long.
+(define_mode_iterator QIHI [QI HI])
+
+;; A list of the modes that are up to double-word long.
+(define_mode_iterator DIDF [DI DF])
+
+
+;;----------------------------------------------------------------------------
+;; Mode attributes.
+;;----------------------------------------------------------------------------
+
+(define_mode_attr size [(QI "b") (HI "h") (SI "w")])
+
+(define_mode_attr byte [(QI "1") (HI "2") (SI "4")])
+
+
+;;----------------------------------------------------------------------------
+;; Code iterators.
+;;----------------------------------------------------------------------------
+
+
+;;----------------------------------------------------------------------------
+;; Code attributes.
+;;----------------------------------------------------------------------------
+
+
+;;----------------------------------------------------------------------------
diff --git gcc/config/nds32/nds32-modes.def gcc/config/nds32/nds32-modes.def
new file mode 100644
index 0000000..9d32ada
--- /dev/null
+++ gcc/config/nds32/nds32-modes.def
@@ -0,0 +1,21 @@ 
+/* Extra machine modes of Andes NDS32 cpu for GNU compiler
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Andes Technology Corporation.
+
+   This file is part of GCC.
+
+   GCC 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.
+
+   GCC 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 GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+/* So far, there is no need to define any modes for nds32 target.  */
diff --git gcc/config/nds32/nds32-opts.h gcc/config/nds32/nds32-opts.h
new file mode 100644
index 0000000..86d8b4f
--- /dev/null
+++ gcc/config/nds32/nds32-opts.h
@@ -0,0 +1,35 @@ 
+/* Definitions for option handling of Andes NDS32 cpu for GNU compiler
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Andes Technology Corporation.
+
+   This file is part of GCC.
+
+   GCC 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.
+
+   GCC 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 GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef nds32_OPTS_H
+#define nds32_OPTS_H
+
+#define NDS32_DEFAULT_CACHE_BLOCK_SIZE 16
+#define NDS32_DEFAULT_ISR_VECTOR_SIZE (TARGET_ISA_V3 ? 4 : 16)
+
+/* The various ANDES ISA.  */
+enum nds32_arch_type
+{
+  ARCH_V2,
+  ARCH_V3,
+  ARCH_V3M
+};
+
+#endif
diff --git gcc/config/nds32/nds32-protos.h gcc/config/nds32/nds32-protos.h
new file mode 100644
index 0000000..8e1e93e
--- /dev/null
+++ gcc/config/nds32/nds32-protos.h
@@ -0,0 +1,123 @@ 
+/* Prototypes for exported functions of Andes NDS32 cpu for GNU compiler
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Andes Technology Corporation.
+
+   This file is part of GCC.
+
+   GCC 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.
+
+   GCC 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 GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+
+/* ------------------------------------------------------------------------ */
+
+/* ======================================================================== */
+/* Defining Data Structures for Per-function Information.  */
+/* ======================================================================== */
+
+extern void nds32_init_expanders (void);
+
+/* ======================================================================== */
+/* Register Usage.  */
+/* ======================================================================== */
+
+/* How Values Fit in Registers.  */
+
+extern int nds32_hard_regno_nregs (int, enum machine_mode);
+extern int nds32_hard_regno_mode_ok (int, enum machine_mode);
+
+/* ======================================================================== */
+/* Register Classes.  */
+/* ======================================================================== */
+
+extern enum reg_class nds32_regno_reg_class (int);
+
+/* ======================================================================== */
+/* Stack Layout and Calling Conventions.  */
+/* ======================================================================== */
+
+/* Basic Stack Layout.  */
+
+extern rtx nds32_return_addr_rtx (int, rtx);
+
+/* Eliminating Frame Pointer and Arg Pointer.  */
+
+extern HOST_WIDE_INT nds32_initial_elimination_offset (unsigned int,
+						       unsigned int);
+
+/* Passing Arguments in Registers.  */
+
+extern void nds32_init_cumulative_args (CUMULATIVE_ARGS *,
+					tree, rtx, tree, int);
+
+/* Function Entry and Exit.  */
+
+extern void nds32_expand_prologue (void);
+extern void nds32_expand_epilogue (void);
+extern void nds32_expand_prologue_v3push (void);
+extern void nds32_expand_epilogue_v3pop (void);
+
+/* ------------------------------------------------------------------------ */
+
+/* ======================================================================== */
+/* Auxiliary External Functions Prototype.  */
+/* ======================================================================== */
+
+/* Auxiliary functions for auxiliary macros in nds32.h.  */
+
+extern bool nds32_ls_333_p (rtx, rtx, rtx, enum machine_mode);
+
+/* Auxiliary functions for expanding rtl used in nds32.multiple.md.  */
+
+extern rtx nds32_expand_load_multiple (int, int, rtx, rtx);
+extern rtx nds32_expand_store_multiple (int, int, rtx, rtx);
+extern int nds32_expand_movmemqi (rtx, rtx, rtx, rtx);
+
+/* Auxiliary functions for bit operation detection.  */
+
+extern int nds32_can_use_bclr_p (int);
+extern int nds32_can_use_bset_p (int);
+extern int nds32_can_use_btgl_p (int);
+
+extern int nds32_can_use_bitci_p (int);
+
+/* Auxiliary function for 'Computing the Length of an Insn'.  */
+
+extern int nds32_adjust_insn_length (rtx, int);
+
+/* Auxiliary functions for FP_AS_GP detection.  */
+
+extern bool nds32_symbol_load_store_p (rtx);
+extern int nds32_fp_as_gp_check_available (void);
+
+/* Auxiliary functions for jump table generation.  */
+
+extern const char *nds32_output_casesi_pc_relative (rtx *);
+extern const char *nds32_output_casesi (rtx *);
+
+/* Auxiliary functions to identify 16 bit addresing mode.  */
+
+extern enum nds32_16bit_address_type nds32_mem_format (rtx);
+
+/* Auxiliary functions to output assembly code.  */
+
+extern const char *nds32_output_16bit_store (rtx *, int);
+extern const char *nds32_output_16bit_load (rtx *, int);
+extern const char *nds32_output_32bit_store (rtx *, int);
+extern const char *nds32_output_32bit_load (rtx *, int);
+
+/* Auxiliary functions to decide output alignment or not.  */
+
+extern int nds32_target_alignment (rtx);
+
+/* ------------------------------------------------------------------------ */
diff --git gcc/config/nds32/nds32.doubleword.md gcc/config/nds32/nds32.doubleword.md
new file mode 100644
index 0000000..c44ff36
--- /dev/null
+++ gcc/config/nds32/nds32.doubleword.md
@@ -0,0 +1,391 @@ 
+;; DImode/DFmode patterns description of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC 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.
+;;
+;; GCC 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 GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; -------------------------------------------------------------
+;; Move DImode/DFmode instructions.
+;; -------------------------------------------------------------
+
+
+(define_expand "movdi"
+  [(set (match_operand:DI 0 "general_operand" "")
+	(match_operand:DI 1 "general_operand" ""))]
+  ""
+{
+  /* Need to force register if mem <- !reg.  */
+  if (GET_CODE (operands[0]) == MEM && !REG_P (operands[1]))
+    operands[1] = force_reg (DImode, operands[1]);
+})
+
+(define_expand "movdf"
+  [(set (match_operand:DF 0 "general_operand" "")
+	(match_operand:DF 1 "general_operand" ""))]
+  ""
+{
+  /* Need to force register if mem <- !reg.  */
+  if (GET_CODE (operands[0]) == MEM && !REG_P (operands[1]))
+    operands[1] = force_reg (DFmode, operands[1]);
+})
+
+
+(define_insn "move_<mode>"
+  [(set (match_operand:DIDF 0 "nonimmediate_operand" "=r, r, r, m")
+	(match_operand:DIDF 1 "general_operand"      " r, i, m, r"))]
+  ""
+{
+  rtx addr;
+  rtx otherops[5];
+
+  switch (which_alternative)
+    {
+    case 0:
+      return "movd44\t%0, %1";
+
+    case 1:
+      /* reg <- const_int, we ask gcc to split instruction.  */
+      return "#";
+
+    case 2:
+      /* Refer to nds32_legitimate_address_p() in nds32.c,
+         we only allow "reg", "symbol_ref", "const", and "reg + const_int"
+         as address rtx for DImode/DFmode memory access.  */
+      addr = XEXP (operands[1], 0);
+
+      otherops[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
+      otherops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+      otherops[2] = addr;
+
+      if (REG_P (addr))
+	{
+	  /* (reg) <- (mem (reg)) */
+	  output_asm_insn ("lmw.bi\t%0, [%2], %1, 0", otherops);
+	}
+      else if (GET_CODE (addr) == PLUS)
+	{
+	  /* (reg) <- (mem (plus (reg) (const_int))) */
+	  rtx op0 = XEXP (addr, 0);
+	  rtx op1 = XEXP (addr, 1);
+
+	  if (REG_P (op0))
+	    {
+	      otherops[2] = op0;
+	      otherops[3] = op1;
+	      otherops[4] = gen_int_mode (INTVAL (op1) + 4, SImode);
+	    }
+	  else
+	    {
+	      otherops[2] = op1;
+	      otherops[3] = op0;
+	      otherops[4] = gen_int_mode (INTVAL (op0) + 4, SImode);
+	    }
+
+	  /* To avoid base overwrite when REGNO(%0) == REGNO(%2).  */
+	  if (REGNO (otherops[0]) != REGNO (otherops[2]))
+	    {
+	      output_asm_insn ("lwi\t%0, [%2 + (%3)]", otherops);
+	      output_asm_insn ("lwi\t%1, [%2 + (%4)]", otherops);
+	    }
+	  else
+	    {
+	      output_asm_insn ("lwi\t%1, [%2 + (%4)]", otherops);
+	      output_asm_insn ("lwi\t%0,[ %2 + (%3)]", otherops);
+	    }
+	}
+      else
+	{
+	  /* (reg) <- (mem (symbol_ref ...))
+	     (reg) <- (mem (const ...)) */
+	  output_asm_insn ("lwi.gp\t%0, [ + %2]", otherops);
+	  output_asm_insn ("lwi.gp\t%1, [ + %2 + 4]", otherops);
+	}
+
+      /* We have already used output_asm_insn() by ourself,
+         so return an empty string.  */
+      return "";
+
+    case 3:
+      /* Refer to nds32_legitimate_address_p() in nds32.c,
+         we only allow "reg", "symbol_ref", "const", and "reg + const_int"
+         as address rtx for DImode/DFmode memory access.  */
+      addr = XEXP (operands[0], 0);
+
+      otherops[0] = gen_rtx_REG (SImode, REGNO (operands[1]));
+      otherops[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
+      otherops[2] = addr;
+
+      if (REG_P (addr))
+	{
+	  /* (mem (reg)) <- (reg) */
+	  output_asm_insn ("smw.bi\t%0, [%2], %1, 0", otherops);
+	}
+      else if (GET_CODE (addr) == PLUS)
+	{
+	  /* (mem (plus (reg) (const_int))) <- (reg) */
+	  rtx op0 = XEXP (addr, 0);
+	  rtx op1 = XEXP (addr, 1);
+
+	  if (REG_P (op0))
+	    {
+	      otherops[2] = op0;
+	      otherops[3] = op1;
+	      otherops[4] = gen_int_mode (INTVAL (op1) + 4, SImode);
+	    }
+	  else
+	    {
+	      otherops[2] = op1;
+	      otherops[3] = op0;
+	      otherops[4] = gen_int_mode (INTVAL (op0) + 4, SImode);
+	    }
+
+	  /* To avoid base overwrite when REGNO(%0) == REGNO(%2).  */
+	  if (REGNO (otherops[0]) != REGNO (otherops[2]))
+	    {
+	      output_asm_insn ("swi\t%0, [%2 + (%3)]", otherops);
+	      output_asm_insn ("swi\t%1, [%2 + (%4)]", otherops);
+	    }
+	  else
+	    {
+	      output_asm_insn ("swi\t%1, [%2 + (%4)]", otherops);
+	      output_asm_insn ("swi\t%0, [%2 + (%3)]", otherops);
+	    }
+	}
+      else
+	{
+	  /* (mem (symbol_ref ...)) <- (reg)
+	     (mem (const ...))      <- (reg) */
+	  output_asm_insn ("swi.gp\t%0, [ + %2]", otherops);
+	  output_asm_insn ("swi.gp\t%1, [ + %2 + 4]", otherops);
+	}
+
+      /* We have already used output_asm_insn() by ourself,
+         so return an empty string.  */
+      return "";
+
+    default:
+      gcc_unreachable ();
+    }
+}
+  [(set_attr "type"   "move,move,move,move")
+   (set_attr "length" "   4,  16,   8,   8")])
+
+(define_split
+  [(set (match_operand:DIDF 0 "register_operand"     "")
+	(match_operand:DIDF 1 "const_double_operand" ""))]
+  "reload_completed"
+  [(set (match_dup 2) (match_dup 3))
+   (set (match_dup 4) (match_dup 5))]
+{
+  /* Construct lowpart rtx.  */
+  operands[2] = gen_lowpart (SImode, operands[0]);
+  operands[3] = gen_lowpart (SImode, operands[1]);
+
+  /* Construct highpart rtx.  */
+  /* Note that operands[1] can be VOIDmode constant,
+     so we need to use gen_highpart_mode().
+     Refer to gcc/emit-rtl.c for more information.  */
+  operands[4] = gen_highpart (SImode, operands[0]);
+  operands[5] = gen_highpart_mode (SImode,
+				   GET_MODE (operands[0]), operands[1]);
+})
+
+(define_split
+  [(set (match_operand:DIDF 0 "register_operand" "")
+	(match_operand:DIDF 1 "register_operand" ""))]
+  "reload_completed
+   && (TARGET_ISA_V2 || !TARGET_16_BIT)"
+  [(set (match_dup 0) (match_dup 1))
+   (set (match_dup 2) (match_dup 3))]
+{
+  operands[2] = gen_highpart (SImode, operands[0]);
+  operands[3] = gen_highpart (SImode, operands[1]);
+  operands[0] = gen_lowpart (SImode, operands[0]);
+  operands[1] = gen_lowpart (SImode, operands[1]);
+
+  /* Handle a partial overlap.  */
+  if (rtx_equal_p (operands[0], operands[3]))
+    {
+      rtx tmp0 = operands[0];
+      rtx tmp1 = operands[1];
+
+      operands[0] = operands[2];
+      operands[1] = operands[3];
+      operands[2] = tmp0;
+      operands[3] = tmp1;
+    }
+})
+
+;; -------------------------------------------------------------
+;; Boolean DImode instructions.
+;; -------------------------------------------------------------
+
+;; Boolean and,ior,xor insns.
+
+;; 'and' operation.
+
+(define_expand "anddi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(and:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "register_operand" "")))]
+  ""
+  ""
+)
+
+; Use '#' to split instruction.
+(define_insn "*anddi3_insn"
+  [(set (match_operand:DI 0 "register_operand"          "=&r, &r")
+	(and:DI (match_operand:DI 1 "register_operand"  " %0,  r")
+		(match_operand:DI 2 "register_operand"  "  r,  r")))]
+  ""
+  "#"
+  [(set_attr "length" "8")])
+
+; Use '#' to split instruction.
+; The zero extend of operand 2 clears the high word of the output operand.
+(define_insn_and_split "*anddi_zesidi_di"
+  [(set (match_operand:DI 0 "register_operand"                          "=&r, &r")
+	(and:DI (zero_extend:DI (match_operand:SI 2 "register_operand"  "  r,  r"))
+		(match_operand:DI 1 "register_operand"                  "  0,  r")))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
+   (set (match_dup 3) (const_int 0))]
+{
+  operands[3] = gen_highpart (SImode, operands[0]);
+  operands[0] = gen_lowpart (SImode, operands[0]);
+  operands[1] = gen_lowpart (SImode, operands[1]);
+}
+  [(set_attr "length" "8")])
+
+; Use '#' to split instruction.
+(define_insn "*anddi_sesidi_di"
+  [(set (match_operand:DI 0 "register_operand"                          "=&r, &r")
+	(and:DI (sign_extend:DI (match_operand:SI 2 "register_operand"  "  r,  r"))
+		(match_operand:DI 1 "register_operand"                  "  0,  r")))]
+  ""
+  "#"
+  [(set_attr "length" "8")])
+
+
+;; 'ior' operation.
+
+(define_expand "iordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(ior:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "register_operand" "")))]
+  ""
+  ""
+)
+
+; Use '#' to split instruction.
+(define_insn "*iordi3_insn"
+  [(set (match_operand:DI 0 "register_operand"          "=&r, &r")
+	(ior:DI (match_operand:DI 1 "register_operand"  " %0,  r")
+		(match_operand:DI 2 "register_operand"  "  r,  r")))]
+  ""
+  "#"
+  [(set_attr "length" "8")])
+
+; Use '#' to split instruction.
+(define_insn "*iordi_zesidi_di"
+  [(set (match_operand:DI 0 "register_operand"                          "=&r, &r")
+	(ior:DI (zero_extend:DI (match_operand:SI 2 "register_operand"  "  r,  r"))
+		(match_operand:DI 1 "register_operand"                  "  0, ?r")))]
+  ""
+  "#"
+  [(set_attr "length" "8")])
+
+; Use '#' to split instruction.
+(define_insn "*iordi_sesidi_di"
+  [(set (match_operand:DI 0 "register_operand"                          "=&r, &r")
+	(ior:DI (sign_extend:DI (match_operand:SI 2 "register_operand"  "  r,  r"))
+		(match_operand:DI 1 "register_operand"                  "  0,  r")))]
+  ""
+  "#"
+  [(set_attr "length" "8")])
+
+
+;; 'xor' operation.
+
+(define_expand "xordi3"
+  [(set (match_operand:DI 0 "register_operand" "")
+	(xor:DI (match_operand:DI 1 "register_operand" "")
+		(match_operand:DI 2 "register_operand" "")))]
+  ""
+  ""
+)
+
+; Use '#' to split instruction.
+(define_insn "*xordi3_insn"
+  [(set (match_operand:DI 0 "register_operand"          "=&r, &r")
+	(xor:DI (match_operand:DI 1 "register_operand"  " %0,  r")
+		(match_operand:DI 2 "register_operand"  "  r,  r")))]
+  ""
+  "#"
+  [(set_attr "length" "8")])
+
+; Use '#' to split instruction.
+(define_insn "*xordi_zesidi_di"
+  [(set (match_operand:DI 0 "register_operand"                          "=&r, &r")
+	(xor:DI (zero_extend:DI (match_operand:SI 2 "register_operand"  "  r,  r"))
+		(match_operand:DI 1 "register_operand"                  "  0, ?r")))]
+  ""
+  "#"
+  [(set_attr "length" "8")])
+
+; Use '#' to split instruction.
+(define_insn "*xordi_sesidi_di"
+  [(set (match_operand:DI 0 "register_operand"                          "=&r, &r")
+	(xor:DI (sign_extend:DI (match_operand:SI 2 "register_operand"  "  r,  r"))
+		(match_operand:DI 1 "register_operand"                  "  0,  r")))]
+  ""
+  "#"
+  [(set_attr "length" "8")])
+
+
+;; Split up double word logical operations.
+
+;; Split up simple DImode logical operations.  Simply perform the logical
+;; operation on the upper and lower halves of the registers.
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+	(match_operator:DI 6 "nds32_logical_binary_operator"
+	  [(match_operand:DI 1 "register_operand" "")
+	   (match_operand:DI 2 "register_operand" "")]))]
+  "reload_completed"
+  [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
+   (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
+{
+  /* Note that operands[0], operands[1],
+     and operands[2] will be assigned new rtx,
+     so be careful of the order when using them.  */
+
+  operands[3] = gen_highpart (SImode, operands[0]);
+  operands[0] = gen_lowpart  (SImode, operands[0]);
+
+  operands[4] = gen_highpart (SImode, operands[1]);
+  operands[1] = gen_lowpart  (SImode, operands[1]);
+
+  operands[5] = gen_highpart (SImode, operands[2]);
+  operands[2] = gen_lowpart  (SImode, operands[2]);
+})
+
+
+;; -------------------------------------------------------------
diff --git gcc/config/nds32/nds32.intrinsic.md gcc/config/nds32/nds32.intrinsic.md
new file mode 100644
index 0000000..4ee2d85
--- /dev/null
+++ gcc/config/nds32/nds32.intrinsic.md
@@ -0,0 +1,97 @@ 
+;; Intrinsic patterns description of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC 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.
+;;
+;; GCC 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 GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+;; ------------------------------------------------------------------------
+
+;; Register Transfer.
+
+(define_insn "unspec_volatile_mfsr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MFSR))]
+  ""
+  "mfsr\t%0, %V1"
+  [(set_attr "type"   "misc")
+   (set_attr "length"    "4")]
+)
+
+(define_insn "unspec_volatile_mfusr"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MFUSR))]
+  ""
+  "mfusr\t%0, %V1"
+  [(set_attr "type"   "misc")
+   (set_attr "length"    "4")]
+)
+
+(define_insn "unspec_volatile_mtsr"
+  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
+			(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTSR)]
+  ""
+  "mtsr\t%0, %V1"
+  [(set_attr "type"   "misc")
+   (set_attr "length"    "4")]
+)
+
+(define_insn "unspec_volatile_mtusr"
+  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")
+			(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTUSR)]
+  ""
+  "mtusr\t%0, %V1"
+  [(set_attr "type"   "misc")
+   (set_attr "length"    "4")]
+)
+
+;; ------------------------------------------------------------------------
+
+;; Interrupt Instructions.
+
+(define_insn "unspec_volatile_setgie_en"
+  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETGIE_EN)]
+  ""
+  "setgie.e"
+  [(set_attr "type" "misc")]
+)
+
+(define_insn "unspec_volatile_setgie_dis"
+  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETGIE_DIS)]
+  ""
+  "setgie.d"
+  [(set_attr "type" "misc")]
+)
+
+;; ------------------------------------------------------------------------
+
+;; Cache Synchronization Instructions
+
+(define_insn "unspec_volatile_isync"
+  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_ISYNC)]
+  ""
+  "isync\t%0"
+  [(set_attr "type" "misc")]
+)
+
+(define_insn "unspec_volatile_isb"
+  [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_ISB)]
+  ""
+  "isb"
+  [(set_attr "type" "misc")]
+)
+
+;; ------------------------------------------------------------------------
diff --git gcc/config/nds32/nds32.multiple.md gcc/config/nds32/nds32.multiple.md
new file mode 100644
index 0000000..1b3e05b
--- /dev/null
+++ gcc/config/nds32/nds32.multiple.md
@@ -0,0 +1,410 @@ 
+;; Load/Store Multiple patterns description of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.for NDS32.
+;;
+;; This file is part of GCC.
+;;
+;; GCC 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.
+;;
+;; GCC 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 GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; Load Multiple Insns.
+;;
+;; opernads[0] is the first of the consecutive registers.
+;; operands[1] is the first memory location.
+;; operands[2] is the number of consecutive registers.
+
+(define_expand "load_multiple"
+  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
+			  (match_operand:SI 1 "" ""))
+		     (use (match_operand:SI 2 "" ""))])]
+  ""
+{
+  int maximum;
+
+  /* Because reduced-set regsiters has few registers
+     (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' cannot
+     be used for register allocation),
+     using 8 registers for load_multiple may easily consume all of them.
+     It makes register allocation/spilling hard to work.
+     So we only allow maximum=4 registers for load_multiple
+     under reduced-set registers.  */
+  if (TARGET_REDUCED_REGS)
+    maximum = 4;
+  else
+    maximum = 8;
+
+  /* Here are the conditions that must be all passed,
+     otherwise we have to FAIL this rtx generation:
+       1. The number of consecutive registers must be integer.
+       2. Maximum 4 or 8 registers for lmw.bi instruction
+          (based on this nds32.multiple.md design).
+       3. Minimum 2 registers for lmw.bi instruction
+          (based on this nds32.multiple.md design).
+       4. operands[0] must be register for sure.
+       5. operands[1] must be memory for sure.
+       6. Do not cross $r15 register because it is not allocatable.  */
+  if (GET_CODE (operands[2]) != CONST_INT
+      || INTVAL (operands[2]) > maximum
+      || INTVAL (operands[2]) < 2
+      || GET_CODE (operands[0]) != REG
+      || GET_CODE (operands[1]) != MEM
+      || REGNO (operands[0]) + INTVAL (operands[2]) > TA_REGNUM)
+    FAIL;
+
+  /* For (mem addr), we force_reg on addr here,
+     so that nds32_expand_load_multiple can easily use it.  */
+  operands[3] = nds32_expand_load_multiple (REGNO (operands[0]),
+					    INTVAL (operands[2]),
+					    force_reg (SImode,
+						       XEXP (operands[1], 0)),
+					    operands[1]);
+})
+
+;; Ordinary Load Multiple.
+
+(define_insn "*lmwsi8"
+  [(match_parallel 0 "nds32_load_multiple_operation"
+    [(set (match_operand:SI 2 "register_operand" "")
+	  (mem:SI (match_operand:SI 1 "register_operand" "r")))
+     (set (match_operand:SI 3 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+     (set (match_operand:SI 4 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
+     (set (match_operand:SI 5 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))
+     (set (match_operand:SI 6 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 16))))
+     (set (match_operand:SI 7 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 20))))
+     (set (match_operand:SI 8 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 24))))
+     (set (match_operand:SI 9 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 28))))])]
+  "(XVECLEN (operands[0], 0) == 8)"
+  "lmw.bi\t%2, [%1], %9, 0x0"
+  [(set_attr "type"   "load")
+   (set_attr "length"    "4")]
+)
+
+(define_insn "*lmwsi7"
+  [(match_parallel 0 "nds32_load_multiple_operation"
+    [(set (match_operand:SI 2 "register_operand" "")
+	  (mem:SI (match_operand:SI 1 "register_operand" "r")))
+     (set (match_operand:SI 3 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+     (set (match_operand:SI 4 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
+     (set (match_operand:SI 5 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))
+     (set (match_operand:SI 6 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 16))))
+     (set (match_operand:SI 7 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 20))))
+     (set (match_operand:SI 8 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 24))))])]
+  "(XVECLEN (operands[0], 0) == 7)"
+  "lmw.bi\t%2, [%1], %8, 0x0"
+  [(set_attr "type"   "load")
+   (set_attr "length"    "4")]
+)
+
+(define_insn "*lmwsi6"
+  [(match_parallel 0 "nds32_load_multiple_operation"
+    [(set (match_operand:SI 2 "register_operand" "")
+	  (mem:SI (match_operand:SI 1 "register_operand" "r")))
+     (set (match_operand:SI 3 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+     (set (match_operand:SI 4 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
+     (set (match_operand:SI 5 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))
+     (set (match_operand:SI 6 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 16))))
+     (set (match_operand:SI 7 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 20))))])]
+  "(XVECLEN (operands[0], 0) == 6)"
+  "lmw.bi\t%2, [%1], %7, 0x0"
+  [(set_attr "type"   "load")
+   (set_attr "length"    "4")]
+)
+
+(define_insn "*lmwsi5"
+  [(match_parallel 0 "nds32_load_multiple_operation"
+    [(set (match_operand:SI 2 "register_operand" "")
+	  (mem:SI (match_operand:SI 1 "register_operand" "r")))
+     (set (match_operand:SI 3 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+     (set (match_operand:SI 4 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
+     (set (match_operand:SI 5 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))
+     (set (match_operand:SI 6 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 16))))])]
+  "(XVECLEN (operands[0], 0) == 5)"
+  "lmw.bi\t%2, [%1], %6, 0x0"
+  [(set_attr "type"   "load")
+   (set_attr "length"    "4")]
+)
+
+(define_insn "*lmwsi4"
+  [(match_parallel 0 "nds32_load_multiple_operation"
+    [(set (match_operand:SI 2 "register_operand" "")
+	  (mem:SI (match_operand:SI 1 "register_operand" "r")))
+     (set (match_operand:SI 3 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+     (set (match_operand:SI 4 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))
+     (set (match_operand:SI 5 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
+  "(XVECLEN (operands[0], 0) == 4)"
+  "lmw.bi\t%2, [%1], %5, 0x0"
+  [(set_attr "type"   "load")
+   (set_attr "length"    "4")]
+)
+
+(define_insn "*lmwsi3"
+  [(match_parallel 0 "nds32_load_multiple_operation"
+    [(set (match_operand:SI 2 "register_operand" "")
+	  (mem:SI (match_operand:SI 1 "register_operand" "r")))
+     (set (match_operand:SI 3 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))
+     (set (match_operand:SI 4 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
+  "(XVECLEN (operands[0], 0) == 3)"
+  "lmw.bi\t%2, [%1], %4, 0x0"
+  [(set_attr "type"   "load")
+   (set_attr "length"    "4")]
+)
+
+(define_insn "*lmwsi2"
+  [(match_parallel 0 "nds32_load_multiple_operation"
+    [(set (match_operand:SI 2 "register_operand" "")
+	  (mem:SI (match_operand:SI 1 "register_operand" "r")))
+     (set (match_operand:SI 3 "register_operand" "")
+	  (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
+  "(XVECLEN (operands[0], 0) == 2)"
+  "lmw.bi\t%2, [%1], %3, 0x0"
+  [(set_attr "type"   "load")
+   (set_attr "length"    "4")]
+)
+
+
+;; Store Multiple Insns.
+;;
+;; operands[0] is the first memory location.
+;; opernads[1] is the first of the consecutive registers.
+;; operands[2] is the number of consecutive registers.
+
+(define_expand "store_multiple"
+  [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
+			  (match_operand:SI 1 "" ""))
+		     (use (match_operand:SI 2 "" ""))])]
+  ""
+{
+  int maximum;
+
+  /* Because reduced-set regsiters has few registers
+     (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' cannot
+     be used for register allocation),
+     using 8 registers for store_multiple may easily consume all of them.
+     It makes register allocation/spilling hard to work.
+     So we only allow maximum=4 registers for store_multiple
+     under reduced-set registers.  */
+  if (TARGET_REDUCED_REGS)
+    maximum = 4;
+  else
+    maximum = 8;
+
+  /* Here are the conditions that must be all passed,
+     otherwise we have to FAIL this rtx generation:
+       1. The number of consecutive registers must be integer.
+       2. Maximum 4 or 8 registers for smw.bi instruction
+          (based on this nds32.multiple.md design).
+       3. Minimum 2 registers for smw.bi instruction
+          (based on this nds32.multiple.md design).
+       4. operands[0] must be memory for sure.
+       5. operands[1] must be register for sure.
+       6. Do not cross $r15 register because it is not allocatable.  */
+  if (GET_CODE (operands[2]) != CONST_INT
+      || INTVAL (operands[2]) > maximum
+      || INTVAL (operands[2]) < 2
+      || GET_CODE (operands[0]) != MEM
+      || GET_CODE (operands[1]) != REG
+      || REGNO (operands[1]) + INTVAL (operands[2]) > TA_REGNUM)
+    FAIL;
+
+  /* For (mem addr), we force_reg on addr here,
+     so that nds32_expand_store_multiple can easily use it.  */
+  operands[3] = nds32_expand_store_multiple (REGNO (operands[1]),
+					     INTVAL (operands[2]),
+					     force_reg (SImode,
+							XEXP (operands[0], 0)),
+					     operands[0]);
+})
+
+;; Ordinary Store Multiple.
+
+(define_insn "*stmsi8"
+  [(match_parallel 0 "nds32_store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+	  (match_operand:SI 2 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+	  (match_operand:SI 3 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+	  (match_operand:SI 4 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+	  (match_operand:SI 5 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+	  (match_operand:SI 6 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+	  (match_operand:SI 7 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+	  (match_operand:SI 8 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 28)))
+	  (match_operand:SI 9 "register_operand" ""))])]
+  "(XVECLEN (operands[0], 0) == 8)"
+  "smw.bi\t%2, [%1], %9, 0x0"
+  [(set_attr "type"   "store")
+   (set_attr "length"     "4")]
+)
+
+(define_insn "*stmsi7"
+  [(match_parallel 0 "nds32_store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+	  (match_operand:SI 2 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+	  (match_operand:SI 3 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+	  (match_operand:SI 4 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+	  (match_operand:SI 5 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+	  (match_operand:SI 6 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+	  (match_operand:SI 7 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+	  (match_operand:SI 8 "register_operand" ""))])]
+  "(XVECLEN (operands[0], 0) == 7)"
+  "smw.bi\t%2, [%1], %8, 0x0"
+  [(set_attr "type"   "store")
+   (set_attr "length"     "4")]
+)
+
+(define_insn "*stmsi6"
+  [(match_parallel 0 "nds32_store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+	  (match_operand:SI 2 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+	  (match_operand:SI 3 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+	  (match_operand:SI 4 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+	  (match_operand:SI 5 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+	  (match_operand:SI 6 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+	  (match_operand:SI 7 "register_operand" ""))])]
+  "(XVECLEN (operands[0], 0) == 6)"
+  "smw.bi\t%2, [%1], %7, 0x0"
+  [(set_attr "type"   "store")
+   (set_attr "length"     "4")]
+)
+
+(define_insn "*stmsi5"
+  [(match_parallel 0 "nds32_store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+	  (match_operand:SI 2 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+	  (match_operand:SI 3 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+	  (match_operand:SI 4 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+	  (match_operand:SI 5 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+	  (match_operand:SI 6 "register_operand" ""))])]
+  "(XVECLEN (operands[0], 0) == 5)"
+  "smw.bi\t%2, [%1], %6, 0x0"
+  [(set_attr "type"   "store")
+   (set_attr "length"     "4")]
+)
+
+(define_insn "*stmsi4"
+  [(match_parallel 0 "nds32_store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+	  (match_operand:SI 2 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+	  (match_operand:SI 3 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+	  (match_operand:SI 4 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+	  (match_operand:SI 5 "register_operand" ""))])]
+  "(XVECLEN (operands[0], 0) == 4)"
+  "smw.bi\t%2, [%1], %5, 0x0"
+  [(set_attr "type"   "store")
+   (set_attr "length"     "4")]
+)
+
+(define_insn "*stmsi3"
+  [(match_parallel 0 "nds32_store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+	  (match_operand:SI 2 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+	  (match_operand:SI 3 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+	  (match_operand:SI 4 "register_operand" ""))])]
+  "(XVECLEN (operands[0], 0) == 3)"
+  "smw.bi\t%2, [%1], %4, 0x0"
+  [(set_attr "type"   "store")
+   (set_attr "length"     "4")]
+)
+
+(define_insn "*stmsi2"
+  [(match_parallel 0 "nds32_store_multiple_operation"
+    [(set (mem:SI (match_operand:SI 1 "register_operand" "r"))
+	  (match_operand:SI 2 "register_operand" ""))
+     (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+	  (match_operand:SI 3 "register_operand" ""))])]
+  "(XVECLEN (operands[0], 0) == 2)"
+  "smw.bi\t%2, [%1], %3, 0x0"
+  [(set_attr "type"   "store")
+   (set_attr "length"     "4")]
+)
+
+;; Move a block of memory if it is word aligned and MORE than 2 words long.
+;; We could let this apply for blocks of less than this, but it clobbers so
+;; many registers that there is then probably a better way.
+;;
+;; operands[0] is the destination block of memory.
+;; operands[1] is the source block of memory.
+;; operands[2] is the number of bytes to move.
+;; operands[3] is the known shared alignment.
+
+(define_expand "movmemqi"
+  [(match_operand:BLK 0 "general_operand" "")
+   (match_operand:BLK 1 "general_operand" "")
+   (match_operand:SI 2 "const_int_operand" "")
+   (match_operand:SI 3 "const_int_operand" "")]
+  ""
+{
+  if (nds32_expand_movmemqi (operands[0],
+			     operands[1],
+			     operands[2],
+			     operands[3]))
+    DONE;
+
+  FAIL;
+})
+
+;; ------------------------------------------------------------------------
diff --git gcc/config/nds32/nds32.opt gcc/config/nds32/nds32.opt
new file mode 100644
index 0000000..b7303e3
--- /dev/null
+++ gcc/config/nds32/nds32.opt
@@ -0,0 +1,98 @@ 
+; Options of Andes NDS32 cpu for GNU compiler
+; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+; Contributed by Andes Technology Corporation.
+;
+; This file is part of GCC.
+;
+; GCC 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.
+;
+; GCC 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 GCC; see the file COPYING3.  If not see
+; <http://www.gnu.org/licenses/>.
+
+HeaderInclude
+config/nds32/nds32-opts.h
+
+mbig-endian
+Target Report RejectNegative Negative(mlittle-endian) Mask(BIG_ENDIAN)
+Generate code in big-endian mode.
+
+mlittle-endian
+Target Report RejectNegative Negative(mbig-endian) InverseMask(BIG_ENDIAN)
+Generate code in little-endian mode.
+
+mreduced-regs
+Target Report RejectNegative Negative(mfull-regs) Mask(REDUCED_REGS)
+Use reduced-set registers for register allocation.
+
+mfull-regs
+Target Report RejectNegative Negative(mreduced-regs) InverseMask(REDUCED_REGS)
+Use full-set registers for register allocation.
+
+mcmov
+Target Report Mask(CMOV)
+Generate conditional move instructions.
+
+mperf-ext
+Target Report Mask(PERF_EXT)
+Generate performance extension instructions.
+
+mv3push
+Target Report Mask(V3PUSH)
+Generate v3 push25/pop25 instructions.
+
+m16-bit
+Target Report Mask(16_BIT)
+Generate 16-bit instructions.
+
+mgp-direct
+Target Report Mask(GP_DIRECT)
+Generate GP base instructions directly.
+
+misr-vector-size=
+Target Report RejectNegative Joined UInteger Var(nds32_isr_vector_size) Init(NDS32_DEFAULT_ISR_VECTOR_SIZE)
+Specify the size of each vector for interrupt handler.  The valid value is 4 or 16.
+
+mcache-block-size=
+Target Report RejectNegative Joined UInteger Var(nds32_cache_block_size) Init(NDS32_DEFAULT_CACHE_BLOCK_SIZE)
+Specify the size of each cache block.  The size is the power of 2 in bytes.  The valid value is: 4, 8, 16, 32, 64, 128, 256, or 512.
+
+march=
+Target RejectNegative Joined Enum(nds32_arch_type) Var(nds32_arch_option) Init(ARCH_V3)
+Specify the name of the target architecture.  The valid value is: v2, v3, or v3m.
+
+Enum
+Name(nds32_arch_type) Type(enum nds32_arch_type)
+
+EnumValue
+Enum(nds32_arch_type) String(v2) Value(ARCH_V2)
+
+EnumValue
+Enum(nds32_arch_type) String(v3) Value(ARCH_V3)
+
+EnumValue
+Enum(nds32_arch_type) String(v3m) Value(ARCH_V3M)
+
+mforce-fp-as-gp
+Target Report RejectNegative Mask(FORCE_FP_AS_GP)
+Prevent $fp being allocated during register allocation so that compiler is able to force using $fp to access static and global variables for code-size reduction.  Then compiler will use special directives and code generation to guide linker doing fp-as-gp optimization (NOTE: This is link time optimization so make sure you pass '--relax' option to linker at linking stage).
+
+mforbid-fp-as-gp
+Target Report RejectNegative Mask(FORBID_FP_AS_GP)
+Forbid using $fp to access static and global variables.  This option strictly forbids fp-as-gp optimization regardless of '-mforce-fp-as-gp'.
+
+mex9
+Target Report RejectNegative Mask(EX9)
+Use special directives to guide linker doing ex9 optimization (NOTE: This is link time optimization so make sure you pass '--relax' and '--mex9' option to linker at linking stage).
+
+mno-ctor-dtor
+Target Report RejectNegative
+Disable constructor/destructor feature.
diff --git gcc/config/nds32/nds32.peephole2.md gcc/config/nds32/nds32.peephole2.md
new file mode 100644
index 0000000..c1f1f1f
--- /dev/null
+++ gcc/config/nds32/nds32.peephole2.md
@@ -0,0 +1,160 @@ 
+;; define_peephole2 optimization patterns of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC 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.
+;;
+;; GCC 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 GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+
+;; Merge single move to sign_extend load.
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "register_operand" ""))
+   (set (match_operand:SI 2 "register_operand" "")
+	(sign_extend:SI (mem:QIHISI (plus:SI (match_dup 0)
+					     (match_operand:SI 3 "immediate_operand")))))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 2)
+	(sign_extend:SI (mem:QIHISI (plus:SI (match_dup 1)
+					     (match_dup 3)))))]
+)
+
+;; Merge single move to zero_extend load.
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "register_operand" ""))
+   (set (match_operand:SI 2 "register_operand" "")
+	(zero_extend:SI (mem:QIHISI (plus:SI (match_dup 0)
+					     (match_operand:SI 3 "immediate_operand")))))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 2)
+	(zero_extend:SI (mem:QIHISI (plus:SI (match_dup 1)
+					     (match_dup 3)))))]
+)
+
+;; Merge single move to load.
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "register_operand" ""))
+   (set (match_operand:QIHISI 2 "register_operand" "")
+	(mem:QIHISI (plus:SI (match_dup 0)
+			     (match_operand:SI 3 "immediate_operand"))))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (match_dup 2)
+	(mem:QIHISI (plus:SI (match_dup 1)
+			     (match_dup 3))))]
+)
+
+;; Merge single move to store.
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(match_operand:SI 1 "register_operand" ""))
+   (set (mem:QIHISI (plus:SI (match_dup 0)
+			     (match_operand:SI 3 "immediate_operand")))
+	(match_operand:QIHISI 2 "register_operand" ""))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (mem:QIHISI (plus:SI (match_dup 1)
+			     (match_dup 3)))
+	(match_dup 2))]
+)
+
+;; ------------------------------------------------------------------------------------
+
+;; Merge single addi to sign_extend load.
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(plus:SI (match_operand:SI 1 "register_operand" "")
+		 (match_operand:SI 4 "immediate_operand" "")))
+   (set (match_operand:SI 2 "register_operand" "")
+	(sign_extend:SI (mem:QIHISI (plus:SI (match_dup 0)
+					     (match_operand:SI 3 "immediate_operand")))))]
+  "peep2_reg_dead_p (2, operands[0])
+   && CONST_INT_P (operands[4])
+   && CONST_INT_P (operands[3])
+   && ((INTVAL (operands[3]) + INTVAL (operands[4])) % <byte> == 0)
+   && satisfies_constraint_Is15 (GEN_INT (trunc_int_for_mode (INTVAL (operands[3]) + INTVAL (operands[4]), SImode)))"
+  [(set (match_dup 2)
+	(sign_extend:SI (mem:QIHISI (plus:SI (match_dup 1)
+					     (match_dup 3)))))]
+{
+  operands[3] = gen_int_mode (INTVAL(operands[3]) + INTVAL(operands[4]),
+			      SImode);
+})
+
+;; Merge single addi to zero_extend load.
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(plus:SI (match_operand:SI 1 "register_operand" "")
+		 (match_operand:SI 4 "immediate_operand" "")))
+   (set (match_operand:SI 2 "register_operand" "")
+	(zero_extend:SI (mem:QIHISI (plus:SI (match_dup 0)
+					     (match_operand:SI 3 "immediate_operand")))))]
+  "peep2_reg_dead_p (2, operands[0])
+   && CONST_INT_P (operands[4])
+   && CONST_INT_P (operands[3])
+   && ((INTVAL (operands[3]) + INTVAL (operands[4])) % <byte> == 0)
+   && satisfies_constraint_Is15 (GEN_INT (trunc_int_for_mode (INTVAL (operands[3]) + INTVAL (operands[4]), SImode)))"
+  [(set (match_dup 2)
+	(zero_extend:SI (mem:QIHISI (plus:SI (match_dup 1)
+					     (match_dup 3)))))]
+{
+  operands[3] = gen_int_mode (INTVAL(operands[3]) + INTVAL(operands[4]),
+			      SImode);
+})
+
+;; Merge single addi to load.
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(plus:SI (match_operand:SI 1 "register_operand" "")
+		 (match_operand:SI 4 "immediate_operand" "")))
+   (set (match_operand:QIHISI 2 "register_operand" "")
+	(mem:QIHISI (plus:SI (match_dup 0)
+			     (match_operand:SI 3 "immediate_operand"))))]
+  "peep2_reg_dead_p (2, operands[0])
+   && CONST_INT_P (operands[4])
+   && CONST_INT_P (operands[3])
+   && ((INTVAL (operands[3]) + INTVAL (operands[4])) % <byte> == 0)
+   && satisfies_constraint_Is15 (GEN_INT (trunc_int_for_mode (INTVAL (operands[3]) + INTVAL (operands[4]), SImode)))"
+  [(set (match_dup 2)
+	(mem:QIHISI (plus:SI (match_dup 1)
+			     (match_dup 3))))]
+{
+  operands[3] = gen_int_mode (INTVAL(operands[3]) + INTVAL(operands[4]),
+			      SImode);
+})
+
+;; Merge single addi to store.
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(plus:SI (match_operand:SI 1 "register_operand" "")
+		 (match_operand:SI 4 "immediate_operand" "")))
+   (set (mem:QIHISI (plus:SI (match_dup 0)
+			     (match_operand:SI 3 "immediate_operand")))
+	(match_operand:QIHISI 2 "register_operand" ""))]
+  "peep2_reg_dead_p (2, operands[0])
+   && CONST_INT_P (operands[4])
+   && CONST_INT_P (operands[3])
+   && ((INTVAL (operands[3]) + INTVAL (operands[4])) % <byte> == 0)
+   && satisfies_constraint_Is15 (GEN_INT (trunc_int_for_mode (INTVAL (operands[3]) + INTVAL (operands[4]), SImode)))"
+  [(set (mem:QIHISI (plus:SI (match_dup 1)
+			     (match_dup 3)))
+	(match_dup 2))]
+{
+  operands[3] = gen_int_mode (INTVAL(operands[3]) + INTVAL(operands[4]),
+			      SImode);
+})
+
+;; ------------------------------------------------------------------------
diff --git gcc/config/nds32/nds32_intrinsic.h gcc/config/nds32/nds32_intrinsic.h
new file mode 100644
index 0000000..33064a9
--- /dev/null
+++ gcc/config/nds32/nds32_intrinsic.h
@@ -0,0 +1,37 @@ 
+/* Intrinsic definitions of Andes NDS32 cpu for GNU compiler
+   Copyright (C) 2012-2013 Free Software Foundation, Inc.
+   Contributed by Andes Technology Corporation.
+
+   This file is part of GCC.
+
+   GCC 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.
+
+   GCC 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.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _NDS32_INTRINSIC_H
+#define _NDS32_INTRINSIC_H
+
+enum nds32_intrinsic_registers
+{
+  __NDS32_REG_PSW__ = 1024,
+  __NDS32_REG_IPSW__,
+  __NDS32_REG_ITYPE__,
+  __NDS32_REG_IPC__
+};
+
+#endif /* nds32_intrinsic.h */
diff --git gcc/config/nds32/pipelines.md gcc/config/nds32/pipelines.md
new file mode 100644
index 0000000..9c8c56b
--- /dev/null
+++ gcc/config/nds32/pipelines.md
@@ -0,0 +1,29 @@ 
+;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC 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.
+;;
+;; GCC 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 GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_automaton "nds32_machine")
+
+(define_cpu_unit "general_unit" "nds32_machine")
+
+(define_insn_reservation "simple_insn" 1
+			 (eq_attr "type" "unknown,load,store,move,alu,compare,branch,call,misc")
+			 "general_unit")
+
+;; ------------------------------------------------------------------------
diff --git gcc/config/nds32/predicates.md gcc/config/nds32/predicates.md
new file mode 100644
index 0000000..12f7e68
--- /dev/null
+++ gcc/config/nds32/predicates.md
@@ -0,0 +1,179 @@ 
+;; Predicate definitions of Andes NDS32 cpu for GNU compiler
+;; Copyright (C) 2012-2013 Free Software Foundation, Inc.
+;; Contributed by Andes Technology Corporation.
+;;
+;; This file is part of GCC.
+;;
+;; GCC 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.
+;;
+;; GCC 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 GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_predicate "nds32_equality_comparison_operator"
+  (match_code "eq,ne"))
+
+(define_predicate "nds32_greater_less_comparison_operator"
+  (match_code "gt,ge,lt,le"))
+
+(define_special_predicate "nds32_logical_binary_operator"
+  (match_code "and,ior,xor"))
+
+;; Reg, subreg(reg) or const_int.
+(define_predicate "nds32_reg_or_int_operand"
+  (ior (match_operand 0 "immediate_operand")
+       (match_operand 0 "register_operand"))
+{
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+
+  if (REG_P (op))
+    return true;
+
+  if (GET_CODE (op) == CONST_INT)
+    return true;
+  return false;
+})
+
+(define_predicate "nds32_rimm15s_operand"
+  (match_operand 0 "general_operand")
+{
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+  if (GET_CODE (op) == REG)
+    return true;
+  if (GET_CODE (op) != CONST_INT)
+    return false;
+
+  return satisfies_constraint_Is15 (op);
+})
+
+(define_predicate "nds32_nonmemory_nonsymbol_operand"
+  (match_operand 0 "nonmemory_operand")
+{
+  switch (GET_CODE (op))
+    {
+      case SYMBOL_REF:
+      case LABEL_REF:
+      case CONST:
+        return false;
+      default:
+        return true;
+    }
+})
+
+(define_predicate "nds32_symbolic_operand"
+  (match_code "const,symbol_ref,label_ref"))
+
+(define_predicate "nds32_reg_constant_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "const_int_operand")))
+
+(define_predicate "nds32_imm5u_operand"
+  (match_operand 0 "immediate_operand")
+{
+  return satisfies_constraint_Iu05 (op);
+})
+
+(define_special_predicate "nds32_load_multiple_operation"
+  (match_code "parallel")
+{
+  HOST_WIDE_INT count;
+  int dest_regno;
+  rtx src_addr;
+
+  int i;
+  rtx elt;
+
+  /* Get the counts of elements in the parallel rtx.  */
+  count = XVECLEN (op, 0);
+
+  /* Pick up the first element.  */
+  elt = XVECEXP (op, 0, 0);
+
+  /* Perform some quick check for the first element in the parallel rtx.  */
+  if (GET_CODE (elt) != SET
+      || count <= 1
+      || count > 8
+      || GET_CODE (SET_DEST (elt)) != REG
+      || GET_CODE (SET_SRC  (elt)) != MEM)
+    return false;
+
+  dest_regno = REGNO (SET_DEST (elt));
+  src_addr   = XEXP (SET_SRC (elt), 0);
+
+  /* Perform detail check for each element.  */
+  for (i = 0; i < count; i++)
+    {
+      elt = XVECEXP (op, 0, i);
+
+      /* Refer to nds32.multiple.md for more information
+         about following checking.  */
+      if (GET_CODE (elt) != SET
+          || GET_CODE (SET_DEST (elt)) != REG
+          || GET_MODE (SET_DEST (elt)) != SImode
+          || REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i)
+          || GET_CODE (SET_SRC (elt)) != MEM
+          || GET_MODE (SET_SRC (elt)) != SImode
+          || (GET_CODE (src_addr) != REG && GET_CODE (src_addr) != PLUS))
+        return false;
+    }
+
+  return true;
+})
+
+(define_special_predicate "nds32_store_multiple_operation"
+  (match_code "parallel")
+{
+  HOST_WIDE_INT count;
+  int src_regno;
+  rtx dest_addr;
+
+  int i;
+  rtx elt;
+
+  /* Get the counts of elements in the parallel rtx.  */
+  count = XVECLEN (op, 0);
+
+  /* Pick up the first element.  */
+  elt = XVECEXP (op, 0, 0);
+
+  /* Perform some quick check for the first element in the parallel rtx.  */
+  if (GET_CODE (elt) != SET
+      || count <= 1
+      || count > 8
+      || GET_CODE (SET_SRC  (elt)) != REG
+      || GET_CODE (SET_DEST (elt)) != MEM)
+    return false;
+
+  src_regno = REGNO (SET_SRC (elt));
+  dest_addr = XEXP (SET_DEST (elt), 0);
+
+  /* Perform detail check for each element.  */
+  for (i = 0; i < count; i++)
+    {
+      elt = XVECEXP (op, 0, i);
+
+      /* Refer to nds32.multiple.md for more information
+         about following checking.  */
+      if (GET_CODE (elt) != SET
+          || GET_CODE (SET_SRC (elt)) != REG
+          || GET_MODE (SET_SRC (elt)) != SImode
+          || REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i)
+          || GET_CODE (SET_DEST (elt)) != MEM
+          || GET_MODE (SET_DEST (elt)) != SImode
+          || (GET_CODE (dest_addr) != REG && GET_CODE (dest_addr) != PLUS))
+        return false;
+    }
+
+  return true;
+})
+;; ------------------------------------------------------------------------
diff --git gcc/config/nds32/t-mlibs gcc/config/nds32/t-mlibs
new file mode 100644
index 0000000..d770824
--- /dev/null
+++ gcc/config/nds32/t-mlibs
@@ -0,0 +1,30 @@ 
+# The multilib settings of Andes NDS32 cpu for GNU compiler
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+# Contributed by Andes Technology Corporation.
+#
+# This file is part of GCC.
+#
+# GCC 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.
+#
+# GCC 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 GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# We need to build following multilibs:
+#   -mlittle-endian
+#   -mbig-endian
+#
+# We also define a macro MULTILIB_DEFAULTS in nds32.h that tells the
+# driver program which options are defaults for this target and thus
+# do not need to be handled specially.
+MULTILIB_OPTIONS = mlittle-endian/mbig-endian
+
+# ------------------------------------------------------------------------