]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/nios2/nios2.md
Update copyright years.
[thirdparty/gcc.git] / gcc / config / nios2 / nios2.md
index e3a803c59b56d7c43a0bdf331cbdf5a83681cd7d..2a064946fe05df622ba3c45d6eab8adb9c10d144 100644 (file)
@@ -1,5 +1,5 @@
 ;; Machine Description for Altera Nios II.
-;; Copyright (C) 2012-2014 Free Software Foundation, Inc.
+;; Copyright (C) 2012-2024 Free Software Foundation, Inc.
 ;; Contributed by Jonah Graham (jgraham@altera.com) and 
 ;; Will Reece (wreece@altera.com).
 ;; Contributed by Mentor Graphics, Inc.
@@ -30,6 +30,7 @@
 
    (TP_REGNO              23)  ; Thread pointer register
    (GP_REGNO             26)   ; Global pointer register
+   (SP_REGNO             27)   ; Stack pointer register
    (FP_REGNO             28)   ; Frame pointer register
    (EA_REGNO             29)   ; Exception return address register
    (RA_REGNO              31)  ; Return address register
   UNSPECV_CUSTOM_XNXX
   UNSPECV_LDXIO
   UNSPECV_STXIO
+  UNSPECV_RDPRS
+  UNSPECV_FLUSHD
+  UNSPECV_FLUSHDA
+  UNSPECV_WRPIE
+  UNSPECV_ENI
+  UNSPECV_LDEX
+  UNSPECV_LDSEX
+  UNSPECV_STEX
+  UNSPECV_STSEX
 ])
 
 (define_c_enum "unspec" [
 ; incuring a stall.
 
 ; length of an instruction (in bytes)
-(define_attr "length" "" (const_int 4))
+(define_attr "length" ""
+  (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)")
+    (const_int 2)
+    (const_int 4)))
+
 (define_attr "type" 
-  "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom" 
+  "unknown,complex,control,alu,cond_alu,st,ld,stwm,ldwm,push,pop,mul,div,\
+   custom,add,sub,mov,and,or,xor,neg,not,sll,srl,sra,rol,ror,nop"
   (const_string "complex"))
 
 (define_asm_attributes
   "cpu")
 
 (define_insn_reservation "control" 1
-  (eq_attr "type" "control")
+  (eq_attr "type" "control,pop")
   "cpu")
 
 (define_insn_reservation "alu" 1
-  (eq_attr "type" "alu")
+  (eq_attr "type" "alu,add,sub,mov,and,or,xor,neg,not")
   "cpu")
 
 (define_insn_reservation "cond_alu" 1
   "cpu")
 
 (define_insn_reservation "st" 1
-  (eq_attr "type" "st")
+  (eq_attr "type" "st,stwm,push")
   "cpu")
   
 (define_insn_reservation "custom" 1
 
 ; shifts, muls and lds have three cycle latency
 (define_insn_reservation "ld" 3
-  (eq_attr "type" "ld")
+  (eq_attr "type" "ld,ldwm")
   "cpu")
 
 (define_insn_reservation "shift" 3
-  (eq_attr "type" "shift")
+  (eq_attr "type" "sll,srl,sra,rol,ror")
   "cpu")
 
 (define_insn_reservation "mul" 3
     DONE;
 })
 
-(define_insn "movqi_internal"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r, r")
-        (match_operand:QI 1 "general_operand"       "rM,m,rM,I"))]
+(define_insn "*high"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (high:SI (match_operand:SI 1 "immediate_operand" "i")))]
+  ""
+  "movhi\\t%0, %H1"
+  [(set_attr "type" "alu")])
+
+(define_insn "*lo_sum"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (lo_sum:SI (match_operand:SI 1 "register_operand"  "r")
+                   (match_operand:SI 2 "immediate_operand" "i")))]
+  ""
+  "addi\\t%0, %1, %L2"
+  [(set_attr "type" "alu")])
+
+(define_insn_and_split "movqi_internal"
+  [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r")
+        (match_operand:QI 1 "general_operand"       "rM,m,rI"))]
   "(register_operand (operands[0], QImode)
     || reg_or_0_operand (operands[1], QImode))"
