rs6000.md (UNSPEC_SYNC, [...]): Delete.
authorDavid Edelsohn <edelsohn@gnu.org>
Thu, 7 Jul 2005 14:30:14 +0000 (14:30 +0000)
committerDavid Edelsohn <dje@gcc.gnu.org>
Thu, 7 Jul 2005 14:30:14 +0000 (10:30 -0400)
* config/rs6000/rs6000.md (UNSPEC_SYNC, UNSPEC_SYNC_OP,
UNSPEC_SYNC_SWAP, UNSPEC_LWSYNC, UNSPEC_ISYNC): Delete.
(UNSPECV_LL, UNSPECV_SC, UNSPECV_ATOMIC, UNSPECV_SYNC,
UNSPECV_SYNC_OP, UNSPECV_CMPXCHG, UNSPECV_LWSYNC, UNSPECV_ISYNC): New.
(define_attr "type"): Add isync, sync, load_l, store_c.
* config/rs6000/sync.md (memory_barrier): Change to define_expand.
Create scratch volatile MEM.
(sync_internal): New.  POWER mnemonic is dcs, not ics.  Attribute
sync.
(load_locked_<mode>): New.
(store_conditional_<mode>): New.
(sync_compare_and_swap<mode>): Replace with splitter.
(sync_lock_test_and_set<mode>): Replace with splitter.
(sync_<fetchop><mode>): Change to unspec_volatile UNSPECV_SYNC_OP
and UNSPECV_ISYNC.
(isync): Change to unspec_volatile UNSPECV_ISYNC.  POWER mnemonic
is ics.  Attribute isync.
(lwsync): Change to unspec_volatile UNSPECV_LWSYNC.  Attribute
lwsync.
* config/rs6000/rs6000.c (rs6000_emit_sync): Use UNSPEC_VOLATILE
and UNSPECV_SYNC_OP.
(emit_unlikely_jump): New.
(emit_load_locked): New.
(emit_store_conditional): New.
(rs6000_split_compare_and_swap): New.
(rs6000_split_lock_test_and_set): New.
(is_dispatch_slot_restricted): Return 4 for TYPE_LOAD_L,
TYPE_STORE_C, TYPE_ISYNC, TYPE_SYNC.
* config/rs6000/rs6000-protos.h (rs6000_split_compare_and_swap,
rs6000_split_lock_test_and_set): Declare.
* config/rs6000/{40x.md,440.md,603.md,6xx.md,7450.md,7xx.md,8540.md,
mpc.md,power4.md,power5.md,rios1.md,rios2.md,rs64.md): Add load_l,
store_c, isync, sync.

From-SVN: r101712

18 files changed:
gcc/ChangeLog
gcc/config/rs6000/40x.md
gcc/config/rs6000/440.md
gcc/config/rs6000/603.md
gcc/config/rs6000/6xx.md
gcc/config/rs6000/7450.md
gcc/config/rs6000/7xx.md
gcc/config/rs6000/8540.md
gcc/config/rs6000/mpc.md
gcc/config/rs6000/power4.md
gcc/config/rs6000/power5.md
gcc/config/rs6000/rios1.md
gcc/config/rs6000/rios2.md
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/rs64.md
gcc/config/rs6000/sync.md

index ad5f7c926fbfbb3d0fcd17ef94503ec4b288aa32..1536408978b2cd8ea6b9a119123c2c57e8389c17 100644 (file)
@@ -1,3 +1,39 @@
+2005-07-07  David Edelsohn  <edelsohn@gnu.org>
+
+       * config/rs6000/rs6000.md (UNSPEC_SYNC, UNSPEC_SYNC_OP,
+       UNSPEC_SYNC_SWAP, UNSPEC_LWSYNC, UNSPEC_ISYNC): Delete.
+       (UNSPECV_LL, UNSPECV_SC, UNSPECV_ATOMIC, UNSPECV_SYNC,
+       UNSPECV_SYNC_OP, UNSPECV_CMPXCHG, UNSPECV_LWSYNC, UNSPECV_ISYNC): New.
+       (define_attr "type"): Add isync, sync, load_l, store_c.
+       * config/rs6000/sync.md (memory_barrier): Change to define_expand.
+       Create scratch volatile MEM.
+       (sync_internal): New.  POWER mnemonic is dcs, not ics.  Attribute
+       sync.
+       (load_locked_<mode>): New.
+       (store_conditional_<mode>): New.
+       (sync_compare_and_swap<mode>): Replace with splitter.
+       (sync_lock_test_and_set<mode>): Replace with splitter.
+       (sync_<fetchop><mode>): Change to unspec_volatile UNSPECV_SYNC_OP
+       and UNSPECV_ISYNC.
+       (isync): Change to unspec_volatile UNSPECV_ISYNC.  POWER mnemonic
+       is ics.  Attribute isync.
+       (lwsync): Change to unspec_volatile UNSPECV_LWSYNC.  Attribute
+       lwsync.
+       * config/rs6000/rs6000.c (rs6000_emit_sync): Use UNSPEC_VOLATILE
+       and UNSPECV_SYNC_OP.
+       (emit_unlikely_jump): New.
+       (emit_load_locked): New.
+       (emit_store_conditional): New.
+       (rs6000_split_compare_and_swap): New.
+       (rs6000_split_lock_test_and_set): New.
+       (is_dispatch_slot_restricted): Return 4 for TYPE_LOAD_L,
+       TYPE_STORE_C, TYPE_ISYNC, TYPE_SYNC.
+       * config/rs6000/rs6000-protos.h (rs6000_split_compare_and_swap,
+       rs6000_split_lock_test_and_set): Declare.
+       * config/rs6000/{40x.md,440.md,603.md,6xx.md,7450.md,7xx.md,8540.md,
+       mpc.md,power4.md,power5.md,rios1.md,rios2.md,rs64.md): Add load_l,
+       store_c, isync, sync.
+
 2005-07-07  Kelley Cook  <kcook@gcc.gnu.org>
 
        * Makefile.in (echo_quoted_to_gtyp): New template for outputing
