This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch,avr] Add support for devices with flash accessible by LD.


On 12.06.2017 08:30, Pitchumani Sivanupandi wrote:
On Friday 09 June 2017 03:59 PM, Georg-Johann Lay wrote:
Hi,

This patch adds support for devices that can access flash memory
by LD* instructions, hence there is no need to put .rodata in RAM.

The default linker script for the new multilib versions already
supports this feature, it's similar to avrtiny, cf.

https://sourceware.org/PR21472

This patch does the following:

* Add multilib variants avrxmega3 and avrxmega3/short-calls.

* Add new option -mshort-calls for multilib selection between
  devices with <= 8KiB flash and > 8KiB flash.

* Add specs handling for -mshort-calls:  The compiler knows
  if this option is needed or not appropriate (similar to -msp8).

* Add new ISA feature AVR_ISA_RCALL for multilib selection
  via -mshort-calls.

* Add a new row to architecture description that contains the
  start address of flash memory in the RAM address range.
  (The actual value is not needed).

* For devices with flash in RAM space, don't let .rodata
  objects trigger need for __do_copy_data.

* Add some devices.

* Add configure test for Binutils PR21472.

* Adjust documentation etc.

Even the smaller devices with flash <= 8KiB support JMP+CALL,
but we get better code by assuming RJMP+RCALL:  Jump tables
are more efficient and insn length computation is more exact
(CALL -> RCALL relaxation would need -mrelax and insn size
would still be 4 bytes).

Moreover, avr-libc uses __AVR_HAVE_JMP_CALL__ to determine
vector entry size, and libgcc uses that macro for flash size
estimation.
Hi Johann,

+  AVR_ISA_RCALL   = 0x10 /* Use RJMP / RCALL even though RJMP / RCALL
+                            are available (-mshort-calls).  */

I think you meant "even though JMP/ CALL are avariable".

+AVR_MCU ("attiny817",        ARCH_AVRXMEGA3, AVR_ISA_RCALL,
"__AVR_ATtiny817__",   0x3e00, 0x0, 0x2000)
+AVR_MCU ("attiny1616",       ARCH_AVRXMEGA3, AVR_ISA_NONE,
"__AVR_ATtiny1616__",  0x3800, 0x0, 0x4000)

Add attiny1614 device.
AVR_MCU ("attiny1614",       ARCH_AVRXMEGA3, AVR_ISA_NONE,
"__AVR_ATtiny1614__",  0x3800, 0x0, 0x4000)

Regards,
Pitchumani

Updated patch.

	* config/avr/avr-arch.h (avr_arch_id) <ARCH_AVRXMEGA3>: New enum.
	(avr_mcu_t) <flash_pm_offset>: New field.
	(avr_device_specific_features) <AVR_ISA_RCALL>: New enum.
	* config/avr/avr.h (AVR_SHORT_CALLS): New define.
	(AVR_HAVE_JMP_CALL): Don't set if AVR_SHORT_CALLS.
	(AVR_TINY_PM_OFFSET): Remove macro.
	* config/avr/avr.opt (-mshort-calls): New option.
	* config/avr/gen-avr-mmcu-specs.c (print_mcu)
	[*self_spec]: Add / remove -mshort-calls depending on AVR_ISA_RCALL.
	* config/avr/avr-c.c (avr_cpu_cpp_builtins)
	<__AVR_SHORT_CALLS__>: Built-in define if AVR_SHORT_CALLS.
	<__AVR_HAVE_JMP_CALL__>: Use AVR_HAVE_JMP_CALL as condition
	instead of avr_arch->have_jmp_call.
	<__AVR_PM_BASE_ADDRESS__>: Built-in define if avr_arch->flash_pm_offset.
	[AVR_TINY] <__AVR_TINY_PM_BASE_ADDRESS__>: Use
	avr_arch->flash_pm_offset to define.
	* config/avr/avr-devices.c (avr_arch_types): Add initializers for
	new field flash_pm_offset.  Add entry for avrxmega3.
	(avr_texinfo): Add entry for avrxmega3.
	* avr-mcus.def: Add entries for: avrxmega3, attiny212, attiny214,
	attiny412, attiny414, attiny416, attiny417, attiny814,
	attiny816, attiny817, attiny1614, attiny1616, attiny1617,
	attiny3214, attiny3216, attiny3217.
	* config/avr/avr.c (avr_assemble_integer)[AVR_TINY]: Use
	avr_arch->flash_pm_offset instead of AVR_TINY_PM_OFFSET.
	(avr_print_operand_address) [AVR_TINY]: Same.
	(avr_asm_init_sections) <readonly_data_section>: Only patch
	callback if avr_arch->flash_pm_offset = 0.
	(avr_asm_named_section) <avr_need_copy_data_p>: Skip setting it
	for rodata if avr_arch->flash_pm_offset != 0.
	(avr_encode_section_info) [AVR_TINY]: Adjust comment.
	* config/avr/genmultilib.awk (dir_rcall, opt_rcall): New vars.
	(opts) [AVR_ISA_RCALL]: Append opt_rcall.
	(m_options): Append opt_rcall.
	(m_dirnames): Append dir_rcall.
	* config/avr/t-multilib: Regenerate.

	* configure.ac [target=avr]: Check whether avrxmega3 default
	linker description file works as needed.
	* configure: Regenerate.
	* doc/avr-mmcu.texi: Regenerate.
	* doc/invoke.texi (AVR Options) <-mshort-calls>: Document it.
	<__AVR_ARCH__>: Document avrxmega3 and 103.
	<__AVR_HAVE_JMP_CALL__>: Adjust documentation.
	<__AVR_SHORT_CALLS__>: Document it.
	<__AVR_PM_BASE_ADDRESS__>: Document it.
	* doc/extend.texi (AVR Options) <-mshort-calls>: Document it.
	(AVR Variable Attributes) <progmem>: Document this is
	not needed for avrxmega3.
	(AVR Named Address Spaces) <__flash>: Dito.


