]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/mips/mips.md
extend.texi: (micromips, nomicromips, nocompression): Document new function attributes.
[thirdparty/gcc.git] / gcc / config / mips / mips.md
index 18ae42302004681d6144c678c5ec2cf74942067d..d8de3405fa16a3dd1c4d9282df4c3eee0f1cb2fe 100644 (file)
 ;; syncloop    memory atomic operation implemented as a sync loop
 ;; nop         no operation
 ;; ghost       an instruction that produces no real code
+;; multimem    microMIPS multiword load and store
 (define_attr "type"
   "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore,
    prefetch,prefetchx,condmove,mtc,mfc,mthi,mtlo,mfhi,mflo,const,arith,logical,
    shift,slt,signext,clz,pop,trap,imul,imul3,imul3nc,imadd,idiv,idiv3,move,
    fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt,
    frsqrt,frsqrt1,frsqrt2,dspmac,dspmacsat,accext,accmod,dspalu,dspalusat,
-   multi,atomic,syncloop,nop,ghost"
+   multi,atomic,syncloop,nop,ghost,multimem"
   (cond [(eq_attr "jal" "!unset") (const_string "call")
         (eq_attr "got" "load") (const_string "load")
 
 
 ;; Length of instruction in bytes.
 (define_attr "length" ""
-   (cond [;; Direct branch instructions have a range of [-0x20000,0x1fffc],
-         ;; relative to the address of the delay slot.  If a branch is
-         ;; outside this range, we have a choice of two sequences.
+   (cond [(and (eq_attr "extended_mips16" "yes")
+              (match_test "TARGET_MIPS16"))
+         (const_int 8)
+
+         ;; Direct microMIPS branch instructions have a range of
+         ;; [-0x10000,0xfffe], otherwise the range is [-0x20000,0x1fffc].
+         ;; If a branch is outside this range, we have a choice of two
+         ;; sequences.
+         ;;
          ;; For PIC, an out-of-range branch like:
          ;;
          ;;    bne     r1,r2,target
          ;; from the shorten_branches reference address.
          (and (eq_attr "type" "branch")
               (not (match_test "TARGET_MIPS16")))
-         (cond [(and (le (minus (match_dup 0) (pc)) (const_int 131064))
-                     (le (minus (pc) (match_dup 0)) (const_int 131068)))
+         (cond [;; Any variant can handle the 17-bit range.
+                (and (le (minus (match_dup 0) (pc)) (const_int 65532))
+                     (le (minus (pc) (match_dup 0)) (const_int 65534)))
+                  (const_int 4)
+
+                ;; The 18-bit range is OK other than for microMIPS.
+                (and (not (match_test "TARGET_MICROMIPS"))
+                     (and (le (minus (match_dup 0) (pc)) (const_int 131064))
+                          (le (minus (pc) (match_dup 0)) (const_int 131068))))
                   (const_int 4)
 
                 ;; The non-PIC case: branch, first delay slot, and J.
 ;; modes.
 (define_mode_iterator GPR2 [SI (DI "TARGET_64BIT")])
 
+(define_mode_iterator MOVEP1 [SI SF])
+(define_mode_iterator MOVEP2 [SI SF])
+
 ;; This mode iterator allows :HILO to be used as the mode of the
 ;; concatenated HI and LO registers.
 (define_mode_iterator HILO [(DI "!TARGET_64BIT") (TI "TARGET_64BIT")])
 (define_insn "mov_<load>l"
   [(set (match_operand:GPR 0 "register_operand" "=d")
        (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m")
-                    (match_operand:QI 2 "memory_operand" "m")]
+                    (match_operand:QI 2 "memory_operand" "ZC")]
                    UNSPEC_LOAD_LEFT))]
   "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])"
   "<load>l\t%0,%2"
 (define_insn "mov_<load>r"
   [(set (match_operand:GPR 0 "register_operand" "=d")
        (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m")
-                    (match_operand:QI 2 "memory_operand" "m")
+                    (match_operand:QI 2 "memory_operand" "ZC")
                     (match_operand:GPR 3 "register_operand" "0")]
                    UNSPEC_LOAD_RIGHT))]
   "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])"
 (define_insn "mov_<store>l"
   [(set (match_operand:BLK 0 "memory_operand" "=m")
        (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
-                    (match_operand:QI 2 "memory_operand" "m")]
+                    (match_operand:QI 2 "memory_operand" "ZC")]
                    UNSPEC_STORE_LEFT))]
   "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])"
   "<store>l\t%z1,%2"
 (define_insn "mov_<store>r"
   [(set (match_operand:BLK 0 "memory_operand" "+m")
        (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
-                    (match_operand:QI 2 "memory_operand" "m")
+                    (match_operand:QI 2 "memory_operand" "ZC")
                     (match_dup 0)]
                    UNSPEC_STORE_RIGHT))]
   "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])"
         (pc)))]
   "!TARGET_MIPS16"
 {
+  /* For a simple BNEZ or BEQZ microMIPS branch.  */
+  if (TARGET_MICROMIPS
+      && operands[3] == const0_rtx
+      && get_attr_length (insn) <= 8)
+    return mips_output_conditional_branch (insn, operands,
+                                          "%*b%C1z%:\t%2,%0",
+                                          "%*b%N1z%:\t%2,%0");
+
   return mips_output_conditional_branch (insn, operands,
                                         MIPS_BRANCH ("b%C1", "%2,%z3,%0"),
                                         MIPS_BRANCH ("b%N1", "%2,%z3,%0"));
         (label_ref (match_operand 0 "" ""))))]
   "!TARGET_MIPS16"
 {
+  /* For a simple BNEZ or BEQZ microMIPS branch.  */
+  if (TARGET_MICROMIPS
+      && operands[3] == const0_rtx
+      && get_attr_length (insn) <= 8)
+    return mips_output_conditional_branch (insn, operands,
+                                          "%*b%N0z%:\t%2,%1",
+                                          "%*b%C0z%:\t%2,%1");
+
   return mips_output_conditional_branch (insn, operands,
                                         MIPS_BRANCH ("b%N1", "%2,%z3,%0"),
                                         MIPS_BRANCH ("b%C1", "%2,%z3,%0"));
   [(set (pc)
        (label_ref (match_operand 0)))]
   "!TARGET_MIPS16 && TARGET_ABSOLUTE_JUMPS"
-  { return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/"); }
+{
+  /* Use a branch for microMIPS.  The assembler will choose
+     a 16-bit branch, a 32-bit branch, or a 32-bit jump.  */
+  if (TARGET_MICROMIPS && !TARGET_ABICALLS_PIC2)
+    return "%*b\t%l0%/";
+  else
+    return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/");
+}
   [(set_attr "type" "jump")])
 
 (define_insn "*jump_pic"
 (define_insn "indirect_jump_<mode>"
   [(set (pc) (match_operand:P 0 "register_operand" "d"))]
   ""
-  "%*j\t%0%/"
+{
+  if (TARGET_MICROMIPS)
+    return "%*jr%:\t%0";
+  else
+    return "%*j\t%0%/";
+}
   [(set_attr "type" "jump")
    (set_attr "mode" "none")])
 
        (match_operand:P 0 "register_operand" "d"))
    (use (label_ref (match_operand 1 "" "")))]
   ""
-  "%*j\t%0%/"
+{
+  if (TARGET_MICROMIPS)
+    return "%*jr%:\t%0";
+  else
+    return "%*j\t%0%/";
+}
   [(set_attr "type" "jump")
    (set_attr "mode" "none")])
 
   [(any_return)
    (use (match_operand 0 "pmode_register_operand" ""))]
   ""
-  "%*j\t%0%/"
+{
+  if (TARGET_MICROMIPS)
+    return "%*jr%:\t%0";
+  else
+    return "%*j\t%0%/";
+}
   [(set_attr "type"    "jump")
    (set_attr "mode"    "none")])
 
   [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S"))
         (match_operand 1 "" ""))]
   "TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
-  { return MIPS_CALL ("j", operands, 0, 1); }
+{
+  if (TARGET_MICROMIPS)
+    return MICROMIPS_J ("j", operands, 0);
+  else
+    return MIPS_CALL ("j", operands, 0, 1);
+}
   [(set_attr "jal" "indirect,direct")
    (set_attr "jal_macro" "no")])
 
         (call (mem:SI (match_operand 1 "call_insn_operand" "j,S"))
               (match_operand 2 "" "")))]
   "TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
