gcc/ChangeLog:

        * config/loongarch/loongarch.md (*and<mode>3): Delete.
        (*and<mode>3_extend): New.
        (zero_extend<SHORT:mode><GPR:mode>2_la32r): New.
        (extend<SHORT:mode><GPR:mode>2_la32r): New.
        (extendqihi2_la32r): Add TARGET_32BIT_S condition.
        * config/loongarch/sync.md (atomic_<amop><mode>): Change to 
define_expand.
        (la64_atomic_<amop><mode>): New.
        (la32_atomic_<amop>si): New.
        (atomic_fetch_<amop><mode>):  Change to define_expand.
        (la64_atomic_fetch_<amop><mode>): New.
        (la32_atomic_fetch_<amop>si): New.
        (atomic_exchange<mode>):  Change to define_expand.
        (la64_atomic_exchange<mode>): New.
        (la32_atomic_exchangesi): New.
---
 gcc/config/loongarch/loongarch.md | 191 +++++++++++++++++++-----------
 gcc/config/loongarch/sync.md      | 120 +++++++++++++++++--
 2 files changed, 233 insertions(+), 78 deletions(-)

diff --git a/gcc/config/loongarch/loongarch.md 
b/gcc/config/loongarch/loongarch.md
index e23c973c38b..1ea71a84403 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -633,7 +633,7 @@ (define_int_attr bytepick_imm [(8 "1")
 ;; so the redundant sign extension can be removed if the output is used as
 ;; an input of a bitwise operation.  Note plus, rotl, and div are handled
 ;; separately.
-(define_code_iterator shift_w [any_shift rotatert])
+(define_code_iterator shift_w [any_shift (rotatert "!TARGET_32BIT_R")])
 (define_code_iterator arith_w [minus mult])
 
 (define_expand "<optab><mode>3"
@@ -1376,7 +1376,7 @@ (define_insn "ldexp<mode>3"
        (unspec:ANYF [(match_operand:ANYF    1 "register_operand" "f")
                      (match_operand:<IMODE> 2 "register_operand" "f")]
                     UNSPEC_FSCALEB))]
-  "TARGET_HARD_FLOAT"
+  "TARGET_64BIT"
   "fscaleb.<fmt>\t%0,%1,%2"
   [(set_attr "type" "fscaleb")
    (set_attr "mode" "<UNITMODE>")])
@@ -1392,7 +1392,7 @@ (define_insn "logb_non_negative<mode>2"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
        (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
                     UNSPEC_FLOGB))]
-  "TARGET_HARD_FLOAT"
+  "TARGET_64BIT"
   "flogb.<fmt>\t%0,%1"
   [(set_attr "type" "flogb")
    (set_attr "mode" "<UNITMODE>")])