Index: config/avr/avr-arch.h
===================================================================
--- config/avr/avr-arch.h	(revision 249064)
+++ config/avr/avr-arch.h	(working copy)
@@ -41,6 +41,7 @@ enum avr_arch_id
   ARCH_AVR6,
   ARCH_AVRTINY,
   ARCH_AVRXMEGA2,
+  ARCH_AVRXMEGA3,
   ARCH_AVRXMEGA4,
   ARCH_AVRXMEGA5,
   ARCH_AVRXMEGA6,
@@ -86,6 +87,9 @@ typedef struct
   /* Default start of data section address for architecture.  */
   int default_data_section_start;
 
+  /* Offset where flash memory is seen in RAM address range or 0.  */
+  int flash_pm_offset;
+
   /* Offset between SFR address and RAM address:
      SFR-address = RAM-address - sfr_offset  */
   int sfr_offset;
@@ -150,7 +154,16 @@ AVR_ERRATA_SKIP
 
      For information please refer the following respective errata links
        http://www.atmel.com/dyn/resources/prod_documents/doc2494.pdf
-       http://www.atmel.com/dyn/resources/prod_documents/doc1436.pdf  */
+       http://www.atmel.com/dyn/resources/prod_documents/doc1436.pdf
+
+AVR_ISA_RCALL
+  Always use RJMP / RCALL and assume JMP / CALL are not available.
+  This affects multilib selection via specs generation and -mshort-calls.
+  Even if a device like ATtiny417 from avrxmega3 supports JMP / CALL, we
+  assume these instructions are not available and we set the built-in
+  macro __AVR_HAVE_JMP_CALL__ accordingly.  This macro is used to
+  determine a rough estimate of flash size in libgcc, and AVR-LibC uses
+  this macro to determine vector sizes.  */
 
 enum avr_device_specific_features
 {
@@ -158,8 +171,10 @@ enum avr_device_specific_features
   AVR_ISA_RMW     = 0x1, /* device has RMW instructions. */
   AVR_SHORT_SP    = 0x2, /* Stack Pointer has 8 bits width. */
   AVR_ERRATA_SKIP = 0x4, /* device has a core erratum. */
-  AVR_ISA_LDS     = 0x8  /* whether LDS / STS is valid for all data in static
+  AVR_ISA_LDS     = 0x8, /* whether LDS / STS is valid for all data in static
                             storage.  Only useful for reduced Tiny.  */
+  AVR_ISA_RCALL   = 0x10 /* Use RJMP / RCALL even though JMP / CALL
+                            are available (-mshort-calls).  */
 };
 
 /* Map architecture to its texinfo string.  */
Index: config/avr/avr-c.c
===================================================================
--- config/avr/avr-c.c	(revision 249064)
+++ config/avr/avr-c.c	(working copy)
@@ -313,11 +313,16 @@ cpp_define_formatted (pfile, "__AVR_ARCH
       cpp_define (pfile, "__AVR_ENHANCED__");
       cpp_define (pfile, "__AVR_HAVE_MUL__");
     }
+
+  if (AVR_HAVE_JMP_CALL)
+    cpp_define (pfile, "__AVR_HAVE_JMP_CALL__");
+
   if (avr_arch->have_jmp_call)
-    {
-      cpp_define (pfile, "__AVR_MEGA__");
-      cpp_define (pfile, "__AVR_HAVE_JMP_CALL__");
-    }
+    cpp_define (pfile, "__AVR_MEGA__");
+
+  if (AVR_SHORT_CALLS)
+    cpp_define (pfile, "__AVR_SHORT_CALLS__");
+
   if (AVR_XMEGA)
     cpp_define (pfile, "__AVR_XMEGA__");
 
@@ -335,9 +340,13 @@ start address.  This macro shall be used
          (ATtiny4/5/9/10/20 and 40) mapped program memory starts at 0x4000. */
 
       cpp_define_formatted (pfile, "__AVR_TINY_PM_BASE_ADDRESS__=0x%x",
-                            AVR_TINY_PM_OFFSET);
+                            avr_arch->flash_pm_offset);
     }
 