index 9167cb5c3ecaa9950969fb203164ba9ae6b954d9..c1fdce0fc2510dad0f34d0ade1d67d714214ff04 100644 (file)
@@ -27,7 +27,8 @@
 ;; In-order execution
 ;; Max issue two insns/cycle (includes one branch)
 (define_insn_reservation "ppc403-load" 2
-  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+                       load_l,store_c,sync")
        (eq_attr "cpu" "ppc403,ppc405"))
   "iu_40x")
 
   "iu_40x")
 
 (define_insn_reservation "ppc403-jmpreg" 1
-  (and (eq_attr "type" "jmpreg,branch")
+  (and (eq_attr "type" "jmpreg,branch,isync")
        (eq_attr "cpu" "ppc403,ppc405"))
   "bpu_40x")
 
   "bpu_40x")
 
 (define_insn_reservation "ppc405-float" 11
-  (and (eq_attr "type" "fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,fpcompare,fp,dmul,sdiv,ddiv")
+  (and (eq_attr "type" "fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,\
+                       fpcompare,fp,dmul,sdiv,ddiv")
        (eq_attr "cpu" "ppc405"))
   "fpu_405*10")
index 31a5591c25cdf633c3e6722921527d52ef22bd10..6b1b4554d1464dc2be511e570a9f95acee0f70b9 100644 (file)
@@ -34,7 +34,8 @@
 
 
 (define_insn_reservation "ppc440-load" 3
-  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+                       load_l,store_c,sync")
        (eq_attr "cpu" "ppc440"))
   "ppc440_issue,ppc440_l_pipe")
 