-  "@
-    stb%o0\\t%z1, %0
-    ldbu%o1\\t%0, %1
-    mov\\t%0, %z1
-    movi\\t%0, %1"
-  [(set_attr "type" "st,ld,alu,alu")])
-
-(define_insn "movhi_internal"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r, r")
-        (match_operand:HI 1 "general_operand"       "rM,m,rM,I"))]
+  {
+    switch (which_alternative)
+      {
+      case 0:
+       if (get_attr_length (insn) != 2)
+         return "stb%o0\\t%z1, %0";
+       else if (const_0_operand (operands[1], QImode))
+         return "stbz.n\\t%z1, %0";
+       else
+         return "stb.n\\t%z1, %0";
+      case 1:
+       return "ldbu%o1%.\\t%0, %1";
+      case 2:
+       return "mov%i1%.\\t%0, %z1";
+      default:
+       gcc_unreachable ();
+      }
+  }
+  "(nios2_large_constant_memory_operand_p (operands[0]) 
+   || nios2_large_constant_memory_operand_p (operands[1]))"
+  [(set (match_dup 0) (match_dup 1))]
+  {
+    if (nios2_large_constant_memory_operand_p (operands[0]))
+      operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
+    else
+      operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
+  }
+  [(set_attr "type" "st,ld,mov")])
+
+(define_insn_and_split "movhi_internal"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r")
+        (match_operand:HI 1 "general_operand"       "rM,m,rI"))]
   "(register_operand (operands[0], HImode)
     || reg_or_0_operand (operands[1], HImode))"
-  "@
-    sth%o0\\t%z1, %0
-    ldhu%o1\\t%0, %1
-    mov\\t%0, %z1
-    movi\\t%0, %1"
-  [(set_attr "type" "st,ld,alu,alu")])
-
-(define_insn "movsi_internal"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r,r")
-        (match_operand:SI 1 "general_operand"       "rM,m,rM,I,J,K,S,i"))]
+  {
+    switch (which_alternative)
+      {
+      case 0:
+        return "sth%o0%.\\t%z1, %0";
+      case 1:
+        return "ldhu%o1%.\\t%0, %1";
+      case 2:
+        return "mov%i1%.\\t%0, %z1";
+      default:
+       gcc_unreachable ();
+      }
+  }
+  "(nios2_large_constant_memory_operand_p (operands[0]) 
+   || nios2_large_constant_memory_operand_p (operands[1]))"
+  [(set (match_dup 0) (match_dup 1))]
+  {
+    if (nios2_large_constant_memory_operand_p (operands[0]))
+      operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
+    else
+      operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
+  }
+  [(set_attr "type" "st,ld,mov")])
+
+(define_insn_and_split "movsi_internal"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r,   r")
+        (match_operand:SI 1 "general_operand"       "rM,m,rIJK,S"))]
   "(register_operand (operands[0], SImode)
     || reg_or_0_operand (operands[1], SImode))"
-  "@
-    stw%o0\\t%z1, %0
-    ldw%o1\\t%0, %1
-    mov\\t%0, %z1
-    movi\\t%0, %1
-    movui\\t%0, %1
-    movhi\\t%0, %H1
-    addi\\t%0, gp, %%gprel(%1)
-    movhi\\t%0, %H1\;addi\\t%0, %0, %L1"
-  [(set_attr "type" "st,ld,alu,alu,alu,alu,alu,alu")
-   (set_attr "length" "4,4,4,4,4,4,4,8")])
+  {
+    switch (which_alternative)
+      {
+      case 0:
+       if (get_attr_length (insn) != 2)
+         return "stw%o0\\t%z1, %0";
+       else if (stack_memory_operand (operands[0], SImode))
+         return "stwsp.n\\t%z1, %0";
+       else if (const_0_operand (operands[1], SImode))
+         return "stwz.n\\t%z1, %0";
+       else
+         return "stw.n\\t%z1, %0";
+      case 1:
+       if (get_attr_length (insn) != 2)
+         return "ldw%o1\\t%0, %1";
+       else if (stack_memory_operand (operands[1], SImode))
+         return "ldwsp.n\\t%0, %1";
+       else
+         return "ldw.n\\t%0, %1";
+      case 2:
+       return "mov%i1%.\\t%0, %z1";
+      case 3:
+       return "addi\\t%0, gp, %%gprel(%1)";
+      default:
+       gcc_unreachable ();
+      }
+  }
+  "(nios2_large_constant_memory_operand_p (operands[0]) 
+    || nios2_large_constant_memory_operand_p (operands[1])
+    || (nios2_large_constant_p (operands[1])
+        && !(CONST_INT_P (operands[1])
+            && (SMALL_INT_UNSIGNED (INTVAL (operands[1]))
+                || UPPER16_INT (INTVAL (operands[1]))))))"
+  [(set (match_dup 0) (match_dup 1))]
+  {
+    if (nios2_large_constant_memory_operand_p (operands[0]))
+      operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
+    else if (nios2_large_constant_memory_operand_p (operands[1]))
+      operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
+    else
+      operands[1] = nios2_split_large_constant (operands[1], operands[0]);
+  }
+  [(set_attr "type" "st,ld,mov,alu")])
 
 (define_mode_iterator BH [QI HI])
 (define_mode_iterator BHW [QI HI SI])
 (define_mode_attr bhw [(QI "b") (HI "h") (SI "w")])
 (define_mode_attr bhw_uns [(QI "bu") (HI "hu") (SI "w")])
 
