public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Chung-Ju Wu <jasonwucj@gmail.com>
To: gcc-patches <gcc-patches@gcc.gnu.org>, rdsandiford@googlemail.com
Subject: Re: [PATCH 2/6] Andes nds32: machine description of nds32 porting (3).
Date: Sat, 05 Oct 2013 18:22:00 -0000	[thread overview]
Message-ID: <525058CC.1040502@gmail.com> (raw)
In-Reply-To: <8738oklw7t.fsf@talisman.default>

[-- Attachment #1: Type: text/plain, Size: 628 bytes --]

On 10/2/13 1:47 AM, Richard Sandiford wrote:
> Chung-Ju Wu <jasonwucj@gmail.com> writes:
> 
>> +mforce-fp-as-gp
>> +Target Report Mask(FORCE_FP_AS_GP)
>> +Prevent $fp being allocated during register allocation so that compiler is able to force performing fp-as-gp optimization.
> 
> Maybe:
> 
>   Prevent $fp from being used by the register allocator, so that it is always available for the fp-as-gp optimization.
> 

Thanks for rewording the sentence.
Modify it accordingly.


> Looks good otherwise, thanks.
> 
> Richard
> 
A revised patch for other md files is attached.
Thanks for the comments! :)

Best regards,
jasonwucj


