Commit 0c578db6 by Georg-Johann Lay Committed by Georg-Johann Lay

builtin_insert_bits-1.c: New test.

gcc/testsuite/
	* gcc.target/avr/torture/builtin_insert_bits-1.c: New test.
	* gcc.target/avr/torture/builtin_insert_bits-2.c: New test.

gcc/
	* doc/extend.texi (AVR Built-in Functions): Remove doc for
	__builtin_avr_map8, __builtin_avr_map16.
	Document __builtin_avr_insert_bits.
	* config/avr/avr.md (map_bitsqi, map_bitshi): Remove.
	(insert_bits): New insn.
	(adjust_len.map_bits): Rename to insert_bits.
	(UNSPEC_MAP_BITS): Rename to UNSPEC_INSERT_BITS.
	* avr-protos.h (avr_out_map_bits): Remove.
	(avr_out_insert_bits, avr_has_nibble_0xf): New.
	* config/avr/constraints.md (Cxf,C0f): New.
	* config/avr/avr.c (avr_cpu_cpp_builtins): Remove built-in
	defines __BUILTIN_AVR_MAP8, __BUILTIN_AVR_MAP16.
	New built-in define __BUILTIN_AVR_INSERT_BITS.
	* config/avr/avr.c (TARGET_FOLD_BUILTIN): New define.
	(enum avr_builtin_id): Add AVR_BUILTIN_INSERT_BITS.
	(avr_move_bits): Rewrite.
	(avr_fold_builtin, avr_map_metric, avr_map_decompose): New static
	functions.
	(avr_map_op_t): New typedef.
	(avr_map_op): New static variable.
	(avr_out_insert_bits, avr_has_nibble_0xf): New functions.
	(adjust_insn_length): Handle ADJUST_LEN_INSERT_BITS.
	(avr_init_builtins): Add definition for __builtin_avr_insert_bits.
	(bdesc_3arg, avr_expand_triop_builtin): New.
	(avr_expand_builtin): Use them. And handle AVR_BUILTIN_INSERT_BITS.
	(avr_revert_map, avr_swap_map, avr_id_map, avr_sig_map): Remove.
	(avr_map_hamming_byte, avr_map_hamming_nonstrict): Remove.
	(avr_map_equal_p, avr_map_sig_p): Remove.
	(avr_out_swap_bits, avr_out_revert_bits, avr_out_map_bits): Remove.
	(bdesc_2arg): Remove AVR_BUILTIN_MAP8, AVR_BUILTIN_MAP16.
	(adjust_insn_length): Remove handling for ADJUST_LEN_MAP_BITS.
	(enum avr_builtin_id): Remove AVR_BUILTIN_MAP8, AVR_BUILTIN_MAP16.
	(avr_init_builtins): Remove __builtin_avr_map8, __builtin_avr_map16.
	(avr_expand_builtin): Remove AVR_BUILTIN_MAP8, AVR_BUILTIN_MAP16.