-(define_insn "ld<bhw_uns>io"
+(define_insn_and_split "ld<bhw_uns>io"
   [(set (match_operand:BHW 0 "register_operand" "=r")
         (unspec_volatile:BHW
-          [(match_operand:BHW 1 "memory_operand" "m")] UNSPECV_LDXIO))]
+          [(match_operand:BHW 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO))]
   ""
   "ld<bhw_uns>io\\t%0, %1"
+  "nios2_large_constant_memory_operand_p (operands[1])"
+  [(set (match_dup 0) 
+        (unspec_volatile:BHW [(match_dup 1)] UNSPECV_LDXIO))]
+  {
+    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
+  }
   [(set_attr "type" "ld")])
 
 (define_expand "ld<bh>io"
   [(set (match_operand:BH 0 "register_operand" "=r")
-        (match_operand:BH 1 "memory_operand"    "m"))]
+        (match_operand:BH 1 "ldstio_memory_operand" "w"))]
   ""
 {
   rtx tmp = gen_reg_rtx (SImode);
   DONE;
 })
 
-(define_insn "ld<bh>io_signed"
+(define_insn_and_split "ld<bh>io_signed"
   [(set (match_operand:SI 0 "register_operand" "=r")
         (sign_extend:SI
           (unspec_volatile:BH
-            [(match_operand:BH 1 "memory_operand" "m")] UNSPECV_LDXIO)))]
+            [(match_operand:BH 1 "ldstio_memory_operand" "w")] UNSPECV_LDXIO)))]
   ""
   "ld<bh>io\\t%0, %1"
+  "nios2_large_constant_memory_operand_p (operands[1])"
+  [(set (match_dup 0) 
+        (sign_extend:SI (unspec_volatile:BH [(match_dup 1)] UNSPECV_LDXIO)))]
+  {
+    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
+  }
   [(set_attr "type" "ld")])
 