-  { return MIPS_CALL ("j", operands, 1, 2); }
+{
+  if (TARGET_MICROMIPS)
+    return MICROMIPS_J ("j", operands, 1);
+  else
+    return MIPS_CALL ("j", operands, 1, 2);
+}
   [(set_attr "jal" "indirect,direct")
    (set_attr "jal_macro" "no")])
 
        (call (mem:SI (match_dup 1))
              (match_dup 2)))]
   "TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
-  { return MIPS_CALL ("j", operands, 1, 2); }
+{
+  if (TARGET_MICROMIPS)
+    return MICROMIPS_J ("j", operands, 1);
+  else
+    return MIPS_CALL ("j", operands, 1, 2);
+}
   [(set_attr "jal" "indirect,direct")
    (set_attr "jal_macro" "no")])
 
 
 
 (define_insn "prefetch"
-  [(prefetch (match_operand:QI 0 "address_operand" "p")
+  [(prefetch (match_operand:QI 0 "address_operand" "ZD")
             (match_operand 1 "const_int_operand" "n")
             (match_operand 2 "const_int_operand" "n"))]
   "ISA_HAS_PREFETCH && TARGET_EXPLICIT_RELOCS"
 ; MIPS fixed-point instructions.
 (include "mips-fixed.md")
 
+; microMIPS patterns.
+(include "micromips.md")
+
 ; ST-Microelectronics Loongson-2E/2F-specific patterns.
 (include "loongson.md")