1;; GCC machine description for SPARC synchronization instructions. 2;; Copyright (C) 2005 3;; Free Software Foundation, Inc. 4;; 5;; This file is part of GCC. 6;; 7;; GCC is free software; you can redistribute it and/or modify 8;; it under the terms of the GNU General Public License as published by 9;; the Free Software Foundation; either version 2, or (at your option) 10;; any later version. 11;; 12;; GCC is distributed in the hope that it will be useful, 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15;; GNU General Public License for more details. 16;; 17;; You should have received a copy of the GNU General Public License 18;; along with GCC; see the file COPYING. If not, write to 19;; the Free Software Foundation, 51 Franklin Street, Fifth Floor, 20;; Boston, MA 02110-1301, USA. 21 22(define_mode_macro I12MODE [QI HI]) 23(define_mode_macro I24MODE [HI SI]) 24(define_mode_macro I48MODE [SI (DI "TARGET_ARCH64 || TARGET_V8PLUS")]) 25(define_mode_attr modesuffix [(SI "") (DI "x")]) 26 27(define_expand "memory_barrier" 28 [(set (mem:BLK (match_dup 0)) 29 (unspec_volatile:BLK [(mem:BLK (match_dup 0)) (match_dup 1)] 30 UNSPECV_MEMBAR))] 31 "TARGET_V8 || TARGET_V9" 32{ 33 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode)); 34 MEM_VOLATILE_P (operands[0]) = 1; 35 if (TARGET_V9) 36 /* member #StoreStore | #LoadStore | #StoreLoad | #LoadLoad */ 37 operands[1] = GEN_INT (15); 38 else 39 /* stbar */ 40 operands[1] = GEN_INT (8); 41}) 42 43(define_insn "*stbar" 44 [(set (match_operand:BLK 0 "" "") 45 (unspec_volatile:BLK [(match_operand:BLK 1 "" "") 46 (const_int 8)] UNSPECV_MEMBAR))] 47 "TARGET_V8" 48 "stbar" 49 [(set_attr "type" "multi")]) 50 51(define_insn "*membar" 52 [(set (match_operand:BLK 0 "" "") 53 (unspec_volatile:BLK [(match_operand:BLK 1 "" "") 54 (match_operand:SI 2 "immediate_operand" "I")] 55 UNSPECV_MEMBAR))] 56 "TARGET_V9" 57 "membar\t%2" 58 [(set_attr "type" "multi")]) 59 60(define_expand "sync_compare_and_swap<mode>" 61 [(match_operand:I12MODE 0 "register_operand" "") 62 (match_operand:I12MODE 1 "memory_operand" "") 63 (match_operand:I12MODE 2 "register_operand" "") 64 (match_operand:I12MODE 3 "register_operand" "")] 65 "TARGET_V9" 66{ 67 sparc_expand_compare_and_swap_12 (operands[0], operands[1], 68 operands[2], operands[3]); 69 DONE; 70}) 71 72(define_expand "sync_compare_and_swap<mode>" 73 [(parallel 74 [(set (match_operand:I48MODE 0 "register_operand" "=r") 75 (match_operand:I48MODE 1 "memory_operand" "")) 76 (set (match_dup 1) 77 (unspec_volatile:I48MODE 78 [(match_operand:I48MODE 2 "register_operand" "") 79 (match_operand:I48MODE 3 "register_operand" "")] 80 UNSPECV_CAS))])] 81 "TARGET_V9" 82{ 83 if (! REG_P (XEXP (operands[1], 0))) 84 { 85 rtx addr = force_reg (Pmode, XEXP (operands[1], 0)); 86 operands[1] = replace_equiv_address (operands[1], addr); 87 } 88 emit_insn (gen_memory_barrier ()); 89}) 90 91(define_insn "*sync_compare_and_swap<mode>" 92 [(set (match_operand:I48MODE 0 "register_operand" "=r") 93 (match_operand:I48MODE 1 "memory_reg_operand" "+m")) 94 (set (match_dup 1) 95 (unspec_volatile:I48MODE 96 [(match_operand:I48MODE 2 "register_operand" "r") 97 (match_operand:I48MODE 3 "register_operand" "0")] 98 UNSPECV_CAS))] 99 "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)" 100 "cas<modesuffix>\t%1, %2, %0" 101 [(set_attr "type" "multi")]) 102 103(define_insn "*sync_compare_and_swapdi_v8plus" 104 [(set (match_operand:DI 0 "register_operand" "=h") 105 (match_operand:DI 1 "memory_reg_operand" "+m")) 106 (set (match_dup 1) 107 (unspec_volatile:DI 108 [(match_operand:DI 2 "register_operand" "h") 109 (match_operand:DI 3 "register_operand" "0")] 110 UNSPECV_CAS))] 111 "TARGET_V8PLUS" 112{ 113 if (sparc_check_64 (operands[3], insn) <= 0) 114 output_asm_insn ("srl\t%L3, 0, %L3", operands); 115 output_asm_insn ("sllx\t%H3, 32, %H3", operands); 116 output_asm_insn ("or\t%L3, %H3, %L3", operands); 117 if (sparc_check_64 (operands[2], insn) <= 0) 118 output_asm_insn ("srl\t%L2, 0, %L2", operands); 119 output_asm_insn ("sllx\t%H2, 32, %H3", operands); 120 output_asm_insn ("or\t%L2, %H3, %H3", operands); 121 output_asm_insn ("casx\t%1, %H3, %L3", operands); 122 return "srlx\t%L3, 32, %H3"; 123} 124 [(set_attr "type" "multi") 125 (set_attr "length" "8")]) 126 127(define_expand "sync_lock_test_and_set<mode>" 128 [(match_operand:I12MODE 0 "register_operand" "") 129 (match_operand:I12MODE 1 "memory_operand" "") 130 (match_operand:I12MODE 2 "arith_operand" "")] 131 "!TARGET_V9" 132{ 133 if (operands[2] != const1_rtx) 134 FAIL; 135 if (TARGET_V8) 136 emit_insn (gen_memory_barrier ()); 137 if (<MODE>mode != QImode) 138 operands[1] = adjust_address (operands[1], QImode, 0); 139 emit_insn (gen_ldstub<mode> (operands[0], operands[1])); 140 DONE; 141}) 142 143(define_expand "sync_lock_test_and_setsi" 144 [(parallel 145 [(set (match_operand:SI 0 "register_operand" "") 146 (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "")] 147 UNSPECV_SWAP)) 148 (set (match_dup 1) 149 (match_operand:SI 2 "arith_operand" ""))])] 150 "" 151{ 152 if (! TARGET_V8 && ! TARGET_V9) 153 { 154 if (operands[2] != const1_rtx) 155 FAIL; 156 operands[1] = adjust_address (operands[1], QImode, 0); 157 emit_insn (gen_ldstubsi (operands[0], operands[1])); 158 DONE; 159 } 160 emit_insn (gen_memory_barrier ()); 161 operands[2] = force_reg (SImode, operands[2]); 162}) 163 164(define_insn "*swapsi" 165 [(set (match_operand:SI 0 "register_operand" "=r") 166 (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "+m")] 167 UNSPECV_SWAP)) 168 (set (match_dup 1) 169 (match_operand:SI 2 "register_operand" "0"))] 170 "TARGET_V8 || TARGET_V9" 171 "swap\t%1, %0" 172 [(set_attr "type" "multi")]) 173 174(define_expand "ldstubqi" 175 [(parallel [(set (match_operand:QI 0 "register_operand" "") 176 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")] 177 UNSPECV_LDSTUB)) 178 (set (match_dup 1) (const_int -1))])] 179 "" 180 "") 181 182(define_expand "ldstub<mode>" 183 [(parallel [(set (match_operand:I24MODE 0 "register_operand" "") 184 (zero_extend:I24MODE 185 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")] 186 UNSPECV_LDSTUB))) 187 (set (match_dup 1) (const_int -1))])] 188 "" 189 "") 190 191(define_insn "*ldstubqi" 192 [(set (match_operand:QI 0 "register_operand" "=r") 193 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")] 194 UNSPECV_LDSTUB)) 195 (set (match_dup 1) (const_int -1))] 196 "" 197 "ldstub\t%1, %0" 198 [(set_attr "type" "multi")]) 199 200(define_insn "*ldstub<mode>" 201 [(set (match_operand:I24MODE 0 "register_operand" "=r") 202 (zero_extend:I24MODE 203 (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")] 204 UNSPECV_LDSTUB))) 205 (set (match_dup 1) (const_int -1))] 206 "" 207 "ldstub\t%1, %0" 208 [(set_attr "type" "multi")]) 209