-(define_insn "st<bhw>io"
-  [(set (match_operand:BHW 0 "memory_operand" "=m")
+(define_insn_and_split "st<bhw>io"
+  [(set (match_operand:BHW 0 "ldstio_memory_operand" "=w")
         (unspec_volatile:BHW
           [(match_operand:BHW 1 "reg_or_0_operand" "rM")] UNSPECV_STXIO))]
   ""
   "st<bhw>io\\t%z1, %0"
+  "nios2_large_constant_memory_operand_p (operands[0])"
+  [(set (match_dup 0) (unspec_volatile:BHW [(match_dup 1)] UNSPECV_STXIO))]
+  {
+    operands[0] = nios2_split_large_constant_memory_operand (operands[0]);
+  }
   [(set_attr "type" "st")])
 
 \f
 (define_mode_iterator QX [HI SI])
 
 ;; Zero extension patterns
-(define_insn "zero_extendhisi2"
+(define_insn_and_split "zero_extendhisi2"
   [(set (match_operand:SI 0 "register_operand" "=r,r")
         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
   ""
   "@
-    andi\\t%0, %1, 0xffff
-    ldhu%o1\\t%0, %1"
-  [(set_attr "type"     "alu,ld")])
+    andi%.\\t%0, %1, 0xffff
+    ldhu%o1%.\\t%0, %1"
+  "nios2_large_constant_memory_operand_p (operands[1])"
+  [(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
+  {
+    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
+  }
+  [(set_attr "type"     "and,ld")])
 
-(define_insn "zero_extendqi<mode>2"
+(define_insn_and_split "zero_extendqi<mode>2"
   [(set (match_operand:QX 0 "register_operand" "=r,r")
         (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
   ""
   "@
-    andi\\t%0, %1, 0xff
-    ldbu%o1\\t%0, %1"
-  [(set_attr "type"     "alu,ld")])
+    andi%.\\t%0, %1, 0xff
+    ldbu%o1%.\\t%0, %1"
+  "nios2_large_constant_memory_operand_p (operands[1])"
+  [(set (match_dup 0) (zero_extend:QX (match_dup 1)))]
+  {
+    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
+  }
+  [(set_attr "type"     "and,ld")])
 
 ;; Sign extension patterns
 
-(define_insn "extendhisi2"
+(define_insn_and_split "extendhisi2"
   [(set (match_operand:SI 0 "register_operand"                     "=r,r")
         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand"  "r,m")))]
   ""
   "@
    #
-   ldh%o1\\t%0, %1"
+   ldh%o1%.\\t%0, %1"
+  "nios2_large_constant_memory_operand_p (operands[1])"
+  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
+  {
+    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
+  }
   [(set_attr "type" "alu,ld")])
 
-(define_insn "extendqi<mode>2"
+(define_insn_and_split "extendqi<mode>2"
   [(set (match_operand:QX 0 "register_operand"                     "=r,r")
         (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand"  "r,m")))]
   ""
   "@
    #
-   ldb%o1\\t%0, %1"
+   ldb%o1%.\\t%0, %1"
+  "nios2_large_constant_memory_operand_p (operands[1])"
+  [(set (match_dup 0) (sign_extend:QX (match_dup 1)))]
+  {
+    operands[1] = nios2_split_large_constant_memory_operand (operands[1]);
+  }
   [(set_attr "type" "alu,ld")])
 
 ;; Split patterns for register alternative cases.
         (plus:SI (match_operand:SI 1 "register_operand"   "%r")
                  (match_operand:SI 2 "add_regimm_operand" "rIT")))]
   ""
-  "add%i2\\t%0, %1, %z2"
-  [(set_attr "type" "alu")])
+{
+  return nios2_add_insn_asm (insn, operands);
+}
+  [(set_attr "type" "add")])
 
 (define_insn "subsi3"
   [(set (match_operand:SI 0 "register_operand"           "=r")
         (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
                   (match_operand:SI 2 "register_operand" "r")))]
   ""
-  "sub\\t%0, %z1, %2"
-  [(set_attr "type" "alu")])
+  "sub%.\\t%0, %z1, %2"
+  [(set_attr "type" "sub")])
 
 (define_insn "mulsi3"
   [(set (match_operand:SI 0 "register_operand"          "=r")
   [(set (match_operand:SI 0 "register_operand"        "=r")
         (neg:SI (match_operand:SI 1 "register_operand" "r")))]
   ""
-  "sub\\t%0, zero, %1"
-  [(set_attr "type" "alu")])
+{
+  if (get_attr_length (insn) == 2)
+    return "neg.n\\t%0, %1";
+  else
+    return "sub\\t%0, zero, %1";
+}
+  [(set_attr "type" "neg")])
 
 (define_insn "one_cmplsi2"
   [(set (match_operand:SI 0 "register_operand"        "=r")
         (not:SI (match_operand:SI 1 "register_operand" "r")))]
   ""
-  "nor\\t%0, zero, %1"
-  [(set_attr "type" "alu")])
+{
+  if (get_attr_length (insn) == 2)
+    return "not.n\\t%0, %1";
+  else
+    return "nor\\t%0, zero, %1";
+}
+  [(set_attr "type" "not")])
 
 \f
 ;;  Integer logical Operations
 
-(define_code_iterator LOGICAL [and ior xor])
-(define_code_attr logical_asm [(and "and") (ior "or") (xor "xor")])
+(define_insn "andsi3"
+  [(set (match_operand:SI 0 "register_operand"          "=r")
+        (and:SI (match_operand:SI 1 "register_operand"  "%r")
+                (match_operand:SI 2 "and_operand"     "rJKP")))]
+  ""
+  "and%x2%.\\t%0, %1, %y2"
+  [(set_attr "type" "and")])
+
+(define_code_iterator LOGICAL [ior xor])
+(define_code_attr logical_asm [(ior "or") (xor "xor")])
 
 (define_insn "<code>si3"
-  [(set (match_operand:SI 0 "register_operand"             "=r,r,r")
-        (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r,r,r")
-                    (match_operand:SI 2 "logical_operand"  "rM,J,K")))]
+  [(set (match_operand:SI 0 "register_operand"             "=r")
+        (LOGICAL:SI (match_operand:SI 1 "register_operand" "%r")
+                    (match_operand:SI 2 "logical_operand" "rJK")))]
   ""
-  "@
-    <logical_asm>\\t%0, %1, %z2
-    <logical_asm>%i2\\t%0, %1, %2
-    <logical_asm>h%i2\\t%0, %1, %U2"
-  [(set_attr "type" "alu")])
+  "<logical_asm>%x2%.\\t%0, %1, %y2"
+  [(set_attr "type" "<logical_asm>")])
 
 (define_insn "*norsi3"
   [(set (match_operand:SI 0 "register_operand"                 "=r")
         (SHIFT:SI (match_operand:SI 1 "register_operand" "r")
                   (match_operand:SI 2 "shift_operand"    "rL")))]
   ""
-  "<shift_asm>%i2\\t%0, %1, %z2"
-  [(set_attr "type" "shift")])
+  "<shift_asm>%i2%.\\t%0, %1, %z2"
+  [(set_attr "type" "<shift_asm>")])
 
 (define_insn "rotrsi3"
   [(set (match_operand:SI 0 "register_operand"             "=r")
                      (match_operand:SI 2 "register_operand" "r")))]
   ""
   "ror\\t%0, %1, %2"
-  [(set_attr "type" "shift")])
+  [(set_attr "type" "ror")])
+
+;; Nios II R2 Bit Manipulation Extension (BMX), provides
+;; bit merge/insertion/extraction instructions.
+
+(define_insn "*merge"
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand"   "+r")
+                        (match_operand:SI 1 "const_shift_operand" "L")
+                        (match_operand:SI 2 "const_shift_operand" "L"))
+        (zero_extract:SI (match_operand:SI 3 "register_operand"    "r")
+                         (match_dup 1) (match_dup 2)))]
+  "TARGET_HAS_BMX"
+{
+  operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
+  return "merge\\t%0, %3, %4, %2";
+}
+  [(set_attr "type" "alu")])
+
+(define_insn "extzv"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (zero_extract:SI (match_operand:SI 1 "register_operand"    "r")
+                         (match_operand:SI 2 "const_shift_operand" "L")
+                         (match_operand:SI 3 "const_shift_operand" "L")))]
+  "TARGET_HAS_BMX"
+{
+  operands[4] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
+  return "extract\\t%0, %1, %4, %3";
+}
+  [(set_attr "type" "alu")])
+
+(define_insn "insv"
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand"   "+r")
+                        (match_operand:SI 1 "const_shift_operand" "L")
+                        (match_operand:SI 2 "const_shift_operand" "L"))
+       (match_operand:SI 3 "reg_or_0_operand" "rM"))]
+  "TARGET_HAS_BMX"
+{
+  operands[4] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
+  return "insert\\t%0, %z3, %4, %2";
+}
+  [(set_attr "type" "alu")])
+
 
 \f
 ;; Floating point instructions
   DONE;
 })
 