@@ -86,7 +87,7 @@
   "ppc440_issue,ppc440_i_pipe*33")
 
 (define_insn_reservation "ppc440-branch" 1
-  (and (eq_attr "type" "branch,jmpreg")
+  (and (eq_attr "type" "branch,jmpreg,isync")
        (eq_attr "cpu" "ppc440"))
   "ppc440_issue,ppc440_i_pipe")
 
index de8983f25642ebce840e33ef86c6bf25388d095d..b094d2a8af71bbcbb400328c96f54adafe98856b 100644 (file)
 ;; CR insns get executed in the SRU.  Not modelled.
 
 (define_insn_reservation "ppc603-load" 2
-  (and (eq_attr "type" "load,load_ext,load_ux,load_u")
+  (and (eq_attr "type" "load,load_ext,load_ux,load_u,load_l")
        (eq_attr "cpu" "ppc603"))
   "lsu_603")
 
-(define_insn_reservation "ppc603-store" 1
+(define_insn_reservation "ppc603-store" 2
   (and (eq_attr "type" "store,store_ux,store_u,fpstore,fpstore_ux,fpstore_u")
        (eq_attr "cpu" "ppc603"))
   "lsu_603")
        (eq_attr "cpu" "ppc603"))
   "lsu_603")
 
+(define_insn_reservation "ppc603-storec" 8
+  (and (eq_attr "type" "store_c")
+       (eq_attr "cpu" "ppc603"))
+  "lsu_603")
+
 (define_insn_reservation "ppc603-integer" 1
   (and (eq_attr "type" "integer,insert_word")
        (eq_attr "cpu" "ppc603"))
   "sru_603")
 
 (define_insn_reservation "ppc603-mfjmpr" 2
-  (and (eq_attr "type" "mfjmpr")
+  (and (eq_attr "type" "mfjmpr,isync,sync")
        (eq_attr "cpu" "ppc603"))
   "sru_603")
 
index f2b1f0aa059646f8b0ce9d4caf6a865de0088fdb..deb0e89c0580b5046d91a6daea5dfe63aa5c7b87 100644 (file)
        (eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
   "lsu_6xx")
 
+(define_insn_reservation "ppc604-llsc" 3
+  (and (eq_attr "type" "load_l,store_c")
+       (eq_attr "cpu" "ppc604,ppc604e"))
+  "lsu_6xx")
+  
+(define_insn_reservation "ppc630-llsc" 4
+  (and (eq_attr "type" "load_l,store_c")
+       (eq_attr "cpu" "ppc620,ppc630"))
+  "lsu_6xx")
+  
 (define_insn_reservation "ppc604-integer" 1
   (and (eq_attr "type" "integer,insert_word")
        (eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
        (eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
   "bpu_6xx")
 
+(define_insn_reservation "ppc604-isync" 0
+  (and (eq_attr "type" "isync")
+       (eq_attr "cpu" "ppc604,ppc604e"))
+  "bpu_6xx")
+  
+(define_insn_reservation "ppc630-isync" 6
+  (and (eq_attr "type" "isync")
+       (eq_attr "cpu" "ppc620,ppc630"))
+  "bpu_6xx")
+  
+(define_insn_reservation "ppc604-sync" 35
+  (and (eq_attr "type" "sync")
+       (eq_attr "cpu" "ppc604,ppc604e"))
+  "lsu_6xx")
+  
+(define_insn_reservation "ppc630-sync" 26
+  (and (eq_attr "type" "sync")
+       (eq_attr "cpu" "ppc620,ppc630"))
+  "lsu_6xx")
+  
index 8514b04944a6e752af2a55983a97f046279b01bc..99e87125fb95e10eaab5b6e9ac6f713930f8cc95 100644 (file)
        (eq_attr "cpu" "ppc7450"))
   "ppc7450_du,lsu_7450*3")
 
+(define_insn_reservation "ppc7450-llsc" 3
+  (and (eq_attr "type" "load_l,store_c")
+       (eq_attr "cpu" "ppc7450"))
+  "ppc7450_du,lsu_7450")
+
+(define_insn_reservation "ppc7450-sync" 35
+  (and (eq_attr "type" "sync")
+       (eq_attr "cpu" "ppc7450"))
+  "ppc7450_du,lsu_7450")
+
 (define_insn_reservation "ppc7450-integer" 1
   (and (eq_attr "type" "integer,insert_word")
        (eq_attr "cpu" "ppc7450"))
   "nothing,mciu_7450*2")
 
 (define_insn_reservation "ppc7450-jmpreg" 1
-  (and (eq_attr "type" "jmpreg,branch")
+  (and (eq_attr "type" "jmpreg,branch,isync")
        (eq_attr "cpu" "ppc7450"))
   "nothing,bpu_7450")
 
index 930882421fc8ba5a220f9a9a41ea1676b730bb25..77e58a3cb6c958bd869a1a3532caabbef1f54b1d 100644 (file)
 
 (define_insn_reservation "ppc750-load" 2
   (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,\
-                       load_ux,load_u,fpload,fpload_ux,fpload_u,vecload")
+                       load_ux,load_u,fpload,fpload_ux,fpload_u,\
+                       vecload,load_l")
        (eq_attr "cpu" "ppc750,ppc7400"))
   "ppc750_du,lsu_7xx")
 
-(define_insn_reservation "ppc750-store" 1
+(define_insn_reservation "ppc750-store" 2
   (and (eq_attr "type" "store,store_ux,store_u,\
                        fpstore,fpstore_ux,fpstore_u,vecstore")
        (eq_attr "cpu" "ppc750,ppc7400"))
   "ppc750_du,lsu_7xx")
 
+(define_insn_reservation "ppc750-storec" 8
+  (and (eq_attr "type" "store_c")
+       (eq_attr "cpu" "ppc750,ppc7400"))
+  "ppc750_du,lsu_7xx")
+
 (define_insn_reservation "ppc750-integer" 1
   (and (eq_attr "type" "integer,insert_word")
        (eq_attr "cpu" "ppc750,ppc7400"))
 (define_insn_reservation "ppc750-crlogical" 3
   (and (eq_attr "type" "cr_logical,delayed_cr")
        (eq_attr "cpu" "ppc750,ppc7400"))
-  "ppc750_du,sru_7xx*2")
+  "nothing,sru_7xx*2")
 
 (define_insn_reservation "ppc750-mtjmpr" 2
-  (and (eq_attr "type" "mtjmpr")
+  (and (eq_attr "type" "mtjmpr,isync,sync")
        (eq_attr "cpu" "ppc750,ppc7400"))
   "nothing,sru_7xx*2")
 
   "nothing,sru_7xx*2")
 
 (define_insn_reservation "ppc750-jmpreg" 1
-  (and (eq_attr "type" "jmpreg,branch")
+  (and (eq_attr "type" "jmpreg,branch,isync")
        (eq_attr "cpu" "ppc750,ppc7400"))
   "nothing,bpu_7xx")
 
index 4b9e7e05d822b364f11f6a3cc8e91c6935e975a3..b42e2472a415c58f60381e435f01dfb140542177 100644 (file)
 
 ;; Branch.  Actually this latency time is not used by the scheduler.
 (define_insn_reservation "ppc8540_branch" 1
-  (and (eq_attr "type" "jmpreg,branch")
+  (and (eq_attr "type" "jmpreg,branch,isync")
        (eq_attr "cpu" "ppc8540"))
   "ppc8540_decode,ppc8540_bu,ppc8540_retire")
 
 
 ;; Loads
 (define_insn_reservation "ppc8540_load" 3
-  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+                       load_l,sync")
        (eq_attr "cpu" "ppc8540"))
   "ppc8540_decode,ppc8540_issue+ppc8540_lsu,nothing,ppc8540_retire")
 
 ;; Stores.
 (define_insn_reservation "ppc8540_store" 3
-  (and (eq_attr "type" "store,store_ux,store_u")
+  (and (eq_attr "type" "store,store_ux,store_u,store_c")
        (eq_attr "cpu" "ppc8540"))
   "ppc8540_decode,ppc8540_issue+ppc8540_lsu,nothing,ppc8540_retire")
 
index 8429d4f329675df13876f9569ef1029429cb6230..242382c01322a534b087e361197a5658ad618df8 100644 (file)
@@ -27,7 +27,8 @@
 ;; 505/801/821/823
 
 (define_insn_reservation "mpccore-load" 2
-  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+                       load_l,store_c,sync")
        (eq_attr "cpu" "mpccore"))
   "lsu_mpc")
 
   "bpu_mpc")
 
 (define_insn_reservation "mpccore-jmpreg" 1
-  (and (eq_attr "type" "jmpreg,branch,cr_logical,delayed_cr,mfcr,mtcr")
+  (and (eq_attr "type" "jmpreg,branch,cr_logical,delayed_cr,mfcr,mtcr,isync")
        (eq_attr "cpu" "mpccore"))
   "bpu_mpc")
 
index 92f63cb32f63022eafc36413610c15a4c3f69efb..53ac066d856a45522429a1cd0b77406a0b5e7231 100644 (file)
   |(du3_power4,lsu2_power4,vec_power4)\
   |(du4_power4,lsu1_power4,vec_power4)")
 
+(define_insn_reservation "power4-llsc" 11
+  (and (eq_attr "type" "load_l,store_c,sync")
+       (eq_attr "cpu" "power4"))
+  "du1_power4+du2_power4+du3_power4+du4_power4,\
+  lsu1_power4")
+
 
 ; Integer latency is 2 cycles
 (define_insn_reservation "power4-integer" 2
   |(du3_power4,fpu2_power4*35)\
   |(du4_power4,fpu2_power4*35)")
 
+(define_insn_reservation "power4-isync" 2
+  (and (eq_attr "type" "isync")
+       (eq_attr "cpu" "power4"))
+  "du1_power4+du2_power4+du3_power4+du4_power4,\
+  lsu1_power4")
+
 
 ; VMX
 (define_insn_reservation "power4-vecsimple" 2
index 0dc1fdc4c02b710805a7d905d7b245450d591fc9..ce6892605d1f3ad06a01bc6ca84c7571fe977e26 100644 (file)
        (eq_attr "cpu" "power5"))
   "du1_power5+du2_power5,lsu1_power5+iu2_power5,fpu1_power5")
 
+(define_insn_reservation "power5-llsc" 11
+  (and (eq_attr "type" "load_l,store_c,sync")
+       (eq_attr "cpu" "power5"))
+  "du1_power5+du2_power5+du3_power5+du4_power5,\
+  lsu1_power5")
+
 
 ; Integer latency is 2 cycles
 (define_insn_reservation "power5-integer" 2
   |(du3_power5,fpu2_power5*35)\
   |(du4_power5,fpu2_power5*35)")
 
+(define_insn_reservation "power5-isync" 2 
+  (and (eq_attr "type" "isync")
+       (eq_attr "cpu" "power5"))
+  "du1_power5+du2_power5+du3_power5+du4_power5,\
+  lsu1_power5")
+
index 0cbca162b2de3334d8cf222cd78bc52c4023ca88..945ee10dd0697b4317e90f35e78df7f16c75dd5d 100644 (file)
@@ -26,7 +26,8 @@
 ;; RIOS1  32-bit IU, FPU, BPU
 
 (define_insn_reservation "rios1-load" 2
-  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+  (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+                       load_l,store_c,sync")
        (eq_attr "cpu" "rios1,ppc601"))
   "iu_rios1")
 
   "iu_rios1,bpu_rios1")
 
 (define_insn_reservation "rios1-branch" 1
-  (and (eq_attr "type" "jmpreg,branch")
+  (and (eq_attr "type" "jmpreg,branch,isync")
        (eq_attr "cpu" "rios1,ppc601"))
   "bpu_rios1")
 
index 8417e354c02a993d069539f56143267d26c42489..6c0966ede41de671123da7dad3504be9f62ce01a 100644 (file)
@@ -29,7 +29,8 @@
 
 (define_insn_reservation "rios2-load" 2
   (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,\
-                       load_ux,load_u,fpload,fpload_ux,fpload_u")
+                       load_ux,load_u,fpload,fpload_ux,fpload_u,\
+                       load_l,store_c,sync")
        (eq_attr "cpu" "rios2"))
   "iu1_rios2|iu2_rios2")
 
   "iu1_rios2,bpu_rios2")
 
 (define_insn_reservation "rios2-branch" 1
-  (and (eq_attr "type" "jmpreg,branch")
+  (and (eq_attr "type" "jmpreg,branch,isync")
        (eq_attr "cpu" "rios2"))
   "bpu_rios2")
 
index 4aebf53d5e6d8d5e2a391f2f9abd0c200f4c66f8..20bdded1cca0e0f851fe62744b082189162143a5 100644 (file)
@@ -82,6 +82,8 @@ extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
 extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
 extern void rs6000_emit_sync (enum rtx_code, enum machine_mode,
                              rtx, rtx, rtx, rtx, bool);
+extern void rs6000_split_compare_and_swap (rtx, rtx, rtx, rtx, rtx);
+extern void rs6000_split_lock_test_and_set (rtx, rtx, rtx, rtx);
 extern void rs6000_emit_swdivsf (rtx, rtx, rtx);
 extern void rs6000_emit_swdivdf (rtx, rtx, rtx);
 extern void output_toc (FILE *, rtx, int, enum machine_mode);
index fb5f3ae4074c4dbbded668e6cadfcdfd640012b8..921d16ff78333068fcfbc01dd1aa446eee14a85b 100644 (file)
@@ -11643,8 +11643,9 @@ rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
   set_after = gen_rtx_SET (VOIDmode, after, the_op);
   set_before = gen_rtx_SET (VOIDmode, before, used_m);
   set_atomic = gen_rtx_SET (VOIDmode, used_m,
-                           gen_rtx_UNSPEC (used_mode, gen_rtvec (1, the_op),
-                                           UNSPEC_SYNC_OP));
+                           gen_rtx_UNSPEC_VOLATILE (used_mode,
+                                                    gen_rtvec (1, the_op),
+                                                    UNSPECV_SYNC_OP));
   cc_scratch = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (CCmode));
 
   if (code == PLUS && used_mode != mode)
@@ -11675,7 +11676,112 @@ rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
     emit_insn (gen_isync ());
 }
 
-/* Emit instructions to move SRC to DST.  Called by splitters for
+/* A subroutine of the atomic operation splitters.  Jump to LABEL if
+   COND is true.  Mark the jump as unlikely to be taken.  */
+
+static void
+emit_unlikely_jump (rtx cond, rtx label)
+{
+  rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
+  rtx x;
+
+  x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
+  x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
+  REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
+}
+
+/* A subroutine of the atomic operation splitters.  Emit a load-locked
+   instruction in MODE.  */
+
+static void
+emit_load_locked (enum machine_mode mode, rtx reg, rtx mem)
+{
+  rtx (*fn) (rtx, rtx) = NULL;
+  if (mode == SImode)
+    fn = gen_load_locked_si;
+  else if (mode == DImode)
+    fn = gen_load_locked_di;
+  emit_insn (fn (reg, mem));
+}
+
+/* A subroutine of the atomic operation splitters.  Emit a store-conditional
+   instruction in MODE.  */
+
+static void
+emit_store_conditional (enum machine_mode mode, rtx res, rtx mem, rtx val)
+{
+  rtx (*fn) (rtx, rtx, rtx) = NULL;
+  if (mode == SImode)
+    fn = gen_store_conditional_si;
+  else if (mode == DImode)
+    fn = gen_store_conditional_di;
+
+  if (PPC405_ERRATUM77)
+    emit_insn (gen_memory_barrier ());
+
+  emit_insn (fn (res, mem, val));
+}
+
+/* Expand an atomic compare and swap operation.  MEM is the memory on which
+   to operate.  OLDVAL is the old value to be compared.  NEWVAL is the new
+   value to be stored.  SCRATCH is a scratch GPR.  */
+
+void
+rs6000_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
+                              rtx scratch)
+{
+  enum machine_mode mode = GET_MODE (mem);
+  rtx label1, label2, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+
+  emit_insn (gen_memory_barrier ());
+
+  label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+  label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+  emit_label (XEXP (label1, 0));
+
+  emit_load_locked (mode, retval, mem);
+
+  x = gen_rtx_COMPARE (CCmode, retval, oldval);
+  emit_insn (gen_rtx_SET (VOIDmode, cond, x));
+
+  x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+  emit_unlikely_jump (x, label2);
+
+  emit_move_insn (scratch, newval);
+  emit_store_conditional (mode, cond, mem, scratch);
+
+  x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+  emit_unlikely_jump (x, label1);
+
+  emit_insn (gen_isync ());
+  emit_label (XEXP (label2, 0));
+}
+
+/* Expand an atomic test and set operation.  MEM is the memory on which
+   to operate.  VAL is the value set.  SCRATCH is a scratch GPR.  */
+
+void
+rs6000_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
+{
+  enum machine_mode mode = GET_MODE (mem);
+  rtx label, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+
+  emit_insn (gen_memory_barrier ());
+
+  label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+  emit_label (XEXP (label, 0));
+
+  emit_load_locked (mode, retval, mem);
+  emit_move_insn (scratch, val);
+  emit_store_conditional (mode, cond, mem, scratch);
+
+  x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+  emit_unlikely_jump (x, label);
+
+  emit_insn (gen_isync ());
+}
+
+  /* Emit instructions to move SRC to DST.  Called by splitters for
    multi-register moves.  It will emit at most one instruction for
    each register that is accessed; that is, it won't emit li/lis pairs
    (or equivalent for 64-bit code).  One of SRC or DST must be a hard
@@ -15795,6 +15901,11 @@ is_dispatch_slot_restricted (rtx insn)
     case TYPE_IDIV:
     case TYPE_LDIV:
       return 2;
+    case TYPE_LOAD_L:
+    case TYPE_STORE_C:
+    case TYPE_ISYNC:
+    case TYPE_SYNC:
+      return 4;
     default:
       if (rs6000_cpu == PROCESSOR_POWER5
          && is_cracked_insn (insn))
index f363a96a339baf4f92e037302e4d960fe7aefd69..1381f7d7865d176cb38af454e2e9990ed434f99d 100644 (file)
    (UNSPEC_FIX_TRUNC_TF                30)     ; fadd, rounding towards zero
    (UNSPEC_MV_CR_GT            31)     ; move_from_CR_eq_bit
    (UNSPEC_STFIWX              32)
-   (UNSPEC_SYNC                        33)
-   (UNSPEC_SYNC_OP             34)
-   (UNSPEC_SYNC_SWAP           35)
-   (UNSPEC_LWSYNC              36)
-   (UNSPEC_ISYNC               37)
    (UNSPEC_POPCNTB             38)
    (UNSPEC_FRES                        39)
    (UNSPEC_SP_SET              40)
 
 (define_constants
   [(UNSPECV_BLOCK              0)
+   (UNSPECV_LL                 1)      ; load-locked
+   (UNSPECV_SC                 2)      ; store-conditional
+   (UNSPECV_ATOMIC             3)
+   (UNSPECV_SYNC               4)
+   (UNSPECV_SYNC_OP            5)
+   (UNSPECV_CMPXCHG            6)
+   (UNSPECV_LWSYNC             7)
+   (UNSPECV_ISYNC              8)
    (UNSPECV_EH_RR              9)      ; eh_reg_restore
   ])
 \f
 ;; Define an insn type attribute.  This is used in function unit delay
 ;; computations.
-(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv"
+(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,isync,sync,load_l,store_c"
   (const_string "integer"))
 
 ;; Length (in bytes).
index 001ab79230eae32f53b35d71e792570cb8c78ffe..503130f332643a00b5ec56fcc43c3a02b0d62a2e 100644 (file)
        (eq_attr "cpu" "rs64a"))
   "lsu_rs64")
 
+(define_insn_reservation "rs64a-llsc" 2
+  (and (eq_attr "type" "load_l,store_c")
+       (eq_attr "cpu" "rs64a"))
+  "lsu_rs64")
+
 (define_insn_reservation "rs64a-integer" 1
   (and (eq_attr "type" "integer,insert_word")
        (eq_attr "cpu" "rs64a"))
        (eq_attr "cpu" "rs64a"))
   "bpu_rs64")
 
+(define_insn_reservation "rs64a-isync" 6
+  (and (eq_attr "type" "isync")
+       (eq_attr "cpu" "rs64a"))
+  "bpu_rs64")
+
+(define_insn_reservation "rs64a-sync" 1
+  (and (eq_attr "type" "sync")
+       (eq_attr "cpu" "rs64a"))
+  "lsu_rs64")
+
index ac8e64990c6df283c32cebd39e09ae5d549e4dcd..a98dc1545d350574fbec24dbcb2df0d33d669796 100644 (file)
 (define_mode_attr larx [(SI "lwarx") (DI "ldarx")])
 (define_mode_attr stcx [(SI "stwcx.") (DI "stdcx.")])
 
-(define_insn "memory_barrier"
-  [(set (mem:BLK (match_scratch 0 "X"))
-       (unspec:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_SYNC))]
+(define_expand "memory_barrier"
+  [(set (mem:BLK (match_dup 0))
+        (unspec_volatile:BLK [(mem:BLK (match_dup 0))] UNSPECV_SYNC))]
   ""
-  "{ics|sync}")
-
-(define_expand "sync_compare_and_swap<mode>"
-  [(parallel [(set (match_operand:GPR 1 "memory_operand" "")
-                  (unspec:GPR [(match_dup 1)
-                               (match_operand:GPR 2 "reg_or_short_operand" "")
-                               (match_operand:GPR 3 "gpc_reg_operand" "")]
-                              UNSPEC_SYNC_SWAP))
-             (set (match_operand:GPR 0 "gpc_reg_operand" "") (match_dup 1))
-             (set (mem:BLK (match_scratch 5 ""))
-                  (unspec:BLK [(mem:BLK (match_scratch 6 ""))] UNSPEC_SYNC))
-             (clobber (match_scratch:CC 4 ""))])]
-  "TARGET_POWERPC")
-
-(define_insn "sync_compare_and_swap<mode>_internal"
-  [(set (match_operand:GPR 1 "memory_operand" "+Z")
-       (unspec:GPR [(match_dup 1)
-                    (match_operand:GPR 2 "reg_or_short_operand" "rI")
-                    (match_operand:GPR 3 "gpc_reg_operand" "r")]
-                   UNSPEC_SYNC_SWAP))
-   (set (match_operand:GPR 0 "gpc_reg_operand" "=&r") (match_dup 1))
-   (set (mem:BLK (match_scratch 5 "X"))
-       (unspec:BLK [(mem:BLK (match_scratch 6 "X"))] UNSPEC_SYNC))
-   (clobber (match_scratch:CC 4 "=&x"))]
-  "TARGET_POWERPC && !PPC405_ERRATUM77"
-  "sync\n\t<larx> %0,%y1\n\tcmp<wd>%I2 %0,%2\n\tbne- $+12\n\t<stcx> %3,%y1\n\tbne- $-16\n\tisync"
-  [(set_attr "length" "28")])
+{
+  operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+  MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*sync_internal"
+  [(set (match_operand:BLK 0 "" "")
+        (unspec_volatile:BLK [(match_operand:BLK 1 "" "")] UNSPECV_SYNC))]
+  ""
+  "{dcs|sync}"
+  [(set_attr "type" "sync")])
+
+(define_insn "load_locked_<mode>"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+       (unspec_volatile:GPR
+         [(match_operand:GPR 1 "memory_operand" "m")] UNSPECV_LL))]
+  "TARGET_POWERPC"
+  "<larx> %0,%y1"
+  [(set_attr "type" "load_l")])
+
+(define_insn "store_conditional_<mode>"
+  [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+       (unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
+   (set (match_operand:GPR 1 "memory_operand" "=m")
+       (match_operand:GPR 2 "gpc_reg_operand" "r"))]
+  "TARGET_POWERPC"
+  "<stcx> %2,%y1"
+  [(set_attr "type" "store_c")])
+
+(define_insn_and_split "sync_compare_and_swap<mode>"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
+       (match_operand:GPR 1 "memory_operand" "+m"))
+   (set (match_dup 1)
+       (unspec_volatile:GPR
+         [(match_operand:GPR 2 "reg_or_short_operand" "rI")
+          (match_operand:GPR 3 "gpc_reg_operand" "r")]
+         UNSPECV_CMPXCHG))
+   (clobber (match_scratch:GPR 4 "=&r"))
+   (clobber (match_scratch:CC 5 "=&x"))]
+  "TARGET_POWERPC"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  rs6000_split_compare_and_swap (operands[0], operands[1], operands[2],
+                                operands[3], operands[4]);
+  DONE;
+})
 
-(define_insn "sync_compare_and_swap<mode>_ppc405"
-  [(set (match_operand:GPR 1 "memory_operand" "+Z")
-       (unspec:GPR [(match_dup 1)
-                    (match_operand:GPR 2 "reg_or_short_operand" "rI")
-                    (match_operand:GPR 3 "gpc_reg_operand" "r")]
-                   UNSPEC_SYNC_SWAP))
-   (set (match_operand:GPR 0 "gpc_reg_operand" "=&r") (match_dup 1))
-   (set (mem:BLK (match_scratch 5 "X"))
-       (unspec:BLK [(mem:BLK (match_scratch 6 "X"))] UNSPEC_SYNC))
+(define_insn_and_split "sync_lock_test_and_set<mode>"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
+        (match_operand:GPR 1 "memory_operand" "+m"))
+   (set (match_dup 1)
+       (unspec_volatile:GPR
+         [(match_operand:GPR 2 "reg_or_short_operand" "rL")]
+         UNSPECV_CMPXCHG))
+   (clobber (match_scratch:GPR 3 "=&r"))
    (clobber (match_scratch:CC 4 "=&x"))]
-  "TARGET_POWERPC && PPC405_ERRATUM77"
-  "sync\n\t<larx> %0,%y1\n\tcmp<wd>%I2 %0,%2\n\tbne- $+12\n\tsync\n\t<stcx> %3,%y1\n\tbne- $-16\n\tisync"
-  [(set_attr "length" "32")])
+  "TARGET_POWERPC"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  rs6000_split_lock_test_and_set (operands[0], operands[1], operands[2],
+                                 operands[3]);
+  DONE;
+})
 
 (define_expand "sync_add<mode>"
   [(use (match_operand:INT1 0 "memory_operand" ""))
                 (match_operand:GPR 1 "add_operand" "rI,L")))
    (set (match_operand:GPR 3 "gpc_reg_operand" "=&b,&b") (match_dup 0))
    (set (match_dup 0) 
-       (unspec:GPR [(plus:GPR (match_dup 0) (match_dup 1))]
-                  UNSPEC_SYNC_OP))
+       (unspec_volatile:GPR [(plus:GPR (match_dup 0) (match_dup 1))]
+                  UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 4 "=&x,&x"))]
   "TARGET_POWERPC && !PPC405_ERRATUM77"
   "@
                (and:SI (not:SI (match_dup 4)) (match_dup 0))))
    (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
    (set (match_dup 0) 
-       (unspec:SI [(ior:SI (and:SI (plus:SI (match_dup 0) (match_dup 1))
+       (unspec_volatile:SI [(ior:SI (and:SI (plus:SI (match_dup 0) (match_dup 1))
                                    (match_dup 4))
                            (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
-                  UNSPEC_SYNC_OP))
+                  UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 5 "=&x"))
    (clobber (match_scratch:SI 6 "=&r"))]
   "TARGET_POWERPC && !PPC405_ERRATUM77"
                  (match_operand:GPR 1 "gpc_reg_operand" "r")))
    (set (match_operand:GPR 3 "gpc_reg_operand" "=&b") (match_dup 0))
    (set (match_dup 0) 
-       (unspec:GPR [(minus:GPR (match_dup 0) (match_dup 1))]
-                  UNSPEC_SYNC_OP))
+       (unspec_volatile:GPR [(minus:GPR (match_dup 0) (match_dup 1))]
+                  UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 4 "=&x"))]
   "TARGET_POWERPC && !PPC405_ERRATUM77"
   "<larx> %3,%y0\n\tsubf %2,%1,%3\n\t<stcx> %2,%y0\n\tbne- $-12"
                (match_operand:SI 1 "and_operand" "r,T,K,L")))
    (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b,&b") (match_dup 0))
    (set (match_dup 0) 
-       (unspec:SI [(and:SI (match_dup 0) (match_dup 1))]
-                  UNSPEC_SYNC_OP))
+       (unspec_volatile:SI [(and:SI (match_dup 0) (match_dup 1))]
+                  UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 4 "=&x,&x,&x,&x"))]
   "TARGET_POWERPC && !PPC405_ERRATUM77"
   "@
                (match_operand:DI 1 "and_operand" "r,S,T,K,J")))
    (set (match_operand:DI 3 "gpc_reg_operand" "=&b,&b,&b,&b,&b") (match_dup 0))
    (set (match_dup 0) 
-       (unspec:DI [(and:DI (match_dup 0) (match_dup 1))]
-                  UNSPEC_SYNC_OP))
+       (unspec_volatile:DI [(and:DI (match_dup 0) (match_dup 1))]
+                  UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 4 "=&x,&x,&x,&x,&x"))]
   "TARGET_POWERPC64"
   "@
         [(match_operand:SI 0 "memory_operand" "+Z,Z,Z")
          (match_operand:SI 1 "logical_operand" "r,K,L")]))
    (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0))
-   (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
+   (set (match_dup 0) (unspec_volatile:SI [(match_dup 4)] UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 5 "=&x,&x,&x"))]
   "TARGET_POWERPC && !PPC405_ERRATUM77"
   "@
         [(match_operand:DI 0 "memory_operand" "+Z,Z,Z")
          (match_operand:DI 1 "logical_operand" "r,K,JF")]))
    (set (match_operand:DI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0))
-   (set (match_dup 0) (unspec:DI [(match_dup 4)] UNSPEC_SYNC_OP))
+   (set (match_dup 0) (unspec_volatile:DI [(match_dup 4)] UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 5 "=&x,&x,&x"))]
   "TARGET_POWERPC64"
   "@
         [(not:GPR (match_operand:GPR 0 "memory_operand" "+Z"))
          (match_operand:GPR 1 "gpc_reg_operand" "r")]))
    (set (match_operand:GPR 3 "gpc_reg_operand" "=&b") (match_dup 0))
-   (set (match_dup 0) (unspec:GPR [(match_dup 4)] UNSPEC_SYNC_OP))
+   (set (match_dup 0) (unspec_volatile:GPR [(match_dup 4)] UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 5 "=&x"))]
   "TARGET_POWERPC && !PPC405_ERRATUM77"
   "<larx> %3,%y0\n\t%q4 %2,%1,%3\n\t<stcx> %2,%y0\n\tbne- $-12"
                  (match_operand:SI 5 "logical_operand" "rK"))
          (match_operand:SI 1 "gpc_reg_operand" "r")]))
    (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
-   (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
+   (set (match_dup 0) (unspec_volatile:SI [(match_dup 4)] UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 6 "=&x"))]
   "TARGET_POWERPC && !PPC405_ERRATUM77"
   "lwarx %3,%y0\n\txor%I2 %2,%3,%5\n\t%q4 %2,%2,%1\n\tstwcx. %2,%y0\n\tbne- $-16"
         [(not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))
          (match_operand:GPR 0 "memory_operand" "+Z")]))
    (set (match_operand:GPR 3 "gpc_reg_operand" "=&b") (match_dup 0))
-   (set (match_dup 0) (unspec:GPR [(match_dup 4)] UNSPEC_SYNC_OP))
+   (set (match_dup 0) (unspec_volatile:GPR [(match_dup 4)] UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 5 "=&x"))]
   "TARGET_POWERPC && !PPC405_ERRATUM77"
   "<larx> %3,%y0\n\t%q4 %2,%3,%1\n\t<stcx> %2,%y0\n\tbne- $-12"
         [(not:GPR (match_operand:GPR 0 "memory_operand" "+Z"))
          (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r"))]))
    (set (match_operand:GPR 3 "gpc_reg_operand" "=&b") (match_dup 0))
-   (set (match_dup 0) (unspec:GPR [(match_dup 4)] UNSPEC_SYNC_OP))
+   (set (match_dup 0) (unspec_volatile:GPR [(match_dup 4)] UNSPECV_SYNC_OP))
    (clobber (match_scratch:CC 5 "=&x"))]
   "TARGET_POWERPC && !PPC405_ERRATUM77"
   "<larx> %3,%y0\n\t%q4 %2,%1,%3\n\t<stcx> %2,%y0\n\tbne- $-12"
 
 (define_insn "isync"
   [(set (mem:BLK (match_scratch 0 "X"))
-        (unspec:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_ISYNC))]
-  "TARGET_POWERPC"
-  "isync")
-
-(define_insn "sync_lock_test_and_set<mode>"
-  [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
-       (match_operand:GPR 1 "memory_operand" "+Z"))
-   (set (match_dup 1) (unspec:GPR [(match_operand:GPR 2 "gpc_reg_operand" "r")] 
-                                UNSPEC_SYNC_OP))
-   (clobber (match_scratch:CC 3 "=&x"))
-   (set (mem:BLK (match_scratch 4 "X"))
-        (unspec:BLK [(mem:BLK (match_scratch 5 "X"))] UNSPEC_ISYNC))]
-  "TARGET_POWERPC && !PPC405_ERRATUM77"
-  "<larx> %0,%y1\n\t<stcx> %2,%y1\n\tbne- $-8\n\tisync"
-  [(set_attr "length" "16")])
+        (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPECV_ISYNC))]
+  ""
+  "{ics|isync}"
+  [(set_attr "type" "isync")])
 
 (define_expand "sync_lock_release<mode>"
   [(set (match_operand:INT 0 "memory_operand")
 ; Some AIX assemblers don't accept lwsync, so we use a .long.
 (define_insn "lwsync"
   [(set (mem:BLK (match_scratch 0 "X"))
-        (unspec:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_LWSYNC))]
+        (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPECV_LWSYNC))]
   ""
-  ".long 0x7c2004ac")
+  ".long 0x7c2004ac"
+  [(set_attr "type" "sync")])