Commit bae3b1bf by Georg-Johann Lay Committed by Georg-Johann Lay

re PR target/49868 (Implement named address space to place/access data in flash memory)

	PR target/49868
	PR target/52261
	* doc/extend.texi (AVR Named Address Spaces): No more try to fix
	address spaces located outside of device flash.
	* config/avr/avr.h (base_arch_s): Remove field n_segments.
	(mcu_type_s): Add field n_flash.
	* config/avr/avr-devices.c (avr_arch_types): Remove .n_segments.
	Set .have_elpm and .have_elpmx to 1 for avrxmega4 and avrxmega5.
	(AVR_MCU): Add N_FLASH argument.
	* config/avr/avr-mcus.def (AVR_MCU): Add initializer for .n_flash.
	* config/avr/avr-c.c (avr_cpu_cpp_builtins): Only define built-in
	macro __FLASH<n> if that address space makes sense for the device.
	* config/avr/avr.c (avr_out_lpm): Don't try to fix address spaces
	outside of target flash.
	(avr_asm_named_section): Ditto.
	(avr_asm_select_section): Ditto.
	(avr_addr_space_convert): Ditto.
	(avr_emit_movmemhi): Ditto.
	(avr_nonconst_pointer_addrspace, avr_pgm_check_var_decl): Error if
	address space is outside of device flash.
	(avr_insert_attributes): Ditto.
	(avr_xload_libgcc_p): Use avr_current_device->n_flash instead of
	avr_current_arch->n_segments.