-(define_insn "return"
+(define_expand "return"
   [(simple_return)]
   "nios2_can_use_return_insn ()"
-  "ret")
+{
+  if (nios2_expand_return ())
+    DONE;
+})
 
 (define_insn "simple_return"
   [(simple_return)]
   ""
-  "ret")
+  "ret%."
+  [(set_attr "type" "control")])
 
 ;; Block any insns from being moved before this point, since the
 ;; profiling call to mcount can use various registers that aren't
 ; check or adjust for overflow.
 
 (define_insn "indirect_jump"
-  [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+  [(set (pc) (match_operand:SI 0 "register_operand" "c"))]
   ""
-  "jmp\\t%0"
+  "jmp%!\\t%0"
   [(set_attr "type" "control")])
 
 (define_insn "jump"
         (label_ref (match_operand 0 "" "")))]
   ""
   {
-    if (flag_pic || get_attr_length (insn) == 4)
+    if (get_attr_length (insn) == 2)
+      return "br.n\\t%0";
+    else if (get_attr_length (insn) == 4)
       return "br\\t%0";
     else
       return "jmpi\\t%0";
   [(set_attr "type" "control")
    (set (attr "length") 
         (if_then_else
-           (and (ge (minus (match_dup 0) (pc)) (const_int -32768))
-                (le (minus (match_dup 0) (pc)) (const_int 32764)))
-           (const_int 4)
-           (const_int 8)))])
-
+           (and (match_test "TARGET_HAS_CDX")
+                (and (ge (minus (match_dup 0) (pc)) (const_int -1022))
+                     (le (minus (match_dup 0) (pc)) (const_int 1022))))
+           (const_int 2)
+           (if_then_else
+               (ior (match_test "flag_pic")
+                    (and (ge (minus (match_dup 0) (pc)) (const_int -32764))
+                         (le (minus (match_dup 0) (pc)) (const_int 32764))))
+               (const_int 4)
+               (const_int 8))))])
 
 (define_expand "call"
   [(parallel [(call (match_operand 0 "" "")
                     (match_operand 1 "" ""))
               (clobber (reg:SI RA_REGNO))])]
   ""
-  "nios2_adjust_call_address (&operands[0]);")
+  "nios2_adjust_call_address (&operands[0], NULL_RTX);")
 
 (define_expand "call_value"
   [(parallel [(set (match_operand 0 "" "")
                          (match_operand 2 "" "")))
               (clobber (reg:SI RA_REGNO))])]
   ""