+  if (avr_arch->flash_pm_offset)
+    cpp_define_formatted (pfile, "__AVR_PM_BASE_ADDRESS__=0x%x",
+                          avr_arch->flash_pm_offset);
+
   if (AVR_HAVE_EIJMP_EICALL)
     {
       cpp_define (pfile, "__AVR_HAVE_EIJMP_EICALL__");
Index: config/avr/avr-devices.c
===================================================================
--- config/avr/avr-devices.c	(revision 249064)
+++ config/avr/avr-devices.c	(working copy)
@@ -34,30 +34,31 @@ const avr_arch_t
 avr_arch_types[] =
 {
   /* unknown device specified */
-  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, NULL, AVR_MMCU_DEFAULT },
+  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 0,      32, NULL, AVR_MMCU_DEFAULT },
   /*
-    A  M  J  LM E  E  E  X  R  T  d S   S O   A
-    S  U  M  PO L  L  I  M  A  I  a t   F ff  r
-    M  L  P  MV P  P  J  E  M  N  t a   R s   c
-             XW M  M  M  G  P  Y  a r     e   h
-                   X  P  A  D       t     t   ID   */
-  { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "1",   "avr1"  },
-  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "2",   "avr2"  },
-  { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "25",  "avr25" },
-  { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "3",   "avr3"  },
-  { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, "31",  "avr31" },
-  { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "35",  "avr35" },
-  { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "4",   "avr4"  },
-  { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "5",   "avr5"  },
-  { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0x0060, 32, "51",  "avr51" },
-  { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, "6",   "avr6"  },
+    A  M  J  LM E  E  E  X  R  T  d S     FPO     S O   A
+    S  U  M  PO L  L  I  M  A  I  a t     lMff    F ff  r
+    M  L  P  MV P  P  J  E  M  N  t a     a s     R s   c
+             XW M  M  M  G  P  Y  a r     s e       e   h
+                   X  P  A  D       t     h t       t   ID   */
+  { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 0,      32, "1",   "avr1"  },
+  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 0,      32, "2",   "avr2"  },
+  { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 0,      32, "25",  "avr25" },
+  { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0x0060, 0,      32, "3",   "avr3"  },
+  { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 0,      32, "31",  "avr31" },
+  { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 0,      32, "35",  "avr35" },
+  { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 0,      32, "4",   "avr4"  },
+  { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0x0060, 0,      32, "5",   "avr5"  },
+  { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0x0060, 0,      32, "51",  "avr51" },
+  { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 0,      32, "6",   "avr6"  },
 
-  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x0040,  0, "100", "avrtiny" },
-  { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0x2000,  0, "102", "avrxmega2" },
-  { 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0x2000,  0, "104", "avrxmega4" },
-  { 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0x2000,  0, "105", "avrxmega5" },
-  { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0x2000,  0, "106", "avrxmega6" },
-  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000,  0, "107", "avrxmega7" }
+  { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0x0040, 0x4000, 0, "100", "avrtiny" },
+  { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0x2000, 0,      0, "102", "avrxmega2" },
+  { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0x2000, 0x8000, 0, "103", "avrxmega3" },
+  { 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0x2000, 0,      0, "104", "avrxmega4" },
+  { 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0x2000, 0,      0, "105", "avrxmega5" },
+  { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0x2000, 0,      0, "106", "avrxmega6" },
+  { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000, 0,      0, "107", "avrxmega7" }
 };
 
 const avr_arch_info_t
@@ -95,6 +96,9 @@ avr_texinfo[] =
   { ARCH_AVRXMEGA2,
     "``XMEGA'' devices with more than 8@tie{}KiB and up to 64@tie{}KiB "
     "of program memory." },
+  { ARCH_AVRXMEGA3,
+    "``XMEGA'' devices with up to 64@tie{}KiB of combined program memory "
+	"and RAM, and with program memory visible in the RAM address space." },
   { ARCH_AVRXMEGA4,
     "``XMEGA'' devices with more than 64@tie{}KiB and up to 128@tie{}KiB "
     "of program memory." },
