diff mbox

[avr,RFC] Add var attribute "absdata" to support LDS / STS on AVR_TINY.

Message ID a6c7cd00-d442-1f9f-738c-996506b3dd92@gjlay.de
State New
Headers show

Commit Message

Georg-Johann Lay Aug. 8, 2016, 11:04 a.m. UTC
On 08.08.2016 07:10, Sandra Loosemore wrote:
> On 08/03/2016 10:17 AM, Georg-Johann Lay wrote:
>
>> Index: doc/extend.texi
>> ===================================================================
>> --- doc/extend.texi    (revision 238983)
>> +++ doc/extend.texi    (working copy)
>> @@ -5957,6 +5957,25 @@ memory-mapped peripherals that may lie o
>>  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 @code{ATtiny40}.
>> +
>> +@item
>> +There is currently no Binutils support for this attribute and the user has
>> +to make sure that respective data is located into an address range that
>> +can actually be handled by @code{LDS} and @code{STS}.
>> +This applies to addresses in the range @code{0x40}@dots{}@code{0xbf}.
>
> The wording here is a little awkward -- in particular, "the user" is really
> "you", the reader of the manual.  How about something like this instead?
>
> @item
> You must use an appropriate linker script to locate the data in the address
> range accessible by @code{LDS} and @code{STS} (@code{0x40}@dots{}@code{0xbf}).
>
> -Sandra
>

Thanks for the help.  Attached is an updated patch.
diff mbox

Patch

Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(revision 238983)
+++ doc/extend.texi	(working copy)
@@ -5957,6 +5957,32 @@  memory-mapped peripherals that may lie o
 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 @code{ATtiny40}.
+
+@item
+You must use an appropriate linker script to locate the data in the
+address range accessible by @code{LDS} and @code{STS}
+(@code{0x40}@dots{}@code{0xbf}).
+
+@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: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 238983)
+++ config/avr/avr.c	(working copy)
@@ -81,9 +81,13 @@ 
    / SYMBOL_FLAG_MACH_DEP)
 
 /* (AVR_TINY only): Symbol has attribute progmem */
-#define AVR_SYMBOL_FLAG_TINY_PM \
+#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 "))"
@@ -1802,6 +1806,28 @@  avr_mode_dependent_address_p (const_rtx
 }
 
 
+/* 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
@@ -1886,8 +1912,7 @@  avr_legitimate_address_p (machine_mode m
       /* 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)
@@ -1929,8 +1954,7 @@  avr_legitimize_address (rtx x, rtx oldx,
   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);
         }
@@ -9124,6 +9148,32 @@  avr_handle_fntype_attribute (tree *node,
 }
 
 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)
 {
@@ -9230,6 +9280,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 }
 };
 
@@ -9314,6 +9366,17 @@  avr_progmem_p (tree decl, tree attribute
 }
 
 
+/* 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.
@@ -9738,14 +9801,29 @@  avr_encode_section_info (tree decl, rtx
   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)))
+        {
+          // 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");
+        }
     }
 }