From-SVN: r184264
parent 1c4ae4e5
2012-02-15 Georg-Johann Lay <avr@gjlay.de>
* doc/extend.texi (AVR Built-in Functions): Remove doc for
__builtin_avr_map8, __builtin_avr_map16.
Document __builtin_avr_insert_bits.
* config/avr/avr.md (map_bitsqi, map_bitshi): Remove.
(insert_bits): New insn.
(adjust_len.map_bits): Rename to insert_bits.
(UNSPEC_MAP_BITS): Rename to UNSPEC_INSERT_BITS.
* avr-protos.h (avr_out_map_bits): Remove.
(avr_out_insert_bits, avr_has_nibble_0xf): New.
* config/avr/constraints.md (Cxf,C0f): New.
* config/avr/avr.c (avr_cpu_cpp_builtins): Remove built-in
defines __BUILTIN_AVR_MAP8, __BUILTIN_AVR_MAP16.
New built-in define __BUILTIN_AVR_INSERT_BITS.
* config/avr/avr.c (TARGET_FOLD_BUILTIN): New define.
(enum avr_builtin_id): Add AVR_BUILTIN_INSERT_BITS.
(avr_move_bits): Rewrite.
(avr_fold_builtin, avr_map_metric, avr_map_decompose): New static
functions.
(avr_map_op_t): New typedef.
(avr_map_op): New static variable.
(avr_out_insert_bits, avr_has_nibble_0xf): New functions.
(adjust_insn_length): Handle ADJUST_LEN_INSERT_BITS.
(avr_init_builtins): Add definition for __builtin_avr_insert_bits.
(bdesc_3arg, avr_expand_triop_builtin): New.
(avr_expand_builtin): Use them. And handle AVR_BUILTIN_INSERT_BITS.
(avr_revert_map, avr_swap_map, avr_id_map, avr_sig_map): Remove.
(avr_map_hamming_byte, avr_map_hamming_nonstrict): Remove.
(avr_map_equal_p, avr_map_sig_p): Remove.
(avr_out_swap_bits, avr_out_revert_bits, avr_out_map_bits): Remove.
(bdesc_2arg): Remove AVR_BUILTIN_MAP8, AVR_BUILTIN_MAP16.
(adjust_insn_length): Remove handling for ADJUST_LEN_MAP_BITS.
(enum avr_builtin_id): Remove AVR_BUILTIN_MAP8, AVR_BUILTIN_MAP16.
(avr_init_builtins): Remove __builtin_avr_map8, __builtin_avr_map16.
(avr_expand_builtin): Remove AVR_BUILTIN_MAP8, AVR_BUILTIN_MAP16.
2012-02-14 Bernd Schmidt <bernds@codesourcery.com>
* config/c6x/c6x.md (reserve_cycles): New attribute.
......
......@@ -163,8 +163,7 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile)
cpp_define (pfile, "__BUILTIN_AVR_WDR");
cpp_define (pfile, "__BUILTIN_AVR_SLEEP");
cpp_define (pfile, "__BUILTIN_AVR_SWAP");
cpp_define (pfile, "__BUILTIN_AVR_MAP8");
cpp_define (pfile, "__BUILTIN_AVR_MAP16");
cpp_define (pfile, "__BUILTIN_AVR_INSERT_BITS");
cpp_define (pfile, "__BUILTIN_AVR_DELAY_CYCLES");
cpp_define (pfile, "__BUILTIN_AVR_FMUL");
......
......@@ -94,8 +94,9 @@ extern const char* avr_out_plus64 (rtx, int*);
extern const char* avr_out_addto_sp (rtx*, int*);
extern const char* avr_out_xload (rtx, rtx*, int*);
extern const char* avr_out_movmem (rtx, rtx*, int*);
extern const char* avr_out_map_bits (rtx, rtx*, int*);
extern const char* avr_out_insert_bits (rtx*, int*);
extern bool avr_popcount_each_byte (rtx, int, int);
extern bool avr_has_nibble_0xf (rtx);
extern int extra_constraint_Q (rtx x);
extern int adjust_insn_length (rtx insn, int len);
......
......@@ -68,7 +68,7 @@
UNSPEC_FMULSU
UNSPEC_COPYSIGN
UNSPEC_IDENTITY
UNSPEC_MAP_BITS
UNSPEC_INSERT_BITS
])
(define_c_enum "unspecv"
......@@ -144,7 +144,7 @@
ashlhi, ashrhi, lshrhi,
ashlsi, ashrsi, lshrsi,
ashlpsi, ashrpsi, lshrpsi,
map_bits,
insert_bits,
no"
(const_string "no"))
......@@ -5264,28 +5264,20 @@
[(set_attr "length" "9")
(set_attr "cc" "clobber")])
(define_insn "map_bitsqi"
[(set (match_operand:QI 0 "register_operand" "=d")
(unspec:QI [(match_operand:SI 1 "const_int_operand" "n")
(match_operand:QI 2 "register_operand" "r")]
UNSPEC_MAP_BITS))]
""
{
return avr_out_map_bits (insn, operands, NULL);
}
[(set_attr "adjust_len" "map_bits")
(set_attr "cc" "clobber")])
(define_insn "map_bitshi"
[(set (match_operand:HI 0 "register_operand" "=&r")
(unspec:HI [(match_operand:DI 1 "const_double_operand" "n")
(match_operand:HI 2 "register_operand" "r")]
UNSPEC_MAP_BITS))]
;; __builtin_avr_insert_bits
(define_insn "insert_bits"
[(set (match_operand:QI 0 "register_operand" "=r ,d ,r")
(unspec:QI [(match_operand:SI 1 "const_int_operand" "C0f,Cxf,C0f")
(match_operand:QI 2 "register_operand" "r ,r ,r")
(match_operand:QI 3 "nonmemory_operand" "n ,0 ,0")]
UNSPEC_INSERT_BITS))]
""
{
return avr_out_map_bits (insn, operands, NULL);
return avr_out_insert_bits (operands, NULL);
}
[(set_attr "adjust_len" "map_bits")
[(set_attr "adjust_len" "insert_bits")
(set_attr "cc" "clobber")])
......
......@@ -182,3 +182,13 @@
"Integer constant in the range -6 @dots{} 6."
(and (match_code "const_int")
(match_test "IN_RANGE (ival, -6, 6)")))
(define_constraint "Cxf"
"32-bit integer constant where at least one nibble is 0xf."
(and (match_code "const_int")
(match_test "avr_has_nibble_0xf (op)")))
(define_constraint "C0f"
"32-bit integer constant where no nibble equals 0xf."
(and (match_code "const_int")
(match_test "!avr_has_nibble_0xf (op)")))
......@@ -8812,33 +8812,53 @@ might increase delay time. @code{ticks} must be a compile time
integer constant; delays with a variable number of cycles are not supported.
@smallexample
unsigned char __builtin_avr_map8 (unsigned long map, unsigned char val)
unsigned char __builtin_avr_insert_bits (unsigned long map, unsigned char bits, unsigned char val)
@end smallexample
@noindent
Each bit of the result is copied from a specific bit of @code{val}.
@code{map} is a compile time constant that represents a map composed
of 8 nibbles (4-bit groups):
The @var{n}-th nibble of @code{map} specifies which bit of @code{val}
is to be moved to the @var{n}-th bit of the result.
For example, @code{map = 0x76543210} represents identity: The MSB of
the result is read from the 7-th bit of @code{val}, the LSB is
read from the 0-th bit to @code{val}, etc.
Two more examples: @code{0x01234567} reverses the bit order and
@code{0x32107654} is equivalent to a @code{swap} instruction.
Insert bits from @var{bits} into @var{val} and return the resulting
value. The nibbles of @var{map} determine how the insertion is
performed: Let @var{X} be the @var{n}-th nibble of @var{map}
@enumerate
@item If @var{X} is @code{0xf},
then the @var{n}-th bit of @var{val} is returned unaltered.
@item If X is in the range 0@dots{}7,
then the @var{n}-th result bit is set to the @var{X}-th bit of @var{bits}
@item If X is in the range 8@dots{}@code{0xe},
then the @var{n}-th result bit is undefined.
@end enumerate
@noindent
One typical use case for this and the following built-in is adjusting input and
output values to non-contiguous port layouts.
One typical use case for this built-in is adjusting input and
output values to non-contiguous port layouts. Some examples:
@smallexample
unsigned int __builtin_avr_map16 (unsigned long long map, unsigned int val)
// same as val, bits is unused
__builtin_avr_insert_bits (0xffffffff, bits, val)
@end smallexample
@noindent
Similar to the previous built-in except that it operates on @code{int}
and thus 16 bits are involved. Again, @code{map} must be a compile
time constant.
@smallexample
// same as bits, val is unused
__builtin_avr_insert_bits (0x76543210, bits, val)
@end smallexample
@smallexample
// same as rotating bits by 4
__builtin_avr_insert_bits (0x32107654, bits, 0)
@end smallexample
@smallexample
// high-nibble of result is the high-nibble of val
// low-nibble of result is the low-nibble of bits
__builtin_avr_insert_bits (0xffff3210, bits, val)
@end smallexample
@smallexample
// reverse the bit order of bits
__builtin_avr_insert_bits (0x01234567, bits, 0)
@end smallexample
@node Blackfin Built-in Functions
@subsection Blackfin Built-in Functions
......
2012-02-15 Georg-Johann Lay <avr@gjlay.de>
* gcc.target/avr/torture/builtin_insert_bits-1.c: New test.
* gcc.target/avr/torture/builtin_insert_bits-2.c: New test.
2012-02-15 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/discr35.ad[sb]: New test.
......
/* { dg-do run } */
#include <stdlib.h>
#define MASK_F(M) \
(0 \
| ((0xf == (0xf & ((M) >> (4*0)))) ? (1 << 0) : 0) \
| ((0xf == (0xf & ((M) >> (4*1)))) ? (1 << 1) : 0) \
| ((0xf == (0xf & ((M) >> (4*2)))) ? (1 << 2) : 0) \
| ((0xf == (0xf & ((M) >> (4*3)))) ? (1 << 3) : 0) \
| ((0xf == (0xf & ((M) >> (4*4)))) ? (1 << 4) : 0) \
| ((0xf == (0xf & ((M) >> (4*5)))) ? (1 << 5) : 0) \
| ((0xf == (0xf & ((M) >> (4*6)))) ? (1 << 6) : 0) \
| ((0xf == (0xf & ((M) >> (4*7)))) ? (1 << 7) : 0) \
| 0)
#define MASK_0_7(M) \
(0 \
| ((8 > (0xf & ((M) >> (4*0)))) ? (1 << 0) : 0) \
| ((8 > (0xf & ((M) >> (4*1)))) ? (1 << 1) : 0) \
| ((8 > (0xf & ((M) >> (4*2)))) ? (1 << 2) : 0) \
| ((8 > (0xf & ((M) >> (4*3)))) ? (1 << 3) : 0) \
| ((8 > (0xf & ((M) >> (4*4)))) ? (1 << 4) : 0) \
| ((8 > (0xf & ((M) >> (4*5)))) ? (1 << 5) : 0) \
| ((8 > (0xf & ((M) >> (4*6)))) ? (1 << 6) : 0) \
| ((8 > (0xf & ((M) >> (4*7)))) ? (1 << 7) : 0) \
| 0)
#define INSERT_BITS(M,B,V) \
(__extension__({ \
unsigned char _n, _r = 0; \
_n = 0xf & (M >> (4*0)); if (_n<8) _r |= (!!(B & (1 << _n))) << 0; \
_n = 0xf & (M >> (4*1)); if (_n<8) _r |= (!!(B & (1 << _n))) << 1; \
_n = 0xf & (M >> (4*2)); if (_n<8) _r |= (!!(B & (1 << _n))) << 2; \
_n = 0xf & (M >> (4*3)); if (_n<8) _r |= (!!(B & (1 << _n))) << 3; \
_n = 0xf & (M >> (4*4)); if (_n<8) _r |= (!!(B & (1 << _n))) << 4; \
_n = 0xf & (M >> (4*5)); if (_n<8) _r |= (!!(B & (1 << _n))) << 5; \
_n = 0xf & (M >> (4*6)); if (_n<8) _r |= (!!(B & (1 << _n))) << 6; \
_n = 0xf & (M >> (4*7)); if (_n<8) _r |= (!!(B & (1 << _n))) << 7; \
(unsigned char) ((V) & MASK_F(M)) | _r; \
}))
#define MASK_USED(M) (MASK_F(M) | MASK_0_7(M))
#define TEST2(M,B,V) \
do { \
__asm volatile (";" #M); \
r1 = MASK_USED (M) \
& __builtin_avr_insert_bits (M,B,V); \
r2 = INSERT_BITS (M,B,V); \
if (r1 != r2) \
abort (); \
} while(0)
#define TEST1(M,X) \
do { \
TEST2 (M,X,0x00); TEST2 (M,0x00,X); \
TEST2 (M,X,0xff); TEST2 (M,0xff,X); \
TEST2 (M,X,0xaa); TEST2 (M,0xaa,X); \
TEST2 (M,X,0xcc); TEST2 (M,0xcc,X); \
TEST2 (M,X,0x96); TEST2 (M,0x96,X); \
} while(0)
void test8 (void)
{
unsigned char r1, r2;
unsigned char ib;
static const unsigned char V[] =
{
0, 0xaa, 0xcc, 0xf0, 0xff, 0x5b, 0x4d
};
for (ib = 0; ib < sizeof (V) / sizeof (*V); ib++)
{
unsigned char b = V[ib];
TEST1 (0x76543210, b);
TEST1 (0x3210ffff, b);
TEST1 (0x67452301, b);
TEST1 (0xf0f1f2f3, b);
TEST1 (0xff10ff54, b);
TEST1 (0x01234567, b);
TEST1 (0xff765f32, b);
}
}
/****************************************************************/
int main()
{
test8();
exit(0);
}
/* { dg-do run } */
#include <stdlib.h>
#define MASK_F(M) \
(0 \
| ((0xf == (0xf & ((M) >> (4*0)))) ? (1 << 0) : 0) \
| ((0xf == (0xf & ((M) >> (4*1)))) ? (1 << 1) : 0) \
| ((0xf == (0xf & ((M) >> (4*2)))) ? (1 << 2) : 0) \
| ((0xf == (0xf & ((M) >> (4*3)))) ? (1 << 3) : 0) \
| ((0xf == (0xf & ((M) >> (4*4)))) ? (1 << 4) : 0) \
| ((0xf == (0xf & ((M) >> (4*5)))) ? (1 << 5) : 0) \
| ((0xf == (0xf & ((M) >> (4*6)))) ? (1 << 6) : 0) \
| ((0xf == (0xf & ((M) >> (4*7)))) ? (1 << 7) : 0) \
| 0)
#define MASK_0_7(M) \
(0 \
| ((8 > (0xf & ((M) >> (4*0)))) ? (1 << 0) : 0) \
| ((8 > (0xf & ((M) >> (4*1)))) ? (1 << 1) : 0) \
| ((8 > (0xf & ((M) >> (4*2)))) ? (1 << 2) : 0) \
| ((8 > (0xf & ((M) >> (4*3)))) ? (1 << 3) : 0) \
| ((8 > (0xf & ((M) >> (4*4)))) ? (1 << 4) : 0) \
| ((8 > (0xf & ((M) >> (4*5)))) ? (1 << 5) : 0) \
| ((8 > (0xf & ((M) >> (4*6)))) ? (1 << 6) : 0) \
| ((8 > (0xf & ((M) >> (4*7)))) ? (1 << 7) : 0) \
| 0)
#define INSERT_BITS(M,B,V) \
(__extension__({ \
unsigned char _n, _r = 0; \
_n = 0xf & (M >> (4*0)); if (_n<8) _r |= (!!(B & (1 << _n))) << 0; \
_n = 0xf & (M >> (4*1)); if (_n<8) _r |= (!!(B & (1 << _n))) << 1; \
_n = 0xf & (M >> (4*2)); if (_n<8) _r |= (!!(B & (1 << _n))) << 2; \
_n = 0xf & (M >> (4*3)); if (_n<8) _r |= (!!(B & (1 << _n))) << 3; \
_n = 0xf & (M >> (4*4)); if (_n<8) _r |= (!!(B & (1 << _n))) << 4; \
_n = 0xf & (M >> (4*5)); if (_n<8) _r |= (!!(B & (1 << _n))) << 5; \
_n = 0xf & (M >> (4*6)); if (_n<8) _r |= (!!(B & (1 << _n))) << 6; \
_n = 0xf & (M >> (4*7)); if (_n<8) _r |= (!!(B & (1 << _n))) << 7; \
(unsigned char) ((V) & MASK_F(M)) | _r; \
}))
#define MASK_USED(M) (MASK_F(M) | MASK_0_7(M))
#define TEST2(M,B,V) \
do { \
__asm volatile (";" #M); \
r1 = MASK_USED (M) \
& __builtin_avr_insert_bits (M,B,V); \
r2 = INSERT_BITS (M,B,V); \
if (r1 != r2) \
abort (); \
} while(0)
void test8 (void)
{
unsigned char r1, r2;
unsigned char ib, iv;
static const unsigned char V[] =
{
0, 0xaa, 0xcc, 0xf0, 0xff, 0x5b, 0x4d
};
for (ib = 0; ib < sizeof (V) / sizeof (*V); ib++)
{
unsigned char b = V[ib];
for (iv = 0; iv < sizeof (V) / sizeof (*V); iv++)
{
unsigned char v = V[iv];
TEST2 (0x76543210, b, v);
TEST2 (0xffffffff, b, v);
TEST2 (0x3210ffff, b, v);
TEST2 (0x67452301, b, v);
TEST2 (0xf0f1f2f3, b, v);
TEST2 (0xff10ff54, b, v);
TEST2 (0x0765f321, b, v);
TEST2 (0x11223344, b, v);
TEST2 (0x01234567, b, v);
TEST2 (0xff7765f3, b, v);
}
}
}
/****************************************************************/
int main()
{
test8();
exit(0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment