1169689Skan;; GCC machine description for SPARC synchronization instructions. 2169689Skan;; Copyright (C) 2005 3169689Skan;; Free Software Foundation, Inc. 4169689Skan;; 5169689Skan;; This file is part of GCC. 6169689Skan;; 7169689Skan;; GCC is free software; you can redistribute it and/or modify 8169689Skan;; it under the terms of the GNU General Public License as published by 9169689Skan;; the Free Software Foundation; either version 2, or (at your option) 10169689Skan;; any later version. 11169689Skan;; 12169689Skan;; GCC is distributed in the hope that it will be useful, 13169689Skan;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14169689Skan;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15169689Skan;; GNU General Public License for more details. 16169689Skan;; 17169689Skan;; You should have received a copy of the GNU General Public License 18169689Skan;; along with GCC; see the file COPYING. If not, write to 19169689Skan;; the Free Software Foundation, 51 Franklin Street, Fifth Floor, 20169689Skan;; Boston, MA 02110-1301, USA. 21169689Skan 22169689Skan(define_mode_macro I12MODE [QI HI]) 23169689Skan(define_mode_macro I24MODE [HI SI]) 24169689Skan(define_mode_macro I48MODE [SI (DI "TARGET_ARCH64 || TARGET_V8PLUS")]) 25169689Skan(define_mode_attr modesuffix [(SI "") (DI "x")]) 26169689Skan 27169689Skan(define_expand "memory_barrier" 28169689Skan [(set (mem:BLK (match_dup 0)) 29169689Skan (unspec_volatile:BLK [(mem:BLK (match_dup 0)) (match_dup 1)] 30169689Skan UNSPECV_MEMBAR))] 31169689Skan "TARGET_V8 || TARGET_V9" 32169689Skan{ 33169689Skan operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode)); 34169689Skan MEM_VOLATILE_P (operands[0]) = 1; 35169689Skan if (TARGET_V9) 36169689Skan /* member #StoreStore | #LoadStore | #StoreLoad | #LoadLoad */ 37169689Skan operands[1] = GEN_INT (15); 38169689Skan else 39169689Skan /* stbar */ 40169689Skan operands[1] = GEN_INT (8); 41169689Skan}) 42169689Skan 43169689Skan(define_insn "*stbar" 44169689Skan [(set (match_operand:BLK 0 "" "") 45169689Skan (unspec_volatile:BLK [(match_operand:BLK 1 "" "") 46169689Skan (const_int 8)] UNSPECV_MEMBAR))] 47169689Skan "TARGET_V8" 48169689Skan "stbar" 49169689Skan [(set_attr "type" "multi")]) 50169689Skan 51169689Skan(define_insn "*membar" 52169689Skan [(set (match_operand:BLK 0 "" "") 53169689Skan (unspec_volatile:BLK [(match_operand:BLK 1 "" "") 54169689Skan (match_operand:SI 2 "immediate_operand" "I")] 55169689Skan UNSPECV_MEMBAR))] 56169689Skan "TARGET_V9" 57169689Skan "membar\t%2" 58169689Skan [(set_attr "type" "multi")]) 59169689Skan 60169689Skan(define_expand "sync_compare_and_swap<mode>" 61169689Skan [(match_operand:I12MODE 0 "register_operand" "") 62169689Skan (match_operand:I12MODE 1 "memory_operand" "") 63169689Skan (match_operand:I12MODE 2 "register_operand" "") 64169689Skan (match_operand:I12MODE 3 "register_operand" "")] 65169689Skan "TARGET_V9" 66169689Skan{ 67169689Skan sparc_expand_compare_and_swap_12 (operands[0], operands[1], 68169689Skan operands[2], operands[3]); 69169689Skan DONE; 70169689Skan}) 71169689Skan 72169689Skan(define_expand "sync_compare_and_swap<mode>" 73169689Skan [(parallel 74169689Skan [(set (match_operand:I48MODE 0 "register_operand" "=r") 75169689Skan (match_operand:I48MODE 1 "memory_operand" "")) 76169689Skan (set (match_dup 1) 77169689Skan (unspec_volatile:I48MODE 78169689Skan [(match_operand:I48MODE 2 "register_operand" "") 79169689Skan (match_operand:I48MODE 3 "register_operand" "")] 80169689Skan UNSPECV_CAS))])] 81169689Skan "TARGET_V9" 82169689Skan{ 83169689Skan if (! REG_P (XEXP (operands[1], 0))) 84169689Skan { 85169689Skan rtx addr = force_reg (Pmode, XEXP (operands[1], 0)); 86169689Skan operands[1] = replace_equiv_address (operands[1], addr); 87169689Skan } 88169689Skan emit_insn (gen_memory_barrier ()); 89169689Skan}) 90169689Skan 91169689Skan(define_insn "*sync_compare_and_swap<mode>" 92169689Skan [(set (match_operand:I48MODE 0 "register_operand" "=r") 93169689Skan (match_operand:I48MODE 1 "memory_reg_operand" "+m")) 94169689Skan (set (match_dup 1) 95169689Skan (unspec_volatile:I48MODE 96169689Skan [(match_operand:I48MODE 2 "register_operand" "r") 97169689Skan (match_operand:I48MODE 3 "register_operand" "0")] 98169689Skan UNSPECV_CAS))] 99169689Skan "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)" 100169689Skan "cas<modesuffix>\t%1, %2, %0" 101169689Skan [(set_attr "type" "multi")]) 102169689Skan 103169689Skan(define_insn "*sync_compare_and_swapdi_v8plus" 104169689Skan [(set (match_operand:DI 0 "register_operand" "=h") 105169689Skan (match_operand:DI 1 "memory_reg_operand" "+m")) 106169689Skan (set (match_dup 1) 107169689Skan (unspec_volatile:DI 108169689Skan [(match_operand:DI 2 "register_operand" "h") 109169689Skan (match_operand:DI 3 "register_operand" "0")] 110169689Skan UNSPECV_CAS))] 111169689Skan "TARGET_V8PLUS" 112169689Skan{ 113169689Skan if (sparc_check_64 (operands[3], insn) <= 0) 114169689Skan output_asm_insn ("srl\t%L3, 0, %L3", operands); 115169689Skan output_asm_insn ("sllx\t%H3, 32, %H3", operands); 116169689Skan output_asm_insn ("or\t%L3, %H3, %L3", operands); 117169689Skan if (sparc_check_64 (operands[2], insn) <= 0) 118169689Skan output_asm_insn ("srl\t%L2, 0, %L2", operands); 119169689Skan output_asm_insn ("sllx\t%H2, 32, %H3", operands); 120169689Skan output_asm_insn ("or\t%L2, %H3, %H3", operands); 121169689Skan output_asm_insn ("casx\t%1, %H3, %L3", operands); 122169689Skan return "srlx\t%L3, 32, %H3"; 123169689Skan} 124169689Skan [(set_attr "type" "multi") 125169689Skan (set_attr "length" "8")]) 126169689Skan 127169689Skan(define_expand "sync_lock_test_and_set<mode>" 128169689Skan [(match_operand:I12MODE 0 "register_operand" "") 129169689Skan (match_operand:I12MODE 1 "memory_operand" "") 130169689Skan (match_operand:I12MODE 2 "arith_operand" "")] 131169689Skan "!TARGET_V9" 132169689Skan{ 133169689Skan if (operands[2] != const1_rtx) 134169689Skan FAIL; 135169689Skan if (TARGET_V8) 136169689Skan emit_insn (gen_memory_barrier ()); 137169689Skan if (<MODE>mode != QImode) 138169689Skan operands[1] = adjust_address (operands[1], QImode, 0); 139169689Skan emit_insn (gen_ldstub<mode> (operands[0], operands[1])); 140169689Skan DONE; 141169689Skan}) 142169689Skan 143169689Skan(define_expand "sync_lock_test_and_setsi" 144169689Skan [(parallel 145169689Skan [(set (match_operand:SI 0 "register_operand" "") 146169689Skan (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "")] 147169689Skan UNSPECV_SWAP)) 148169689Skan (set (match_dup 1) 149169689Skan (match_operand:SI 2 "arith_operand" ""))])] 150169689Skan "" 151169689Skan{ 152169689Skan if (! TARGET_V8 && ! TARGET_V9) 153169689Skan { 154169689Skan if (operands[2] != const1_rtx) 155169689Skan FAIL; 156169689Skan operands[1] = adjust_address (operands[1], QImode, 0); 157169689Skan emit_insn (gen_ldstubsi (operands[0], operands[1])); 158169689Skan DONE; 159169689Skan } 160169689Skan emit_insn (gen_memory_barrier ()); 161169689Skan operands[2] = force_reg (SImode, operands[2]); 162169689Skan}) 163169689Skan 164169689Skan(define_insn "*swapsi" 165169689Skan [(set (match_operand:SI 0 "register_operand" "=r") 166169689Skan (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "+m")] 167169689Skan UNSPECV_SWAP)) 168169689Skan (set (match_dup 1) 169169689Skan (match_operand:SI 2 "register_operand" "0"))] 170169689Skan "TARGET_V8 || TARGET_V9" 171169689Skan "swap\t%1, %0" 172169689Skan [(set_attr "type" "multi")]) 173169689Skan 174169689Skan(define_expand "ldstubqi" 175169689Skan [(parallel [(set (match_operand:QI 0 "register_operand" "") 176169689Skan (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")] 177169689Skan UNSPECV_LDSTUB)) 178169689Skan (set (match_dup 1) (const_int -1))])] 179169689Skan "" 180169689Skan "") 181169689Skan 182169689Skan(define_expand "ldstub<mode>" 183169689Skan [(parallel [(set (match_operand:I24MODE 0 "register_operand" "") 184169689Skan (zero_extend:I24MODE 185169689Skan (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")] 186169689Skan UNSPECV_LDSTUB))) 187169689Skan (set (match_dup 1) (const_int -1))])] 188169689Skan "" 189169689Skan "") 190169689Skan 191169689Skan(define_insn "*ldstubqi" 192169689Skan [(set (match_operand:QI 0 "register_operand" "=r") 193169689Skan (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")] 194169689Skan UNSPECV_LDSTUB)) 195169689Skan (set (match_dup 1) (const_int -1))] 196169689Skan "" 197169689Skan "ldstub\t%1, %0" 198169689Skan [(set_attr "type" "multi")]) 199169689Skan 200169689Skan(define_insn "*ldstub<mode>" 201169689Skan [(set (match_operand:I24MODE 0 "register_operand" "=r") 202169689Skan (zero_extend:I24MODE 203169689Skan (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")] 204169689Skan UNSPECV_LDSTUB))) 205169689Skan (set (match_dup 1) (const_int -1))] 206169689Skan "" 207169689Skan "ldstub\t%1, %0" 208169689Skan [(set_attr "type" "multi")]) 209