diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 1ab3033..e557fcd 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -3388,3 +3388,74 @@ clr __zero_reg__" [(set_attr "length" "3") (set_attr "cc" "clobber")]) + +(define_expand "extzv" + [(set (match_operand:QI 0 "register_operand" "") + (zero_extract:QI + (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "const1_operand" "") + (match_operand:QI 3 "const_0_to_7_operand" "")))] + "" + "") + +(define_expand "insv" + [(set (zero_extract:QI + (match_operand:QI 0 "register_operand" "") + (match_operand:QI 1 "const1_operand" "") + (match_operand:QI 2 "const_0_to_7_operand" "")) + (match_operand:QI 3 "nonmemory_operand" ""))] + "" + "") + +(define_insn "*movbitqi_reg_ext" + [(set (match_operand:QI 0 "register_operand" "=r") + (zero_extract:QI + (match_operand:QI 1 "register_operand" "r") + (const_int 1) + (match_operand 2 "const_0_to_7_operand" "")))] + "" + "bst %1,%2\;bld %0,0" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +(define_insn "*movbitqi_ext_ext" + [(set (zero_extract:QI + (match_operand:QI 0 "register_operand" "+r") + (const_int 1) + (match_operand 1 "const_0_to_7_operand" "")) + (zero_extract:QI + (match_operand:QI 2 "register_operand" "r") + (const_int 1) + (match_operand 3 "const_0_to_7_operand" "")))] + "" + "bst %2,%3\;bld %0,%1" + [(set_attr "length" "2") + (set_attr "cc" "none")]) + +(define_insn "*movbitqi_ext_reg" + [(set (zero_extract:QI + (match_operand:QI 0 "register_operand" "+*d,*d,r,r,r") + (const_int 1) + (match_operand 1 "const_0_to_7_operand" "")) + (match_operand:QI 2 "nonmemory_operand" "L,P,L,P,r"))] + "" +{ + switch (which_alternative) + { + case 0: + operands[2] = gen_int_mode (~(1 << INTVAL (operands[1])), QImode); + return "andi %0,%2"; + case 1: + operands[2] = gen_int_mode (1 << INTVAL (operands[1]), QImode); + return "ori %0,%2"; + case 2: + return "clt\;bld %0,%1"; + case 3: + return "set\;bld %0,%1"; + case 4: + return "bst %2,0\;bld %0,%1"; + } + gcc_unreachable (); +} + [(set_attr "length" "1,1,2,2,2") + (set_attr "cc" "set_zn,set_zn,none,none,none")]) diff --git a/gcc/config/avr/predicates.md b/gcc/config/avr/predicates.md index 9a3473b..e0142d1 100755 --- a/gcc/config/avr/predicates.md +++ b/gcc/config/avr/predicates.md @@ -62,6 +62,11 @@ (and (match_code "const_int,const_double") (match_test "op == CONST0_RTX (mode)"))) +;; Return 1 if OP is the one constant for MODE. +(define_predicate "const1_operand" + (and (match_code "const_int") + (match_test "op == CONST1_RTX (mode)"))) + ;; Returns true if OP is either the constant zero or a register. (define_predicate "reg_or_0_operand" (ior (match_operand 0 "register_operand") @@ -106,6 +111,11 @@ (and (match_code "const_int") (match_test "exact_log2(~INTVAL (op) & GET_MODE_MASK (mode)) >= 0"))) +;; Return true if OP is a constant between 0 and 7. +(define_predicate "const_0_to_7_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 0, 7)"))) + ;; (define_predicate "avr_sp_immediate_operand" (and (match_code "const_int")