Index: config/avr/avr-mcus.def
===================================================================
--- config/avr/avr-mcus.def	(revision 249064)
+++ config/avr/avr-mcus.def	(working copy)
@@ -299,6 +299,23 @@ AVR_MCU ("atxmega16c4",      ARCH_AVRXME
 AVR_MCU ("atxmega32a4u",     ARCH_AVRXMEGA2, AVR_ISA_RMW,  "__AVR_ATxmega32A4U__", 0x2000, 0x0, 0x9000)
 AVR_MCU ("atxmega32c4",      ARCH_AVRXMEGA2, AVR_ISA_RMW,  "__AVR_ATxmega32C4__",  0x2000, 0x0, 0x9000)
 AVR_MCU ("atxmega32e5",      ARCH_AVRXMEGA2, AVR_ISA_NONE, "__AVR_ATxmega32E5__",  0x2000, 0x0, 0x9000)
+/* Xmega, Flash + RAM < 64K, flash visible in RAM address space */
+AVR_MCU ("avrxmega3",        ARCH_AVRXMEGA3, AVR_ISA_NONE,  NULL,                  0x3f00, 0x0, 0x8000)
+AVR_MCU ("attiny212",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny212__",   0x3f80, 0x0, 0x800)
+AVR_MCU ("attiny214",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny214__",   0x3f80, 0x0, 0x800)
+AVR_MCU ("attiny412",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny412__",   0x3f00, 0x0, 0x1000)
+AVR_MCU ("attiny414",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny414__",   0x3f00, 0x0, 0x1000)
+AVR_MCU ("attiny416",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny416__",   0x3f00, 0x0, 0x1000)
+AVR_MCU ("attiny417",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny417__",   0x3f00, 0x0, 0x1000)
+AVR_MCU ("attiny814",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny814__",   0x3e00, 0x0, 0x2000)
+AVR_MCU ("attiny816",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny816__",   0x3e00, 0x0, 0x2000)
+AVR_MCU ("attiny817",        ARCH_AVRXMEGA3, AVR_ISA_RCALL, "__AVR_ATtiny817__",   0x3e00, 0x0, 0x2000)
+AVR_MCU ("attiny1614",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny1614__",  0x3800, 0x0, 0x4000)
+AVR_MCU ("attiny1616",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny1616__",  0x3800, 0x0, 0x4000)
+AVR_MCU ("attiny1617",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny1617__",  0x3800, 0x0, 0x4000)
+AVR_MCU ("attiny3214",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny3214__",  0x3800, 0x0, 0x8000)
+AVR_MCU ("attiny3216",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny3216__",  0x3800, 0x0, 0x8000)
+AVR_MCU ("attiny3217",       ARCH_AVRXMEGA3, AVR_ISA_NONE,  "__AVR_ATtiny3217__",  0x3800, 0x0, 0x8000)
 /* Xmega, 64K < Flash <= 128K, RAM <= 64K */
 AVR_MCU ("avrxmega4",        ARCH_AVRXMEGA4, AVR_ISA_NONE, NULL,                   0x2000, 0x0, 0x11000)
 AVR_MCU ("atxmega64a3",      ARCH_AVRXMEGA4, AVR_ISA_NONE, "__AVR_ATxmega64A3__",  0x2000, 0x0, 0x11000)
Index: config/avr/avr.c
===================================================================
--- config/avr/avr.c	(revision 249064)
+++ config/avr/avr.c	(working copy)
@@ -2502,7 +2502,7 @@ avr_print_operand_address (FILE *file, m
   if (AVR_TINY
       && avr_address_tiny_pm_p (addr))
     {
-      addr = plus_constant (Pmode, addr, AVR_TINY_PM_OFFSET);
+      addr = plus_constant (Pmode, addr, avr_arch->flash_pm_offset);
     }
 
   switch (GET_CODE (addr))
@@ -9398,7 +9398,7 @@ avr_assemble_integer (rtx x, unsigned in
   if (AVR_TINY
       && avr_address_tiny_pm_p (x))
     {
-      x = plus_constant (Pmode, x, AVR_TINY_PM_OFFSET);
+      x = plus_constant (Pmode, x, avr_arch->flash_pm_offset);
     }
 
   return default_assemble_integer (x, size, aligned_p);
@@ -9998,9 +9998,11 @@ static void
 avr_asm_init_sections (void)
 {
   /* Override section callbacks to keep track of `avr_need_clear_bss_p'
-     resp. `avr_need_copy_data_p'.  */
+     resp. `avr_need_copy_data_p'.  If flash is not mapped to RAM then
+     we have also to track .rodata because it is located in RAM then.  */
 
-  readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
+  if (0 == avr_arch->flash_pm_offset)
+    readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
   data_section->unnamed.callback = avr_output_data_section_asm_op;
   bss_section->unnamed.callback = avr_output_bss_section_asm_op;
 }
@@ -10032,9 +10034,13 @@ avr_asm_named_section (const char *name,
 
   if (!avr_need_copy_data_p)
     avr_need_copy_data_p = (STR_PREFIX_P (name, ".data")
-                            || STR_PREFIX_P (name, ".rodata")
                             || STR_PREFIX_P (name, ".gnu.linkonce.d"));
 
+  if (!avr_need_copy_data_p
+      && 0 == avr_arch->flash_pm_offset)
+    avr_need_copy_data_p = (STR_PREFIX_P (name, ".rodata")
+                            || STR_PREFIX_P (name, ".gnu.linkonce.r"));
+
   if (!avr_need_clear_bss_p)
     avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss");
 
@@ -10201,7 +10207,7 @@ avr_encode_section_info (tree decl, rtx
 
       if (progmem_p)
         {
-          // Tag symbols for later addition of 0x4000 (AVR_TINY_PM_OFFSET).
+          // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset).
           SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
         }
 
Index: config/avr/avr.h
===================================================================
--- config/avr/avr.h	(revision 249064)
+++ config/avr/avr.h	(working copy)
@@ -60,7 +60,9 @@ enum
 
 #define TARGET_CPU_CPP_BUILTINS()	avr_cpu_cpp_builtins (pfile)
 
-#define AVR_HAVE_JMP_CALL (avr_arch->have_jmp_call)
+#define AVR_SHORT_CALLS (TARGET_SHORT_CALLS                             \
+                         && avr_arch == &avr_arch_types[ARCH_AVRXMEGA3])
+#define AVR_HAVE_JMP_CALL (avr_arch->have_jmp_call && ! AVR_SHORT_CALLS)
 #define AVR_HAVE_MUL (avr_arch->have_mul)
 #define AVR_HAVE_MOVW (avr_arch->have_movw_lpmx)
 #define AVR_HAVE_LPM (!AVR_TINY)
@@ -74,8 +76,6 @@ enum
                         || avr_arch->have_rampd)
 #define AVR_HAVE_EIJMP_EICALL (avr_arch->have_eijmp_eicall)
 
-#define AVR_TINY_PM_OFFSET (0x4000)
-
 /* Handling of 8-bit SP versus 16-bit SP is as follows:
 
 FIXME: DRIVER_SELF_SPECS has changed.
Index: config/avr/avr.opt
===================================================================
--- config/avr/avr.opt	(revision 249064)
+++ config/avr/avr.opt	(working copy)
@@ -44,6 +44,10 @@ Target Report Undocumented Mask(ALL_DEBU
 mlog=
 Target RejectNegative Joined Undocumented Var(avr_log_details)
 
+mshort-calls
+Target Report RejectNegative Mask(SHORT_CALLS)
+Use RJMP / RCALL even though CALL / JMP are available.
+
 mint8
 Target Report Mask(INT8)
 Use an 8-bit 'int' type.
Index: config/avr/gen-avr-mmcu-specs.c
===================================================================
--- config/avr/gen-avr-mmcu-specs.c	(revision 249064)
+++ config/avr/gen-avr-mmcu-specs.c	(working copy)
@@ -113,6 +113,7 @@ static void
 print_mcu (const avr_mcu_t *mcu)
 {
   const char *sp8_spec;
+  const char *rcall_spec;
   const avr_mcu_t *arch_mcu;
   const avr_arch_t *arch;
   enum avr_arch_id arch_id = mcu->arch_id;
@@ -134,6 +135,7 @@ for (arch_mcu = mcu; arch_mcu->macro; )
   bool errata_skip = 0 != (mcu->dev_attribute & AVR_ERRATA_SKIP);
   bool rmw = 0 != (mcu->dev_attribute & AVR_ISA_RMW);
   bool sp8 = 0 != (mcu->dev_attribute & AVR_SHORT_SP);
+  bool rcall = (mcu->dev_attribute & AVR_ISA_RCALL);
   bool is_arch = NULL == mcu->macro;
   bool is_device = ! is_arch;
 
@@ -150,13 +152,25 @@ bool is_arch = NULL == mcu->macro;
       sp8_spec = sp8 ? "-msp8" :"%<msp8";
     }
 
+  if (is_arch
+      && ARCH_AVRXMEGA3 == arch_id)
+    {
+      // Leave "avrxmega3" alone.  This architectures is the only one
+      // that mixes devices with and without JMP / CALL.
+      rcall_spec = "";
+    }
+  else
+    {
+      rcall_spec = rcall ? "-mshort-calls" : "%<mshort-calls";
+    }
+
   fprintf (f, "#\n"
            "# Auto-generated specs for AVR ");
   if (is_arch)
     fprintf (f, "core architecture %s\n", arch->name);
   else
-    fprintf (f, "device %s (core %s, %d-bit SP)\n",
-             mcu->name, arch->name, sp8 ? 8 : 16);
+    fprintf (f, "device %s (core %s, %d-bit SP%s)\n", mcu->name,
+			 arch->name, sp8 ? 8 : 16, rcall ? ", short-calls" : "");
   fprintf (f, "%s\n", header);
 
   if (is_device)
@@ -255,6 +269,7 @@ bool is_arch = NULL == mcu->macro;
     {
       fprintf (f, "*self_spec:\n");
       fprintf (f, "\t%%{!mmcu=avr*: %%<mmcu=* -mmcu=%s} ", arch->name);
+      fprintf (f, "%s ", rcall_spec);
       fprintf (f, "%s\n\n", sp8_spec);
 
 #if defined (WITH_AVRLIBC)
Index: config/avr/genmultilib.awk
===================================================================
--- config/avr/genmultilib.awk	(revision 249064)
+++ config/avr/genmultilib.awk	(working copy)
@@ -35,6 +35,9 @@ BEGIN {
     dir_tiny = "tiny-stack"
     opt_tiny = "msp8"
 
+    dir_rcall = "short-calls"
+    opt_rcall = "mshort-calls"
+
     #    awk Variable         Makefile Variable  
     #  ------------------------------------------
     #    m_options     <->    MULTILIB_OPTIONS
@@ -116,6 +119,8 @@ BEGIN {
     {
       if (dev_attribute[i] == "AVR_SHORT_SP")
         opts = opts "/" opt_tiny
+      if (dev_attribute[i] == "AVR_ISA_RCALL")
+        opts = opts "/" opt_rcall
     }
 
     if (!have[opts])
@@ -140,7 +145,7 @@ END {
 
     # Intended Target: ./gcc/config/avr/t-multilib
 
-    print m_options  " " opt_tiny
-    print m_dirnames " " dir_tiny
+    print m_options  " " opt_tiny " " opt_rcall
+    print m_dirnames " " dir_tiny " " dir_rcall
     print m_required
 }
Index: config/avr/t-multilib
===================================================================
--- config/avr/t-multilib	(revision 249064)
+++ config/avr/t-multilib	(working copy)
@@ -21,9 +21,9 @@
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
 
-MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7/mmcu=avrtiny msp8
+MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega3/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7/mmcu=avrtiny msp8 mshort-calls
 
-MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny tiny-stack
+MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny tiny-stack short-calls
 
 MULTILIB_REQUIRED = \
 	msp8 \
@@ -37,6 +37,8 @@ MULTILIB_REQUIRED = \
 	mmcu=avr51 \
 	mmcu=avr6 \
 	mmcu=avrxmega2 \
+	mmcu=avrxmega3/mshort-calls \
+	mmcu=avrxmega3 \
 	mmcu=avrxmega4 \
 	mmcu=avrxmega5 \
 	mmcu=avrxmega6 \
Index: configure
===================================================================
--- configure	(revision 249064)
+++ configure	(working copy)
@@ -24819,6 +24819,61 @@ $as_echo "#define HAVE_AS_AVR_MRMW_OPTIO
 
 fi
 
+
+    # Check how default linker description file implements .rodata for
+    # avrxmega3 (PR21472).  avr-gcc assumes .rodata is *not* loaded to
+    # RAM so avr-gcc skips __do_copy_data for .rodata objects.
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking binutils for avrxmega3 .rodata support" >&5
+$as_echo_n "checking binutils for avrxmega3 .rodata support... " >&6; }
+    cat > conftest.s <<EOF
+        .section .rodata,"a",@progbits
+        .global xxvaryy
+    ;; avr-nm should print "... R xxvaryy", not "... D xxvaryy".
+    xxvaryy:
+        .word 1
+EOF
+    rm -f conftest.nm
+    { ac_try='$gcc_cv_as -mmcu=avrxmega3 conftest.s -o conftest.o'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    { ac_try='$gcc_cv_ld -mavrxmega3 conftest.o -o conftest.elf'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    { ac_try='$gcc_cv_nm conftest.elf > conftest.nm'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    if test -f conftest.nm
+    then
+	if grep ' R xxvaryy' conftest.nm > /dev/null; then
+	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+	    rm -f conftest.s conftest.o conftest.elf conftest.nm
+	else
+	    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no: avrxmega3 .rodata located in RAM" >&5
+$as_echo "no: avrxmega3 .rodata located in RAM" >&6; }
+	    echo "$as_me: nm output was" >&5
+	    cat conftest.nm >&5
+	    rm -f conftest.s conftest.o conftest.elf conftest.nm
+	    avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`"
+	    as_fn_error "support for avrxmega3 needs Binutils 2.29 or higher (have $avr_ld_ver)" "$LINENO" 5
+	fi
+    else
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: test failed" >&5
+$as_echo "test failed" >&6; }
+	echo "$as_me: failed program was" >&5
+	cat conftest.s >&5
+	rm -f conftest.s conftest.o conftest.elf
+	as_fn_error "see \`config.log' for details" "$LINENO" 5
+    fi
     ;;
 
   cris-*-*)
Index: configure.ac
===================================================================
--- configure.ac	(revision 249064)
+++ configure.ac	(working copy)
@@ -3816,6 +3816,42 @@ [	.set nomacro
       [-mrmw], [.text],,
       [AC_DEFINE(HAVE_AS_AVR_MRMW_OPTION, 1,
 		[Define if your avr assembler supports -mrmw option.])])
+
+    # Check how default linker description file implements .rodata for
+    # avrxmega3 (PR21472).  avr-gcc assumes .rodata is *not* loaded to
+    # RAM so avr-gcc skips __do_copy_data for .rodata objects.
+    AC_MSG_CHECKING(binutils for avrxmega3 .rodata support)
+    cat > conftest.s <<EOF
+        .section .rodata,"a",@progbits
+        .global xxvaryy
+    ;; avr-nm should print "... R xxvaryy", not "... D xxvaryy".
+    xxvaryy:
+        .word 1
+EOF
+    rm -f conftest.nm
+    AC_TRY_COMMAND([$gcc_cv_as -mmcu=avrxmega3 conftest.s -o conftest.o])
+    AC_TRY_COMMAND([$gcc_cv_ld -mavrxmega3 conftest.o -o conftest.elf])
+    AC_TRY_COMMAND([$gcc_cv_nm conftest.elf > conftest.nm])
+    if test -f conftest.nm
+    then
+	if grep ' R xxvaryy' conftest.nm > /dev/null; then
+	    AC_MSG_RESULT(yes)
+	    rm -f conftest.s conftest.o conftest.elf conftest.nm
+	else
+	    AC_MSG_RESULT(no: avrxmega3 .rodata located in RAM)
+	    echo "$as_me: nm output was" >&AS_MESSAGE_LOG_FD
+	    cat conftest.nm >&AS_MESSAGE_LOG_FD
+	    rm -f conftest.s conftest.o conftest.elf conftest.nm
+	    avr_ld_ver="`$gcc_cv_ld -v | sed -e 's:^.* ::'`"
+	    AC_MSG_ERROR([[support for avrxmega3 needs Binutils 2.29 or higher (have $avr_ld_ver)]])
+	fi
+    else
+	AC_MSG_RESULT(test failed)
+	echo "$as_me: failed program was" >&AS_MESSAGE_LOG_FD
+	cat conftest.s >&AS_MESSAGE_LOG_FD
+	rm -f conftest.s conftest.o conftest.elf
+	AC_MSG_ERROR([[see `config.log' for details]])
+    fi
     ;;
 
   cris-*-*)
Index: doc/avr-mmcu.texi
===================================================================
--- doc/avr-mmcu.texi	(revision 249064)
+++ doc/avr-mmcu.texi	(working copy)
@@ -52,6 +52,10 @@
 ``XMEGA'' devices with more than 8@tie{}KiB and up to 64@tie{}KiB of program memory.
 @*@var{mcu}@tie{}= @code{atxmega16a4}, @code{atxmega16a4u}, @code{atxmega16c4}, @code{atxmega16d4}, @code{atxmega16e5}, @code{atxmega32a4}, @code{atxmega32a4u}, @code{atxmega32c3}, @code{atxmega32c4}, @code{atxmega32d3}, @code{atxmega32d4}, @code{atxmega32e5}, @code{atxmega8e5}.
 
+@item avrxmega3
+``XMEGA'' devices with up to 64@tie{}KiB of combined program memory and RAM, and with program memory visible in the RAM address space.
+@*@var{mcu}@tie{}= @code{attiny1614}, @code{attiny1616}, @code{attiny1617}, @code{attiny212}, @code{attiny214}, @code{attiny3214}, @code{attiny3216}, @code{attiny3217}, @code{attiny412}, @code{attiny414}, @code{attiny416}, @code{attiny417}, @code{attiny814}, @code{attiny816}, @code{attiny817}.
+
 @item avrxmega4
 ``XMEGA'' devices with more than 64@tie{}KiB and up to 128@tie{}KiB of program memory.
 @*@var{mcu}@tie{}= @code{atxmega64a3}, @code{atxmega64a3u}, @code{atxmega64a4u}, @code{atxmega64b1}, @code{atxmega64b3}, @code{atxmega64c3}, @code{atxmega64d3}, @code{atxmega64d4}.
Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(revision 249064)
+++ doc/extend.texi	(working copy)
@@ -1312,11 +1312,24 @@ in order to put read-only data into the
 data by means of the special instructions @code{LPM} or @code{ELPM}
 needed to read from flash.
 
-Per default, any data including read-only data is located in RAM
-(the generic address space) so that non-generic address spaces are
-needed to locate read-only data in flash memory
-@emph{and} to generate the right instructions to access this data
-without using (inline) assembler code.
+Devices belonging to @code{avrtiny} and @code{avrxmega3} can access
+flash memory by means of @code{LD*} instructions because the flash
+memory is mapped into the RAM address space.  There is @emph{no need}
+for language extensions like @code{__flash} or attribute
+@ref{AVR Variable Attributes,,@code{progmem}}.
+The default linker description files for these devices cater for that
+feature and @code{.rodata} stays in flash: The compiler just generates
+@code{LD*} instructions, and the linker script adds core specific
+offsets to all @code{.rodata} symbols: @code{0x4000} in the case of
+@code{avrtiny} and @code{0x8000} in the case of @code{avrxmega3}.
+See @ref{AVR Options} for a list of respective devices.
+
+For devices not in @code{avrtiny} or @code{avrxmega3},
+any data including read-only data is located in RAM (the generic
+address space) because flash memory is not visible in the RAM address
+space.  In order to locate read-only data in flash memory @emph{and}
+to generate the right instructions to access this data without
+using (inline) assembler code, special address spaces are needed.
 
 @table @code
 @item __flash
@@ -1447,14 +1460,11 @@ extern const __memx char foo;
 const __memx void *pfoo = &foo;
 @end smallexample
 
-@noindent
-Such code requires at least binutils 2.23, see
-@w{@uref{https://sourceware.org/PR13503,PR13503}}.
-
 @item
 On the reduced Tiny devices like ATtiny40, no address spaces are supported.
-Data can be put into and read from flash memory by means of
-attribute @code{progmem}, see @ref{AVR Variable Attributes}.
+Just use vanilla C / C++ code without overhead as outlined above.
+Attribute @code{progmem} is supported but works differently,
+see @ref{AVR Variable Attributes}.
 
 @end itemize
 
@@ -5936,6 +5946,19 @@ normally resides in the data memory (RAM
 See also the @ref{AVR Named Address Spaces} section for
 an alternate way to locate and access data in flash memory.
 
+@item @bullet{}@tie{} AVR cores with flash memory visible in the RAM address range:
+On such devices, there is no need for attribute @code{progmem} or
+@ref{AVR Named Address Spaces,,@code{__flash}} qualifier at all.
+Just use standard C / C++.  The compiler will generate @code{LD*}
+instructions.  As flash memory is visible in the RAM address range,
+and the default linker script does @emph{not} locate @code{.rodata} in
+RAM, no special features are needed in order not to waste RAM for
+read-only data or to read from flash.  You might even get slightly better
+performance by
+avoiding @code{progmem} and @code{__flash}.  This applies to devices from
+families @code{avrtiny} and @code{avrxmega3}, see @ref{AVR Options} for
+an overview.
+
 @item @bullet{}@tie{}Reduced AVR Tiny cores like ATtiny40:
 The compiler adds @code{0x4000}
 to the addresses of objects and declarations in @code{progmem} and locates
@@ -5957,28 +5980,7 @@ int read_var (int i)
 @end smallexample
 
 Please notice that on these devices, there is no need for @code{progmem}
-at all.  Just use an appropriate linker description file like outlined below.
-
-@smallexample
-  .text :
-  @{ ...
-  @} > text
-  /* Leave .rodata in flash and add an offset of 0x4000 to all
-     addresses so that respective objects can be accessed by
-     LD instructions and open coded C/C++.  This means there
-     is no need for progmem in the source and no overhead by
-     read-only data in RAM.  */
-  .rodata ADDR(.text) + SIZEOF (.text) + 0x4000 :
-  @{
-    *(.rodata)
-    *(.rodata*)
-    *(.gnu.linkonce.r*)
-  @} AT> text
-  /* No more need to put .rodata into .data:
-     Removed all .rodata entries from .data.  */
-  .data :
-  @{ ...
-@end smallexample
+at all.
 
 @end table
 
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 249064)
+++ doc/invoke.texi	(working copy)
@@ -662,7 +662,7 @@ -imacros @var{file}  -imultilib @var{dir
 -mbranch-cost=@var{cost} @gol
 -mcall-prologues  -mint8  -mn_flash=@var{size}  -mno-interrupts @gol
 -mrelax  -mrmw  -mstrict-X  -mtiny-stack  -mfract-convert-truncate @gol
--nodevicelib @gol
+-mshort-calls  -nodevicelib @gol
 -Waddr-space-convert  -Wmisspelled-isr}
 
 @emph{Blackfin Options}
@@ -15635,6 +15635,15 @@ section on @code{EIND} and linker stubs
 Assume that the device supports the Read-Modify-Write
 instructions @code{XCH}, @code{LAC}, @code{LAS} and @code{LAT}.
 
+@item -mshort-calls
+@opindex mshort-calls
+
+Assume that @code{RJMP} and @code{RCALL} can target the whole
+program memory.
+
+This option is used internally for multilib selection.  It is
+not an optimization option, and you don't need to set it by hand.
+
 @item -msp8
 @opindex msp8
 Treat the stack pointer register as an 8-bit register,
@@ -15895,10 +15904,12 @@ for @var{mcu}=@code{avr2}, @code{avr25},
 
 respectively and
 
-@code{100}, @code{102}, @code{104},
+@code{100},
+@code{102}, @code{103}, @code{104},
 @code{105}, @code{106}, @code{107}
 
-for @var{mcu}=@code{avrtiny}, @code{avrxmega2}, @code{avrxmega4},
+for @var{mcu}=@code{avrtiny},
+@code{avrxmega2}, @code{avrxmega3}, @code{avrxmega4},
 @code{avrxmega5}, @code{avrxmega6}, @code{avrxmega7}, respectively.
 If @var{mcu} specifies a device, this built-in macro is set
 accordingly. For example, with @option{-mmcu=atmega8} the macro is
@@ -15950,7 +15961,7 @@ The device has a hardware multiplier.
 
 @item __AVR_HAVE_JMP_CALL__
 The device has the @code{JMP} and @code{CALL} instructions.
-This is the case for devices with at least 16@tie{}KiB of program
+This is the case for devices with more than 8@tie{}KiB of program
 memory.
 
 @item __AVR_HAVE_EIJMP_EICALL__
@@ -16007,6 +16018,21 @@ or @code{STS}. This offset depends on th
 to be subtracted from the RAM address in order to get the
 respective I/O@tie{}address.
 
+@item __AVR_SHORT_CALLS__
+The @option{-mshort-calls} command line option is set.
+
+@item __AVR_PM_BASE_ADDRESS__=@var{addr}
+Some devices support reading from flash memory by means of @code{LD*}
+instructions.  The flash memory is seen in the data address space
+at an offset of @code{__AVR_PM_BASE_ADDRESS__}.  If this macro
+is not defined, this feature is not available.  If defined,
+the address space is linear and there is no need to put
+@code{.rodata} into RAM.  This is handled by the default linker
+description file, and is currently available for
+@code{avrtiny} and @code{avrxmega3}.  Even more convenient,
+there is no need to use address spaces like @code{__flash} or
+features like attribute @code{progmem} and @code{pgm_read_*}.
+
 @item __WITH_AVRLIBC__
 The compiler is configured to be used together with AVR-Libc.
 See the @option{--with-avrlibc} configure option.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]