Commit b1b6774f by Georg-Johann Lay Committed by Georg-Johann Lay

re PR target/78093 ([avr] New variable attribute "absdata" and option…

re PR target/78093 ([avr] New variable attribute "absdata" and option "-mabsdata" to enable LDS / STS on Reduced Tiny)

gcc/
	PR target/78093
	* doc/extend.texi (AVR Variable Attributes) [absdata]: Document it.
	* config/avr/avr.c (AVR_SYMBOL_FLAG_TINY_ABSDATA): New macro.
	(avr_address_tiny_absdata_p): New static function.
	(avr_legitimate_address_p, avr_legitimize_address) [AVR_TINY]: Use
	it to determine validity of constant addresses.
	(avr_attribute_table) [absdata]: New variable attribute...
	(avr_handle_absdata_attribute): ...and handler.
	(avr_decl_absdata_p): New static function.
	(avr_encode_section_info) [AVR_TINY]: Use it to add flag
	AVR_SYMBOL_FLAG_TINY_ABSDATA to respective symbols_refs.
	(avr_address_cost) [AVR_TINY]: absdata addresses cost 2.
gcc/testsuite/
	PR target/78093
	* lib/target-supports.exp (check_effective_target_avr_tiny): New proc.
	* gcc.target/avr/torture/tiny-absdata-1.c: New test.

From-SVN: r241468
parent 06d1ff90
2016-10-24 Georg-Johann Lay <avr@gjlay.de>
PR target/78093
* doc/extend.texi (AVR Variable Attributes) [absdata]: Document it.
* config/avr/avr.c (AVR_SYMBOL_FLAG_TINY_ABSDATA): New macro.
(avr_address_tiny_absdata_p): New static function.
(avr_legitimate_address_p, avr_legitimize_address) [AVR_TINY]: Use
it to determine validity of constant addresses.
(avr_attribute_table) [absdata]: New variable attribute...
(avr_handle_absdata_attribute): ...and handler.
(avr_decl_absdata_p): New static function.
(avr_encode_section_info) [AVR_TINY]: Use it to add flag
AVR_SYMBOL_FLAG_TINY_ABSDATA to respective symbols_refs.
(avr_address_cost) [AVR_TINY]: absdata addresses cost 2.
2016-10-24 Richard Biener <rguenther@suse.de>
PR tree-optimization/78076
......
......@@ -85,6 +85,10 @@
#define AVR_SYMBOL_FLAG_TINY_PM \
(SYMBOL_FLAG_MACH_DEP << 7)
/* (AVR_TINY only): Symbol has attribute absdata */
#define AVR_SYMBOL_FLAG_TINY_ABSDATA \
(SYMBOL_FLAG_MACH_DEP << 8)
#define TINY_ADIW(REG1, REG2, I) \
"subi " #REG1 ",lo8(-(" #I "))" CR_TAB \
"sbci " #REG2 ",hi8(-(" #I "))"
......@@ -1791,6 +1795,28 @@ avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
}
/* Return true if rtx X is a CONST_INT, CONST or SYMBOL_REF
address with the `absdata' variable attribute, i.e. respective
data can be read / written by LDS / STS instruction.
This is used only for AVR_TINY. */
static bool
avr_address_tiny_absdata_p (rtx x, machine_mode mode)
{
if (CONST == GET_CODE (x))
x = XEXP (XEXP (x, 0), 0);
if (SYMBOL_REF_P (x))
return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_ABSDATA;
if (CONST_INT_P (x)
&& IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)))
return true;
return false;
}
/* Helper function for `avr_legitimate_address_p'. */
static inline bool
......@@ -1875,8 +1901,7 @@ avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
/* avrtiny's load / store instructions only cover addresses 0..0xbf:
IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf. */
ok = (CONST_INT_P (x)
&& IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)));
ok = avr_address_tiny_absdata_p (x, mode);
}
if (avr_log.legitimate_address_p)
......@@ -1918,8 +1943,7 @@ avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
if (AVR_TINY)
{
if (CONSTANT_ADDRESS_P (x)
&& !(CONST_INT_P (x)
&& IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode))))
&& ! avr_address_tiny_absdata_p (x, mode))
{
x = force_reg (Pmode, x);
}
......@@ -9149,6 +9173,32 @@ avr_handle_fntype_attribute (tree *node, tree name,
}
static tree
avr_handle_absdata_attribute (tree *node, tree name, tree /* args */,
int /* flags */, bool *no_add)
{
location_t loc = DECL_SOURCE_LOCATION (*node);
if (AVR_TINY)
{
if (TREE_CODE (*node) != VAR_DECL
|| (!TREE_STATIC (*node) && !DECL_EXTERNAL (*node)))
{
warning_at (loc, OPT_Wattributes, "%qE attribute only applies to"
" variables in static storage", name);
*no_add = true;
}
}
else
{
warning_at (loc, OPT_Wattributes, "%qE attribute only supported"
" for reduced Tiny cores", name);
*no_add = true;
}
return NULL_TREE;
}
static tree
avr_handle_addr_attribute (tree *node, tree name, tree args,
int flags ATTRIBUTE_UNUSED, bool *no_add)
{
......@@ -9218,8 +9268,8 @@ avr_eval_addr_attrib (rtx x)
if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
{
attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
if (!attr || !TREE_VALUE (attr))
attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
if (!attr || !TREE_VALUE (attr))
attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
gcc_assert (attr);
}
if (!attr || !TREE_VALUE (attr))
......@@ -9255,6 +9305,8 @@ avr_attribute_table[] =
false },
{ "address", 1, 1, false, false, false, avr_handle_addr_attribute,
false },
{ "absdata", 0, 0, true, false, false, avr_handle_absdata_attribute,
false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
......@@ -9339,6 +9391,17 @@ avr_progmem_p (tree decl, tree attributes)
}
/* Return true if DECL has attribute `absdata' set. This function should
only be used for AVR_TINY. */
static bool
avr_decl_absdata_p (tree decl, tree attributes)
{
return (TREE_CODE (decl) == VAR_DECL
&& NULL_TREE != lookup_attribute ("absdata", attributes));
}
/* Scan type TYP for pointer references to address space ASn.
Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
the AS are also declared to be CONST.
......@@ -9694,6 +9757,8 @@ avr_section_type_flags (tree decl, const char *name, int reloc)
static void
avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
{
tree addr_attr = NULL_TREE;
/* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
readily available, see PR34734. So we postpone the warning
about uninitialized data in program memory section until here. */
......@@ -9735,7 +9800,7 @@ avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
tree io_low_attr = lookup_attribute ("io_low", attr);
tree io_attr = lookup_attribute ("io", attr);
tree addr_attr;
if (io_low_attr
&& TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
addr_attr = io_attr;
......@@ -9763,14 +9828,32 @@ avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
if (AVR_TINY
&& decl
&& VAR_DECL == TREE_CODE (decl)
&& -1 == avr_progmem_p (decl, DECL_ATTRIBUTES (decl))
&& MEM_P (rtl)
&& SYMBOL_REF_P (XEXP (rtl, 0)))
{
/* Tag symbols for later addition of 0x4000 (AVR_TINY_PM_OFFSET). */
rtx sym = XEXP (rtl, 0);
SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
if (-1 == avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
{
// Tag symbols for later addition of 0x4000 (AVR_TINY_PM_OFFSET).
SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
}
if (avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl))
|| (addr_attr
// If addr_attr is non-null, it has an argument. Peek into it.
&& TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (addr_attr))) < 0xc0))
{
// May be accessed by LDS / STS.
SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_ABSDATA;
}
if (-1 == avr_progmem_p (decl, DECL_ATTRIBUTES (decl))
&& avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl)))
{
error ("%q+D has incompatible attributes %qs and %qs",
decl, "progmem", "absdata");
}
}
}
......@@ -10900,6 +10983,10 @@ avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
if (optimize > 0
&& io_address_operand (x, QImode))
cost = 2;
if (AVR_TINY
&& avr_address_tiny_absdata_p (x, QImode))
cost = 2;
}
if (avr_log.address_cost)
......
......@@ -5973,6 +5973,33 @@ memory-mapped peripherals that may lie outside the io address range.
volatile int porta __attribute__((address (0x600)));
@end smallexample
@item absdata
@cindex @code{absdata} variable attribute, AVR
Variables in static storage and with the @code{absdata} attribute can
be accessed by the @code{LDS} and @code{STS} instructions which take
absolute addresses.
@itemize @bullet
@item
This attribute is only supported for the reduced AVR Tiny core
like ATtiny40.
@item
You must make sure that respective data is located in the
address range @code{0x40}@dots{}@code{0xbf} accessible by
@code{LDS} and @code{STS}. One way to achieve this as an
appropriate linker description file.
@item
If the location does not fit the address range of @code{LDS}
and @code{STS}, there is currently (Binutils 2.26) just an unspecific
warning like
@quotation
@code{module.c:(.text+0x1c): warning: internal error: out of range error}
@end quotation
@end itemize
@end table
@node Blackfin Variable Attributes
......
2016-10-24 Georg-Johann Lay <avr@gjlay.de>
PR target/78093
* lib/target-supports.exp (check_effective_target_avr_tiny): New proc.
* gcc.target/avr/torture/tiny-absdata-1.c: New test.
2016-10-24 Andre Vieira <andre.simoesdiasvieira@arm.com>
* gcc.target/arm/pure-code/pure-code.exp: Restore saved globals.
......
/* { dg-do compile } */
/* { dg-require-effective-target avr_tiny } */
typedef struct
{
char a, b, c;
} abc_t;
extern char varA __attribute__((absdata));
extern char varB __attribute__((absdata));
extern int arrayA[] __attribute__((absdata));
extern int arrayB[] __attribute__((absdata));
extern char arrayC[] __attribute__((address(0x80)));
extern abc_t abc __attribute__((absdata));
char get_1 (void)
{
return varA;
}
int get_2 (void)
{
return arrayA[3];
}
char get_3 (void)
{
return abc.a + abc.b + abc.c;
}
void put_1 (char b)
{
varB = b;
}
void put_2 (int b)
{
arrayB[3] = b;
}
void put_3 (void)
{
abc.a = abc.b = abc.c = 0;
}
void put_4 (void)
{
arrayC[0] = arrayC[1] = arrayC[2] = 0;
}
/* { dg-final { scan-assembler "lds r\[0-9\]+,varA" } } */
/* { dg-final { scan-assembler "lds r\[0-9\]+,arrayA\\+6" } } */
/* { dg-final { scan-assembler "lds r\[0-9\]+,arrayA\\+6\\+1" } } */
/* { dg-final { scan-assembler "lds r\[0-9\]+,abc" } } */
/* { dg-final { scan-assembler "lds r\[0-9\]+,abc\\+1" } } */
/* { dg-final { scan-assembler "lds r\[0-9\]+,abc\\+2" } } */
/* { dg-final { scan-assembler "sts varB," } } */
/* { dg-final { scan-assembler "sts arrayB\\+6," } } */
/* { dg-final { scan-assembler "sts arrayB\\+6\\+1," } } */
/* { dg-final { scan-assembler "sts arrayC," } } */
/* { dg-final { scan-assembler "sts arrayC\\+1," } } */
/* { dg-final { scan-assembler "sts arrayC\\+2," } } */
/* { dg-final { scan-assembler "sts abc," } } */
/* { dg-final { scan-assembler "sts abc\\+1," } } */
/* { dg-final { scan-assembler "sts abc\\+2," } } */
......@@ -7784,6 +7784,24 @@ proc check_effective_target_aarch64_large { } {
}
}
# Return 1 if this is a reduced AVR Tiny core. Such cores have different
# register set, instruction set, addressing capabilities and ABI.
proc check_effective_target_avr_tiny { } {
if { [istarget avr*-*-*] } {
return [check_no_compiler_messages avr_tiny object {
#ifdef __AVR_TINY__
int dummy;
#else
#error target not a reduced AVR Tiny core
#endif
}]
} else {
return 0
}
}
# Return 1 if <fenv.h> is available with all the standard IEEE
# exceptions and floating-point exceptions are raised by arithmetic
# operations. (If the target requires special options for "inexact"
......
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