[-- Attachment #2: 2-nds32-backend-md-part3.v3.revised-2.patch --]
[-- Type: text/plain, Size: 60138 bytes --]

diff --git gcc/config/nds32/constants.md gcc/config/nds32/constants.md
new file mode 100644
index 0000000..03a21db
--- /dev/null
+++ gcc/config/nds32/constants.md
@@ -0,0 +1,46 @@
+;; 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 unspec_volatile operation index.
+(define_c_enum "unspec_volatile_element" [
+  UNSPEC_VOLATILE_FUNC_RETURN
+  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..4b9db23
--- /dev/null
+++ gcc/config/nds32/constraints.md
@@ -0,0 +1,260 @@
+;; 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/V3M 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 "In03"
+  "Negative immediate 3-bit value in the range of -7 to 0"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (ival, -7, 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")))
+
+(define_constraint "In05"
+  "Negative immediate 5-bit value in the range of -31 to 0"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (ival, -31, 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 "Izeh"
+  "The immediate value 0xffff"
+  (and (match_code "const_int")
+       (match_test "(ival == 0xffff)")))
+
+(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)
+		    && (IN_RANGE (exact_log2 (ival), 0, 7))")))
+
+(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)
+		    && (IN_RANGE (exact_log2 (ival + 1), 1, 8))")))
+
+
+(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)
+		    && (GET_MODE (op) == SImode)")))
+
+(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)
+		    && (GET_MODE (op) == SImode)")))
+
+;; ------------------------------------------------------------------------
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-doubleword.md gcc/config/nds32/nds32-doubleword.md
new file mode 100644
index 0000000..a6c30d6
--- /dev/null
+++ gcc/config/nds32/nds32-doubleword.md
@@ -0,0 +1,245 @@
+;; 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 (MEM_P (operands[0]) && !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 (MEM_P (operands[0]) && !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]);
+})
+
+;; There is 'movd44' instruction for DImode/DFmode movement under V3/V3M ISA.
+;; We only need to split it under V2 ISA or none-16-bit code generation.
+(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.
+;; -------------------------------------------------------------
+
+;; Nowadays, the generic code is supposed to split the DImode
+;; boolean operations and have good code generation.
+;; Unless we find out some bad cases, there is no need to
+;; define DImode boolean operations by ourself.
+
+;; -------------------------------------------------------------
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-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-multiple.md gcc/config/nds32/nds32-multiple.md
new file mode 100644
index 0000000..da89a49
--- /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.
+;;
+;; operands[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-opts.h gcc/config/nds32/nds32-opts.h
new file mode 100644
index 0000000..b38672f
--- /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-peephole2.md gcc/config/nds32/nds32-peephole2.md
new file mode 100644
index 0000000..dbe2d6c
--- /dev/null
+++ gcc/config/nds32/nds32-peephole2.md
@@ -0,0 +1,25 @@
+;; 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/>.
+
+
+;; Use define_peephole and define_peephole2 to handle possible
+;; target-specific optimization in this file.
+
+;; ------------------------------------------------------------------------
diff --git gcc/config/nds32/nds32-protos.h gcc/config/nds32/nds32-protos.h
new file mode 100644
index 0000000..2bc405d
--- /dev/null
+++ gcc/config/nds32/nds32-protos.h
@@ -0,0 +1,128 @@
+/* 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/>.  */
+
+
+/* ------------------------------------------------------------------------ */
+\f
+/* Defining Data Structures for Per-function Information.  */
+
+extern void nds32_init_expanders (void);
+
+\f
+/* 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);
+
+\f
+/* Register Classes.  */
+
+extern enum reg_class nds32_regno_reg_class (int);
+
+\f
+/* 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 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 multiple load/store predicate checking.  */
+
+extern bool nds32_valid_multiple_load_store (rtx, bool);
+
+/* Auxiliary functions for stack operation predicate checking.  */
+
+extern bool nds32_valid_stack_push_pop (rtx, bool);
+
+/* 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);
+extern const char *nds32_output_32bit_load_s (rtx *, int);
+
+/* Auxiliary functions to output stack push/pop instruction.  */
+
+extern const char *nds32_output_stack_push (void);
+extern const char *nds32_output_stack_pop (void);
+
+/* Auxiliary functions to decide output alignment or not.  */
+
+extern int nds32_target_alignment (rtx);
+
+/* ------------------------------------------------------------------------ */
diff --git gcc/config/nds32/nds32.opt gcc/config/nds32/nds32.opt
new file mode 100644
index 0000000..b2b45bb
--- /dev/null
+++ gcc/config/nds32/nds32.opt
@@ -0,0 +1,102 @@
+; 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 RejectNegative Joined UInteger Var(nds32_isr_vector_size) Init(NDS32_DEFAULT_ISR_VECTOR_SIZE)
+Specify the size of each interrupt vector, which must be 4 or 16.
+
+mcache-block-size=
+Target RejectNegative Joined UInteger Var(nds32_cache_block_size) Init(NDS32_DEFAULT_CACHE_BLOCK_SIZE)
+Specify the size of each cache block, which must be a power of 2 between 4 and 512.
+
+march=
+Target RejectNegative Joined Enum(nds32_arch_type) Var(nds32_arch_option) Init(ARCH_V3)
+Specify the name of the target architecture.
+
+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 Mask(FORCE_FP_AS_GP)
+Prevent $fp being allocated during register allocation so that compiler is able to force performing fp-as-gp optimization.
+
+mforbid-fp-as-gp
+Target Report 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 Mask(EX9)
+Use special directives to guide linker doing ex9 optimization.
+
+mctor-dtor
+Target Report
+Enable constructor/destructor feature.
+
+mrelax
+Target Report
+Guide linker to relax instructions.
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..6783594
--- /dev/null
+++ gcc/config/nds32/predicates.md
@@ -0,0 +1,82 @@
+;; 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"))
+
+(define_predicate "nds32_symbolic_operand"
+  (match_code "const,symbol_ref,label_ref"))
+
+(define_predicate "nds32_nonsymbolic_operand"
+  (and (match_operand 0 "general_operand")
+       (not (match_code "high,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_rimm15s_operand"
+  (ior (match_operand 0 "register_operand")
+       (and (match_operand 0 "const_int_operand")
+	    (match_test "satisfies_constraint_Is15 (op)"))))
+
+(define_predicate "nds32_imm5u_operand"
+  (and (match_operand 0 "const_int_operand")
+       (match_test "satisfies_constraint_Iu05 (op)")))
+
+(define_special_predicate "nds32_load_multiple_operation"
+  (match_code "parallel")
+{
+  /* To verify 'load' operation, pass 'true' for the second argument.
+     See the implementation in nds32.c for details.  */
+  return nds32_valid_multiple_load_store (op, true);
+})
+
+(define_special_predicate "nds32_store_multiple_operation"
+  (match_code "parallel")
+{
+  /* To verify 'store' operation, pass 'false' for the second argument.
+     See the implementation in nds32.c for details.  */
+  return nds32_valid_multiple_load_store (op, false);
+})
+
+(define_special_predicate "nds32_stack_push_operation"
+  (match_code "parallel")
+{
+  /* To verify 'push' operation, pass 'true' for the second argument.
+     See the implementation in nds32.c for details.  */
+  return nds32_valid_stack_push_pop (op, true);
+})
+
+(define_special_predicate "nds32_stack_pop_operation"
+  (match_code "parallel")
+{
+  /* To verify 'pop' operation, pass 'false' for the second argument.
+     See the implementation in nds32.c for details.  */
+  return nds32_valid_stack_push_pop (op, false);
+})
+
+;; ------------------------------------------------------------------------
diff --git gcc/config/nds32/t-mlibs gcc/config/nds32/t-mlibs
new file mode 100644
index 0000000..ec546e4
--- /dev/null
+++ gcc/config/nds32/t-mlibs
@@ -0,0 +1,38 @@
+# 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 combinations:
+#
+#   1. <None multilibs>
+#   2. -mlittle-endian
+#   3. -mbig-endian
+#   4. -mgp-direct
+#   5. -mno-gp-direct
+#   6. -mlittle-endian -mgp-direct
+#   7. -mlittle-endian -mno-gp-direct
+#   8. -mbig-endian -mgp-direct
+#   9. -mlittle-endian -mno-gp-direct
+#
+# 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 mgp-direct/mno-gp-direct
+
+# ------------------------------------------------------------------------

      reply	other threads:[~2013-10-05 18:22 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-08 10:59 Chung-Ju Wu
2013-07-10  0:04 ` Joseph S. Myers
2013-07-24 16:05   ` Chung-Ju Wu
2013-07-25  9:50     ` Chung-Ju Wu
2013-09-08 16:17       ` Chung-Ju Wu
2013-09-15 14:46         ` Richard Sandiford
2013-09-27 18:50           ` Chung-Ju Wu
2013-10-01 17:47             ` Richard Sandiford
2013-10-05 18:22               ` Chung-Ju Wu [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=525058CC.1040502@gmail.com \
    --to=jasonwucj@gmail.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=rdsandiford@googlemail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).