-  "nios2_adjust_call_address (&operands[1]);")
+  "nios2_adjust_call_address (&operands[1], NULL_RTX);")
 
 (define_insn "*call"
   [(call (mem:QI (match_operand:SI 0 "call_operand" "i,r"))
   ""
   "@
    call\\t%0
-   callr\\t%0"
+   callr%.\\t%0"
   [(set_attr "type" "control")])
 
 (define_insn "*call_value"
   ""
   "@
    call\\t%1
-   callr\\t%1"
+   callr%.\\t%1"
   [(set_attr "type" "control")])
 
 (define_expand "sibcall"
                     (match_operand 1 "" ""))
               (return)])]
   ""
-  "nios2_adjust_call_address (&operands[0]);")
+  "nios2_adjust_call_address (&operands[0], NULL_RTX);")
 
 (define_expand "sibcall_value"
   [(parallel [(set (match_operand 0 "" "")
                          (match_operand 2 "" "")))
               (return)])]
   ""
-  "nios2_adjust_call_address (&operands[1]);")
+  "nios2_adjust_call_address (&operands[1], NULL_RTX);")
 
-(define_insn "*sibcall"
+(define_insn "sibcall_internal"
  [(call (mem:QI (match_operand:SI 0 "call_operand" "i,j"))
         (match_operand 1 "" ""))
   (return)]
   ""
   "@
    jmpi\\t%0
-   jmp\\t%0"
+   jmp%!\\t%0"
   [(set_attr "type" "control")])
 
-(define_insn "*sibcall_value"
+(define_insn "sibcall_value_internal"
  [(set (match_operand 0 "register_operand" "")
        (call (mem:QI (match_operand:SI 1 "call_operand" "i,j"))
              (match_operand 2 "" "")))
   ""
   "@
    jmpi\\t%1
-   jmp\\t%1"
+   jmp%!\\t%1"
   [(set_attr "type" "control")])
 
 (define_expand "tablejump"
 
 (define_insn "*tablejump"
   [(set (pc)
-        (match_operand:SI 0 "register_operand" "r"))
+        (match_operand:SI 0 "register_operand" "c"))
    (use (label_ref (match_operand 1 "" "")))]
   ""
-  "jmp\\t%0"
+  "jmp%!\\t%0"
   [(set_attr "type" "control")])
 
 \f
        (label_ref (match_operand 3 "" ""))
        (pc)))]
   ""
