re PR target/78093 ([avr] New variable attribute "absdata" and option "-mabsdata...
authorGeorg-Johann Lay <avr@gjlay.de>
Mon, 24 Oct 2016 11:02:51 +0000 (11:02 +0000)
committerGeorg-Johann Lay <gjl@gcc.gnu.org>
Mon, 24 Oct 2016 11:02:51 +0000 (11:02 +0000)
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

gcc/ChangeLog
gcc/config/avr/avr.c
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/avr/torture/tiny-absdata-1.c [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp

index a0c6c37056405a2c476b47fc815ade0150901289..291ef4507de8dc21990ef0aabb8bf5a55244b1ca 100644 (file)
@@ -1,3 +1,18 @@
+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
index 3945122e2f3b46a39b02cbecb9f687a426fea0f5..1a49fdc0d9651252ce5b033f3c4745f296764a57 100644 (file)
 #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);
         }
@@ -9148,6 +9172,32 @@ avr_handle_fntype_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
+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)
index 62a5f2963db51ce59ebf078531e24780fd5c2cfb..0669f7999beb078822e471352036d8f13517812d 100644 (file)
@@ -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
index d43a909a0dde3410df9c960cfde692c433048523..bc9bf6760327c0681cdd20432f18ffc60b7382a5 100644 (file)
@@ -1,3 +1,9 @@
+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.
diff --git a/gcc/testsuite/gcc.target/avr/torture/tiny-absdata-1.c b/gcc/testsuite/gcc.target/avr/torture/tiny-absdata-1.c
new file mode 100644 (file)
index 0000000..c1c645f
--- /dev/null
@@ -0,0 +1,70 @@
+/* { 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," } } */
index 2394ac4a13115b7bd92d0380b36e589ad7abd26a..b5a9faab5a47d01371c6402a5b07d34071dbc34b 100644 (file)
@@ -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"