Patchwork [avr] PR55897: Allocate __memx to .progmemx.data

login
register
mail settings
Submitter Georg-Johann Lay
Date Jan. 7, 2013, 2:43 p.m.
Message ID <50EADF22.3040006@gjlay.de>
Download mbox | patch
Permalink /patch/209939/
State New
Headers show

Comments

Georg-Johann Lay - Jan. 7, 2013, 2:43 p.m.
Currently, data in address space __memx is allocated to .progmem.data, i.e. the
same section as for __flash resp. progmem.  However, there os no need that
__memx goes onto the same section and wastes precious memory in the first 64 Ki.

The patch puts __memx data into .progmemx.data so that a linker script can
allocate it after .text and it can be distinguished from data in __flash or
progmem.

The current default linker script contains .progmem* so that the patch does not
change anything here.  A new default script is still to come (binutils PR14406).

Moreover, there is some code clean-up like avoid magic "6" and use
ADDR_SPACE_COUNT instead.

Ok to apply?

Johann


	PR target/55897
	* config/avr/avr.h (ADDR_SPACE_COUNT): New enum.
	(avr_addrspace_t): Add .section_name field.
	* config/avr/avr.c (progmem_section): Use ADDR_SPACE_COUNT as
	array size.
	(avr_addrspace): Same.  Initialize .section_name.  Remove last
	NULL entry.  Put __memx into .progmemx.data.
	(progmem_section_prefix): Remove.
	(avr_asm_init_sections): No need to initialize progmem_section.
	(avr_asm_named_section): Use avr_addrspace[].section_name to get
	section name prefix.
	(avr_asm_select_section): Ditto.  And use get_unnamed_section to
	retrieve the progmem section.
	* avr-c.c (avr_cpu_cpp_builtins): Use ADDR_SPACE_COUNT as loop
	boundary to run over avr_addrspace[].
	(avr_register_target_pragmas): Ditto.
Denis Chertykov - Jan. 7, 2013, 6:18 p.m.
2013/1/7 Georg-Johann Lay <avr@gjlay.de>
>
> Currently, data in address space __memx is allocated to .progmem.data, i.e. the
> same section as for __flash resp. progmem.  However, there os no need that
> __memx goes onto the same section and wastes precious memory in the first 64 Ki.
>
> The patch puts __memx data into .progmemx.data so that a linker script can
> allocate it after .text and it can be distinguished from data in __flash or
> progmem.
>
> The current default linker script contains .progmem* so that the patch does not
> change anything here.  A new default script is still to come (binutils PR14406).
>
> Moreover, there is some code clean-up like avoid magic "6" and use
> ADDR_SPACE_COUNT instead.
>
> Ok to apply?
>
> Johann
>
>
>         PR target/55897
>         * config/avr/avr.h (ADDR_SPACE_COUNT): New enum.
>         (avr_addrspace_t): Add .section_name field.
>         * config/avr/avr.c (progmem_section): Use ADDR_SPACE_COUNT as
>         array size.
>         (avr_addrspace): Same.  Initialize .section_name.  Remove last
>         NULL entry.  Put __memx into .progmemx.data.
>         (progmem_section_prefix): Remove.
>         (avr_asm_init_sections): No need to initialize progmem_section.
>         (avr_asm_named_section): Use avr_addrspace[].section_name to get
>         section name prefix.
>         (avr_asm_select_section): Ditto.  And use get_unnamed_section to
>         retrieve the progmem section.
>         * avr-c.c (avr_cpu_cpp_builtins): Use ADDR_SPACE_COUNT as loop
>         boundary to run over avr_addrspace[].
>         (avr_register_target_pragmas): Ditto.

Approved.

Denis.

Patch

Index: avr-c.c
===================================================================
--- avr-c.c	(revision 194964)
+++ avr-c.c	(working copy)
@@ -43,7 +43,7 @@  avr_register_target_pragmas (void)
   /* Register address spaces.  The order must be the same as in the respective
      enum from avr.h (or designated initialized must be used in avr.c).  */
 
