1;; GCC machine description for i386 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 IMODE [QI HI SI (DI "TARGET_64BIT")]) 23(define_mode_attr modesuffix [(QI "b") (HI "w") (SI "l") (DI "q")]) 24(define_mode_attr modeconstraint [(QI "q") (HI "r") (SI "r") (DI "r")]) 25(define_mode_attr immconstraint [(QI "i") (HI "i") (SI "i") (DI "e")]) 26 27;; ??? It would be possible to use cmpxchg8b on pentium for DImode 28;; changes. It's complicated because the insn uses ecx:ebx as the 29;; new value; note that the registers are reversed from the order 30;; that they'd be in with (reg:DI 2 ecx). Similarly for TImode 31;; data in 64-bit mode. 32 33(define_insn "sync_compare_and_swap<mode>" 34 [(set (match_operand:IMODE 0 "register_operand" "=a") 35 (match_operand:IMODE 1 "memory_operand" "+m")) 36 (set (match_dup 1) 37 (unspec_volatile:IMODE 38 [(match_dup 1) 39 (match_operand:IMODE 2 "register_operand" "a") 40 (match_operand:IMODE 3 "register_operand" "<modeconstraint>")] 41 UNSPECV_CMPXCHG_1)) 42 (clobber (reg:CC FLAGS_REG))] 43 "TARGET_CMPXCHG" 44 "lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}") 45 46(define_expand "sync_compare_and_swap_cc<mode>" 47 [(parallel 48 [(set (match_operand:IMODE 0 "register_operand" "") 49 (match_operand:IMODE 1 "memory_operand" "")) 50 (set (match_dup 1) 51 (unspec_volatile:IMODE 52 [(match_dup 1) 53 (match_operand:IMODE 2 "register_operand" "") 54 (match_operand:IMODE 3 "register_operand" "")] 55 UNSPECV_CMPXCHG_1)) 56 (set (match_dup 4) 57 (compare:CCZ 58 (unspec_volatile:IMODE 59 [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2) 60 (match_dup 2)))])] 61 "TARGET_CMPXCHG" 62{ 63 operands[4] = gen_rtx_REG (CCZmode, FLAGS_REG); 64 ix86_compare_op0 = operands[3]; 65 ix86_compare_op1 = NULL; 66 ix86_compare_emitted = operands[4]; 67}) 68 69(define_insn "*sync_compare_and_swap_cc<mode>" 70 [(set (match_operand:IMODE 0 "register_operand" "=a") 71 (match_operand:IMODE 1 "memory_operand" "+m")) 72 (set (match_dup 1) 73 (unspec_volatile:IMODE 74 [(match_dup 1) 75 (match_operand:IMODE 2 "register_operand" "a") 76 (match_operand:IMODE 3 "register_operand" "<modeconstraint>")] 77 UNSPECV_CMPXCHG_1)) 78 (set (reg:CCZ FLAGS_REG) 79 (compare:CCZ 80 (unspec_volatile:IMODE 81 [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2) 82 (match_dup 2)))] 83 "TARGET_CMPXCHG" 84 "lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}") 85 86(define_insn "sync_old_add<mode>" 87 [(set (match_operand:IMODE 0 "register_operand" "=<modeconstraint>") 88 (unspec_volatile:IMODE 89 [(match_operand:IMODE 1 "memory_operand" "+m")] UNSPECV_XCHG)) 90 (set (match_dup 1) 91 (plus:IMODE (match_dup 1) 92 (match_operand:IMODE 2 "register_operand" "0"))) 93 (clobber (reg:CC FLAGS_REG))] 94 "TARGET_XADD" 95 "lock\;xadd{<modesuffix>}\t{%0, %1|%1, %0}") 96 97;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space. 98(define_insn "sync_lock_test_and_set<mode>" 99 [(set (match_operand:IMODE 0 "register_operand" "=<modeconstraint>") 100 (unspec_volatile:IMODE 101 [(match_operand:IMODE 1 "memory_operand" "+m")] UNSPECV_XCHG)) 102 (set (match_dup 1) 103 (match_operand:IMODE 2 "register_operand" "0"))] 104 "" 105 "xchg{<modesuffix>}\t{%1, %0|%0, %1}") 106 107(define_insn "sync_add<mode>" 108 [(set (match_operand:IMODE 0 "memory_operand" "=m") 109 (unspec_volatile:IMODE 110 [(plus:IMODE (match_dup 0) 111 (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))] 112 UNSPECV_LOCK)) 113 (clobber (reg:CC FLAGS_REG))] 114 "" 115 "lock\;add{<modesuffix>}\t{%1, %0|%0, %1}") 116 117(define_insn "sync_sub<mode>" 118 [(set (match_operand:IMODE 0 "memory_operand" "=m") 119 (unspec_volatile:IMODE 120 [(minus:IMODE (match_dup 0) 121 (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))] 122 UNSPECV_LOCK)) 123 (clobber (reg:CC FLAGS_REG))] 124 "" 125 "lock\;sub{<modesuffix>}\t{%1, %0|%0, %1}") 126 127(define_insn "sync_ior<mode>" 128 [(set (match_operand:IMODE 0 "memory_operand" "=m") 129 (unspec_volatile:IMODE 130 [(ior:IMODE (match_dup 0) 131 (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))] 132 UNSPECV_LOCK)) 133 (clobber (reg:CC FLAGS_REG))] 134 "" 135 "lock\;or{<modesuffix>}\t{%1, %0|%0, %1}") 136 137(define_insn "sync_and<mode>" 138 [(set (match_operand:IMODE 0 "memory_operand" "=m") 139 (unspec_volatile:IMODE 140 [(and:IMODE (match_dup 0) 141 (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))] 142 UNSPECV_LOCK)) 143 (clobber (reg:CC FLAGS_REG))] 144 "" 145 "lock\;and{<modesuffix>}\t{%1, %0|%0, %1}") 146 147(define_insn "sync_xor<mode>" 148 [(set (match_operand:IMODE 0 "memory_operand" "=m") 149 (unspec_volatile:IMODE 150 [(xor:IMODE (match_dup 0) 151 (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))] 152 UNSPECV_LOCK)) 153 (clobber (reg:CC FLAGS_REG))] 154 "" 155 "lock\;xor{<modesuffix>}\t{%1, %0|%0, %1}") 156