Index: doc/extend.texi =================================================================== --- doc/extend.texi (Revision 175104) +++ doc/extend.texi (Arbeitskopie) @@ -8203,6 +8203,21 @@ int __builtin_avr_fmuls (char, char) int __builtin_avr_fmulsu (char, unsigned char) @end smallexample +The following built-in functions are a supplements to gcc's +@code{__builtin_parity*} resp. @code{__builtin_popcount*} built-ins +for 8-bit values and are implemented as library calls: +@smallexample +unsigned char __builtin_avr_parity8 (unsigned char) +unsigned char __builtin_avr_popcount8 (unsigned char) +@end smallexample + +@smallexample +unsigned char __builtin_avr_pow2 (unsigned char) +@end smallexample +This built-in supplies a fast, loop-free implementation for the @var{N}-th +power of two as of @code{1 << (N & 7)} that takes about seven ticks resp. +seven instructions. + In order to delay execution for a specific number of cycles, GCC implements @smallexample Index: config/avr/avr.md =================================================================== --- config/avr/avr.md (Revision 175104) +++ config/avr/avr.md (Arbeitskopie) @@ -3321,6 +3321,62 @@ (define_insn "delay_cycles_4" [(set_attr "length" "9") (set_attr "cc" "clobber")]) +;; __builtin_avr_parity8 +(define_expand "parityqi2" + [(set (reg:QI 24) + (match_operand:QI 1 "register_operand" "")) + (set (reg:HI 24) + (zero_extend:HI (parity:QI (reg:QI 24)))) + (set (match_operand:QI 0 "register_operand" "") + (reg:QI 24))] + "" + "") + +(define_insn "*parityqihi2.libgcc" + [(set (reg:HI 24) + (zero_extend:HI (parity:QI (reg:QI 24))))] + "" + "%~call __parityqi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +;; __builtin_avr_popcount8 +(define_expand "popcountqi2" + [(set (reg:QI 24) + (match_operand:QI 1 "register_operand" "")) + (set (reg:QI 24) + (popcount:QI (reg:QI 24))) + (set (match_operand:QI 0 "register_operand" "") + (reg:QI 24))] + "" + "") + +(define_insn "*popcountqi2.libgcc" + [(set (reg:QI 24) + (popcount:QI (reg:QI 24)))] + "" + "%~call __popcountqi2" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +;; __builtin_avr_pow2 +;; $0 = (1 << ($1 & 7)) +(define_insn "ashlqi2_1" + [(set (match_operand:QI 0 "register_operand" "=&d") + (ashift:QI (const_int 1) + (and:QI (match_operand:QI 1 "register_operand" "r") + (const_int 7))))] + "" + "ldi %0, 1 + sbrc %1, 1 + ldi %0, 4 + sbrc %1, 0 + lsl %0 + sbrc %1, 2 + swap %0" + [(set_attr "length" "7") + (set_attr "cc" "clobber")]) + ;; CPU instructions ;; NOP taking 1 or 2 Ticks Index: config/avr/avr-c.c =================================================================== --- config/avr/avr-c.c (Revision 175104) +++ config/avr/avr-c.c (Arbeitskopie) @@ -93,6 +93,9 @@ avr_cpu_cpp_builtins (struct cpp_reader cpp_define (pfile, "__BUILTIN_AVR_SLEEP"); cpp_define (pfile, "__BUILTIN_AVR_SWAP"); cpp_define (pfile, "__BUILTIN_AVR_DELAY_CYCLES"); + cpp_define (pfile, "__BUILTIN_AVR_PARITY8"); + cpp_define (pfile, "__BUILTIN_AVR_POPCOUNT8"); + cpp_define (pfile, "__BUILTIN_AVR_POW2"); if (AVR_HAVE_MUL) { Index: config/avr/avr.c =================================================================== --- config/avr/avr.c (Revision 175104) +++ config/avr/avr.c (Arbeitskopie) @@ -4740,9 +4740,11 @@ adjust_insn_length (rtx insn, int len) break; } } - else if (GET_CODE (op[1]) == ASHIFT - || GET_CODE (op[1]) == ASHIFTRT - || GET_CODE (op[1]) == LSHIFTRT) + else if ((GET_CODE (op[1]) == ASHIFT + || GET_CODE (op[1]) == ASHIFTRT + || GET_CODE (op[1]) == LSHIFTRT) + /* Filter out "ashlqi2_1" */ + && AND != GET_CODE (XEXP (op[1], 1))) { rtx ops[10]; ops[0] = op[0]; @@ -6614,7 +6616,10 @@ enum avr_builtin_id AVR_BUILTIN_FMUL, AVR_BUILTIN_FMULS, AVR_BUILTIN_FMULSU, - AVR_BUILTIN_DELAY_CYCLES + AVR_BUILTIN_DELAY_CYCLES, + AVR_BUILTIN_PARITY8, + AVR_BUILTIN_POPCOUNT8, + AVR_BUILTIN_POW2 }; #define DEF_BUILTIN(NAME, TYPE, CODE) \ @@ -6665,6 +6670,12 @@ avr_init_builtins (void) DEF_BUILTIN ("__builtin_avr_swap", uchar_ftype_uchar, AVR_BUILTIN_SWAP); DEF_BUILTIN ("__builtin_avr_delay_cycles", void_ftype_ulong, AVR_BUILTIN_DELAY_CYCLES); + DEF_BUILTIN ("__builtin_avr_parity8", uchar_ftype_uchar, + AVR_BUILTIN_PARITY8); + DEF_BUILTIN ("__builtin_avr_popcount8", uchar_ftype_uchar, + AVR_BUILTIN_POPCOUNT8); + DEF_BUILTIN ("__builtin_avr_pow2", uchar_ftype_uchar, + AVR_BUILTIN_POW2); if (AVR_HAVE_MUL) { @@ -6694,6 +6705,9 @@ static const struct avr_builtin_descript bdesc_1arg[] = { { CODE_FOR_rotlqi3_4, "__builtin_avr_swap", AVR_BUILTIN_SWAP } + , { CODE_FOR_parityqi2, "__builtin_avr_parity8", AVR_BUILTIN_PARITY8 } + , { CODE_FOR_popcountqi2, "__builtin_avr_popcount8", AVR_BUILTIN_POPCOUNT8 } + , { CODE_FOR_ashlqi2_1, "__builtin_avr_pow2", AVR_BUILTIN_POW2 } }; static const struct avr_builtin_description