From-SVN: r184614
parent 5250783d
2012-02-28 Georg-Johann Lay <avr@gjlay.de>
PR target/49868
PR target/52261
* doc/extend.texi (AVR Named Address Spaces): No more try to fix
address spaces located outside of device flash.
* config/avr/avr.h (base_arch_s): Remove field n_segments.
(mcu_type_s): Add field n_flash.
* config/avr/avr-devices.c (avr_arch_types): Remove .n_segments.
Set .have_elpm and .have_elpmx to 1 for avrxmega4 and avrxmega5.
(AVR_MCU): Add N_FLASH argument.
* config/avr/avr-mcus.def (AVR_MCU): Add initializer for .n_flash.
* config/avr/avr-c.c (avr_cpu_cpp_builtins): Only define built-in
macro __FLASH<n> if that address space makes sense for the device.
* config/avr/avr.c (avr_out_lpm): Don't try to fix address spaces
outside of target flash.
(avr_asm_named_section): Ditto.
(avr_asm_select_section): Ditto.
(avr_addr_space_convert): Ditto.
(avr_emit_movmemhi): Ditto.
(avr_nonconst_pointer_addrspace, avr_pgm_check_var_decl): Error if
address space is outside of device flash.
(avr_insert_attributes): Ditto.
(avr_xload_libgcc_p): Use avr_current_device->n_flash instead of
avr_current_arch->n_segments.
2012-02-27 H.J. Lu <hongjiu.lu@intel.com> 2012-02-27 H.J. Lu <hongjiu.lu@intel.com>
PR target/52352 PR target/52352
......
...@@ -143,7 +143,11 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile) ...@@ -143,7 +143,11 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile)
int i; int i;
for (i = 0; avr_addrspace[i].name; i++) for (i = 0; avr_addrspace[i].name; i++)
if (!ADDR_SPACE_GENERIC_P (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
supported, but using it will throw an error. */
&& avr_addrspace[i].segment < avr_current_device->n_flash)
{ {
const char *name = avr_addrspace[i].name; const char *name = avr_addrspace[i].name;
char *Name = (char*) alloca (1 + strlen (name)); char *Name = (char*) alloca (1 + strlen (name));
......
...@@ -30,34 +30,34 @@ const struct base_arch_s ...@@ -30,34 +30,34 @@ const struct base_arch_s
avr_arch_types[] = avr_arch_types[] =
{ {
/* unknown device specified */ /* unknown device specified */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, NULL, "avr2" }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, NULL, "avr2" },
/* /*
A M J LM E E E X R d S S O # F A A M J LM E E E X R d S S O A
S U M PO L L I M A a t F ff 6 l r S U M PO L L I M A a t F ff r
M L P MV P P J E M t a R s 4 a c M L P MV P P J E M t a R s c
XW M M M G P a r e s h XW M M M G P a r e h
X P A D t t k h ID */ X P A D t t ID */
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "1", "avr1" }, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "1", "avr1" },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "2", "avr2" }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0060, 32, "2", "avr2" },
{ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "25", "avr25" }, { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, "25", "avr25" },
{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, 1, "3", "avr3" }, { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0x0060, 32, "3", "avr3" },
{ 0, 0, 1, 0, 1, 0, 0, 0, 0, 0x0060, 32, 2, "31", "avr31" }, { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0x0060, 32, "31", "avr31" },
{ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "35", "avr35" }, { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, "35", "avr35" },
{ 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "4", "avr4" }, { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0x0060, 32, "4", "avr4" },
{ 0, 1, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, 1, "5", "avr5" }, { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0x0060, 32, "5", "avr5" },
{ 0, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, 2, "51", "avr51" }, { 0, 1, 1, 1, 1, 1, 0, 0, 0, 0x0060, 32, "51", "avr51" },
{ 0, 1, 1, 1, 1, 1, 1, 0, 0, 0x0060, 32, 4, "6", "avr6" }, { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0x0060, 32, "6", "avr6" },
{ 0, 1, 1, 1, 0, 0, 0, 1, 0, 0x2000, 0, 1, "102", "avrxmega2" }, { 0, 1, 1, 1, 0, 0, 0, 1, 0, 0x2000, 0, "102", "avrxmega2" },
{ 0, 1, 1, 1, 0, 0, 0, 1, 0, 0x2000, 0, 1, "104", "avrxmega4" }, /* Same */ { 0, 1, 1, 1, 1, 1, 0, 1, 0, 0x2000, 0, "104", "avrxmega4" },
{ 0, 1, 1, 1, 0, 0, 0, 1, 1, 0x2000, 0, 1, "105", "avrxmega5" }, { 0, 1, 1, 1, 1, 1, 0, 1, 1, 0x2000, 0, "105", "avrxmega5" },
{ 0, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000, 0, 4, "106", "avrxmega6" }, { 0, 1, 1, 1, 1, 1, 1, 1, 0, 0x2000, 0, "106", "avrxmega6" },
{ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0x2000, 0, 4, "107", "avrxmega7" } { 0, 1, 1, 1, 1, 1, 1, 1, 1, 0x2000, 0, "107", "avrxmega7" }
}; };
const struct mcu_type_s avr_mcu_types[] = { const struct mcu_type_s avr_mcu_types[] = {
#define AVR_MCU(NAME, ARCH, MACRO, SHORT_SP, ERRATA_SKIP, DATA_SEC, LIBRARY_NAME) \ #define AVR_MCU(NAME,ARCH,MACRO,SHORT_SP,ERRATA_SKIP,DATA_SEC,N_FLASH,LIB_NAME)\
{ NAME, ARCH, MACRO, SHORT_SP, ERRATA_SKIP, DATA_SEC, LIBRARY_NAME }, { NAME, ARCH, MACRO, SHORT_SP, ERRATA_SKIP, DATA_SEC, N_FLASH, LIB_NAME },
#include "avr-mcus.def" #include "avr-mcus.def"
#undef AVR_MCU #undef AVR_MCU
/* End of list. */ /* End of list. */
......
...@@ -2577,7 +2577,7 @@ avr_xload_libgcc_p (enum machine_mode mode) ...@@ -2577,7 +2577,7 @@ avr_xload_libgcc_p (enum machine_mode mode)
int n_bytes = GET_MODE_SIZE (mode); int n_bytes = GET_MODE_SIZE (mode);
return (n_bytes > 1 return (n_bytes > 1
|| avr_current_arch->n_segments > 1); || avr_current_device->n_flash > 1);
} }
...@@ -2773,10 +2773,7 @@ avr_out_lpm (rtx insn, rtx *op, int *plen) ...@@ -2773,10 +2773,7 @@ avr_out_lpm (rtx insn, rtx *op, int *plen)
regno_dest = REGNO (dest); regno_dest = REGNO (dest);
/* Cut down segment number to a number the device actually supports. segment = avr_addrspace[as].segment;
We do this late to preserve the address space's name for diagnostics. */
segment = avr_addrspace[as].segment % avr_current_arch->n_segments;
/* Set RAMPZ as needed. */ /* Set RAMPZ as needed. */
...@@ -7101,6 +7098,7 @@ avr_nonconst_pointer_addrspace (tree typ) ...@@ -7101,6 +7098,7 @@ avr_nonconst_pointer_addrspace (tree typ)
if (POINTER_TYPE_P (typ)) if (POINTER_TYPE_P (typ))
{ {
addr_space_t as;
tree target = TREE_TYPE (typ); tree target = TREE_TYPE (typ);
/* Pointer to function: Test the function's return type. */ /* Pointer to function: Test the function's return type. */
...@@ -7113,12 +7111,16 @@ avr_nonconst_pointer_addrspace (tree typ) ...@@ -7113,12 +7111,16 @@ avr_nonconst_pointer_addrspace (tree typ)
while (TREE_CODE (target) == ARRAY_TYPE) while (TREE_CODE (target) == ARRAY_TYPE)
target = TREE_TYPE (target); target = TREE_TYPE (target);
if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (target)) /* Pointers to non-generic address space must be const.
&& !TYPE_READONLY (target)) Refuse address spaces outside the device's flash. */
{
/* Pointers to non-generic address space must be const. */
return TYPE_ADDR_SPACE (target); as = TYPE_ADDR_SPACE (target);
if (!ADDR_SPACE_GENERIC_P (as)
&& (!TYPE_READONLY (target)
|| avr_addrspace[as].segment >= avr_current_device->n_flash))
{
return as;
} }
/* Scan pointer's target type. */ /* Scan pointer's target type. */
...@@ -7180,12 +7182,29 @@ avr_pgm_check_var_decl (tree node) ...@@ -7180,12 +7182,29 @@ avr_pgm_check_var_decl (tree node)
if (reason) if (reason)
{ {
if (TYPE_P (node)) avr_edump ("%?: %s, %d, %d\n",
error ("pointer targeting address space %qs must be const in %qT", avr_addrspace[as].name,
avr_addrspace[as].name, node); avr_addrspace[as].segment, avr_current_device->n_flash);
if (avr_addrspace[as].segment >= avr_current_device->n_flash)
{
if (TYPE_P (node))
error ("%qT uses address space %qs beyond flash of %qs",
node, avr_addrspace[as].name, avr_current_device->name);
else
error ("%s %q+D uses address space %qs beyond flash of %qs",
reason, node, avr_addrspace[as].name,
avr_current_device->name);
}
else else
error ("pointer targeting address space %qs must be const in %s %q+D", {
avr_addrspace[as].name, reason, node); if (TYPE_P (node))
error ("pointer targeting address space %qs must be const in %qT",
avr_addrspace[as].name, node);
else
error ("pointer targeting address space %qs must be const"
" in %s %q+D",
avr_addrspace[as].name, reason, node);
}
} }
return reason == NULL; return reason == NULL;
...@@ -7203,6 +7222,7 @@ avr_insert_attributes (tree node, tree *attributes) ...@@ -7203,6 +7222,7 @@ avr_insert_attributes (tree node, tree *attributes)
&& (TREE_STATIC (node) || DECL_EXTERNAL (node)) && (TREE_STATIC (node) || DECL_EXTERNAL (node))
&& avr_progmem_p (node, *attributes)) && avr_progmem_p (node, *attributes))
{ {
addr_space_t as;
tree node0 = node; tree node0 = node;
/* For C++, we have to peel arrays in order to get correct /* For C++, we have to peel arrays in order to get correct
...@@ -7214,11 +7234,19 @@ avr_insert_attributes (tree node, tree *attributes) ...@@ -7214,11 +7234,19 @@ avr_insert_attributes (tree node, tree *attributes)
if (error_mark_node == node0) if (error_mark_node == node0)
return; return;
as = TYPE_ADDR_SPACE (TREE_TYPE (node));
if (avr_addrspace[as].segment >= avr_current_device->n_flash)
{
error ("variable %q+D located in address space %qs"
" beyond flash of %qs",
node, avr_addrspace[as].name, avr_current_device->name);
}
if (!TYPE_READONLY (node0) if (!TYPE_READONLY (node0)
&& !TREE_READONLY (node)) && !TREE_READONLY (node))
{ {
addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (node));
const char *reason = "__attribute__((progmem))"; const char *reason = "__attribute__((progmem))";
if (!ADDR_SPACE_GENERIC_P (as)) if (!ADDR_SPACE_GENERIC_P (as))
...@@ -7403,7 +7431,7 @@ avr_asm_named_section (const char *name, unsigned int flags, tree decl) ...@@ -7403,7 +7431,7 @@ avr_asm_named_section (const char *name, unsigned int flags, tree decl)
if (flags & AVR_SECTION_PROGMEM) if (flags & AVR_SECTION_PROGMEM)
{ {
addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP; addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
int segment = avr_addrspace[as].segment % avr_current_arch->n_segments; int segment = avr_addrspace[as].segment;
const char *old_prefix = ".rodata"; const char *old_prefix = ".rodata";
const char *new_prefix = progmem_section_prefix[segment]; const char *new_prefix = progmem_section_prefix[segment];
...@@ -7518,7 +7546,7 @@ avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align) ...@@ -7518,7 +7546,7 @@ avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
&& avr_progmem_p (decl, DECL_ATTRIBUTES (decl))) && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
{ {
addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl)); addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
int segment = avr_addrspace[as].segment % avr_current_arch->n_segments; int segment = avr_addrspace[as].segment;
if (sect->common.flags & SECTION_NAMED) if (sect->common.flags & SECTION_NAMED)
{ {
...@@ -9852,7 +9880,7 @@ avr_addr_space_convert (rtx src, tree type_from, tree type_to) ...@@ -9852,7 +9880,7 @@ avr_addr_space_convert (rtx src, tree type_from, tree type_to)
msb = ADDR_SPACE_GENERIC_P (as_from) msb = ADDR_SPACE_GENERIC_P (as_from)
? 0x80 ? 0x80
: avr_addrspace[as_from].segment % avr_current_arch->n_segments; : avr_addrspace[as_from].segment;
src = force_reg (Pmode, src); src = force_reg (Pmode, src);
...@@ -9936,10 +9964,10 @@ avr_emit_movmemhi (rtx *xop) ...@@ -9936,10 +9964,10 @@ avr_emit_movmemhi (rtx *xop)
} }
else else
{ {
int segment = avr_addrspace[as].segment % avr_current_arch->n_segments; int segment = avr_addrspace[as].segment;
if (segment if (segment
&& avr_current_arch->n_segments > 1) && avr_current_device->n_flash > 1)
{ {
a_hi8 = GEN_INT (segment); a_hi8 = GEN_INT (segment);
emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8)); emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
......
...@@ -60,9 +60,6 @@ struct base_arch_s ...@@ -60,9 +60,6 @@ struct base_arch_s
SFR-address = RAM-address - sfr_offset */ SFR-address = RAM-address - sfr_offset */
int sfr_offset; int sfr_offset;
/* Number of 64k segments in the flash. */
int n_segments;
/* Architecture id to built-in define __AVR_ARCH__ (NULL -> no macro) */ /* Architecture id to built-in define __AVR_ARCH__ (NULL -> no macro) */
const char *const macro; const char *const macro;
...@@ -129,6 +126,9 @@ struct mcu_type_s { ...@@ -129,6 +126,9 @@ struct mcu_type_s {
/* Start of data section. */ /* Start of data section. */
int data_section_start; int data_section_start;
/* Number of 64k segments in the flash. */
int n_flash;
/* Name of device library. */ /* Name of device library. */
const char *const library_name; const char *const library_name;
}; };
......
...@@ -1266,14 +1266,6 @@ address space @code{__flash@var{N}}. ...@@ -1266,14 +1266,6 @@ address space @code{__flash@var{N}}.
The compiler will set the @code{RAMPZ} segment register approptiately The compiler will set the @code{RAMPZ} segment register approptiately
before reading data by means of the @code{ELPM} instruction. before reading data by means of the @code{ELPM} instruction.
On devices with less 64@tie{}kiB flash segments as indicated by the address
space, the compiler will cut down the segment number to a number the
device actually supports. Counting starts at@tie{}@code{0}
for space @code{__flash}. For example, if you access address space
@code{__flash3} on an ATmega128 device with two 64@tie{}kiB flash segments,
the compiler will generate a read from @code{__flash1}, i.e.@: it
will load @code{RAMPZ} with@tie{}@code{1} before reading.
@item __memx @item __memx
@cindex @code{__memx} AVR Named Address Spaces @cindex @code{__memx} AVR Named Address Spaces
This is a 24-bit address space that linearizes flash and RAM: This is a 24-bit address space that linearizes flash and RAM:
......
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