-  {
-    if (flag_pic || get_attr_length (insn) == 4)
-      return "b%0\t%z1, %z2, %l3";
-    else
-      return "b%R0\t%z1, %z2, .+8;jmpi\t%l3";
-  }
+{
+  if (get_attr_length (insn) == 2)
+    return "b%0z.n\t%z1, %l3";
+  else if (get_attr_length (insn) == 4)
+    return "b%0\t%z1, %z2, %l3";
+  else if (get_attr_length (insn) == 6)
+    return "b%R0z.n\t%z1, .+6;jmpi\t%l3";
+  else
+    return "b%R0\t%z1, %z2, .+8;jmpi\t%l3";
+}
   [(set_attr "type" "control")
    (set (attr "length") 
-        (if_then_else
-           (and (ge (minus (match_dup 1) (pc)) (const_int -32768))
-                (le (minus (match_dup 1) (pc)) (const_int 32764)))
-           (const_int 4) (const_int 8)))])
+        (cond
+         [(and (match_test "nios2_cdx_narrow_form_p (insn)")
+               (ge (minus (match_dup 3) (pc)) (const_int -126))
+               (le (minus (match_dup 3) (pc)) (const_int 126)))
+          (const_int 2)
+          (ior (match_test "flag_pic")
+               (and (ge (minus (match_dup 3) (pc)) (const_int -32764))
+                    (le (minus (match_dup 3) (pc)) (const_int 32764))))
+          (const_int 4)
+          (match_test "nios2_cdx_narrow_form_p (insn)")
+          (const_int 6)]
+         (const_int 8)))])
 
 ;; Floating point comparisons
 (define_code_iterator FCMP [eq ne gt ge le lt])
         (UCMP:SI (match_operand:SI 1 "reg_or_0_operand"  "rM")
                  (match_operand:SI 2 "uns_arith_operand" "rJ")))]
   ""
-  "cmp<code>%i2\\t%0, %z1, %z2"
+  "cmp<code>%u2\\t%0, %z1, %z2"
   [(set_attr "type" "alu")])
 
 
 (define_insn "nop"
   [(const_int 0)]
   ""
-  "nop"
-  [(set_attr "type" "alu")])
+  "nop%."
+  [(set_attr "type" "nop")])
 
 ;; Connect 'sync' to 'memory_barrier' standard expand name
 (define_expand "memory_barrier"
   "wrctl\\tctl%0, %z1"
   [(set_attr "type" "control")])
 
+(define_insn "rdprs"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")
+                             (match_operand:SI 2 "arith_operand"   "U")]
+         UNSPECV_RDPRS))]
+  ""
+  "rdprs\\t%0, %1, %2"
+  [(set_attr "type" "control")])
+
+;; Cache Instructions
+
+(define_insn "flushd"
+  [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
+                       UNSPECV_FLUSHD)]
+  ""
+  "flushd\\t%0"
+  [(set_attr "type" "control")])
+
+(define_insn "flushda"
+  [(unspec_volatile:SI [(match_operand:SI 0 "ldstio_memory_operand" "w")]
+                       UNSPECV_FLUSHDA)]
+  ""
+  "flushda\\t%0"
+  [(set_attr "type" "control")])
+
+;; R2 Instructions
+
+(define_insn "wrpie"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+        (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")]
+                            UNSPECV_WRPIE))]
+  "TARGET_ARCH_R2"
+  "wrpie\\t%0, %1"
+  [(set_attr "type" "control")])
+
+(define_insn "eni"
+  [(unspec:VOID [(match_operand 0 "const_int_operand" "i")]
+                UNSPECV_ENI)]
+  "TARGET_ARCH_R2"
+  "eni\\t%0"
+  [(set_attr "type" "control")])
+
 ;; Trap patterns
 (define_insn "trap"
   [(trap_if (const_int 1) (const_int 3))]
   ""
-  "break\\t3"
+  "trap%.\\t3"
   [(set_attr "type" "control")])
 
 (define_insn "ctrapsi4"
                (match_operand:SI 2 "reg_or_0_operand" "rM")])
             (match_operand 3 "const_int_operand" "i"))]
   ""
-  "b%R0\\t%z1, %z2, 1f\;break\\t%3\;1:"
+{
+  if (get_attr_length (insn) == 6)
+    return "b%R0\\t%z1, %z2, 1f\;trap.n\\t%3\;1:";
+  else
+    return "b%R0\\t%z1, %z2, 1f\;trap\\t%3\;1:";
+}
   [(set_attr "type" "control")
-   (set_attr "length" "8")])
+   (set (attr "length")
+        (if_then_else (match_test "nios2_cdx_narrow_form_p (insn)")
+                      (const_int 6) (const_int 8)))])
   
 ;; Load the GOT register.
 (define_insn "load_got_register"
   emit_move_insn (operands[0], gen_rtx_REG (Pmode, TP_REGNO));
   DONE;
 })
+
+;; Synchronization Primitives
+(include "sync.md")
+
+;; Include the ldwm/stwm/push.n/pop.n patterns and peepholes.
+(include "ldstwm.md")
+