Index: a/gcc/config/avr32/predicates.md =================================================================== --- a/gcc/config/avr32/predicates.md (revision 42108) +++ b/gcc/config/avr32/predicates.md (working copy) @@ -333,6 +333,11 @@ && ((GET_CODE(XEXP(op,0)) == CONST_INT) || (GET_CODE(XEXP(op,1)) == CONST_INT))")) )) +;; An offset k16 memory operand +(define_predicate "avr32_ks16_memory_operand" + (and (match_code "mem") + (match_test "avr32_ks16_address_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))"))) + ;; An immediate k11 address operand (define_predicate "avr32_ks11_address_operand" (and (match_operand 0 "address_operand") Index: a/gcc/config/avr32/sync.md =================================================================== --- a/gcc/config/avr32/sync.md (revision 41409) +++ b/gcc/config/avr32/sync.md (working copy) @@ -32,9 +32,14 @@ (define_code_attr atomic_insn [(plus "add") (minus "sub") (and "and") (ior "ior") (xor "xor")]) (define_insn "sync_loadsi" - [(set (match_operand:SI 0 "register_operand" "=r") + ; NB! Put an early clobber on the destination operand to + ; avoid gcc using the same register in the source and + ; destination. This is done in order to avoid gcc to + ; clobber the source operand since these instructions + ; are actually inside a "loop". + [(set (match_operand:SI 0 "register_operand" "=&r") (unspec_volatile:SI - [(match_operand:SI 1 "memory_operand" "RKs16") + [(match_operand:SI 1 "avr32_ks16_memory_operand" "RKs16") (label_ref (match_operand 2 "" ""))] VUNSPEC_SYNC_SET_LOCK_AND_LOAD) )] "" @@ -46,7 +51,7 @@ ) (define_insn "sync_store_if_lock" - [(set (match_operand:SI 0 "memory_operand" "=RKs16") + [(set (match_operand:SI 0 "avr32_ks16_memory_operand" "=RKs16") (unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r") (label_ref (match_operand 2 "" ""))] @@ -62,7 +67,7 @@ (define_expand "sync_si" [(set (match_dup 2) (unspec_volatile:SI - [(match_operand:SI 0 "memory_operand" "") + [(match_operand:SI 0 "avr32_ks16_memory_operand" "") (match_dup 3)] VUNSPEC_SYNC_SET_LOCK_AND_LOAD)) (set (match_dup 2) @@ -72,11 +77,33 @@ (unspec_volatile:SI [(match_dup 2) (match_dup 3)] - VUNSPEC_SYNC_STORE_IF_LOCK) )] + VUNSPEC_SYNC_STORE_IF_LOCK) ) + (use (match_dup 1)) + (use (match_dup 4))] "" { + rtx *mem_expr = &operands[0]; + rtx ptr_reg; + if ( !avr32_ks16_memory_operand (*mem_expr, GET_MODE (*mem_expr)) ) + { + ptr_reg = force_reg (Pmode, XEXP (*mem_expr, 0)); + XEXP (*mem_expr, 0) = ptr_reg; + } + else + { + rtx address = XEXP (*mem_expr, 0); + if ( REG_P (address) ) + ptr_reg = address; + else if ( REG_P (XEXP (address, 0)) ) + ptr_reg = XEXP (address, 0); + else + ptr_reg = XEXP (address, 1); + } + operands[2] = gen_reg_rtx (SImode); operands[3] = gen_rtx_LABEL_REF(Pmode, gen_label_rtx ()); + operands[4] = ptr_reg; + } ) @@ -85,7 +112,7 @@ (define_expand "sync_old_si" [(set (match_operand:SI 0 "register_operand" "") (unspec_volatile:SI - [(match_operand:SI 1 "memory_operand" "") + [(match_operand:SI 1 "avr32_ks16_memory_operand" "") (match_dup 4)] VUNSPEC_SYNC_SET_LOCK_AND_LOAD)) (set (match_dup 3) @@ -95,18 +122,39 @@ (unspec_volatile:SI [(match_dup 3) (match_dup 4)] - VUNSPEC_SYNC_STORE_IF_LOCK) )] + VUNSPEC_SYNC_STORE_IF_LOCK) ) + (use (match_dup 2)) + (use (match_dup 5))] "" { + rtx *mem_expr = &operands[1]; + rtx ptr_reg; + if ( !avr32_ks16_memory_operand (*mem_expr, GET_MODE (*mem_expr)) ) + { + ptr_reg = force_reg (Pmode, XEXP (*mem_expr, 0)); + XEXP (*mem_expr, 0) = ptr_reg; + } + else + { + rtx address = XEXP (*mem_expr, 0); + if ( REG_P (address) ) + ptr_reg = address; + else if ( REG_P (XEXP (address, 0)) ) + ptr_reg = XEXP (address, 0); + else + ptr_reg = XEXP (address, 1); + } + operands[3] = gen_reg_rtx (SImode); operands[4] = gen_rtx_LABEL_REF(Pmode, gen_label_rtx ()); + operands[5] = ptr_reg; } ) (define_expand "sync_new_si" [(set (match_operand:SI 0 "register_operand" "") (unspec_volatile:SI - [(match_operand:SI 1 "memory_operand" "") + [(match_operand:SI 1 "avr32_ks16_memory_operand" "") (match_dup 3)] VUNSPEC_SYNC_SET_LOCK_AND_LOAD)) (set (match_dup 0) @@ -116,10 +164,31 @@ (unspec_volatile:SI [(match_dup 0) (match_dup 3)] - VUNSPEC_SYNC_STORE_IF_LOCK) )] + VUNSPEC_SYNC_STORE_IF_LOCK) ) + (use (match_dup 2)) + (use (match_dup 4))] "" { + rtx *mem_expr = &operands[1]; + rtx ptr_reg; + if ( !avr32_ks16_memory_operand (*mem_expr, GET_MODE (*mem_expr)) ) + { + ptr_reg = force_reg (Pmode, XEXP (*mem_expr, 0)); + XEXP (*mem_expr, 0) = ptr_reg; + } + else + { + rtx address = XEXP (*mem_expr, 0); + if ( REG_P (address) ) + ptr_reg = address; + else if ( REG_P (XEXP (address, 0)) ) + ptr_reg = XEXP (address, 0); + else + ptr_reg = XEXP (address, 1); + } + operands[3] = gen_rtx_LABEL_REF(Pmode, gen_label_rtx ()); + operands[4] = ptr_reg; } )