-  for (i = 0; avr_addrspace[i].name; i++)
+  for (i = 0; i < ADDR_SPACE_COUNT; i++)
     {
       gcc_assert (i == avr_addrspace[i].id);
 
@@ -160,7 +160,7 @@  avr_cpu_cpp_builtins (struct cpp_reader
   
   if (!strcmp (lang_hooks.name, "GNU C"))
     {
-      for (i = 0; avr_addrspace[i].name; i++)
+      for (i = 0; i < ADDR_SPACE_COUNT; i++)
         if (!ADDR_SPACE_GENERIC_P (i)
             /* Only supply __FLASH<n> macro if the address space is reasonable
                for this target.  The address space qualifier itself is still
Index: avr.c
===================================================================
--- avr.c	(revision 194964)
+++ avr.c	(working copy)
@@ -80,29 +80,18 @@ 
 
 /* Known address spaces.  The order must be the same as in the respective
    enum from avr.h (or designated initialized must be used).  */
-const avr_addrspace_t avr_addrspace[] =
+const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
 {
-    { ADDR_SPACE_RAM,  0, 2, ""     ,   0 },
-    { ADDR_SPACE_FLASH,  1, 2, "__flash",   0 },
-    { ADDR_SPACE_FLASH1, 1, 2, "__flash1",  1 },
-    { ADDR_SPACE_FLASH2, 1, 2, "__flash2",  2 },
-    { ADDR_SPACE_FLASH3, 1, 2, "__flash3",  3 },
-    { ADDR_SPACE_FLASH4, 1, 2, "__flash4",  4 },
-    { ADDR_SPACE_FLASH5, 1, 2, "__flash5",  5 },
-    { ADDR_SPACE_MEMX, 1, 3, "__memx",  0 },
-    { 0              , 0, 0, NULL,      0 }
+  { ADDR_SPACE_RAM,  0, 2, "", 0, NULL },
+  { ADDR_SPACE_FLASH,  1, 2, "__flash",   0, ".progmem.data" },
+  { ADDR_SPACE_FLASH1, 1, 2, "__flash1",  1, ".progmem1.data" },
+  { ADDR_SPACE_FLASH2, 1, 2, "__flash2",  2, ".progmem2.data" },
+  { ADDR_SPACE_FLASH3, 1, 2, "__flash3",  3, ".progmem3.data" },
+  { ADDR_SPACE_FLASH4, 1, 2, "__flash4",  4, ".progmem4.data" },
+  { ADDR_SPACE_FLASH5, 1, 2, "__flash5",  5, ".progmem5.data" },
+  { ADDR_SPACE_MEMX, 1, 3, "__memx",  0, ".progmemx.data" },
 };
 
-/* Map 64-k Flash segment to section prefix.  */
-static const char* const progmem_section_prefix[6] =
-  {
-    ".progmem.data",
-    ".progmem1.data",
-    ".progmem2.data",
-    ".progmem3.data",
-    ".progmem4.data",
-    ".progmem5.data"
-  };
 
 /* Holding RAM addresses of some SFRs used by the compiler and that
    are unique over all devices in an architecture like 'avr4'.  */
@@ -205,8 +194,9 @@  const struct mcu_type_s *avr_current_dev
 static GTY(()) section *progmem_swtable_section;
 
 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
-   or to address space __flash*.  */
-static GTY(()) section *progmem_section[6];
+   or to address space __flash* or __memx.  Only used as singletons inside
+   avr_asm_select_section, but it must not be local there because of GTY.  */
+static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
 
 /* Condition for insns/expanders from avr-dimode.md.  */
 bool avr_have_dimode = true;
@@ -8107,8 +8097,6 @@  avr_output_progmem_section_asm_op (const
 static void
 avr_asm_init_sections (void)
 {
-  unsigned int n;
-  
   /* Set up a section for jump tables.  Alignment is handled by
      ASM_OUTPUT_BEFORE_CASE_LABEL.  */
   
@@ -8127,13 +8115,6 @@  avr_asm_init_sections (void)
                                ",\"ax\",@progbits");
     }
 
-  for (n = 0; n < sizeof (progmem_section) / sizeof (*progmem_section); n++)
-    {
-      progmem_section[n]
-        = get_unnamed_section (0, avr_output_progmem_section_asm_op,
-                               progmem_section_prefix[n]);
-    }
-  
   /* Override section callbacks to keep track of `avr_need_clear_bss_p'
      resp. `avr_need_copy_data_p'.  */
   
@@ -8211,10 +8192,9 @@  avr_asm_named_section (const char *name,
   if (flags & AVR_SECTION_PROGMEM)
     {
       addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
-      int segment = avr_addrspace[as].segment;
       const char *old_prefix = ".rodata";
-      const char *new_prefix = progmem_section_prefix[segment];
-      
+      const char *new_prefix = avr_addrspace[as].section_name;
+
       if (STR_PREFIX_P (name, old_prefix))
         {
           const char *sname = ACONCAT ((new_prefix,
@@ -8326,13 +8306,18 @@  avr_asm_select_section (tree decl, int r
       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
     {
       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
-      int segment = avr_addrspace[as].segment;
+
+      /* __progmem__ goes in generic space but shall be allocated to
+         .progmem.data  */
+
+      if (ADDR_SPACE_GENERIC_P (as))
+        as = ADDR_SPACE_FLASH;
       
       if (sect->common.flags & SECTION_NAMED)
         {
           const char * name = sect->named.name;
           const char * old_prefix = ".rodata";
-          const char * new_prefix = progmem_section_prefix[segment];
+          const char * new_prefix = avr_addrspace[as].section_name;
 
           if (STR_PREFIX_P (name, old_prefix))
             {
@@ -8341,8 +8326,15 @@  avr_asm_select_section (tree decl, int r
               return get_section (sname, sect->common.flags, sect->named.decl);
             }
         }
-          
-      return progmem_section[segment];
+
+      if (!progmem_section[as])
+        {
+          progmem_section[as]
+            = get_unnamed_section (0, avr_output_progmem_section_asm_op,
+                                   avr_addrspace[as].section_name);
+        }
+
+      return progmem_section[as];
     }
 
   return sect;
Index: avr.h
===================================================================
--- avr.h	(revision 194964)
+++ avr.h	(working copy)
@@ -37,6 +37,9 @@  typedef struct
 
   /* Segment (i.e. 64k memory chunk) number.  */
   int segment;
+
+  /* Section prefix, e.g. ".progmem1.data"  */
+  const char *section_name;
 } avr_addrspace_t;
 
 extern const avr_addrspace_t avr_addrspace[];
@@ -45,14 +48,16 @@  extern const avr_addrspace_t avr_addrspa
 
 enum
   {
-    ADDR_SPACE_RAM,
+    ADDR_SPACE_RAM, /* ADDR_SPACE_GENERIC */
     ADDR_SPACE_FLASH,
     ADDR_SPACE_FLASH1,
     ADDR_SPACE_FLASH2,
     ADDR_SPACE_FLASH3,
     ADDR_SPACE_FLASH4,
     ADDR_SPACE_FLASH5,
-    ADDR_SPACE_MEMX
+    ADDR_SPACE_MEMX,
+    /* Sentinel */
+    ADDR_SPACE_COUNT
   };
 
 #define TARGET_CPU_CPP_BUILTINS()	avr_cpu_cpp_builtins (pfile)