@@ -1401,7 +1401,7 @@ (define_expand "logb<mode>2"
   [(set (match_operand:ANYF 0 "register_operand")
        (unspec:ANYF [(abs:ANYF (match_operand:ANYF 1 "register_operand"))]
                     UNSPEC_FLOGB))]
-  "TARGET_HARD_FLOAT"
+  "TARGET_64BIT"
 {
   rtx tmp = gen_reg_rtx (<MODE>mode);
 
@@ -1421,7 +1421,7 @@ (define_expand "logb<mode>2"
 (define_insn "clz<mode>2"
   [(set (match_operand:GPR 0 "register_operand" "=r")
        (clz:GPR (match_operand:GPR 1 "register_operand" "r")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "clz.<d>\t%0,%1"
   [(set_attr "type" "clz")
    (set_attr "mode" "<MODE>")])
@@ -1437,7 +1437,7 @@ (define_insn "clz<mode>2"
 (define_insn "ctz<mode>2"
   [(set (match_operand:GPR 0 "register_operand" "=r")
        (ctz:GPR (match_operand:GPR 1 "register_operand" "r")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "ctz.<d>\t%0,%1"
   [(set_attr "type" "clz")
    (set_attr "mode" "<MODE>")])
@@ -1553,28 +1553,26 @@ (define_insn "neg<mode>2"
 
 (define_insn "*<optab><mode>3"
   [(set (match_operand:GPR 0 "register_operand" "=r,r")
-       (any_or:GPR (match_operand:GPR 1 "register_operand" "%r,r")
-                   (match_operand:GPR 2 "uns_arith_operand" "r,K")))]
+       (any_bitwise:GPR (match_operand:GPR 1 "register_operand" "%r,r")
+                        (match_operand:GPR 2 "uns_arith_operand" "r,K")))]
   ""
   "<insn>%i2\t%0,%1,%2"
   [(set_attr "type" "logical")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "*and<mode>3"
-  [(set (match_operand:GPR 0 "register_operand" "=r,r,r,r")
-       (and:GPR (match_operand:GPR 1 "register_operand" "%r,r,r,0")
-                (match_operand:GPR 2 "and_operand" "r,K,Yx,Yy")))]
-  ""
+(define_insn "*and<mode>3_extend"
+  [(set (match_operand:GPR 0 "register_operand" "=r,r")
+       (and:GPR (match_operand:GPR 1 "register_operand" "%r,0")
+                (match_operand:GPR 2 "and_operand" "Yx,Yy")))]
+  "TARGET_64BIT || TARGET_32BIT_S"
   "@
-   and\t%0,%1,%2
-   andi\t%0,%1,%2
    * operands[2] = GEN_INT (INTVAL (operands[2]) \
                            & GET_MODE_MASK (<MODE>mode)); \
      return \"bstrpick.<d>\t%0,%1,%M2\";
    * operands[2] = GEN_INT (~INTVAL (operands[2]) \
                            & GET_MODE_MASK (<MODE>mode)); \
      return \"bstrins.<d>\t%0,%.,%M2\";"
-  [(set_attr "move_type" "logical,logical,pick_ins,pick_ins")
+  [(set_attr "move_type" "pick_ins,pick_ins")
    (set_attr "mode" "<MODE>")])
 
 (define_expand "<optab><mode>3"
@@ -1606,7 +1604,8 @@ (define_insn_and_split "*bstrins_<mode>_for_ior_mask"
                   (match_operand:GPR 2 "const_int_operand" "i"))
          (and:GPR (match_operand:GPR 3 "register_operand" "r")
                   (match_operand:GPR 4 "const_int_operand" "i"))))]
-  "loongarch_pre_reload_split ()
+  "(TARGET_64BIT || TARGET_32BIT_S )
+   && loongarch_pre_reload_split ()
    && loongarch_use_bstrins_for_ior_with_mask (<MODE>mode, operands)"
   "#"
   "&& true"
@@ -1675,7 +1674,7 @@ (define_peephole2
                          (match_operand:SI 3 "const_int_operand")
                          (const_int 0))
        (match_dup 0))]
-  "peep2_reg_dead_p (3, operands[0])"
+  "(TARGET_64BIT || TARGET_32BIT_S) && peep2_reg_dead_p (3, operands[0])"
   [(const_int 0)]
   {
     int len = GET_MODE_BITSIZE (<MODE>mode) - INTVAL (operands[3]);
@@ -1736,7 +1735,7 @@ (define_insn "<optab>n<mode>3"
        (neg_bitwise:X
            (not:X (match_operand:X 2 "register_operand" "r"))
            (match_operand:X 1 "register_operand" "r")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "<insn>n\t%0,%1,%2"
   [(set_attr "type" "logical")
    (set_attr "mode" "<MODE>")])
@@ -1835,7 +1834,7 @@ (define_insn "zero_extend<SHORT:mode><GPR:mode>2"
   [(set (match_operand:GPR 0 "register_operand" "=r,r,r")
        (zero_extend:GPR
             (match_operand:SHORT 1 "nonimmediate_operand" "r,m,k")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "@
    bstrpick.w\t%0,%1,<SHORT:7_or_15>,0
    ld.<SHORT:size>u\t%0,%1
@@ -1843,6 +1842,15 @@ (define_insn "zero_extend<SHORT:mode><GPR:mode>2"
   [(set_attr "move_type" "pick_ins,load,load")
    (set_attr "mode" "<GPR:MODE>")])
 
+(define_insn "zero_extend<SHORT:mode><GPR:mode>2_la32r"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+       (zero_extend:GPR
+            (match_operand:SHORT 1 "nonimmediate_operand" "m")))]
+  "TARGET_32BIT_R"
+  "ld.<SHORT:size>u\t%0,%1"
+  [(set_attr "move_type" "load")
+   (set_attr "mode" "<GPR:MODE>")])
+
 (define_insn "zero_extendqihi2"
   [(set (match_operand:HI 0 "register_operand" "=r,r,r")
        (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,k,m")))]
@@ -1860,7 +1868,7 @@ (define_insn "*zero_extend<GPR:mode>_trunc<SHORT:mode>"
   [(set (match_operand:GPR 0 "register_operand" "=r")
        (zero_extend:GPR
            (truncate:SHORT (match_operand:DI 1 "register_operand" "r"))))]
-  "TARGET_64BIT"
+  "TARGET_64BIT || TARGET_32BIT_S"
   "bstrpick.w\t%0,%1,<SHORT:7_or_15>,0"
   [(set_attr "move_type" "pick_ins")
    (set_attr "mode" "<GPR:MODE>")])
@@ -1899,7 +1907,7 @@ (define_insn "extend<SHORT:mode><GPR:mode>2"
   [(set (match_operand:GPR 0 "register_operand" "=r,r,r")
        (sign_extend:GPR
             (match_operand:SHORT 1 "nonimmediate_operand" "r,m,k")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "@
    ext.w.<SHORT:size>\t%0,%1
    ld.<SHORT:size>\t%0,%1
@@ -1907,11 +1915,20 @@ (define_insn "extend<SHORT:mode><GPR:mode>2"
   [(set_attr "move_type" "signext,load,load")
    (set_attr "mode" "<GPR:MODE>")])
 
+(define_insn "extend<SHORT:mode><GPR:mode>2_la32r"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+       (sign_extend:GPR
+            (match_operand:SHORT 1 "nonimmediate_operand" "m")))]
+  "TARGET_32BIT_R"
+  "ld.<SHORT:size>\t%0,%1"
+  [(set_attr "move_type" "load")
+   (set_attr "mode" "<GPR:MODE>")])
+
 (define_insn "extendqihi2"
   [(set (match_operand:HI 0 "register_operand" "=r,r,r")
        (sign_extend:HI
             (match_operand:QI 1 "nonimmediate_operand" "r,m,k")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "@
    ext.w.b\t%0,%1
    ld.b\t%0,%1
@@ -1919,6 +1936,15 @@ (define_insn "extendqihi2"
   [(set_attr "move_type" "signext,load,load")
    (set_attr "mode" "SI")])
 
+(define_insn "extendqihi2_la32r"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (sign_extend:HI
+            (match_operand:QI 1 "nonimmediate_operand" "m")))]
+  ""
+  "ld.b\t%0,%1"
+  [(set_attr "move_type" "load")
+   (set_attr "mode" "SI")])
+
 (define_insn "extendsfdf2"
   [(set (match_operand:DF 0 "register_operand" "=f")
        (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
@@ -2031,7 +2057,7 @@ (define_expand "fixuns_truncdfsi2"
 (define_expand "fixuns_truncdfdi2"
   [(set (match_operand:DI 0 "register_operand")
        (unsigned_fix:DI (match_operand:DF 1 "register_operand")))]
-  "TARGET_DOUBLE_FLOAT"
+  "TARGET_64BIT && TARGET_DOUBLE_FLOAT"
 {
   rtx reg1 = gen_reg_rtx (DFmode);
   rtx reg2 = gen_reg_rtx (DFmode);
@@ -2113,7 +2139,7 @@ (define_expand "fixuns_truncsfsi2"
 (define_expand "fixuns_truncsfdi2"
   [(set (match_operand:DI 0 "register_operand")
        (unsigned_fix:DI (match_operand:SF 1 "register_operand")))]
-  "TARGET_DOUBLE_FLOAT"
+  "TARGET_64BIT && TARGET_DOUBLE_FLOAT"
 {
   rtx reg1 = gen_reg_rtx (SFmode);
   rtx reg2 = gen_reg_rtx (SFmode);
@@ -2163,7 +2189,7 @@ (define_expand "extzv<mode>"
        (zero_extract:X (match_operand:X 1 "register_operand")
                        (match_operand 2 "const_int_operand")
                        (match_operand 3 "const_int_operand")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
 {
   if (!loongarch_use_ins_ext_p (operands[1], INTVAL (operands[2]),
                                INTVAL (operands[3])))
@@ -2173,10 +2199,11 @@ (define_expand "extzv<mode>"
 (define_insn "*extzv<mode>"
   [(set (match_operand:X 0 "register_operand" "=r")
        (zero_extract:X (match_operand:X 1 "register_operand" "r")
-                         (match_operand 2 "const_int_operand" "")
-                         (match_operand 3 "const_int_operand" "")))]
-  "loongarch_use_ins_ext_p (operands[1], INTVAL (operands[2]),
-                           INTVAL (operands[3]))"
+                       (match_operand 2 "const_int_operand" "")
+                       (match_operand 3 "const_int_operand" "")))]
+  "(TARGET_64BIT || TARGET_32BIT_S)
+   && loongarch_use_ins_ext_p (operands[1], INTVAL (operands[2]),
+                              INTVAL (operands[3]))"
 {
   operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
   return "bstrpick.<d>\t%0,%1,%2,%3";
@@ -2189,7 +2216,7 @@ (define_expand "insv<mode>"
                          (match_operand 1 "const_int_operand")
                          (match_operand 2 "const_int_operand"))
        (match_operand:GPR 3 "reg_or_0_operand"))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
 {
   if (!loongarch_use_ins_ext_p (operands[0], INTVAL (operands[1]),
                                INTVAL (operands[2])))
@@ -2201,8 +2228,9 @@ (define_insn "*insv<mode>"
                          (match_operand:SI 1 "const_int_operand" "")
                          (match_operand:SI 2 "const_int_operand" ""))
        (match_operand:GPR 3 "reg_or_0_operand" "rJ"))]
-  "loongarch_use_ins_ext_p (operands[0], INTVAL (operands[1]),
-                           INTVAL (operands[2]))"
+  "(TARGET_64BIT || TARGET_32BIT_S)
+   && loongarch_use_ins_ext_p (operands[0], INTVAL (operands[1]),
+                              INTVAL (operands[2]))"
 {
   operands[1] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[2]) - 1);
   return "bstrins.<d>\t%0,%z3,%1,%2";
@@ -2319,7 +2347,7 @@ (define_insn "la_pcrel64_two_parts"
        (unspec:DI [(match_operand:DI 2 "") (pc)] UNSPEC_LA_PCREL_64_PART1))
    (set (match_operand:DI 1 "register_operand" "=r")
        (unspec:DI [(match_dup 2) (pc)] UNSPEC_LA_PCREL_64_PART2))]
-  "TARGET_ABI_LP64 && la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE"
+  "TARGET_64BIT && la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE"
   {
     return "pcalau12i\t%0,%r2\n\t"
           "addi.d\t%1,$r0,%L2\n\t"
@@ -2337,6 +2365,15 @@ (define_expand "movsi"
        (match_operand:SI 1 ""))]
   ""
 {
+  if (TARGET_32BIT
+      && ((MEM_P (operands[0])
+          && loongarch_14bit_shifted_offset_address_p (XEXP (operands[0], 0), 
SImode)
+          && !loongarch_12bit_offset_address_p (XEXP (operands[0], 0), SImode))
+         || (MEM_P (operands[1])
+             && loongarch_14bit_shifted_offset_address_p (XEXP (operands[1], 
0), SImode)
+             && !loongarch_12bit_offset_address_p (XEXP (operands[1], 0), 
SImode))))
+    FAIL;
+
   if (loongarch_legitimize_move (SImode, operands[0], operands[1]))
     DONE;
 })
@@ -2345,10 +2382,17 @@ (define_insn_and_split "*movsi_internal"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,w,f,f,r,*m")
        (match_operand:SI 1 "move_operand" "r,Yd,w,rJ,rJ,m,f,*f"))]
   "(register_operand (operands[0], SImode)
-    || reg_or_0_operand (operands[1], SImode))"
+    || reg_or_0_operand (operands[1], SImode))
+   && !(TARGET_32BIT
+       && ((MEM_P (operands[0])
+            && loongarch_14bit_shifted_offset_address_p (XEXP (operands[0], 
0), SImode)
+            && !loongarch_12bit_offset_address_p (XEXP (operands[0], 0), 
SImode))
+           || (MEM_P (operands[1])
+               && loongarch_14bit_shifted_offset_address_p (XEXP (operands[1], 
0), SImode)
+               && !loongarch_12bit_offset_address_p (XEXP (operands[1], 0), 
SImode))))"
   { return loongarch_output_move (operands); }
-  "CONST_INT_P (operands[1]) && REG_P (operands[0]) && GP_REG_P (REGNO
-  (operands[0]))"
+  "&& CONST_INT_P (operands[1]) && REG_P (operands[0])
+   && GP_REG_P (REGNO (operands[0]))"
   [(const_int 0)]
   "
 {
@@ -2423,7 +2467,7 @@ (define_insn "*movqi_internal"
 (define_expand "movsf"
   [(set (match_operand:SF 0 "")
        (match_operand:SF 1 ""))]
-  ""
+  "TARGET_HARD_FLOAT"
 {
   if (loongarch_legitimize_move (SFmode, operands[0], operands[1]))
     DONE;
@@ -2454,7 +2498,7 @@ (define_insn "*movsf_softfloat"
 (define_expand "movdf"
   [(set (match_operand:DF 0 "")
        (match_operand:DF 1 ""))]
-  ""
+  "TARGET_DOUBLE_FLOAT"
 {
   if (loongarch_legitimize_move (DFmode, operands[0], operands[1]))
     DONE;
@@ -2559,8 +2603,9 @@ (define_insn "*sel<code><GPR:mode>_using_<X:mode>"
                        (const_int 0))
         (match_operand:GPR 2 "reg_or_0_operand" "r,J")
         (match_operand:GPR 3 "reg_or_0_operand" "J,r")))]
-  "register_operand (operands[2], <GPR:MODE>mode)
-   != register_operand (operands[3], <GPR:MODE>mode)"
+  "(TARGET_64BIT || TARGET_32BIT_S)
+    && register_operand (operands[2], <GPR:MODE>mode)
+       != register_operand (operands[3], <GPR:MODE>mode)"
   "@
    <sel>\t%0,%2,%1
    <selinv>\t%0,%3,%1"
@@ -2622,7 +2667,7 @@ (define_expand "mov<mode>cc"
        (if_then_else:GPR (match_operator 1 "comparison_operator"
                         [(match_operand:GPR 2 "reg_or_0_operand")
                          (match_operand:GPR 3 "reg_or_0_operand")])))]
-  "TARGET_COND_MOVE_INT"
+  "(TARGET_64BIT || TARGET_32BIT_S) && TARGET_COND_MOVE_INT"
 {
   if (!INTEGRAL_MODE_P (GET_MODE (XEXP (operands[1], 0))))
     FAIL;
@@ -2727,7 +2772,7 @@ (define_insn "@pcalau12i<mode>"
   [(set (match_operand:P 0 "register_operand" "=j")
        (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
        UNSPEC_PCALAU12I))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "pcalau12i\t%0,%%pc_hi20(%1)"
   [(set_attr "type" "move")])
 
@@ -2737,7 +2782,7 @@ (define_insn "@pcalau12i_gr<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
        (unspec:P [(match_operand:P 1 "symbolic_operand" "")]
        UNSPEC_PCALAU12I_GR))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "pcalau12i\t%0,%%pc_hi20(%1)"
   [(set_attr "type" "move")])
 
@@ -2787,7 +2832,7 @@ (define_insn "rint<mode>2"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
        (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
                      UNSPEC_FRINT))]
-  ""
+  "TARGET_64BIT"
   "frint.<fmt>\t%0,%1"
   [(set_attr "type" "fcvt")
    (set_attr "mode" "<MODE>")])
@@ -3043,7 +3088,7 @@ (define_insn "loongarch_lddir_<d>"
                       (match_operand 2 "const_uimm5_operand")]
                       UNSPECV_LDDIR)
    (clobber (mem:BLK (scratch)))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "lddir\t%0,%1,%2"
   [(set_attr "type" "load")
    (set_attr "mode" "<MODE>")])
@@ -3053,7 +3098,7 @@ (define_insn "loongarch_ldpte_<d>"
                       (match_operand 1 "const_uimm5_operand")]
                       UNSPECV_LDPTE)
    (clobber (mem:BLK (scratch)))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "ldpte\t%0,%1"
   [(set_attr "type" "load")
    (set_attr "mode" "<MODE>")])
@@ -3131,7 +3176,7 @@ (define_insn "*rotr<mode>3"
   [(set (match_operand:GPR 0 "register_operand" "=r,r")
        (rotatert:GPR (match_operand:GPR 1 "register_operand" "r,r")
                      (match_operand:SI 2 "arith_operand" "r,I")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "rotr%i2.<d>\t%0,%1,%2"
   [(set_attr "type" "shift,shift")
    (set_attr "mode" "<MODE>")])
@@ -3141,7 +3186,7 @@ (define_insn "rotrsi3_extend"
        (sign_extend:DI
          (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
                       (match_operand:SI 2 "arith_operand" "r,I"))))]
-  "TARGET_64BIT"
+  "TARGET_64BIT || TARGET_32BIT_S"
   "rotr%i2.w\t%0,%1,%2"
   [(set_attr "type" "shift,shift")
    (set_attr "mode" "SI")])
@@ -3153,7 +3198,7 @@ (define_expand "rotl<mode>3"
    (set (match_operand:GPR 0 "register_operand")
        (rotatert:GPR (match_operand:GPR 1 "register_operand")
                      (match_dup 3)))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   {
     operands[3] = gen_reg_rtx (SImode);
 
@@ -3176,7 +3221,7 @@ (define_insn "alsl<mode>3"
        (plus:GPR (ashift:GPR (match_operand:GPR 1 "register_operand" "r")
                              (match_operand 2 "const_immalsl_operand" ""))
                  (match_operand:GPR 3 "register_operand" "r")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "alsl.<d>\t%0,%1,%3,%2"
   [(set_attr "type" "arith")
    (set_attr "mode" "<MODE>")])
@@ -3219,8 +3264,9 @@ (define_insn_and_split "<optab>_shift_reverse<X:mode>"
          (ashift:X (match_operand:X  1 "register_operand"  "r")
                    (match_operand:SI 2 "const_int_operand" "i"))
          (match_operand:X 3 "const_int_operand" "i")))]
-  "(const_immalsl_operand (operands[2], SImode)
-    || !<bitwise_operand> (operands[3], <MODE>mode))
+  "TARGET_64BIT
+   && (const_immalsl_operand (operands[2], SImode)
+       || !<bitwise_operand> (operands[3], <MODE>mode))
    && loongarch_reassoc_shift_bitwise (<is_and>, operands[2], operands[3],
                                       <MODE>mode)"
   "#"
@@ -3301,7 +3347,7 @@ (define_insn "revb_2h"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (rotatert:SI (bswap:SI (match_operand:SI 1 "register_operand" "r"))
                     (const_int 16)))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "revb.2h\t%0,%1"
   [(set_attr "type" "shift")])
 
@@ -3311,14 +3357,14 @@ (define_insn "revb_2h_extend"
          (rotatert:SI
            (bswap:SI (match_operand:SI 1 "register_operand" "r"))
            (const_int 16))))]
-  "TARGET_64BIT"
+  "TARGET_64BIT || TARGET_32BIT_S"
   "revb.2h\t%0,%1"
   [(set_attr "type" "shift")])
 
 (define_insn "bswaphi2"
   [(set (match_operand:HI 0 "register_operand" "=r")
        (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "revb.2h\t%0,%1"
   [(set_attr "type" "shift")])
 
@@ -3340,9 +3386,9 @@ (define_insn "*bswapsi2"
 (define_expand "bswapsi2"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (bswap:SI (match_operand:SI 1 "register_operand" "r")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
 {
-  if (!TARGET_64BIT)
+  if (TARGET_32BIT_S)
     {
       rtx t = gen_reg_rtx (SImode);
       emit_insn (gen_revb_2h (t, operands[1]));
@@ -3506,7 +3552,7 @@ (define_expand "cstore<mode>4"
        (match_operator:SI 1 "loongarch_cstore_operator"
         [(match_operand:GPR 2 "register_operand")
          (match_operand:GPR 3 "nonmemory_operand")]))]
-  ""
+  "TARGET_64BIT"
 {
   loongarch_expand_scc (operands);
   DONE;
@@ -4334,7 +4380,7 @@ (define_insn "*bytepick_w_<bytepick_imm>"
                       (const_int <bytepick_w_lshiftrt_amount>))
          (ashift:SI (match_operand:SI 2 "register_operand" "r")
                     (const_int bytepick_w_ashift_amount))))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "bytepick.w\t%0,%1,%2,<bytepick_imm>"
   [(set_attr "mode" "SI")])
 
@@ -4352,7 +4398,7 @@ (define_insn "bytepick_w_<bytepick_imm>_extend"
          (zero_extract:DI (match_operand:DI 2 "register_operand" "r")
                           (const_int <bytepick_w_ashift_amount>)
                           (const_int <bitsize>))))]
-  "TARGET_64BIT"
+  "TARGET_64BIT || TARGET_32BIT_S"
   "bytepick.w\t%0,%2,%1,<bytepick_imm>"
   [(set_attr "mode" "SI")])
 
@@ -4367,7 +4413,7 @@ (define_insn "bytepick_w_1_extend"
          (zero_extract:DI (match_operand:DI 2 "register_operand" "r")
                           (const_int 8)
                           (const_int 24))))]
-  "TARGET_64BIT"
+  "TARGET_64BIT || TARGET_32BIT_S"
   "bytepick.w\t%0,%2,%1,1"
   [(set_attr "mode" "SI")])
 
@@ -4397,7 +4443,7 @@ (define_insn "bitrev_4b"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
                    UNSPEC_BITREV_4B))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "bitrev.4b\t%0,%1"
   [(set_attr "type" "unknown")
    (set_attr "mode" "SI")])
@@ -4406,7 +4452,7 @@ (define_insn "bitrev_8b"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (unspec:DI [(match_operand:DI 1 "register_operand" "r")]
                    UNSPEC_BITREV_8B))]
-  ""
+  "TARGET_64BIT"
   "bitrev.8b\t%0,%1"
   [(set_attr "type" "unknown")
    (set_attr "mode" "DI")])
@@ -4414,7 +4460,7 @@ (define_insn "bitrev_8b"
 (define_insn "@rbit<mode>"
   [(set (match_operand:GPR 0 "register_operand" "=r")
        (bitreverse:GPR (match_operand:GPR 1 "register_operand" "r")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "bitrev.<size>\t%0,%1"
   [(set_attr "type" "unknown")
    (set_attr "mode" "<MODE>")])
@@ -4433,7 +4479,7 @@ (define_insn "rbitsi_extended"
 (define_insn "rbitqi"
   [(set (match_operand:QI 0 "register_operand" "=r")
        (bitreverse:QI (match_operand:QI 1 "register_operand" "r")))]
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
   "bitrev.4b\t%0,%1"
   [(set_attr "type" "unknown")
    (set_attr "mode" "SI")])
@@ -4576,7 +4622,7 @@ (define_insn "loongarch_<crc>_w_<size>_w"
        (unspec:SI [(match_operand:QHWD 1 "register_operand" "r")
                   (match_operand:SI 2 "register_operand" "r")]
                     CRC))]
-  ""
+  "TARGET_64BIT"
   "<crc>.w.<size>.w\t%0,%1,%2"
   [(set_attr "type" "unknown")
    (set_attr "mode" "<MODE>")])
@@ -4597,7 +4643,7 @@ (define_expand "crc_rev<mode>si4"
    (match_operand:SI   1 "register_operand")   ; old_chksum
    (match_operand:SUBDI        2 "reg_or_0_operand")   ; msg
    (match_operand      3 "const_int_operand")] ; poly
-  ""
+  "TARGET_64BIT"
   {
     unsigned HOST_WIDE_INT poly = UINTVAL (operands[3]);
     rtx msg = operands[2];
@@ -4694,7 +4740,8 @@ (define_insn_and_split "*crc_combine"
 (define_insn_and_rewrite "simple_load<mode>"
   [(set (match_operand:LD_AT_LEAST_32_BIT 0 "register_operand" "=r,f")
        (match_operand:LD_AT_LEAST_32_BIT 1 "mem_simple_ldst_operand" ""))]
-  "loongarch_pre_reload_split ()
+  "(TARGET_64BIT || TARGET_32BIT_S)
+   && loongarch_pre_reload_split ()
    && la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO
    && (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM)"
   "#"
@@ -4707,7 +4754,8 @@ (define_insn_and_rewrite 
"simple_load_<su>ext<SUBDI:mode><GPR:mode>"
   [(set (match_operand:GPR 0 "register_operand" "=r")
        (any_extend:GPR
          (match_operand:SUBDI 1 "mem_simple_ldst_operand" "")))]
-  "loongarch_pre_reload_split ()
+  "(TARGET_64BIT || TARGET_32BIT_S)
+   && loongarch_pre_reload_split ()
    && la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO
    && (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM)"
   "#"
@@ -4719,7 +4767,8 @@ (define_insn_and_rewrite 
"simple_load_<su>ext<SUBDI:mode><GPR:mode>"
 (define_insn_and_rewrite "simple_store<mode>"
   [(set (match_operand:ST_ANY 0 "mem_simple_ldst_operand" "")
        (match_operand:ST_ANY 1 "reg_or_0_operand" "r,f"))]
-  "loongarch_pre_reload_split ()
+  "(TARGET_64BIT || TARGET_32BIT_S)
+   && loongarch_pre_reload_split ()
    && la_opt_explicit_relocs == EXPLICIT_RELOCS_AUTO
    && (TARGET_CMODEL_NORMAL || TARGET_CMODEL_MEDIUM)"
   "#"
diff --git a/gcc/config/loongarch/sync.md b/gcc/config/loongarch/sync.md
index 5784dab92a6..91d76af01cc 100644
--- a/gcc/config/loongarch/sync.md
+++ b/gcc/config/loongarch/sync.md
@@ -45,6 +45,10 @@ (define_code_iterator any_atomic [plus ior xor and])
 ;; particular code.
 (define_code_attr amop [(ior "or") (xor "xor") (and "and") (plus "add")])
 
+;; For 32 bit.
+(define_code_attr atomic_optab_insn
+  [(plus "add.w") (ior "or") (xor "xor") (and "and")])
+
 ;; Memory barriers.
 
 (define_expand "mem_thread_fence"
@@ -260,17 +264,48 @@ (define_expand "atomic_storeti"
   DONE;
 })
 
-(define_insn "atomic_<amop><mode>"
+(define_expand "atomic_<amop><mode>"
+  [(any_atomic:GPR (match_operand:GPR 0 "memory_operand")    ;; mem location
+                  (match_operand:GPR 1 "reg_or_0_operand")) ;; value for op
+   (match_operand:SI 2 "const_int_operand")]                ;; model
+  ""
+{
+  if (TARGET_64BIT)
+    emit_insn (gen_la64_atomic_<amop><mode> (operands[0], operands[1], 
operands[2]));
+  else
+    emit_insn (gen_la32_atomic_<amop>si (operands[0], operands[1], 
operands[2]));
+  DONE;
+})
+
+(define_insn "la64_atomic_<amop><mode>"
   [(set (match_operand:GPR 0 "memory_operand" "+ZB")
        (unspec_volatile:GPR
          [(any_atomic:GPR (match_dup 0)
                           (match_operand:GPR 1 "reg_or_0_operand" "rJ"))
           (match_operand:SI 2 "const_int_operand")] ;; model
         UNSPEC_SYNC_OLD_OP))]
-  ""
+  "TARGET_64BIT"
   "am<amop>%A2.<size>\t$zero,%z1,%0"
   [(set (attr "length") (const_int 4))])
 
+(define_insn "la32_atomic_<amop>si"
+  [(set (match_operand:SI 0 "memory_operand" "+ZB")
+       (unspec_volatile:SI
+         [(any_atomic:SI (match_dup 0)
+                          (match_operand:SI 1 "reg_or_0_operand" "rJ"))
+          (match_operand:SI 2 "const_int_operand")] ;; model
+        UNSPEC_SYNC_OLD_OP))
+   (clobber (match_scratch:SI 3 "=&r"))]
+  "!TARGET_64BIT"
+{
+  return "1:\n\t"
+        "ll.w\t%3,%0\n\t"
+        "<atomic_optab_insn>\t%3,%z1,%3\n\t"
+        "sc.w\t%3,%0\n\t"
+        "beq\t$zero,%3,1b\n\t";
+}
+  [(set (attr "length") (const_int 16))])
+
 (define_insn "atomic_add<mode>"
   [(set (match_operand:SHORT 0 "memory_operand" "+ZB")
        (unspec_volatile:SHORT
@@ -282,7 +317,23 @@ (define_insn "atomic_add<mode>"
   "amadd%A2.<size>\t$zero,%z1,%0"
   [(set (attr "length") (const_int 4))])
 
-(define_insn "atomic_fetch_<amop><mode>"
+(define_expand "atomic_fetch_<amop><mode>"
+  [(match_operand:GPR 0 "register_operand")                 ;; old value at mem
+   (any_atomic:GPR (match_operand:GPR 1 "memory_operand")    ;; mem location
+                  (match_operand:GPR 2 "reg_or_0_operand")) ;; value for op
+   (match_operand:SI 3 "const_int_operand")]                ;; model
+  ""
+  {
+    if (TARGET_64BIT)
+      emit_insn (gen_la64_atomic_fetch_<amop><mode> (operands[0], operands[1],
+                                                    operands[2], operands[3]));
+    else
+      emit_insn (gen_la32_atomic_fetch_<amop>si (operands[0], operands[1],
+                                                    operands[2], operands[3]));
+    DONE;
+  })
+
+(define_insn "la64_atomic_fetch_<amop><mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
        (match_operand:GPR 1 "memory_operand" "+ZB"))
    (set (match_dup 1)
@@ -291,10 +342,30 @@ (define_insn "atomic_fetch_<amop><mode>"
                           (match_operand:GPR 2 "reg_or_0_operand" "rJ"))
           (match_operand:SI 3 "const_int_operand")] ;; model
         UNSPEC_SYNC_OLD_OP))]
-  ""
+  "TARGET_64BIT"
   "am<amop>%A3.<size>\t%0,%z2,%1"
   [(set (attr "length") (const_int 4))])
 
+(define_insn "la32_atomic_fetch_<amop>si"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+       (match_operand:SI 1 "memory_operand" "+ZB"))
+   (set (match_dup 1)
+       (unspec_volatile:SI
+         [(any_atomic:SI (match_dup 1)
+                          (match_operand:SI 2 "reg_or_0_operand" "rJ"))
+          (match_operand:SI 3 "const_int_operand")] ;; model
+        UNSPEC_SYNC_OLD_OP))
+   (clobber (match_scratch:SI 4 "=&r"))]
+  "!TARGET_64BIT"
+{
+  return "1:\n\t"
+         "ll.w\t%0,%1\n\t"
+         "<atomic_optab_insn>\t%4,%z2,%0\n\t"
+         "sc.w\t%4,%1\n\t"
+         "beq\t$zero,%4,1b\n\t";
+}
+  [(set (attr "length") (const_int 16))])
+
 (define_insn "atomic_fetch_nand_mask_inverted<mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
        (match_operand:GPR 1 "memory_operand" "+ZC"))
@@ -338,7 +409,23 @@ (define_expand "atomic_fetch_nand<mode>"
     DONE;
   })
 
-(define_insn "atomic_exchange<mode>"
+(define_expand "atomic_exchange<mode>"
+  [(match_operand:GPR 0 "register_operand")  ;; old value at mem
+   (match_operand:GPR 1 "memory_operand")    ;; mem location
+   (match_operand:GPR 2 "register_operand")  ;; value for op
+   (match_operand:SI 3 "const_int_operand")] ;; model
+  ""
+  {
+    if (TARGET_64BIT)
+      emit_insn (gen_la64_atomic_exchange<mode> (operands[0], operands[1],
+                                                operands[2], operands[3]));
+    else
+      emit_insn (gen_la32_atomic_exchangesi (operands[0], operands[1],
+                                                operands[2], operands[3]));
+    DONE;
+  })
+
+(define_insn "la64_atomic_exchange<mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
        (unspec_volatile:GPR
          [(match_operand:GPR 1 "memory_operand" "+ZB")
@@ -346,10 +433,29 @@ (define_insn "atomic_exchange<mode>"
          UNSPEC_SYNC_EXCHANGE))
    (set (match_dup 1)
        (match_operand:GPR 2 "register_operand" "r"))]
-  ""
+  "TARGET_64BIT"
   "amswap%A3.<size>\t%0,%z2,%1"
   [(set (attr "length") (const_int 4))])
 
+(define_insn "la32_atomic_exchangesi"
+  [(set (match_operand:SI 0 "register_operand" "=&r")
+       (unspec_volatile:SI
+         [(match_operand:SI 1 "memory_operand" "+ZB")
+          (match_operand:SI 3 "const_int_operand")] ;; model
+         UNSPEC_SYNC_EXCHANGE))
+   (set (match_dup 1)
+       (match_operand:SI 2 "register_operand" "r"))
+   (clobber (match_scratch:SI 4 "=&r"))]
+  "!TARGET_64BIT"
+{
+  return "1:\n\t"
+        "ll.w\t%0,%1\n\t"
+        "or\t%4,$zero,%2\n\t"
+        "sc.w\t%4,%1\n\t"
+        "beq\t$zero,%4,1b\n\t";
+}
+  [(set (attr "length") (const_int 16))])
+
 (define_insn "atomic_exchangeti_scq"
   [(set (match_operand:TI 0 "register_operand" "=&r")
        (unspec_volatile:TI
@@ -515,7 +621,7 @@ (define_expand "atomic_fetch_<amop><mode>"
    (any_bitwise (match_operand:SHORT 1 "memory_operand"   "+ZB") ;; memory
                (match_operand:SHORT 2 "reg_or_0_operand" "rJ")) ;; val
    (match_operand:SI 3 "const_int_operand" "")]                         ;; 
model
-  ""
+  "TARGET_64BIT || TARGET_32BIT_S"
 {
   /* We have no QI/HImode bitwise atomics, so use the address LSBs to form
      a mask, then use an aligned SImode atomic.  */
-- 
2.34.1

Reply via email to